Fix is_gimple_condexpr vs is_gimple_condexpr_for_cond

The following fixes wrongly used is_gimple_condexpr and makes
canonicalize_cond_expr_cond honor either, delaying final checking
to callers where all but two in ifcombine are doing the correct
thing already.

This fixes bugs but is now mainly in preparation for making
COND_EXPRs in GIMPLE assignments no longer have a GENERIC expression
as condition operand like we already transitioned VEC_COND_EXPR earlier.

2022-04-11  Richard Biener  <rguenther@suse.de>

	* gimple-expr.cc (is_gimple_condexpr): Adjust comment.
	(canonicalize_cond_expr_cond): Move here from gimple.cc,
	allow both COND_EXPR and GIMPLE_COND forms.
	* gimple-expr.h (canonicalize_cond_expr_cond): Declare.
	* gimple.cc (canonicalize_cond_expr_cond): Remove here.
	* gimple.h (canonicalize_cond_expr_cond): Likewise.
	* gimple-loop-versioning.cc (loop_versioning::version_loop):
	Use is_gimple_condexpr_for_cond.
	* tree-parloops.cc (gen_parallel_loop): Likewise.
	* tree-ssa-ifcombine.cc (ifcombine_ifandif): Check for
	a proper cond expr after canonicalize_cond_expr_cond.
	Use is_gimple_condexpr_for_cond where appropriate.
	* tree-ssa-loop-manip.cc (determine_exit_conditions): Likewise.
	* tree-vect-loop-manip.cc (slpeel_add_loop_guard): Likewise.
This commit is contained in:
Richard Biener 2022-04-11 12:18:48 +02:00
parent 4aa61e08ad
commit c090743b2a
9 changed files with 70 additions and 54 deletions

View File

@ -614,7 +614,8 @@ is_gimple_condexpr_1 (tree t, bool allow_traps, bool allow_cplx)
&& is_gimple_val (TREE_OPERAND (t, 1))));
}
/* Return true if T is a GIMPLE condition. */
/* Return true if T is a condition operand in a GIMPLE assignment
with a COND_EXPR RHS. */
bool
is_gimple_condexpr (tree t)
@ -632,6 +633,50 @@ is_gimple_condexpr_for_cond (tree t)
return is_gimple_condexpr_1 (t, false, true);
}
/* Canonicalize a tree T for use in a COND_EXPR as conditional. Returns
a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
we failed to create one. */
tree
canonicalize_cond_expr_cond (tree t)
{
/* Strip conversions around boolean operations. */
if (CONVERT_EXPR_P (t)
&& (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
== BOOLEAN_TYPE))
t = TREE_OPERAND (t, 0);
/* For !x use x == 0. */
if (TREE_CODE (t) == TRUTH_NOT_EXPR)
{
tree top0 = TREE_OPERAND (t, 0);
t = build2 (EQ_EXPR, TREE_TYPE (t),
top0, build_int_cst (TREE_TYPE (top0), 0));
}
/* For cmp ? 1 : 0 use cmp. */
else if (TREE_CODE (t) == COND_EXPR
&& COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
&& integer_onep (TREE_OPERAND (t, 1))
&& integer_zerop (TREE_OPERAND (t, 2)))
{
tree top0 = TREE_OPERAND (t, 0);
t = build2 (TREE_CODE (top0), TREE_TYPE (t),
TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
}
/* For x ^ y use x != y. */
else if (TREE_CODE (t) == BIT_XOR_EXPR)
t = build2 (NE_EXPR, TREE_TYPE (t),
TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
/* We don't know where this will be used so allow both traps and
_Complex. The caller is responsible for more precise checking. */
if (is_gimple_condexpr_1 (t, true, true))
return t;
return NULL_TREE;
}
/* Return true if T is a gimple address. */
bool

View File

@ -56,6 +56,7 @@ extern bool is_gimple_mem_ref_addr (tree);
extern void flush_mark_addressable_queue (void);
extern void mark_addressable (tree);
extern bool is_gimple_reg_rhs (tree);
extern tree canonicalize_cond_expr_cond (tree);
/* Return true if a conversion from either type of TYPE1 and TYPE2
to the other is not required. Otherwise return false. */

View File

@ -1681,7 +1681,8 @@ loop_versioning::version_loop (class loop *loop)
/* Convert the condition into a suitable gcond. */
gimple_seq stmts = NULL;
cond = force_gimple_operand_1 (cond, &stmts, is_gimple_condexpr, NULL_TREE);
cond = force_gimple_operand_1 (cond, &stmts, is_gimple_condexpr_for_cond,
NULL_TREE);
/* Version the loop. */
initialize_original_copy_tables ();

View File

@ -2380,48 +2380,6 @@ const unsigned char gimple_rhs_class_table[] = {
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
/* Canonicalize a tree T for use in a COND_EXPR as conditional. Returns
a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
we failed to create one. */
tree
canonicalize_cond_expr_cond (tree t)
{
/* Strip conversions around boolean operations. */
if (CONVERT_EXPR_P (t)
&& (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
|| TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
== BOOLEAN_TYPE))
t = TREE_OPERAND (t, 0);
/* For !x use x == 0. */
if (TREE_CODE (t) == TRUTH_NOT_EXPR)
{
tree top0 = TREE_OPERAND (t, 0);
t = build2 (EQ_EXPR, TREE_TYPE (t),
top0, build_int_cst (TREE_TYPE (top0), 0));
}
/* For cmp ? 1 : 0 use cmp. */
else if (TREE_CODE (t) == COND_EXPR
&& COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
&& integer_onep (TREE_OPERAND (t, 1))
&& integer_zerop (TREE_OPERAND (t, 2)))
{
tree top0 = TREE_OPERAND (t, 0);
t = build2 (TREE_CODE (top0), TREE_TYPE (t),
TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
}
/* For x ^ y use x != y. */
else if (TREE_CODE (t) == BIT_XOR_EXPR)
t = build2 (NE_EXPR, TREE_TYPE (t),
TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
if (is_gimple_condexpr (t))
return t;
return NULL_TREE;
}
/* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
the positions marked by the set ARGS_TO_SKIP. */

View File

@ -1611,7 +1611,6 @@ bool gimple_could_trap_p (const gimple *);
bool gimple_assign_rhs_could_trap_p (gimple *);
extern void dump_gimple_statistics (void);
unsigned get_gimple_rhs_num_ops (enum tree_code);
extern tree canonicalize_cond_expr_cond (tree);
gcall *gimple_call_copy_skip_args (gcall *, bitmap);
extern bool gimple_compare_field_offset (tree, tree);
extern tree gimple_unsigned_type (tree);

View File

@ -3070,7 +3070,7 @@ gen_parallel_loop (class loop *loop,
= force_gimple_operand (many_iterations_cond, &stmts, false, NULL_TREE);
if (stmts)
gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts);
if (!is_gimple_condexpr (many_iterations_cond))
if (!is_gimple_condexpr_for_cond (many_iterations_cond))
{
many_iterations_cond
= force_gimple_operand (many_iterations_cond, &stmts,

View File

@ -432,6 +432,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
t = canonicalize_cond_expr_cond (t);
if (!t)
return false;
if (!is_gimple_condexpr_for_cond (t))
{
gsi = gsi_for_stmt (inner_cond);
t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
NULL, true, GSI_SAME_STMT);
}
gimple_cond_set_condition_from_tree (inner_cond, t);
update_stmt (inner_cond);
@ -512,6 +518,12 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
t = canonicalize_cond_expr_cond (t);
if (!t)
return false;
if (!is_gimple_condexpr_for_cond (t))
{
gsi = gsi_for_stmt (inner_cond);
t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
NULL, true, GSI_SAME_STMT);
}
gimple_cond_set_condition_from_tree (inner_cond, t);
update_stmt (inner_cond);
@ -593,8 +605,8 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv,
result_inv = false;
}
gsi = gsi_for_stmt (inner_cond);
t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr, NULL, true,
GSI_SAME_STMT);
t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr_for_cond,
NULL, true, GSI_SAME_STMT);
}
if (result_inv)
t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t);

