typo
[libfirm] / ir / opt / strength_red.c
index 9f57a06..7f6e5e9 100644 (file)
@@ -92,6 +92,7 @@ static induct_var_info *is_induction_variable (ir_node *n, induct_var_info *info
     add_l = get_Add_left(phi_pred_0);
     add_r = get_Add_right(phi_pred_0);
     info->op_pred_pos = 0;
+    info->init_pred_pos = 1;
     if (add_l == n){
       info->increment = add_r;
     } else if (add_r == n){
@@ -102,6 +103,7 @@ static induct_var_info *is_induction_variable (ir_node *n, induct_var_info *info
     add_l = get_Add_left(phi_pred_1);
     add_r = get_Add_right(phi_pred_1);
     info->op_pred_pos = 1;
+    info->init_pred_pos = 0;
     if (add_l == n){
       info->increment = add_r;
     } else if (add_r == n){
@@ -112,6 +114,7 @@ static induct_var_info *is_induction_variable (ir_node *n, induct_var_info *info
     sub_r = get_Sub_right(phi_pred_0);
     sub_l = get_Sub_left(phi_pred_0);
     info->op_pred_pos = 0;
+    info->init_pred_pos = 1;
     if (sub_l == n){
       info->increment = sub_r;
     } else if (sub_r == n){
@@ -122,6 +125,7 @@ static induct_var_info *is_induction_variable (ir_node *n, induct_var_info *info
     sub_r = get_Sub_right(phi_pred_1);
     sub_l = get_Sub_left(phi_pred_1);
     info->op_pred_pos = 1;
+    info->init_pred_pos = 0;
     if (sub_l == n){
       info->increment = sub_r;
     } else return NULL;
@@ -129,28 +133,16 @@ static induct_var_info *is_induction_variable (ir_node *n, induct_var_info *info
     return NULL;
 
   /*Compute the position of the backedge. */
-  if (is_backedge(get_nodes_block(n), 0)){
-    info->be_pos = 0;
-    info->init_pred_pos = 1;
-    info->op = get_Phi_pred(n, 0);
-    info->init = get_Phi_pred(n, 1);
-  } else if (is_backedge(get_nodes_block(n), 1)){
-    info->be_pos = 1;
-    info->init_pred_pos = 0;
-    info->op = get_Phi_pred(n, 1);
-    info->init = get_Phi_pred(n, 0);
+  if (is_backedge(get_nodes_block(n), info->op_pred_pos)){
+    info->be_pos = info->op_pred_pos;
+    info->op = get_Phi_pred(n, info->op_pred_pos);
+    info->init = get_Phi_pred(n, info->init_pred_pos);
   }
 
-  if (info->be_pos == 0) {
-    if (get_Block_dom_depth(get_nodes_block(phi_pred_1))  >=
-    get_Block_dom_depth(get_nodes_block(n))) {
-      return NULL;
-    }
-  } else if (get_Block_dom_depth(get_nodes_block(phi_pred_0))  >=
-         get_Block_dom_depth(get_nodes_block(n))) return NULL;
-
-  if (get_Block_dom_depth(get_nodes_block(info->increment))  >=
-      get_Block_dom_depth(get_nodes_block(n))) return NULL;
+  if (get_Block_dom_depth(get_nodes_block(info->init))  >=
+      get_Block_dom_depth(get_nodes_block(n))) {
+    return NULL;
+  }
 
   return info;
 }
@@ -170,12 +162,12 @@ const char *get_irg_dump_name(ir_graph *irg);
  * phi.
  */
 
-static void reduce_itervar(ir_node *itervar_phi, void *env) {
-  ir_node *strong = NULL, *cmp = NULL, *c, *cmp_const;
-  int phi_pred, strong_in_Phi = 0, cmp_in_phi = 0, out_loop_res = 1;
-int i;
+void reduce_itervar(ir_node *itervar_phi, void *env) {
+  int i;
+  ir_node *strong = NULL, *cmp = NULL, *c, *cmp_const, *old_add;
+  int phi_pred, strong_in_Phi = 0, cmp_in_phi = 0, out_loop_res = 1, Store_in_phi = 0;
+  int op_pred, Store_in_op = 0, strong_in_op = 0;
 
-  // This "if" finds the node to reduce.
   induct_var_info ivi;
 
   // This "if" finds the Phi predecessors for the node that must be reduced.
@@ -183,30 +175,48 @@ int i;
       is_induction_variable(itervar_phi, &ivi) != NULL ) {
     phi_pred = get_irn_n_outs(itervar_phi);
     ir_loop *l_itervar_phi = get_irn_loop(get_nodes_block(itervar_phi));
-
     for (i = 0; i < phi_pred; i++) {
       ir_node *out = get_irn_out(itervar_phi, i);
       ir_op   *out_op = get_irn_op(out);
       if (get_irn_loop(get_nodes_block(out)) != l_itervar_phi)
-    out_loop_res = 0;
-      if (out_op == op_Mul){
-    strong = out;
+        out_loop_res = 0;
+      if ( out_op == op_Store)
+        Store_in_phi++;
+      if (out_op == op_Mul) {
+        strong = out;
         strong_in_Phi++;
       }else if (out_op == op_Cmp){
-    cmp = out;
-    cmp_in_phi++;
+        cmp = out;
+        cmp_in_phi++;
+      }
+    }
+
+    if (strong == NULL){
+      op_pred = get_irn_n_outs(ivi.op);
+      for(i = 0; i < op_pred; i++){
+        ir_node  *out = get_irn_out(ivi.op, i);
+        ir_op *out_op = get_irn_op(out);
+        if(out_op == op_Store)
+          Store_in_op++;
+        if(out_op == op_Mul){
+          strong = out;
+          strong_in_op++;
+        }
       }
     }
-    if (strong == NULL || (strong_in_Phi > 1)) return;
+    if (strong == NULL || (strong_in_Phi > 1) || (strong_in_op > 1)) return;
 
-    if(get_irn_op(get_Mul_right(strong)) == op_Phi)
+    if (get_irn_loop(get_nodes_block(strong)) != l_itervar_phi) return;
+
+    ir_op *mul_right_op = get_irn_op(get_Mul_right(strong));
+    if(mul_right_op == op_Phi || mul_right_op == op_Add || mul_right_op == op_Sub)
       c = get_Mul_left(strong);
     else
       c = get_Mul_right(strong);
 
 
     if (get_Block_dom_depth(get_nodes_block(c))  >=
-    get_Block_dom_depth(get_nodes_block(itervar_phi))) return;
+        get_Block_dom_depth(get_nodes_block(itervar_phi))) return;
 
     if (get_opt_strength_red_verbose() && get_firm_verbosity() > 1) {
       printf("The constant of Reducing node is: "); DDMN(c);
@@ -216,7 +226,8 @@ int i;
       printf("  in graph     "); DDMG(current_ir_graph);
     }
 
-    ir_node *inc , *init , *new_phi, *in[2], *new_op = NULL, *block_init, *block_inc;
+    ir_node *inc , *init , *new_phi, *in[2], *new_op = NULL, *block_init;
+    ir_node *block_inc, *new_add, *symconst;
 
     ir_node *init_block      = get_nodes_block(ivi.init);
     ir_node *increment_block = get_nodes_block(ivi.increment);
@@ -248,16 +259,29 @@ int i;
 
     if (ivi.operation_code == op_Add)
       new_op = new_r_Add(current_ir_graph, get_nodes_block(ivi.op), inc, new_phi,
-             get_irn_mode(inc));
+                         get_irn_mode(inc));
     else if (ivi.operation_code == op_Sub)
       new_op = new_r_Sub(current_ir_graph, get_nodes_block(ivi.op), new_phi, inc,
-             get_irn_mode(inc));
+                         get_irn_mode(inc));
     set_Phi_pred(new_phi, ivi.op_pred_pos, new_op);
 
+    if(strong_in_op){
+      if(get_irn_n_outs(strong) > 1) return;
+      else old_add = get_irn_out(strong, 0);
+      if(get_irn_op(old_add) != op_Add) return;
+      if(get_Add_left(old_add) == strong)
+        symconst = get_Add_right(old_add);
+      else
+        symconst = get_Add_left(old_add);
+      new_add = new_r_Add(current_ir_graph, get_nodes_block(old_add),
+                          new_op, symconst,  get_irn_mode(symconst));
+      exchange(old_add, new_add);
+    }
+
     /* Replace the use of the strength reduced value. */
     exchange(strong, new_phi);
 
-    if (cmp == NULL || cmp_in_phi > 1 || out_loop_res == 0) return;
+    if (cmp == NULL || cmp_in_phi > 1 || out_loop_res == 0 || Store_in_phi != 0 || Store_in_op != 0) return;
 
     if (get_irn_op(get_Cmp_left(cmp)) == op_Const)
       cmp_const = get_Cmp_left(cmp);
@@ -269,7 +293,7 @@ int i;
     if (get_opt_strength_red_verbose() && get_firm_verbosity() > 1) {
       printf("It is possibale to exchange the Cmp with a new Cmp   \n");
       printf("The constant of Cmp node is: "); DDMN(cmp_const);
-      printf("The Phi node is"); DDMN(itervar_phi);
+      printf("The Phi node is  "); DDMN(itervar_phi);
       printf("Cmp node: "); DDMN(cmp);
       printf("  in graph     "); DDMG(current_ir_graph);
     }
@@ -282,9 +306,9 @@ int i;
       block_init = cmp_const_block;
 
     new_cmp_const = new_r_Mul (current_ir_graph, block_init, cmp_const,
-                   c, get_irn_mode(ivi.init));
+                               c, get_irn_mode(ivi.init));
     new_cmp = new_r_Cmp (current_ir_graph, get_nodes_block(cmp),
-             new_phi, new_cmp_const);
+                         new_phi, new_cmp_const);
     exchange(cmp, new_cmp);
   } else return;
 }