** Authors: Martin Trapp, Christian Schaefer
**
** ircons.c: basic and more detailed irnode constructors
-** store, block and parameter administration ,
+** store, block and parameter administration.
** Adapted to extended FIRM nodes (exceptions...) and commented
** by Goetz Lindenmaier
*/
+# include "irgraph_t.h"
+# include "irnode_t.h"
+# include "irmode_t.h"
# include "ircons.h"
# include "common.h"
# include "irvrfy.h"
# include "array.h"
/* memset belongs to string.h */
# include "string.h"
-# include "irnode.h"
#if USE_EXPICIT_PHI_IN_STACK
/* A stack needed for the automatic Phi node construction in constructor
- Phi_in. */
+ Phi_in. Redefinition in irgraph.c!! */
struct Phi_in_stack {
ir_node **stack;
int pos;
};
+typedef struct Phi_in_stack Phi_in_stack;
#endif
/*********************************************** */
/** privat interfaces, for professional use only */
/* Constructs a Block with a fixed number of predecessors.
- Does not set current_block. */
-
+ Does not set current_block. Can not be used with automatic
+ Phi node construction. */
inline ir_node *
new_r_Block (ir_graph *irg, int arity, ir_node **in)
{
ir_node *res;
- res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, arity, in);
+ res = new_ir_node (irg, NULL, op_Block, mode_R, arity, in);
+ set_Block_matured(res, 1);
+ set_Block_block_visited(res, 0);
irn_vrfy (res);
return res;
}
inline ir_node *
-new_r_SymConst (ir_graph *irg, ir_node *block, type_or_id *value,
+new_r_SymConst (ir_graph *irg, ir_node *block, type_or_id_p value,
symconst_kind symkind)
{
ir_node *in[0] = {};
ir_node *res;
- res = new_ir_node (irg, block, op_SymConst, mode_I, 0, in);
+ ir_mode *mode;
+ if (symkind == linkage_ptr_info)
+ mode = mode_p;
+ else
+ mode = mode_I;
+ res = new_ir_node (irg, block, op_SymConst, mode, 0, in);
res->attr.i.num = symkind;
if (symkind == linkage_ptr_info) {
return res;
}
+#if 1
+/* Constructs a Block with a fixed number of predecessors.
+ Does set current_block. Can be used with automatic Phi
+ node construction. */
ir_node *
-new_Block (void)
+new_Block (int arity, ir_node **in)
{
ir_node *res;
- res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, -1, NULL);
+ res = new_r_Block (current_ir_graph, arity, in);
current_ir_graph->current_block = res;
- res->attr.block.matured = 0;
- set_Block_block_visited(res, 0);
- /* forget this optimization. use this only if mature !!!!
- res = optimize (res); */
- irn_vrfy (res);
-
- /** create a new dynamic array, which stores all parameters in irnodes */
- /** using the same obstack as the whole irgraph */
+ /* Create and initialize array for Phi-node construction. */
res->attr.block.graph_arr = NEW_ARR_D (ir_node *, current_ir_graph->obst,
- current_ir_graph->params);
+ current_ir_graph->n_loc);
+ memset(res->attr.block.graph_arr, 0, sizeof(ir_node *)*current_ir_graph->n_loc);
- /** initialize the parameter array */
- memset(res->attr.block.graph_arr, 0, sizeof(ir_node *)*current_ir_graph->params);
+ res = optimize (res);
+ irn_vrfy (res);
return res;
}
+#else
+ir_node *
+new_Block (void)
+{
+ return new_immBlock();
+}
+#endif
/*************************************************************************/
/* Methods necessary for automatic Phi node creation */
return res;
}
-#if 0
+/* 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_r_Phi_in. The original implementation used the obstack
it starts the recursion. This causes an Id at the entry of
every block that has no definition of the value! **/
+#if USE_EXPICIT_PHI_IN_STACK
/* Just a dummy */
Phi_in_stack * new_Phi_in_stack() { return NULL; }
+#endif
inline ir_node *
new_r_Phi_in (ir_graph *irg, ir_node *block, ir_mode *mode,
array. */
res = new_ir_node (irg, block, op_Phi, mode, ins, in);
- /* @@@GL The in-array should not contain NULLS with this algorithm.
- Remove this test if it never is true. Just to make sure the algorithm runs. */
- for (i=0; i < ins; ++i)
- if (in[i] == NULL) assert(0);
-
/* 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
}
}
- /* 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
+ /* 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]);
/* case 4 -- already visited. */
if (get_irn_visited(block) == get_irg_visited(current_ir_graph)) {
+ /* As phi_merge allocates a Phi0 this value is always defined. Here
+ is the critical difference of the two algorithms. */
assert(block->attr.block.graph_arr[pos]);
return block->attr.block.graph_arr[pos];
}
res = block->attr.block.graph_arr[pos];
/* case 2 -- If the value is actually computed, return it. */
- if (res) { return res;};
+ if (res) { return res; };
if (block->attr.block.matured) { /* case 3 */
return res;
}
-#endif /* if 0 */
+#endif /* USE_FAST_PHI_CONSTRUCTION */
/****************************************************************************/
}
ir_node *
-new_SymConst (type_or_id *value, symconst_kind kind)
+new_SymConst (type_or_id_p value, symconst_kind kind)
{
return new_r_SymConst (current_ir_graph, current_ir_graph->current_block,
value, kind);
/*************************************************************************/
/* Comfortable interface with automatic Phi node construction. */
/* (Uses also constructors of ?? interface, except new_Block. */
-/* add an adge to a jmp node */
+/*************************************************************************/
+
+/** Block construction **/
+/* immature Block without predecessors */
+ir_node *new_immBlock (void) {
+ ir_node *res;
+
+ /* creates a new dynamic in-array as length of in is -1 */
+ res = new_ir_node (current_ir_graph, NULL, op_Block, mode_R, -1, NULL);
+ current_ir_graph->current_block = res;
+ res->attr.block.matured = 0;
+ set_Block_block_visited(res, 0);
+
+ /* Create and initialize array for Phi-node construction. */
+ res->attr.block.graph_arr = NEW_ARR_D (ir_node *, current_ir_graph->obst,
+ current_ir_graph->n_loc);
+ memset(res->attr.block.graph_arr, 0, sizeof(ir_node *)*current_ir_graph->n_loc);
+
+ /* Immature block may not be optimized! */
+ irn_vrfy (res);
+
+ return res;
+}
+
+/* add an adge to a jmp/control flow node */
void
add_in_edge (ir_node *block, ir_node *jmp)
{