#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"
#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. */
}
/* 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);
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;
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);
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);
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;
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;
free (ifc_bbs);
ifc_bbs = NULL;
}
+ free_dominance_info (CDI_POST_DOMINATORS);
return todo;
}
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 */