OSDN Git Service

tob@archimedes:~/scratch/gcc> head -n 15 ../intrinsic_use.diff
[pf3gnuchains/gcc-fork.git] / gcc / tree-if-conv.c
index f200d48..0f1caaa 100644 (file)
@@ -175,7 +175,7 @@ init_bb_predicate (basic_block bb)
 {
   bb->aux = XNEW (struct bb_predicate_s);
   set_bb_predicate_gimplified_stmts (bb, NULL);
-  set_bb_predicate (bb, NULL_TREE);
+  set_bb_predicate (bb, boolean_true_node);
 }
 
 /* Free the predicate of basic block BB.  */
@@ -203,6 +203,16 @@ free_bb_predicate (basic_block bb)
   bb->aux = NULL;
 }
 
+/* Free the predicate of BB and reinitialize it with the true
+   predicate.  */
+
+static inline void
+reset_bb_predicate (basic_block bb)
+{
+  free_bb_predicate (bb);
+  init_bb_predicate (bb);
+}
+
 /* Create a new temp variable of type TYPE.  Add GIMPLE_ASSIGN to assign EXP
    to the new variable.  */
 
@@ -249,17 +259,96 @@ is_predicated (basic_block bb)
   return !is_true_predicate (bb_predicate (bb));
 }
 
-/* Add condition NEW_COND to the predicate list of basic block BB.  */
+/* Parses the predicate COND and returns its comparison code and
+   operands OP0 and OP1.  */
+
+static enum tree_code
+parse_predicate (tree cond, tree *op0, tree *op1)
+{
+  gimple s;
+
+  if (TREE_CODE (cond) == SSA_NAME
+      && is_gimple_assign (s = SSA_NAME_DEF_STMT (cond)))
+    {
+      if (TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison)
+       {
+         *op0 = gimple_assign_rhs1 (s);
+         *op1 = gimple_assign_rhs2 (s);
+         return gimple_assign_rhs_code (s);
+       }
+
+      else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR)
+       {
+         tree op = gimple_assign_rhs1 (s);
+         tree type = TREE_TYPE (op);
+         enum tree_code code = parse_predicate (op, op0, op1);
+
+         return code == ERROR_MARK ? ERROR_MARK
+           : invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type)));
+       }
+
+      return ERROR_MARK;
+    }
+
+  if (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison)
+    {
+      *op0 = TREE_OPERAND (cond, 0);
+      *op1 = TREE_OPERAND (cond, 1);
+      return TREE_CODE (cond);
+    }
+
+  return ERROR_MARK;
+}
+
+/* Returns the fold of predicate C1 OR C2 at location LOC.  */
+
+static tree
+fold_or_predicates (location_t loc, tree c1, tree c2)
+{
+  tree op1a, op1b, op2a, op2b;
+  enum tree_code code1 = parse_predicate (c1, &op1a, &op1b);
+  enum tree_code code2 = parse_predicate (c2, &op2a, &op2b);
+
+  if (code1 != ERROR_MARK && code2 != ERROR_MARK)
+    {
+      tree t = maybe_fold_or_comparisons (code1, op1a, op1b,
+                                         code2, op2a, op2b);
+      if (t)
+       return t;
+    }
+
+  return fold_build2_loc (loc, TRUTH_OR_EXPR, boolean_type_node, c1, c2);
+}
+
+/* Add condition NC to the predicate list of basic block BB.  */
 
 static inline void
-add_to_predicate_list (basic_block bb, tree new_cond)
+add_to_predicate_list (basic_block bb, tree nc)
 {
-  tree cond = bb_predicate (bb);
+  tree bc;
+
+  if (is_true_predicate (nc))
+    return;
 
-  set_bb_predicate (bb, is_true_predicate (cond) ? new_cond :
-                   fold_build2_loc (EXPR_LOCATION (cond),
-                                    TRUTH_OR_EXPR, boolean_type_node,
-                                    cond, new_cond));
+  if (!is_predicated (bb))
+    bc = nc;
+  else
+    {
+      bc = bb_predicate (bb);
+      bc = fold_or_predicates (EXPR_LOCATION (bc), nc, bc);
+    }
+
+  if (!is_gimple_condexpr (bc))
+    {
+      gimple_seq stmts;
+      bc = force_gimple_operand (bc, &stmts, true, NULL_TREE);
+      add_bb_predicate_gimplified_stmts (bb, stmts);
+    }
+
+  if (is_true_predicate (bc))
+    reset_bb_predicate (bb);
+  else
+    set_bb_predicate (bb, bc);
 }
 
 /* Add the condition COND to the previous condition PREV_COND, and add
@@ -605,8 +694,7 @@ predicate_bbs (loop_p loop)
         to be processed: skip it.  */
       if (bb == loop->latch)
        {
-         set_bb_predicate (loop->latch, boolean_true_node);
-         set_bb_predicate_gimplified_stmts (loop->latch, NULL);
+         reset_bb_predicate (loop->latch);
          continue;
        }
 
@@ -680,7 +768,7 @@ predicate_bbs (loop_p loop)
     }
 
   /* The loop header is always executed.  */
-  set_bb_predicate (loop->header, boolean_true_node);
+  reset_bb_predicate (loop->header);
   gcc_assert (bb_predicate_gimplified_stmts (loop->header) == NULL
              && bb_predicate_gimplified_stmts (loop->latch) == NULL);
 
@@ -1012,6 +1100,15 @@ insert_gimplified_predicates (loop_p loop)
       basic_block bb = ifc_bbs[i];
       gimple_seq stmts = bb_predicate_gimplified_stmts (bb);
 
+      if (!is_predicated (bb))
+       {
+         /* Do not insert statements for a basic block that is not
+            predicated.  Also make sure that the predicate of the
+            basic block is set to true.  */
+         reset_bb_predicate (bb);
+         continue;
+       }
+
       if (stmts)
        {
          gimple_stmt_iterator gsi = gsi_last_bb (bb);
@@ -1221,10 +1318,13 @@ main_tree_if_conversion (void)
   return changed ? TODO_cleanup_cfg : 0;
 }
 
+/* Returns true when the if-conversion pass is enabled.  */
+
 static bool
 gate_tree_if_conversion (void)
 {
-  return flag_tree_vectorize != 0;
+  return ((flag_tree_vectorize && flag_tree_loop_if_convert != 0)
+         || flag_tree_loop_if_convert == 1);
 }
 
 struct gimple_opt_pass pass_if_conversion =