Commit 3922ba2c authored by Michael Beck's avatar Michael Beck
Browse files

Removed USE_FAST_PHI_CONSTRUCTION and USE_EXPLICIT_PHI_IN_STACK

options: This code is neither used nor usefull in current Firm

Fixed handling of exceptional memory.

[r15935]
parent 93604465
......@@ -67,9 +67,14 @@
*/
/**
* you can work on the graph without considering the different types
* of nodes, it's just a big graph.
* Some projection numbers must be always equal to support automatic phi construction
*/
enum pn_generic {
pn_Generic_M_regular = 0, /**< The memory result. */
pn_Generic_X_regular = 1, /**< Execution result if no exception occurred. */
pn_Generic_X_except = 2, /**< The control flow result branching to the exception handler */
pn_Generic_other = 3 /**< First free projection number */
};
/**
* Checks whether a pointer points to a ir node.
......@@ -585,15 +590,15 @@ void set_Sel_entity (ir_node *node, ir_entity *ent);
* Projection numbers for result of Call node: use for Proj nodes!
*/
typedef enum {
pn_Call_M_regular = 0, /**< The memory result. */
pn_Call_X_regular = 1, /**< The control flow result when no exception occurs. */
pn_Call_X_except = 2, /**< The control flow result branching to the exception handler. */
pn_Call_T_result = 3, /**< The tuple containing all (0, 1, 2, ...) results. */
pn_Call_M_except = 4, /**< The memory result in case the called method terminated with
an exception. */
pn_Call_P_value_res_base = 5,/**< A pointer to the memory region containing copied results
passed by value (for compound result types). */
pn_Call_max = 6 /**< number of projections from a Call */
pn_Call_M_regular = pn_Generic_M_regular, /**< The memory result. */
pn_Call_X_regular = pn_Generic_X_regular, /**< The control flow result when no exception occurs. */
pn_Call_X_except = pn_Generic_X_except, /**< The control flow result branching to the exception handler. */
pn_Call_T_result = pn_Generic_other, /**< The tuple containing all (0, 1, 2, ...) results. */
pn_Call_M_except, /**< The memory result in case the called method terminated with
an exception. */
pn_Call_P_value_res_base, /**< A pointer to the memory region containing copied results
passed by value (for compound result types). */
pn_Call_max /**< number of projections from a Call */
} pn_Call; /* Projection numbers for Call. */
#define pn_Call_M pn_Call_M_regular
......@@ -698,11 +703,11 @@ void set_Quot_resmode(ir_node *node, ir_mode *mode);
* Projection numbers for Quot: use for Proj nodes!
*/
typedef enum {
pn_Quot_M, /**< Memory result. */
pn_Quot_X_regular, /**< Execution result if no exception occurred. */
pn_Quot_X_except, /**< Execution result if exception occurred. */
pn_Quot_res, /**< Result of computation. */
pn_Quot_max /**< number of projections from a Quot */
pn_Quot_M = pn_Generic_M_regular, /**< Memory result. */
pn_Quot_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Quot_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Quot_res = pn_Generic_other, /**< Result of computation. */
pn_Quot_max /**< number of projections from a Quot */
} pn_Quot; /* Projection numbers for Quot. */
ir_node *get_DivMod_left(const ir_node *node);
......@@ -718,12 +723,12 @@ void set_DivMod_resmode(ir_node *node, ir_mode *mode);
* Projection numbers for DivMod: use for Proj nodes!
*/
typedef enum {
pn_DivMod_M, /**< Memory result. */
pn_DivMod_X_regular, /**< Execution result if no exception occurred. */
pn_DivMod_X_except, /**< Execution result if exception occurred. */
pn_DivMod_res_div, /**< Result of computation a / b. */
pn_DivMod_res_mod, /**< Result of computation a % b. */
pn_DivMod_max /**< number of projections from a DivMod */
pn_DivMod_M = pn_Generic_M_regular, /**< Memory result. */
pn_DivMod_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_DivMod_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_DivMod_res_div = pn_Generic_other, /**< Result of computation a / b. */
pn_DivMod_res_mod, /**< Result of computation a % b. */
pn_DivMod_max /**< number of projections from a DivMod */
} pn_DivMod; /* Projection numbers for DivMod. */
ir_node *get_Div_left(const ir_node *node);
......@@ -739,11 +744,11 @@ void set_Div_resmode(ir_node *node, ir_mode *mode);
* Projection numbers for Div: use for Proj nodes!
*/
typedef enum {
pn_Div_M, /**< Memory result. */
pn_Div_X_regular, /**< Execution result if no exception occurred. */
pn_Div_X_except, /**< Execution result if exception occurred. */
pn_Div_res, /**< Result of computation. */
pn_Div_max /**< number of projections from a Div */
pn_Div_M = pn_Generic_M_regular, /**< Memory result. */
pn_Div_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Div_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Div_res = pn_Generic_other, /**< Result of computation. */
pn_Div_max /**< number of projections from a Div */
} pn_Div; /* Projection numbers for Div. */
ir_node *get_Mod_left(const ir_node *node);
......@@ -759,11 +764,11 @@ void set_Mod_resmode(ir_node *node, ir_mode *mode);
* Projection numbers for Mod: use for Proj nodes!
*/
typedef enum {
pn_Mod_M, /**< Memory result. */
pn_Mod_X_regular, /**< Execution result if no exception occurred. */
pn_Mod_X_except, /**< Execution result if exception occurred. */
pn_Mod_res, /**< Result of computation. */
pn_Mod_max /**< number of projections from a Mod */
pn_Mod_M = pn_Generic_M_regular, /**< Memory result. */
pn_Mod_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Mod_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Mod_res = pn_Generic_other, /**< Result of computation. */
pn_Mod_max /**< number of projections from a Mod */
} pn_Mod; /* Projection numbers for Mod. */
ir_node *get_Abs_op(const ir_node *node);
......@@ -926,11 +931,11 @@ void set_memop_ptr(ir_node *node, ir_node *ptr);
* Projection numbers for Load: use for Proj nodes!
*/
typedef enum {
pn_Load_M, /**< Memory result. */
pn_Load_X_regular, /**< Execution result if no exception occurred. */
pn_Load_X_except, /**< Execution result if exception occurred. */
pn_Load_res, /**< Result of load operation. */
pn_Load_max /**< number of projections from a Load */
pn_Load_M = pn_Generic_M_regular, /**< Memory result. */
pn_Load_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Load_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Load_res = pn_Generic_other, /**< Result of load operation. */
pn_Load_max /**< number of projections from a Load */
} pn_Load; /* Projection numbers for Load. */
ir_node *get_Load_mem(ir_node *node);
......@@ -948,10 +953,10 @@ void set_Load_align(ir_node *node, ir_align align);
* Projection numbers for Store: use for Proj nodes!
*/
typedef enum {
pn_Store_M, /**< Memory result. */
pn_Store_X_regular, /**< Execution result if no exception occurred. */
pn_Store_X_except, /**< Execution result if exception occurred. */
pn_Store_max /**< number of projections from a Store */
pn_Store_M = pn_Generic_M_regular, /**< Memory result. */
pn_Store_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Store_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Store_max = pn_Generic_other /**< number of projections from a Store */
} pn_Store; /* Projection numbers for Store. */
ir_node *get_Store_mem(ir_node *node);
......@@ -969,11 +974,11 @@ void set_Store_align(ir_node *node, ir_align align);
* Projection numbers for Alloc: use for Proj nodes!
*/
typedef enum {
pn_Alloc_M, /**< Memory result. */
pn_Alloc_X_regular, /**< Execution result if no exception occurred. */
pn_Alloc_X_except, /**< Execution result if exception occurred. */
pn_Alloc_res, /**< Result of allocation. */
pn_Alloc_max /**< number of projections from an Alloc */
pn_Alloc_M = pn_Generic_M_regular, /**< Memory result. */
pn_Alloc_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Alloc_X_except = pn_Generic_X_except, /**< Execution result if exception occurred. */
pn_Alloc_res = pn_Generic_other, /**< Result of allocation. */
pn_Alloc_max /**< number of projections from an Alloc */
} pn_Alloc; /* Projection numbers for Alloc. */
ir_node *get_Alloc_mem(ir_node *node);
......@@ -1063,12 +1068,12 @@ int get_Psi_n_conds(ir_node *node);
* Projection numbers for result of CopyB node: use for Proj nodes!
*/
typedef enum {
pn_CopyB_M_regular = 0, /**< The memory result. */
pn_CopyB_X_regular = 1, /**< Execution result if no exception occurred. */
pn_CopyB_X_except = 2, /**< The control flow result branching to the exception handler */
pn_CopyB_M_except = 3, /**< The memory result in case the runtime function terminated with
an exception */
pn_CopyB_max = 4 /**< number of projections from a CopyB */
pn_CopyB_M_regular = pn_Generic_M_regular, /**< The memory result. */
pn_CopyB_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_CopyB_X_except = pn_Generic_X_except, /**< The control flow result branching to the exception handler */
pn_CopyB_M_except = pn_Generic_other, /**< The memory result in case the runtime function terminated with
an exception */
pn_CopyB_max /**< number of projections from a CopyB */
} pn_CopyB; /* Projection numbers for CopyB. */
#define pn_CopyB_M pn_CopyB_M_regular
......@@ -1085,13 +1090,13 @@ void set_CopyB_type(ir_node *node, ir_type *data_type);
* Projection numbers for result of InstOf node: use for Proj nodes!
*/
typedef enum {
pn_InstOf_M_regular = 0, /**< The memory result. */
pn_InstOf_X_regular = 1, /**< Execution result if no exception occurred. */
pn_InstOf_X_except = 2, /**< The control flow result branching to the exception handler */
pn_InstOf_res = 3, /**< The checked object pointer. */
pn_InstOf_M_except = 4, /**< The memory result in case the runtime function terminated with
an exception */
pn_InstOf_max = 5 /**< number of projections from an InstOf */
pn_InstOf_M_regular = pn_Generic_M_regular, /**< The memory result. */
pn_InstOf_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_InstOf_X_except = pn_Generic_X_except, /**< The control flow result branching to the exception handler */
pn_InstOf_res = pn_Generic_other, /**< The checked object pointer. */
pn_InstOf_M_except, /**< The memory result in case the runtime function terminated with
an exception */
pn_InstOf_max /**< number of projections from an InstOf */
} pn_InstOf;
#define pn_InstOf_M pn_InstOf_M_regular
......@@ -1121,11 +1126,11 @@ void set_Raise_exo_ptr(ir_node *node, ir_node *exoptr);
* Projection numbers for result of Bound node: use for Proj nodes!
*/
typedef enum {
pn_Bound_M = 0, /**< The memory result. */
pn_Bound_X_regular = 1, /**< Execution result if no exception occurred. */
pn_Bound_X_except = 2, /**< The control flow result branching to the exception handler */
pn_Bound_res = 3, /**< The checked index. */
pn_Bound_max = 4 /**< number of projections from a Bound */
pn_Bound_M = pn_Generic_M_regular, /**< The memory result. */
pn_Bound_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
pn_Bound_X_except = pn_Generic_X_except, /**< The control flow result branching to the exception handler */
pn_Bound_res = pn_Generic_other, /**< The checked index. */
pn_Bound_max /**< number of projections from a Bound */
} pn_Bound;
/** Returns the memory input of a Bound operation. */
......
......@@ -35,19 +35,6 @@
* block with the fragile operation. */
#define PRECISE_EXC_CONTEXT 1
/** There are two implementations of the Phi node construction. The first
* is faster, but does not work for blocks with more than 2 predecessors.
* The second works always but is slower and causes more unnecessary Phi
* nodes.
* Select the implementations by the following preprocessor flag: */
#define USE_FAST_PHI_CONSTRUCTION 0
/** Further there are two versions of the fast Phi node construction.
* If the following flag is set, new_r_Phi_in uses an explicit stack for
* allocating and deallocating Phi nodes. Else it uses the obstack
* as a stack! */
#define USE_EXPLICIT_PHI_IN_STACK 0
/** If this and DEBUG_libfirm are defined irdump uses the nodeid numbers as
* labels for the vcg nodes. This makes the vcg graph better readable.
* Sometimes it's useful to see the pointer values, though. */
......
......@@ -1806,333 +1806,6 @@ new_rd_Phi0(ir_graph *irg, ir_node *block, ir_mode *mode) {
return res;
} /* new_rd_Phi0 */
/* There are two implementations of the Phi node construction. The first
is faster, but does not work for blocks with more than 2 predecessors.
The second works always but is slower and causes more unnecessary Phi
nodes.
Select the implementations by the following preprocessor flag set in
common/common.h: */
#if USE_FAST_PHI_CONSTRUCTION
/* This is a stack used for allocating and deallocating nodes in
new_rd_Phi_in. The original implementation used the obstack
to model this stack, now it is explicit. This reduces side effects.
*/
#if USE_EXPLICIT_PHI_IN_STACK
Phi_in_stack *
new_Phi_in_stack(void) {
Phi_in_stack *res;
res = (Phi_in_stack *) xmalloc(sizeof(Phi_in_stack));
res->stack = NEW_ARR_F(ir_node *, 0);
res->pos = 0;
return res;
} /* new_Phi_in_stack */
void
free_Phi_in_stack(Phi_in_stack *s) {
DEL_ARR_F(s->stack);
free(s);
} /* free_Phi_in_stack */
static INLINE void
free_to_Phi_in_stack(ir_node *phi) {
if (ARR_LEN(current_ir_graph->Phi_in_stack->stack) ==
current_ir_graph->Phi_in_stack->pos)
ARR_APP1 (ir_node *, current_ir_graph->Phi_in_stack->stack, phi);
else
current_ir_graph->Phi_in_stack->stack[current_ir_graph->Phi_in_stack->pos] = phi;
(current_ir_graph->Phi_in_stack->pos)++;
} /* free_to_Phi_in_stack */
static INLINE ir_node *
alloc_or_pop_from_Phi_in_stack(ir_graph *irg, ir_node *block, ir_mode *mode,
int arity, ir_node **in) {
ir_node *res;
ir_node **stack = current_ir_graph->Phi_in_stack->stack;
int pos = current_ir_graph->Phi_in_stack->pos;
if (pos == 0) {
/* We need to allocate a new node */
res = new_ir_node (db, irg, block, op_Phi, mode, arity, in);
res->attr.phi_backedge = new_backedge_arr(irg->obst, arity);
} else {
/* reuse the old node and initialize it again. */
res = stack[pos-1];
assert(res->kind == k_ir_node);
assert(res->op == op_Phi);
res->mode = mode;
res->visited = 0;
res->link = NULL;
assert(arity >= 0);
/* ???!!! How to free the old in array?? Not at all: on obstack ?!! */
res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
res->in[0] = block;
memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
(current_ir_graph->Phi_in_stack->pos)--;
}
return res;
} /* alloc_or_pop_from_Phi_in_stack */
#endif /* USE_EXPLICIT_PHI_IN_STACK */
/**
* Creates a Phi node with a given, fixed array **in of predecessors.
* If the Phi node is unnecessary, as the same value reaches the block
* through all control flow paths, it is eliminated and the value
* returned directly. This constructor is only intended for use in
* the automatic Phi node generation triggered by get_value or mature.
* The implementation is quite tricky and depends on the fact, that
* the nodes are allocated on a stack:
* The in array contains predecessors and NULLs. The NULLs appear,
* if get_r_value_internal, that computed the predecessors, reached
* the same block on two paths. In this case the same value reaches
* this block on both paths, there is no definition in between. We need
* not allocate a Phi where these path's merge, but we have to communicate
* this fact to the caller. This happens by returning a pointer to the
* node the caller _will_ allocate. (Yes, we predict the address. We can
* do so because the nodes are allocated on the obstack.) The caller then
* finds a pointer to itself and, when this routine is called again,
* eliminates itself.
*/
static INLINE ir_node *
new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode, ir_node **in, int ins) {
int i;
ir_node *res, *known;
/* Allocate a new node on the obstack. This can return a node to
which some of the pointers in the in-array already point.
Attention: the constructor copies the in array, i.e., the later
changes to the array in this routine do not affect the
constructed node! If the in array contains NULLs, there will be
missing predecessors in the returned node. Is this a possible
internal state of the Phi node generation? */
#if USE_EXPLICIT_PHI_IN_STACK
res = known = alloc_or_pop_from_Phi_in_stack(irg, block, mode, ins, in);
#else
res = known = new_ir_node (NULL, irg, block, op_Phi, mode, ins, in);
res->attr.phi_backedge = new_backedge_arr(irg->obst, ins);
#endif
/* The in-array can contain NULLs. These were returned by
get_r_value_internal if it reached the same block/definition on a
second path. The NULLs are replaced by the node itself to
simplify the test in the next loop. */
for (i = 0; i < ins; ++i) {
if (in[i] == NULL)
in[i] = res;
}
/* This loop checks whether the Phi has more than one predecessor.
If so, it is a real Phi node and we break the loop. Else the Phi
node merges the same definition on several paths and therefore is
not needed. */
for (i = 0; i < ins; ++i) {
if (in[i] == res || in[i] == known)
continue;
if (known == res)
known = in[i];
else
break;
}
/* i==ins: there is at most one predecessor, we don't need a phi node. */
if (i==ins) {
#if USE_EXPLICIT_PHI_IN_STACK
free_to_Phi_in_stack(res);
#else
edges_node_deleted(res, current_ir_graph);
obstack_free(current_ir_graph->obst, res);
#endif
res = known;
} else {
res = optimize_node (res);
IRN_VRFY_IRG(res, irg);
}
/* return the pointer to the Phi node. This node might be deallocated! */
return res;
} /* new_rd_Phi_in */
static ir_node *
get_r_value_internal(ir_node *block, int pos, ir_mode *mode);
/**
* Allocates and returns this node. The routine called to allocate the
* node might optimize it away and return a real value, or even a pointer
* to a deallocated Phi node on top of the obstack!
* This function is called with an in-array of proper size.
*/
static ir_node *
phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
ir_node *prevBlock, *res;
int i;
/* This loop goes to all predecessor blocks of the block the Phi node is in
and there finds the operands of the Phi node by calling
get_r_value_internal. */
for (i = 1; i <= ins; ++i) {
assert (block->in[i]);
prevBlock = block->in[i]->in[0]; /* go past control flow op to prev block */
assert (prevBlock);
nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
}
/* After collecting all predecessors into the array nin a new Phi node
with these predecessors is created. This constructor contains an
optimization: If all predecessors of the Phi node are identical it
returns the only operand instead of a new Phi node. If the value
passes two different control flow edges without being defined, and
this is the second path treated, a pointer to the node that will be
allocated for the first path (recursion) is returned. We already
know the address of this node, as it is the next node to be allocated
and will be placed on top of the obstack. (The obstack is a _stack_!) */
res = new_rd_Phi_in (current_ir_graph, block, mode, nin, ins);
/* Now we now the value for "pos" and can enter it in the array with
all known local variables. Attention: this might be a pointer to
a node, that later will be allocated!!! See new_rd_Phi_in().
If this is called in mature, after some set_value() in the same block,
the proper value must not be overwritten:
The call order
get_value (makes Phi0, put's it into graph_arr)
set_value (overwrites Phi0 in graph_arr)
mature_immBlock (upgrades Phi0, puts it again into graph_arr, overwriting
the proper value.)
fails. */
if (!block->attr.block.graph_arr[pos]) {
block->attr.block.graph_arr[pos] = res;
} else {
/* printf(" value already computed by %s\n",
get_id_str(block->attr.block.graph_arr[pos]->op->name)); */
}
return res;
}
/**
* This function returns the last definition of a variable. In case
* this variable was last defined in a previous block, Phi nodes are
* inserted. If the part of the firm graph containing the definition
* is not yet constructed, a dummy Phi node is returned.
*/
static ir_node *
get_r_value_internal(ir_node *block, int pos, ir_mode *mode)
{
ir_node *res;
/* There are 4 cases to treat.
1. The block is not mature and we visit it the first time. We can not
create a proper Phi node, therefore a Phi0, i.e., a Phi without
predecessors is returned. This node is added to the linked list (field
"link") of the containing block to be completed when this block is
matured. (Completion will add a new Phi and turn the Phi0 into an Id
node.)
2. The value is already known in this block, graph_arr[pos] is set and we
visit the block the first time. We can return the value without
creating any new nodes.
3. The block is mature and we visit it the first time. A Phi node needs
to be created (phi_merge). If the Phi is not needed, as all it's
operands are the same value reaching the block through different
paths, it's optimized away and the value itself is returned.
4. The block is mature, and we visit it the second time. Now two
subcases are possible:
* The value was computed completely the last time we were here. This
is the case if there is no loop. We can return the proper value.
* The recursion that visited this node and set the flag did not
return yet. We are computing a value in a loop and need to
break the recursion without knowing the result yet.
@@@ strange case. Straight forward we would create a Phi before
starting the computation of it's predecessors. In this case we will
find a Phi here in any case. The problem is that this implementation
only creates a Phi after computing the predecessors, so that it is
hard to compute self references of this Phi. @@@
There is no simple check for the second subcase. Therefore we check
for a second visit and treat all such cases as the second subcase.
Anyways, the basic situation is the same: we reached a block
on two paths without finding a definition of the value: No Phi
nodes are needed on both paths.
We return this information "Two paths, no Phi needed" by a very tricky
implementation that relies on the fact that an obstack is a stack and
will return a node with the same address on different allocations.
Look also at phi_merge and new_rd_phi_in to understand this.
@@@ Unfortunately this does not work, see testprogram
three_cfpred_example.
*/
/* case 4 -- already visited. */
if (get_irn_visited(block) == get_irg_visited(current_ir_graph)) return NULL;
/* visited the first time */
set_irn_visited(block, get_irg_visited(current_ir_graph));
/* Get the local valid value */
res = block->attr.block.graph_arr[pos];
/* case 2 -- If the value is actually computed, return it. */
if (res) return res;
if (block->attr.block.is_matured) { /* case 3 */
/* The Phi has the same amount of ins as the corresponding block. */
int ins = get_irn_arity(block);
ir_node **nin;
NEW_ARR_A(ir_node *, nin, ins);
/* Phi merge collects the predecessors and then creates a node. */
res = phi_merge(block, pos, mode, nin, ins);
} else { /* case 1 */
/* The block is not mature, we don't know how many in's are needed. A Phi
with zero predecessors is created. Such a Phi node is called Phi0
node. (There is also an obsolete Phi0 opcode.) The Phi0 is then added
to the list of Phi0 nodes in this block to be matured by mature_immBlock
later.
The Phi0 has to remember the pos of it's internal value. If the real
Phi is computed, pos is used to update the array with the local
values. */
res = new_rd_Phi0(current_ir_graph, block, mode);
res->attr.phi0_pos = pos;
res->link = block->link;
block->link = res;
}
/* If we get here, the frontend missed a use-before-definition error */
if (!res) {
/* Error Message */
printf("Error: no value set. Use of undefined variable. Initializing to zero.\n");
assert(mode->code >= irm_F && mode->code <= irm_P);
res = new_rd_Const(NULL, current_ir_graph, block, mode, tarval_mode_null[mode->code]);
}
/* The local valid value is available now. */
block->attr.block.graph_arr[pos] = res;
return res;
} /* get_r_value_internal */
#else /* if 0 */
/**
it starts the recursion. This causes an Id at the entry of
every block that has no definition of the value! **/
#if USE_EXPLICIT_PHI_IN_STACK
/* Just dummies */
Phi_in_stack * new_Phi_in_stack() { return NULL; }
void free_Phi_in_stack(Phi_in_stack *s) {}
#endif
static INLINE ir_node *
new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode,
......@@ -2329,6 +2002,28 @@ get_r_frag_value_internal(ir_node *block, ir_node *cfOp, int pos, ir_mode *mode)
} /* get_r_frag_value_internal */
#endif /* PRECISE_EXC_CONTEXT */
/**
* check whether a control flow cf_pred is a exception flow.
*
* @param cf_pred the control flow node
* @param prev_cf_op if cf_pred is a Proj, the predecessor node, else equal to cf_pred
*/
static int is_exception_flow(ir_node *cf_pred, ir_node *prev_cf_op) {
/* all projections from a raise are exceptional control flow */
if (is_Raise(prev_cf_op))
return 1;
if (is_fragile_op(prev_cf_op)) {
if (is_Proj(cf_pred) && get_Proj_proj(cf_pred) == pn_Generic_X_regular) {
/* the regular control flow, NO exception */
return 0;
}
/* Hmm, exception but not a Proj? */
assert(!"unexpected condition: fragile op without a proj");
return 1;
}
return 0;
} /* is_exception_flow */
/**
* Computes the predecessors for the real phi node, and then
* allocates and returns this node. The routine called to allocate the
......@@ -2337,7 +2032,7 @@ get_r_frag_value_internal(ir_node *block, ir_node *cfOp, int pos, ir_mode *mode)
*/
static ir_node *
phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
ir_node *prevBlock, *prevCfOp, *res, *phi0, *phi0_all;
ir_node *prevBlock, *res, *phi0, *phi0_all;
int i;
/* If this block has no value at pos create a Phi0 and remember it
......@@ -2387,26 +2082,26 @@ phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
/* This loop goes to all predecessor blocks of the block the Phi node
is in and there finds the operands of the Phi node by calling
get_r_value_internal. */
for (i = 1; i <= ins; ++i) {
prevCfOp = skip_Proj(block->in[i]);
assert (prevCfOp);
for (i = 1; i <= ins; ++i) {
ir_node *cf_pred = block->in[i];
ir_node *prevCfOp = skip_Proj(cf_pred);
assert(prevCfOp);
if (is_Bad(prevCfOp)) {
/* In case a Cond has been optimized we would get right to the start block