You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This pass implements tree level if-conversion transformation of loops.
Initial goal is to help vectorizer vectorize loops with conditions.
static bool if_convertible_phi_p (struct loop *, basic_block, tree);
static bool if_convertible_modify_expr_p (struct loop *, basic_block, tree);
static bool if_convertible_stmt_p (struct loop *, basic_block, tree);
-static bool if_convertible_bb_p (struct loop *, basic_block, bool);
+static bool if_convertible_bb_p (struct loop *, basic_block, basic_block);
static bool if_convertible_loop_p (struct loop *, bool);
static void add_to_predicate_list (basic_block, tree);
static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree,
BB is inside loop LOOP. */
static bool
-if_convertible_bb_p (struct loop *loop, basic_block bb, bool exit_bb_seen)
+if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
{
edge e;
edge_iterator ei;
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "----------[%d]-------------\n", bb->index);
- if (exit_bb_seen)
+ if (exit_bb)
{
if (bb != loop->latch)
{
fprintf (dump_file, "non empty basic block after exit bb\n");
return false;
}
+ else if (bb == loop->latch
+ && bb != exit_bb
+ && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "latch is not dominated by exit_block\n");
+ return false;
+ }
}
/* Be less adventurous and handle only normal edges. */
unsigned int i;
edge e;
edge_iterator ei;
- bool exit_bb_seen = false;
+ basic_block exit_bb = NULL;
/* Handle only inner most loop. */
if (!loop || loop->inner)
{
bb = ifc_bbs[i];
- if (!if_convertible_bb_p (loop, bb, exit_bb_seen))
+ if (!if_convertible_bb_p (loop, bb, exit_bb))
return false;
/* Check statements. */
return false;
if (bb_with_exit_edge_p (loop, bb))
- exit_bb_seen = true;
+ exit_bb = bb;
}
/* OK. Did not find any potential issues so go ahead in if-convert
tree cond = bb->aux;
if (cond)
- cond = fold (build (TRUTH_OR_EXPR, boolean_type_node,
- unshare_expr (cond), new_cond));
+ cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
+ unshare_expr (cond), new_cond);
else
cond = new_cond;
bsi_insert_before (bsi, tmp_stmts2, BSI_SAME_STMT);
/* new_cond == prev_cond AND cond */
- tmp = build (TRUTH_AND_EXPR, boolean_type_node,
- unshare_expr (prev_cond), cond);
+ tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
+ unshare_expr (prev_cond), cond);
tmp_stmt = ifc_temp_var (boolean_type_node, tmp);
bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT);
new_cond = TREE_OPERAND (tmp_stmt, 0);
S2: x = c ? b : a;
S2 is preferred over S1. Make 'b' first_bb and use its condition.
-
+
2) Do not make loop header first_bb.
3)
S3: x = (c == d) ? b : a;
S3 is preferred over S1 and S2*, Make 'b' first_bb and use
- its condition. */
+ its condition.
+
+ 4) If pred B is dominated by pred A then use pred B's condition.
+ See PR23115. */
/* Select condition that is not TRUTH_NOT_EXPR. */
tmp_cond = first_bb->aux;
second_bb = tmp_bb;
}
- /* Check if FIRST_BB is loop header or not. */
- if (first_bb == loop->header)
+ /* Check if FIRST_BB is loop header or not and make sure that
+ FIRST_BB does not dominate SECOND_BB. */
+ if (first_bb == loop->header
+ || dominated_by_p (CDI_DOMINATORS, second_bb, first_bb))
{
tmp_cond = second_bb->aux;
if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
}
/* Build new RHS using selected condition and arguments. */
- rhs = build (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)),
- unshare_expr (cond), unshare_expr (arg_0),
- unshare_expr (arg_1));
+ rhs = build3 (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)),
+ unshare_expr (cond), unshare_expr (arg_0),
+ unshare_expr (arg_1));
/* Create new MODIFY expression using RHS. */
- new_stmt = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
- unshare_expr (PHI_RESULT (phi)), rhs);
+ new_stmt = build2 (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
+ unshare_expr (PHI_RESULT (phi)), rhs);
/* Make new statement definition of the original phi result. */
SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new_stmt;
add_referenced_tmp_var (var);
/* Build new statement to assign EXP to new variable. */
- stmt = build (MODIFY_EXPR, type, var, exp);
+ stmt = build2 (MODIFY_EXPR, type, var, exp);
/* Get SSA name for the new variable and set make new statement
its definition statement. */