OSDN Git Service

* simplify-rtx.c (simplify_ternary_operation): Use
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index 8869646..489613c 100644 (file)
@@ -114,7 +114,7 @@ static bool if_convertable_stmt_p (struct loop *, basic_block, tree);
 static bool if_convertable_bb_p (struct loop *, basic_block, bool);
 static bool if_convertable_loop_p (struct loop *, bool);
 static void add_to_predicate_list (basic_block, tree);
-static tree add_to_dst_predicate_list (struct loop * loop, tree, tree, tree,
+static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree,
                                       block_stmt_iterator *);
 static void clean_predicate_lists (struct loop *loop);
 static basic_block find_phi_replacement_condition (basic_block, tree *,
@@ -138,7 +138,7 @@ static basic_block *ifc_bbs;
    for vectorizer or not. If it is used for vectorizer, additional checks are
    used. (Vectorization checks are not yet implemented).  */
 
-bool
+static bool
 tree_if_conversion (struct loop *loop, bool for_vectorizer)
 {
   basic_block bb;
@@ -271,14 +271,13 @@ static void
 tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
                           block_stmt_iterator *bsi)
 {
-  tree then_clause, else_clause, c, new_cond;
+  tree c, c2, new_cond;
+  edge true_edge, false_edge;
   new_cond = NULL_TREE;
 
   gcc_assert (TREE_CODE (stmt) == COND_EXPR);
 
-  c = TREE_OPERAND (stmt, 0);
-  then_clause = TREE_OPERAND (stmt, 1);
-  else_clause = TREE_OPERAND (stmt, 2);
+  c = COND_EXPR_COND (stmt);
 
   /* Create temp. for condition.  */
   if (!is_gimple_condexpr (c))
@@ -289,28 +288,27 @@ tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
       c = TREE_OPERAND (new_stmt, 0);
     }
 
+  extract_true_false_edges_from_block (bb_for_stmt (stmt),
+                                      &true_edge, &false_edge);
+
   /* 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, 
-                                         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 true then TRUE_EDGE is taken.  */
+  new_cond = add_to_dst_predicate_list (loop, true_edge->dest, cond,
+                                       unshare_expr (c), bsi);
 
-      /* if 'c' is false then else_clause is reached.  */
-      c2 = invert_truthvalue (unshare_expr (c));
-      add_to_dst_predicate_list (loop, else_clause, cond, c2, bsi);
+  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 FALSE_EDGE is taken.  */
+  c2 = invert_truthvalue (unshare_expr (c));
+  add_to_dst_predicate_list (loop, false_edge->dest, cond, c2, bsi);
+
   /* Now this conditional statement is redundant. Remove it.
      But, do not remove exit condition! Update exit condition
      using new condition.  */
@@ -591,7 +589,7 @@ if_convertable_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
       /* ??? Check data dependency for vectorizer.  */
 
       /* What about phi nodes ? */
-      for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        if (!if_convertable_phi_p (loop, bb, phi))
          return false;
 
@@ -624,19 +622,16 @@ add_to_predicate_list (basic_block bb, tree new_cond)
   bb->aux = cond;
 }
 
-/* Add condition COND into DST's predicate list.  PREV_COND is
+/* Add condition COND into BB's predicate list.  PREV_COND is
    existing condition.  */
 
 static tree
-add_to_dst_predicate_list (struct loop * loop, tree dst,
+add_to_dst_predicate_list (struct loop * loop, basic_block bb,
                           tree prev_cond, tree cond,
                           block_stmt_iterator *bsi)
 {
-  basic_block bb;
   tree new_cond = NULL_TREE;
 
-  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;
 
@@ -662,10 +657,11 @@ add_to_dst_predicate_list (struct loop * loop, tree dst,
 static void
 clean_predicate_lists (struct loop *loop)
 {
-  unsigned int i;
-
-  for (i = 0; i < loop->num_nodes; i++)
-    ifc_bbs[i]->aux = NULL;
+#ifdef ENABLE_CHECKING
+  gcc_assert (loop->num_nodes == 2 || loop->num_nodes == 1);
+#endif
+  loop->header->aux = NULL;
+  loop->latch->aux = NULL;
 }
 
 /* Basic block BB has two predecessors. Using predecessor's aux field, set
@@ -815,7 +811,7 @@ process_phi_nodes (struct loop *loop)
       basic_block true_bb = NULL;
       bb = ifc_bbs[i];
 
-      if (bb == loop->header || bb == loop->latch)
+      if (bb == loop->header)
        continue;
 
       phi = phi_nodes (bb);
@@ -828,7 +824,7 @@ process_phi_nodes (struct loop *loop)
 
       while (phi)
        {
-         tree next = TREE_CHAIN (phi);
+         tree next = PHI_CHAIN (phi);
          replace_phi_with_cond_modify_expr (phi, cond, true_bb, &bsi);
          release_phi_node (phi);
          phi = next;
@@ -863,9 +859,6 @@ combine_blocks (struct loop *loop)
 
       bb = ifc_bbs[i];
 
-      if (bb == loop->latch)
-       continue;
-
       if (!exit_bb && bb_with_exit_edge_p (bb))
          exit_bb = bb;
 
@@ -891,6 +884,9 @@ combine_blocks (struct loop *loop)
          continue;
        }
 
+      if (bb == loop->latch && empty_block_p (bb))
+       continue;
+
       /* It is time to remove this basic block.         First remove edges.  */
       while (EDGE_COUNT (bb->succs) > 0)
        ssa_remove_edge (EDGE_SUCC (bb, 0));
@@ -921,6 +917,8 @@ combine_blocks (struct loop *loop)
        delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
 
       /* Remove basic block.  */
+      if (bb == loop->latch)
+       loop->latch = merge_target_bb;
       remove_bb_from_loops (bb);
       expunge_block (bb);
     }
@@ -928,7 +926,10 @@ combine_blocks (struct loop *loop)
   /* 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 (exit_bb
+      && loop->header != loop->latch
+      && exit_bb != loop->latch 
+      && empty_block_p (loop->latch))
     {
       if (can_merge_blocks_p (loop->header, exit_bb))
        {