View File

@ -1096,7 +1096,7 @@ determine_exit_conditions (class loop *loop, class tree_niter_desc *desc,
/* cond now may be a gimple comparison, which would be OK, but also any
other gimple rhs (say a && b). In this case we need to force it to
operand. */
if (!is_gimple_condexpr (cond))
if (!is_gimple_condexpr_for_cond (cond))
{
cond = force_gimple_operand (cond, &stmts, true, NULL_TREE);
if (stmts)

View File

@ -1260,8 +1260,8 @@ slpeel_add_loop_guard (basic_block guard_bb, tree cond,
enter_e->flags |= EDGE_FALSE_VALUE;
gsi = gsi_last_bb (guard_bb);
cond = force_gimple_operand_1 (cond, &gimplify_stmt_list, is_gimple_condexpr,
NULL_TREE);
cond = force_gimple_operand_1 (cond, &gimplify_stmt_list,
is_gimple_condexpr_for_cond, NULL_TREE);
if (gimplify_stmt_list)
gsi_insert_seq_after (&gsi, gimplify_stmt_list, GSI_NEW_STMT);
@ -3478,8 +3478,8 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
{
gimple_seq tem = NULL;
cond_expr = force_gimple_operand_1 (unshare_expr (cond_expr),
&tem,
is_gimple_condexpr, NULL_TREE);
&tem, is_gimple_condexpr_for_cond,
NULL_TREE);
gimple_seq_add_seq (&cond_expr_stmt_list, tem);
}
@ -3521,7 +3521,7 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
cond_expr = force_gimple_operand_1 (unshare_expr (cond_expr),
&gimplify_stmt_list,
is_gimple_condexpr, NULL_TREE);
is_gimple_condexpr_for_cond, NULL_TREE);
gimple_seq_add_seq (&cond_expr_stmt_list, gimplify_stmt_list);
/* Compute the outermost loop cond_expr and cond_expr_stmt_list are