OSDN Git Service

2004-10-04 Jose Ruiz <ruiz@act-europe.fr>
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index da75585..8869646 100644 (file)
@@ -117,9 +117,9 @@ static void add_to_predicate_list (basic_block, tree);
 static tree add_to_dst_predicate_list (struct loop * loop, tree, tree, tree,
                                       block_stmt_iterator *);
 static void clean_predicate_lists (struct loop *loop);
-static bool find_phi_replacement_condition (basic_block, tree *,
-                                            block_stmt_iterator *);
-static void replace_phi_with_cond_modify_expr (tree, tree, bool,
+static basic_block find_phi_replacement_condition (basic_block, tree *,
+                                                  block_stmt_iterator *);
+static void replace_phi_with_cond_modify_expr (tree, tree, basic_block,
                                                block_stmt_iterator *);
 static void process_phi_nodes (struct loop *);
 static void combine_blocks (struct loop *);
@@ -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;
@@ -257,8 +257,7 @@ tree_if_convert_stmt (struct loop *  loop, tree t, tree cond,
       break;
 
     default:
-      abort ();
-      break;
+      gcc_unreachable ();
     }
   return cond;
 }
@@ -275,17 +274,14 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
   tree then_clause, else_clause, c, new_cond;
   new_cond = NULL_TREE;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE (stmt) != COND_EXPR)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE (stmt) == COND_EXPR);
 
   c = TREE_OPERAND (stmt, 0);
   then_clause = TREE_OPERAND (stmt, 1);
   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));
@@ -296,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);
     }
 
@@ -315,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;
 }
 
@@ -467,12 +466,13 @@ if_convertable_stmt_p (struct loop *loop, basic_block bb, tree stmt)
    - Basic block is after exit block but before latch.
    - Basic block edge(s) is not normal.
    EXIT_BB_SEEN is true if basic block with exit edge is already seen.
-   BB is inside loop LOOP. */
+   BB is inside loop LOOP.  */
 
 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);
@@ -494,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))
       {
@@ -525,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.  */
@@ -557,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;
 
@@ -634,10 +635,7 @@ add_to_dst_predicate_list (struct loop * loop, tree dst,
   basic_block bb;
   tree new_cond = NULL_TREE;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE (dst) != GOTO_EXPR)
-    abort ();
-#endif
+  gcc_assert (TREE_CODE (dst) == GOTO_EXPR);
   bb = label_to_block (TREE_OPERAND (dst, 0));
   if (!flow_bb_inside_loop_p (loop, bb))
     return NULL_TREE;
@@ -671,28 +669,29 @@ clean_predicate_lists (struct loop *loop)
 }
 
 /* Basic block BB has two predecessors. Using predecessor's aux field, set
-   appropriate condition COND for the PHI node replacement. Return true if
-   phi arguments are condition is selected from second predecessor.  */
+   appropriate condition COND for the PHI node replacement. Return true block
+   whose phi arguments are selected when cond is true.  */
 
-static bool
+static basic_block
 find_phi_replacement_condition (basic_block bb, tree *cond,
                                 block_stmt_iterator *bsi)
 {
   edge e;
   basic_block p1 = NULL;
   basic_block p2 = NULL;
-  bool switch_args = false;
+  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;
-      else if (p2 == NULL)
-       p2 = e->src;
-      else
-       /* More than two predecessors. This is not expected.  */
-       abort ();
+       p1 = e->src;
+      else 
+       {
+         gcc_assert (!p2);
+         p2 = e->src;
+       }
     }
 
   /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr.  */
@@ -700,12 +699,12 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
   if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
     {
       *cond  = p2->aux;
-      switch_args = true;
+      true_bb = p2;
     }
   else
     {
       *cond  = p1->aux;
-      switch_args = false;
+      true_bb = p1;
     }
 
   /* Create temp. for the condition. Vectorizer prefers to have gimple
@@ -722,12 +721,9 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
       *cond = TREE_OPERAND (new_stmt, 0);
     }
 
-#ifdef ENABLE_CHECKING
-  if (*cond == NULL_TREE)
-    abort ();
-#endif
+  gcc_assert (*cond);
 
-  return switch_args;
+  return true_bb;
 }
 
 
@@ -738,11 +734,11 @@ find_phi_replacement_condition (basic_block bb, tree *cond,
    is converted into,
      S2: A = cond ? x1 : x2;
    S2 is inserted at the top of basic block's statement list.
-   PHI arguments are switched if SWITCH_ARGS is true.
+   When COND is true, phi arg from TRUE_BB is selected.
 */
 
 static void
