OSDN Git Service

2004-10-04 Jose Ruiz <ruiz@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index 0c9a4b6..8869646 100644 (file)
@@ -187,9 +187,9 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
 
       /* If current bb has only one successor, then consider it as an
         unconditional goto.  */
-      if (bb->succ && !bb->succ->succ_next)
+      if (EDGE_COUNT (bb->succs) == 1)
        {
-         basic_block bb_n = bb->succ->dest;
+         basic_block bb_n = EDGE_SUCC (bb, 0)->dest;
          if (cond != NULL_TREE)
            add_to_predicate_list (bb_n, cond);
          cond = NULL_TREE;
@@ -281,7 +281,7 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
   else_clause = TREE_OPERAND (stmt, 2);
 
   /* Create temp. for condition.  */
-  if (!is_gimple_reg (c))
+  if (!is_gimple_condexpr (c))
     {
       tree new_stmt;
       new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c));
@@ -292,14 +292,22 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
   /* Add new condition into destination's predicate list.  */
   if (then_clause)
     /* if 'c' is true then then_clause is reached.  */
-    new_cond = add_to_dst_predicate_list (loop, then_clause, cond, c, bsi);
+    new_cond = add_to_dst_predicate_list (loop, then_clause, cond, 
+                                         unshare_expr (c), bsi);
 
   if (else_clause)
     {
+      tree c2;
+      if (!is_gimple_reg(c) && is_gimple_condexpr (c))
+       {
+         tree new_stmt;
+         new_stmt = ifc_temp_var (TREE_TYPE (c), unshare_expr (c));
+         bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
+         c = TREE_OPERAND (new_stmt, 0);
+       }
+
       /* if 'c' is false then else_clause is reached.  */
-      tree c2 = build1 (TRUTH_NOT_EXPR,
-                       boolean_type_node,
-                       unshare_expr (c));
+      c2 = invert_truthvalue (unshare_expr (c));
       add_to_dst_predicate_list (loop, else_clause, cond, c2, bsi);
     }
 
@@ -311,11 +319,6 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
       bsi_remove (bsi);
       cond = NULL_TREE;
     }
-  else if (new_cond != NULL_TREE)
-    {
-      TREE_OPERAND (stmt, 0) = new_cond;
-      modify_stmt (stmt);
-    }
   return;
 }
 
@@ -469,6 +472,7 @@ static bool
 if_convertable_bb_p (struct loop *loop, basic_block bb, bool exit_bb_seen)
 {
   edge e;
+  edge_iterator ei;
 
   if (dump_file && (dump_flags & TDF_DETAILS))
     fprintf (dump_file, "----------[%d]-------------\n", bb->index);
@@ -490,7 +494,7 @@ if_convertable_bb_p (struct loop *loop, basic_block bb, bool exit_bb_seen)
     }
 
   /* Be less adventurous and handle only normal edges.  */
-  for (e = bb->succ; e; e = e->succ_next)
+  FOR_EACH_EDGE (e, ei, bb->succs)
     if (e->flags &
        (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
       {
@@ -521,6 +525,7 @@ if_convertable_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
   block_stmt_iterator itr;
   unsigned int i;
   edge e;
+  edge_iterator ei;
   bool exit_bb_seen = false;
 
   /* Handle only inner most loop.  */
@@ -553,7 +558,7 @@ if_convertable_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
 
   /* If one of the loop header's edge is exit edge then do not apply
      if-conversion.  */
-  for (e = loop->header->succ; e; e = e->succ_next)
+  FOR_EACH_EDGE (e, ei, loop->header->succs)
     if ( e->flags & EDGE_LOOP_EXIT)
       return false;
 
@@ -676,11 +681,12 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
   basic_block p2 = NULL;
   basic_block true_bb = NULL; 
   tree tmp_cond;
+  edge_iterator ei;
 
-  for (e = bb->pred; e; e = e->pred_next)
+  FOR_EACH_EDGE (e, ei, bb->preds)
     {
       if (p1 == NULL)
-         p1 = e->src;
+       p1 = e->src;
       else 
        {
          gcc_assert (!p2);
@@ -866,6 +872,7 @@ combine_blocks (struct loop *loop)
       if (bb == exit_bb)
        {
          edge new_e;
+         edge_iterator ei;
 
          /* Connect this node with loop header.  */
          new_e = make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU);
@@ -874,7 +881,7 @@ combine_blocks (struct loop *loop)
          if (exit_bb != loop->latch)
            {
              /* Redirect non-exit edge to loop->latch.  */
-             for (e = bb->succ; e; e = e->succ_next)
+             FOR_EACH_EDGE (e, ei, bb->succs)
                if (!(e->flags & EDGE_LOOP_EXIT))
                  {
                    redirect_edge_and_branch (e, loop->latch);
@@ -885,10 +892,10 @@ combine_blocks (struct loop *loop)
        }
 
       /* It is time to remove this basic block.         First remove edges.  */
-      while (bb->succ != NULL)
-       ssa_remove_edge (bb->succ);
-      while (bb->pred != NULL)
-       ssa_remove_edge (bb->pred);
+      while (EDGE_COUNT (bb->succs) > 0)
+       ssa_remove_edge (EDGE_SUCC (bb, 0));
+      while (EDGE_COUNT (bb->preds) > 0)
+       ssa_remove_edge (EDGE_PRED (bb, 0));
 
       /* Remove labels and make stmts member of loop->header.  */
       for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
@@ -917,6 +924,18 @@ combine_blocks (struct loop *loop)
       remove_bb_from_loops (bb);
       expunge_block (bb);
     }
+
+  /* Now if possible, merge loop header and block with exit edge.
+     This reduces number of basic blocks to 2. Auto vectorizer addresses
+     loops with two nodes only.  FIXME: Use cleanup_tree_cfg().  */
+  if (exit_bb != loop->latch && empty_block_p (loop->latch))
+    {
+      if (can_merge_blocks_p (loop->header, exit_bb))
+       {
+         remove_bb_from_loops (exit_bb);
+         merge_blocks (loop->header, exit_bb);
+       }
+    }
 }
 
 /* Make new  temp variable of type TYPE. Add MODIFY_EXPR to assign EXP
@@ -955,7 +974,8 @@ static bool
 pred_blocks_visited_p (basic_block bb, bitmap *visited)
 {
   edge e;
-  for (e = bb->pred; e; e = e->pred_next)
+  edge_iterator ei;
+  FOR_EACH_EDGE (e, ei, bb->preds)
     if (!bitmap_bit_p (*visited, e->src->index))
       return false;
 
@@ -1026,11 +1046,15 @@ static bool
 bb_with_exit_edge_p (basic_block bb)
 {
   edge e;
+  edge_iterator ei;
   bool exit_edge_found = false;
 
-  for (e = bb->succ; e && !exit_edge_found ; e = e->succ_next)
+  FOR_EACH_EDGE (e, ei, bb->succs)
     if (e->flags & EDGE_LOOP_EXIT)
-      exit_edge_found = true;
+      {
+       exit_edge_found = true;
+       break;
+      }
 
   return exit_edge_found;
 }