Added access routines to external variables.
[libfirm] / ir / ir / iropt.c
index 88555f9..8150b44 100644 (file)
 # include "irvrfy.h"
 # include "tv.h"
 # include "tune.h"
-# include "debinfo.h"
+# include "dbginfo_t.h"
+# include "iropt_dbg.c"
 
 /* Make types visible to allow most efficient access */
 # include "entity_t.h"
 
-/* Trivial inlineable routine for copy propagation.
-   Does follow Ids, needed to optimize inlined code. */
-static inline ir_node *
+/* Trivial INLINEable routine for copy propagation.
+   Does follow Ids, needed to optimize INLINEd code. */
+static INLINE ir_node *
 follow_Id (ir_node *n)
 {
   while (get_irn_op (n) == op_Id) n = get_Id_pred (n);
   return n;
 }
 
-static inline tarval *
+static INLINE tarval *
 value_of (ir_node *n)
 {
   if ((n != NULL) && (get_irn_op(n) == op_Const))
@@ -179,8 +180,8 @@ computed_value (ir_node *n)
         only 1 is used.
          There are several case where we can evaluate a Cmp node:
          1. The nodes compared are both the same.  If we compare for
-            equal, this will return true, else it will return false.
-            This step relies on cse.
+            equal, greater equal, ... this will return true, else it
+           will return false.  This step relies on cse.
          2. The predecessors of Cmp are target values.  We can evaluate
             the Cmp.
          3. The predecessors are Allocs or void* constants.  Allocs never
@@ -281,6 +282,7 @@ equivalent_node (ir_node *n)
   ir_node *a = NULL; /* to shutup gcc */
   ir_node *b = NULL; /* to shutup gcc */
   ir_node *c = NULL; /* to shutup gcc */
+  ir_node *oldn = n;
 
   ins = get_irn_arity (n);
 
@@ -309,7 +311,8 @@ equivalent_node (ir_node *n)
       if ((get_Block_n_cfgpreds(n) == 1) &&
          (get_irn_op(get_Block_cfgpred(n, 0)) == op_Jmp) &&
          (get_opt_control_flow())) {
-       n = get_nodes_Block(get_Block_cfgpred(n, 0));
+       n = get_nodes_Block(get_Block_cfgpred(n, 0));                     DBG_OPT_STG;
+
       } else if ((get_Block_n_cfgpreds(n) == 2) &&
                 (get_opt_control_flow())) {
        /* Test whether Cond jumps twice to this block
@@ -319,10 +322,11 @@ equivalent_node (ir_node *n)
        if ((get_irn_op(a) == op_Proj) &&
            (get_irn_op(b) == op_Proj) &&
            (get_Proj_pred(a) == get_Proj_pred(b)) &&
-           (get_irn_op(get_Proj_pred(a)) == op_Cond)) {
+           (get_irn_op(get_Proj_pred(a)) == op_Cond) &&
+           (get_irn_mode(get_Cond_selector(get_Proj_pred(a))) == mode_b)) {
          /* Also a single entry Block following a single exit Block.  Phis have
             twice the same operand and will be optimized away. */
-         n = get_nodes_Block(a);
+         n = get_nodes_Block(a);                                         DBG_OPT_IFSIM;
        }
       } else if (get_opt_unreachable_code() &&
                 (n != current_ir_graph->start_block) &&
@@ -349,24 +353,23 @@ equivalent_node (ir_node *n)
        /** remove stuff as x+0, x*1 x&true ... constant expression evaluation **/
   case iro_Or:  if (a == b) {n = a; break;}
   case iro_Add:
-  case iro_Eor:
-    { tarval *tv;
-       ir_node *on;
-       /* After running compute_node there is only one constant predecessor.
-          Find this predecessors value and remember the other node: */
-       if ((tv = computed_value (a))) {
-         on = b;
-       } else if ((tv = computed_value (b))) {
-         on = a;
-       } else break;
-
-       /* If this predecessors constant value is zero, the operation is
-          unnecessary. Remove it: */
-       if (tarval_classify (tv) == 0) {
-         n = on;
-       }
+  case iro_Eor: {
+    tarval *tv;
+    ir_node *on;
+    /* After running compute_node there is only one constant predecessor.
+       Find this predecessors value and remember the other node: */
+    if ((tv = computed_value (a))) {
+      on = b;
+    } else if ((tv = computed_value (b))) {
+      on = a;
+    } else break;
+
+    /* If this predecessors constant value is zero, the operation is
+       unnecessary. Remove it: */
+    if (tarval_classify (tv) == 0) {
+      n = on;                                                             DBG_OPT_ALGSIM1;
     }
-    break;
+  } break;
   case iro_Sub:
   case iro_Shl:
   case iro_Shr:
@@ -374,7 +377,7 @@ equivalent_node (ir_node *n)
   case iro_Rot:
     /* these operations are not commutative.  Test only one predecessor. */
     if (tarval_classify (computed_value (b)) == 0) {
-      n = a;
+      n = a;                                                              DBG_OPT_ALGSIM1;
       /* Test if b > #bits of a ==> return 0 / divide b by #bits
          --> transform node? */
     }
@@ -382,15 +385,16 @@ equivalent_node (ir_node *n)
   case iro_Not:   /* NotNot x == x */
   case iro_Minus: /* --x == x */  /* ??? Is this possible or can --x raise an
                                         out of bounds exception if min =! max? */
-    if (get_irn_op(get_unop_op(n)) == get_irn_op(n))
-      n = get_unop_op(get_unop_op(n));
+    if (get_irn_op(get_unop_op(n)) == get_irn_op(n)) {
+      n = get_unop_op(get_unop_op(n));                                    DBG_OPT_ALGSIM2
+    }
     break;
   case iro_Mul:
     /* Mul is commutative and has again an other neutral element. */
     if (tarval_classify (computed_value (a)) == 1) {
-      n = b;
+      n = b;                                                              DBG_OPT_ALGSIM1
     } else if (tarval_classify (computed_value (b)) == 1) {
-      n = a;
+      n = a;                                                              DBG_OPT_ALGSIM1
     }
     break;
   case iro_Div:
@@ -404,26 +408,28 @@ equivalent_node (ir_node *n)
       set_Tuple_pred(n, 2, a);
     }
     break;
-    /* GL: Why are they skipped?  DivMod allocates new nodes --> it's
-       treated in transform node.
-          case iro_Mod, Quot, DivMod
-    */
+  /*
+  case iro_Mod, Quot, DivMod
+    DivMod allocates new nodes --> it's treated in transform node.
+    What about Quot, DivMod?
+  */
   case iro_And:
-    if (a == b) n = a;
-    /* And has it's own neutral element */
-    else if (tarval_classify (computed_value (a)) == -1) {
+    if (a == b) {
+      n = a;    /* And has it's own neutral element */
+    else if (tarval_classify (computed_value (a)) == -1) {
       n = b;
     } else if (tarval_classify (computed_value (b)) == -1) {
       n = a;
     }
+    if (n != oldn)                                                        DBG_OPT_ALGSIM1;
     break;
   case iro_Conv:
     if (get_irn_mode(n) == get_irn_mode(a)) { /* No Conv necessary */
-      n = a;
+      n = a;                                                              DBG_OPT_ALGSIM3;
     } else if (get_irn_mode(n) == mode_b) {
       if (get_irn_op(a) == op_Conv &&
-                 get_irn_mode (get_Conv_op(a)) == mode_b) {
-               n = get_Conv_op(a);     /* Convb(Conv*(xxxb(...))) == xxxb(...) */
+         get_irn_mode (get_Conv_op(a)) == mode_b) {
+       n = get_Conv_op(a);     /* Convb(Conv*(xxxb(...))) == xxxb(...) */ DBG_OPT_ALGSIM2;
       }
     }
     break;
@@ -445,6 +451,8 @@ equivalent_node (ir_node *n)
       n_preds = get_Phi_n_preds(n);
 
       block = get_nodes_Block(n);
+      /* @@@ fliegt 'raus, sollte aber doch immer wahr sein!!!
+        assert(get_irn_arity(block) == n_preds && "phi in wrong block!"); */
       if ((is_Bad(block)) ||                         /* Control dead */
          (block == current_ir_graph->start_block))  /* There should be no Phi nodes */
        return new_Bad();                            /* in the Start Block. */
@@ -503,7 +511,7 @@ equivalent_node (ir_node *n)
 
       /* Fold, if no multiple distinct non-self-referencing inputs */
       if (i >= n_preds) {
-       n = first_val;
+       n = first_val;                                     DBG_OPT_PHI;
       } else {
        /* skip the remaining Ids. */
        while (++i < n_preds) {
@@ -516,7 +524,7 @@ equivalent_node (ir_node *n)
   case iro_Load:
     {
 #if 0  /* Is an illegal transformation: different nodes can
-                 represent the same pointer value!! */
+         represent the same pointer value!! */
  a = skip_Proj(get_Load_mem(n));
  b = get_Load_ptr(n);
 
@@ -542,18 +550,17 @@ equivalent_node (ir_node *n)
           && get_Store_ptr(a) == b
           && skip_Proj(get_Store_value(a)) == c) {
         /* We have twice exactly the same store -- a write after write. */
-               n = a;
+       n = a;                                                         DBG_OPT_WAW;
       } else if (get_irn_op(c) == op_Load
                 && (a == c || skip_Proj(get_Load_mem(c)) == a)
-                 && get_Load_ptr(c) == b )
-       /* !!!??? and a cryptic test */ {
+                 && get_Load_ptr(c) == b ) {
         /* We just loaded the value from the same memory, i.e., the store
            doesn't change the memory -- a write after read. */
        a = get_Store_mem(n);
         turn_into_tuple(n, 2);
         set_Tuple_pred(n, 0, a);
-        set_Tuple_pred(n, 1, new_Bad());
-      }
+        set_Tuple_pred(n, 1, new_Bad());                               DBG_OPT_WAR;
+       }
     }
     break;
 
@@ -564,21 +571,21 @@ equivalent_node (ir_node *n)
       if ( get_irn_op(a) == op_Tuple) {
         /* Remove the Tuple/Proj combination. */
        if ( get_Proj_proj(n) <= get_Tuple_n_preds(a) ) {
-         n = get_Tuple_pred(a, get_Proj_proj(n));
+         n = get_Tuple_pred(a, get_Proj_proj(n));                     DBG_OPT_TUPLE;
        } else {
           assert(0); /* This should not happen! */
          n = new_Bad();
        }
       } else if (get_irn_mode(n) == mode_X &&
                 is_Bad(get_nodes_Block(n))) {
-        /* Remove dead control flow. */
+        /* Remove dead control flow -- early gigo. */
        n = new_Bad();
       }
     }
     break;
 
   case iro_Id:
-    n = follow_Id (n);
+    n = follow_Id (n);                                                 DBG_OPT_ID;
     break;
 
   default: break;
@@ -821,14 +828,6 @@ vt_cmp (const void *elt, const void *key)
       (get_irn_mode(a) != get_irn_mode(b))) return 1;
 
   /* compare if a's in and b's in are equal */
-  /* GL: we optimize only nodes with in arrays of fixed sizes.
-  if (get_irn_arity (a) != -2) {
-    ins = get_irn_arity (a);
-    if (ins != get_irn_arity (b)) return 1;
-    ain = get_irn_in (a);
-    bin = get_irn_in (b);
-  }
-  */
   if (get_irn_arity (a) != get_irn_arity(b))
     return 1;
 
@@ -848,6 +847,8 @@ vt_cmp (const void *elt, const void *key)
     return get_irn_const_attr (a) != get_irn_const_attr (b);
   case iro_Proj:
     return get_irn_proj_attr (a) != get_irn_proj_attr (b);
+  case iro_Filter:
+    return get_Filter_proj(a) != get_Filter_proj(b);
   case iro_Alloc:
     return (get_irn_alloc_attr(a).where != get_irn_alloc_attr(b).where)
       || (get_irn_alloc_attr(a).type != get_irn_alloc_attr(b).type);
@@ -863,8 +864,7 @@ vt_cmp (const void *elt, const void *key)
       || (get_irn_sel_attr(a).ent->name != get_irn_sel_attr(b).ent->name)
       || (get_irn_sel_attr(a).ent->owner != get_irn_sel_attr(b).ent->owner)
       || (get_irn_sel_attr(a).ent->ld_name != get_irn_sel_attr(b).ent->ld_name)
-      || (get_irn_sel_attr(a).ent->type != get_irn_sel_attr(b).ent->type)
-      || (get_irn_sel_attr(a).ltyp != get_irn_sel_attr(b).ltyp);
+      || (get_irn_sel_attr(a).ent->type != get_irn_sel_attr(b).ent->type);
   case iro_Phi:
     return get_irn_phi_attr (a) != get_irn_phi_attr (b);
   default: ;
@@ -909,7 +909,7 @@ del_identities (pset *value_table)
 
 /* Return the canonical node computing the same value as n.
    Looks up the node in a hash table. */
-static inline ir_node *
+static INLINE ir_node *
 identify (pset *value_table, ir_node *n)
 {
   ir_node *o = NULL;
@@ -945,7 +945,7 @@ identify (pset *value_table, ir_node *n)
 /* During construction we set the pinned flag in the graph right when the
    optimizatin is performed.  The flag turning on procedure global cse could
    be changed between two allocations.  This way we are safe. */
-static inline ir_node *
+static INLINE ir_node *
 identify_cons (pset *value_table, ir_node *n) {
   ir_node *old = n;
   n = identify(value_table, n);
@@ -979,7 +979,7 @@ add_identities (pset *value_table, ir_node *node) {
 
 /* garbage in, garbage out. If a node has a dead input, i.e., the
    Bad node is input to the node, return the Bad node.  */
-static inline ir_node *
+static INLINE ir_node *
 gigo (ir_node *node)
 {
   int i;
@@ -1096,6 +1096,7 @@ optimize_in_place_2 (ir_node *n)
     return n;
   }
 
+
   /* constant expression evaluation / constant folding */
   if (get_opt_constant_folding()) {
     /* constants can not be evaluated */
@@ -1105,9 +1106,8 @@ optimize_in_place_2 (ir_node *n)
       if ((get_irn_mode(n) != mode_T) && (tv != NULL)) {
         /* evaluation was succesful -- replace the node. */
        n = new_Const (get_tv_mode (tv), tv);
-       deb_info_copy(n, old_n, id_from_str("const_eval", 10));
+       __dbg_info_merge_pair(n, old_n, dbg_const_eval);
        return n;
-        /* xprintf("* optimize: computed node %I\n", n->op->name);*/
       }
     }
   }
@@ -1116,8 +1116,8 @@ optimize_in_place_2 (ir_node *n)
   /*if (get_opt_constant_folding()) */
   if (get_opt_constant_folding() ||
       (get_irn_op(n) == op_Phi)  ||   /* always optimize these nodes. */
-      (get_irn_op(n) == op_Id)   ||
-      (get_irn_op(n) == op_Proj) ||
+      (get_irn_op(n) == op_Id)   ||   /* ... */
+      (get_irn_op(n) == op_Proj) ||   /* ... */
       (get_irn_op(n) == op_Block)  )  /* Flags tested local. */
     n = equivalent_node (n);