-replace_phi_with_cond_modify_expr (tree phi, tree cond, bool switch_args,
+replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb,
                                    block_stmt_iterator *bsi)
 {
   tree new_stmt;
@@ -750,14 +746,10 @@ replace_phi_with_cond_modify_expr (tree phi, tree cond, bool switch_args,
   tree rhs;
   tree arg_0, arg_1;
 
-#ifdef ENABLE_CHECKING
-  if (TREE_CODE (phi) != PHI_NODE)
-    abort ();
-
+  gcc_assert (TREE_CODE (phi) == PHI_NODE);
+  
   /* If this is not filtered earlier, then now it is too late.  */
-  if (PHI_NUM_ARGS (phi) != 2)
-     abort ();
-#endif
+  gcc_assert (PHI_NUM_ARGS (phi) == 2);
 
   /* Find basic block and initialize iterator.  */
   bb = bb_for_stmt (phi);
@@ -767,7 +759,7 @@ replace_phi_with_cond_modify_expr (tree phi, tree cond, bool switch_args,
   arg_1 = NULL_TREE;
 
   /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr.  */
-  if (switch_args)
+  if (PHI_ARG_EDGE(phi, 1)->src == true_bb)
     {
       arg_0 = PHI_ARG_DEF (phi, 1);
       arg_1 = PHI_ARG_DEF (phi, 0);
@@ -820,7 +812,7 @@ process_phi_nodes (struct loop *loop)
     {
       tree phi, cond;
       block_stmt_iterator bsi;
-      bool switch_args = false;
+      basic_block true_bb = NULL;
       bb = ifc_bbs[i];
 
       if (bb == loop->header || bb == loop->latch)
@@ -832,12 +824,12 @@ process_phi_nodes (struct loop *loop)
       /* BB has two predecessors. Using predecessor's aux field, set
         appropriate condition for the PHI node replacement.  */
       if (phi)
-       switch_args = find_phi_replacement_condition (bb, &cond, &bsi);
+       true_bb = find_phi_replacement_condition (bb, &cond, &bsi);
 
       while (phi)
        {
          tree next = TREE_CHAIN (phi);
-         replace_phi_with_cond_modify_expr (phi, cond, switch_args, &bsi);
+         replace_phi_with_cond_modify_expr (phi, cond, true_bb, &bsi);
          release_phi_node (phi);
          phi = next;
        }
@@ -847,7 +839,7 @@ process_phi_nodes (struct loop *loop)
 }
 
 /* Combine all basic block from the given LOOP into one or two super
-   basic block.  Replace PHI nodes with conditional modify expression. */
+   basic block.  Replace PHI nodes with conditional modify expression.  */
 
 static void
 combine_blocks (struct loop *loop)
@@ -880,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);
@@ -888,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);
@@ -899,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); )
@@ -931,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
@@ -969,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;
 
@@ -991,11 +997,8 @@ get_loop_body_in_if_conv_order (const struct loop *loop)
   unsigned int index = 0;
   unsigned int visited_count = 0;
 
-  if (!loop->num_nodes)
-    abort ();
-
-  if (loop->latch == EXIT_BLOCK_PTR)
-    abort ();
+  gcc_assert (loop->num_nodes);
+  gcc_assert (loop->latch != EXIT_BLOCK_PTR);
 
   blocks = xcalloc (loop->num_nodes, sizeof (basic_block));
   visited = BITMAP_XMALLOC ();
@@ -1043,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;
 }
@@ -1097,5 +1104,6 @@ struct tree_opt_pass pass_if_conversion =
   TODO_dump_func
     | TODO_verify_ssa
     | TODO_verify_stmts
-    | TODO_verify_flow               /* todo_flags_finish */
+    | TODO_verify_flow,              /* todo_flags_finish */
+  0                                 /* letter */
 };