ipa-cp.c (ipcp_cloning_candidate_p): Use opt_for_fn.
[gcc.git] / gcc / tree-if-conv.c
index 69f1e1f06150de5496b6f69af25a200a52103911..0e7a144ed4628a795e6b5124aa5503fb7c068dd9 100644 (file)
@@ -87,6 +87,16 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "stor-layout.h"
 #include "flags.h"
+#include "predict.h"
+#include "vec.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "gimple-pretty-print.h"
 #include "tree-ssa-alias.h"
@@ -115,6 +125,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "dbgcnt.h"
 #include "expr.h"
+#include "insn-codes.h"
 #include "optabs.h"
 
 /* List of basic blocks in if-conversion-suitable order.  */
@@ -396,25 +407,44 @@ fold_build_cond_expr (tree type, tree cond, tree rhs, tree lhs)
 }
 
 /* Add condition NC to the predicate list of basic block BB.  LOOP is
-   the loop to be if-converted.  */
+   the loop to be if-converted. Use predicate of cd-equivalent block
+   for join bb if it exists: we call basic blocks bb1 and bb2 
+   cd-equivalent if they are executed under the same condition.  */
 
 static inline void
 add_to_predicate_list (struct loop *loop, basic_block bb, tree nc)
 {
   tree bc, *tp;
+  basic_block dom_bb;
 
   if (is_true_predicate (nc))
     return;
 
-  if (!is_predicated (bb))
-    {
-      /* If dominance tells us this basic block is always executed, don't
-        record any predicates for it.  */
-      if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
-       return;
+  /* If dominance tells us this basic block is always executed,
+     don't record any predicates for it.  */
+  if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
+    return;
 
-      bc = nc;
+  dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
+  /* We use notion of cd equivalence to get simpler predicate for
+     join block, e.g. if join block has 2 predecessors with predicates
+     p1 & p2 and p1 & !p2, we'd like to get p1 for it instead of
+     p1 & p2 | p1 & !p2.  */
+  if (dom_bb != loop->header
+      && get_immediate_dominator (CDI_POST_DOMINATORS, dom_bb) == bb)
+    {
+      gcc_assert (flow_bb_inside_loop_p (loop, dom_bb));
+      bc = bb_predicate (dom_bb);
+      gcc_assert (!is_true_predicate (bc));
+      set_bb_predicate (bb, bc);
+      if (dump_file && (dump_flags & TDF_DETAILS))
+       fprintf (dump_file, "Use predicate of bb#%d for bb#%d\n",
+                dom_bb->index, bb->index);
+      return;
     }
+
+  if (!is_predicated (bb))
+    bc = nc;
   else
     {
       bc = bb_predicate (bb);
@@ -724,7 +754,7 @@ static bool
 ifcvt_can_use_mask_load_store (gimple stmt)
 {
   tree lhs, ref;
-  enum machine_mode mode;
+  machine_mode mode;
   basic_block bb = gimple_bb (stmt);
   bool is_load;
 
@@ -1176,6 +1206,7 @@ if_convertible_loop_p_1 (struct loop *loop,
     return false;
 
   calculate_dominance_info (CDI_DOMINATORS);
+  calculate_dominance_info (CDI_POST_DOMINATORS);
 
   /* Allow statements that can be handled during if-conversion.  */
   ifc_bbs = get_loop_body_in_if_conv_order (loop);
@@ -1407,8 +1438,11 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
   gimple stmt;
   gimple header_phi = NULL;
   enum tree_code reduction_op;
-  struct loop *loop = gimple_bb (phi)->loop_father;
+  basic_block bb = gimple_bb (phi);
+  struct loop *loop = bb->loop_father;
   edge latch_e = loop_latch_edge (loop);
+  imm_use_iterator imm_iter;
+  use_operand_p use_p;
 
   arg_0 = PHI_ARG_DEF (phi, 0);
   arg_1 = PHI_ARG_DEF (phi, 1);
@@ -1439,9 +1473,17 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
       || gimple_has_volatile_ops (stmt))
     return false;
 
+  if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
+    return false;
+
   if (!is_predicated (gimple_bb (stmt)))
     return false;
 
+  /* Check that stmt-block is predecessor of phi-block.  */
+  if (EDGE_PRED (bb, 0)->src != gimple_bb (stmt)
+      && EDGE_PRED (bb, 1)->src != gimple_bb (stmt))
+    return false;
+
   if (!has_single_use (lhs))
     return false;
 
@@ -1462,6 +1504,18 @@ is_cond_scalar_reduction (gimple phi, gimple *reduc,
   else if (r_op1 != PHI_RESULT (header_phi))
     return false;
 
+  /* Check that R_OP1 is used in reduction stmt or in PHI only.  */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_op1)
+    {
+      gimple use_stmt = USE_STMT (use_p);
+      if (is_gimple_debug (use_stmt))
+       continue;
+      if (use_stmt == stmt)
+       continue;
+      if (gimple_code (use_stmt) != GIMPLE_PHI)
+       return false;
+    }
+
   *op0 = r_op1; *op1 = r_op2;
   *reduc = stmt;
   return true;
@@ -2125,6 +2179,7 @@ tree_if_conversion (struct loop *loop)
       free (ifc_bbs);
       ifc_bbs = NULL;
     }
+  free_dominance_info (CDI_POST_DOMINATORS);
 
   return todo;
 }
@@ -2138,7 +2193,6 @@ const pass_data pass_data_if_conversion =
   GIMPLE_PASS, /* type */
   "ifcvt", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_execute */
   TV_NONE, /* tv_id */
   ( PROP_cfg | PROP_ssa ), /* properties_required */
   0, /* properties_provided */