end block can not be optimized away any more.
[libfirm] / ir / ir / ircons.c
index 3362748..5015199 100644 (file)
@@ -4,11 +4,18 @@
 ** 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
 */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+# 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;
@@ -526,12 +535,17 @@ new_r_Sel (ir_graph *irg, ir_node *block, ir_node *store, ir_node *objptr,
 }
 
 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) {
@@ -565,10 +579,24 @@ new_r_Bad ()
   return current_ir_graph->bad;
 }
 
-/***********************/
+/** ********************/
 /** public interfaces  */
 /** construction tools */
 
+/****f* ircons/new_Start
+ *
+ * NAME
+ *   new_Start -- create a new Start node in the current block
+ *
+ * SYNOPSIS
+ *   s = new_Start(void);
+ *   ir_node* new_Start(void);
+ *
+ * RESULT
+ *   s - pointer to the created Start node
+ *
+ ****
+ */
 ir_node *
 new_Start (void)
 {
@@ -596,32 +624,29 @@ new_End (void)
   return res;
 }
 
+/* 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;
 }
 
-/*************************************************************************/
+/* ***********************************************************************/
 /* Methods necessary for automatic Phi node creation                     */
 /*
   ir_node *phi_merge            (ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins)
@@ -645,7 +670,7 @@ new_Block (void)
               \|/                \|/
            new_r_Phi0          new_r_Phi_in
 
-*****************************************************************************/
+* *************************************************************************** */
 
 /* Creates a Phi node with 0 predecessors */
 inline ir_node *
@@ -657,7 +682,13 @@ new_r_Phi0 (ir_graph *irg, ir_node *block, ir_mode *mode)
   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
@@ -964,8 +995,10 @@ get_r_value_internal (ir_node *block, int pos, ir_mode *mode)
     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,
@@ -978,11 +1011,6 @@ 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
@@ -1048,8 +1076,8 @@ 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
+  /* 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]);
@@ -1123,6 +1151,8 @@ get_r_value_internal (ir_node *block, int pos, ir_mode *mode)
 
   /* 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];
   }
@@ -1134,7 +1164,7 @@ get_r_value_internal (ir_node *block, int pos, ir_mode *mode)
   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 */
 
@@ -1176,9 +1206,9 @@ get_r_value_internal (ir_node *block, int pos, ir_mode *mode)
   return res;
 }
 
-#endif /* if 0 */
+#endif /* USE_FAST_PHI_CONSTRUCTION */
 
-/****************************************************************************/
+/* ************************************************************************** */
 
 /** Finalize a Block node, when all control flows are known.  */
 /** Acceptable parameters are only Block nodes.               */
@@ -1197,6 +1227,7 @@ mature_block (ir_node *block)
     /* turn the dynamic in-array into a static one. */
     ins = ARR_LEN (block->in)-1;
     NEW_ARR_A (ir_node *, nin, ins);
+    /*  @@@ something is strange here... why isn't the array copied? */
 
     /* Traverse a chain of Phi nodes attached to this block and mature
        these, too. **/
@@ -1468,7 +1499,7 @@ new_Sel (ir_node *store, ir_node *objptr, int n_index, ir_node **index, entity *
 }
 
 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);
@@ -1488,10 +1519,34 @@ new_Bad (void)
   return current_ir_graph->bad;
 }
 
-/*************************************************************************/
+/* ********************************************************************* */
 /* 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)
 {
@@ -1511,7 +1566,7 @@ switch_block (ir_node *target)
   current_ir_graph->current_block = target;
 }
 
-/****************************/
+/* ************************ */
 /* parameter administration */
 
 /* get a value from the parameter array from the current block by its index */
@@ -1546,7 +1601,7 @@ set_store (ir_node *store)
   current_ir_graph->current_block->attr.block.graph_arr[0] = store;
 }
 
-/*************************************************************************/
+/* ********************************************************************* */
 /* initialize */
 
 /* call once for each run of the library */