mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
gimple: Add gimple_with_undefined_signed_overflow and use it [PR111276]
While looking into the ifcombine, I noticed that rewrite_to_defined_overflow was rewriting already defined code. In the previous attempt at fixing this, the review mentioned we should not be calling rewrite_to_defined_overflow in those cases. The places which called rewrite_to_defined_overflow didn't always check the lhs of the assignment. This fixes the problem by introducing a helper function which is to be used before calling rewrite_to_defined_overflow. Bootstrapped and tested on x86_64-linux-gnu. gcc/ChangeLog: PR tree-optimization/111276 * gimple-fold.cc (arith_code_with_undefined_signed_overflow): Make static. (gimple_with_undefined_signed_overflow): New function. * gimple-fold.h (arith_code_with_undefined_signed_overflow): Remove. (gimple_with_undefined_signed_overflow): Add declaration. * tree-if-conv.cc (if_convertible_gimple_assign_stmt_p): Use gimple_with_undefined_signed_overflow instead of manually checking lhs and the code of the stmt. (predicate_statements): Likewise. * tree-ssa-ifcombine.cc (ifcombine_rewrite_to_defined_overflow): Likewise. * tree-ssa-loop-im.cc (move_computations_worker): Likewise. * tree-ssa-reassoc.cc (update_range_test): Likewise. Reformat. * tree-scalar-evolution.cc (final_value_replacement_loop): Use gimple_with_undefined_signed_overflow instead of arith_code_with_undefined_signed_overflow. * tree-ssa-loop-split.cc (split_loop): Likewise. Signed-off-by: Andrew Pinski <quic_apinski@quicinc.com>
This commit is contained in:
@@ -10573,7 +10573,7 @@ gimple_fold_indirect_ref (tree t)
|
||||
integer types involves undefined behavior on overflow and the
|
||||
operation can be expressed with unsigned arithmetic. */
|
||||
|
||||
bool
|
||||
static bool
|
||||
arith_code_with_undefined_signed_overflow (tree_code code)
|
||||
{
|
||||
switch (code)
|
||||
@@ -10590,6 +10590,30 @@ arith_code_with_undefined_signed_overflow (tree_code code)
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if STMT has an operation that operates on a signed
|
||||
integer types involves undefined behavior on overflow and the
|
||||
operation can be expressed with unsigned arithmetic. */
|
||||
|
||||
bool
|
||||
gimple_with_undefined_signed_overflow (gimple *stmt)
|
||||
{
|
||||
if (!is_gimple_assign (stmt))
|
||||
return false;
|
||||
tree lhs = gimple_assign_lhs (stmt);
|
||||
if (!lhs)
|
||||
return false;
|
||||
tree lhs_type = TREE_TYPE (lhs);
|
||||
if (!INTEGRAL_TYPE_P (lhs_type)
|
||||
&& !POINTER_TYPE_P (lhs_type))
|
||||
return false;
|
||||
if (!TYPE_OVERFLOW_UNDEFINED (lhs_type))
|
||||
return false;
|
||||
if (!arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Rewrite STMT, an assignment with a signed integer or pointer arithmetic
|
||||
operation that can be transformed to unsigned arithmetic by converting
|
||||
its operand, carrying out the operation in the corresponding unsigned
|
||||
|
||||
@@ -59,7 +59,7 @@ extern tree gimple_get_virt_method_for_vtable (HOST_WIDE_INT, tree,
|
||||
extern tree gimple_fold_indirect_ref (tree);
|
||||
extern bool gimple_fold_builtin_sprintf (gimple_stmt_iterator *);
|
||||
extern bool gimple_fold_builtin_snprintf (gimple_stmt_iterator *);
|
||||
extern bool arith_code_with_undefined_signed_overflow (tree_code);
|
||||
extern bool gimple_with_undefined_signed_overflow (gimple *);
|
||||
extern void rewrite_to_defined_overflow (gimple_stmt_iterator *);
|
||||
extern gimple_seq rewrite_to_defined_overflow (gimple *);
|
||||
extern void replace_call_with_value (gimple_stmt_iterator *, tree);
|
||||
|
||||
@@ -1066,11 +1066,7 @@ if_convertible_gimple_assign_stmt_p (gimple *stmt,
|
||||
fprintf (dump_file, "tree could trap...\n");
|
||||
return false;
|
||||
}
|
||||
else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt)))
|
||||
else if (gimple_with_undefined_signed_overflow (stmt))
|
||||
/* We have to rewrite stmts with undefined overflow. */
|
||||
need_to_rewrite_undefined = true;
|
||||
|
||||
@@ -2830,7 +2826,6 @@ predicate_statements (loop_p loop)
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
|
||||
{
|
||||
gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
|
||||
tree lhs;
|
||||
if (!stmt)
|
||||
;
|
||||
else if (is_false_predicate (cond)
|
||||
@@ -2886,12 +2881,7 @@ predicate_statements (loop_p loop)
|
||||
|
||||
gsi_replace (&gsi, new_stmt, true);
|
||||
}
|
||||
else if (((lhs = gimple_assign_lhs (stmt)), true)
|
||||
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt)))
|
||||
else if (gimple_with_undefined_signed_overflow (stmt))
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
else if (gimple_vdef (stmt))
|
||||
{
|
||||
@@ -2946,7 +2936,7 @@ predicate_statements (loop_p loop)
|
||||
gsi_replace (&gsi, new_call, true);
|
||||
}
|
||||
|
||||
lhs = gimple_get_lhs (gsi_stmt (gsi));
|
||||
tree lhs = gimple_get_lhs (gsi_stmt (gsi));
|
||||
if (lhs && TREE_CODE (lhs) == SSA_NAME)
|
||||
ssa_names.add (lhs);
|
||||
gsi_next (&gsi);
|
||||
|
||||
@@ -3932,10 +3932,7 @@ final_value_replacement_loop (class loop *loop)
|
||||
gsi2 = gsi_start (stmts);
|
||||
while (!gsi_end_p (gsi2))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi2);
|
||||
if (is_gimple_assign (stmt)
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt)))
|
||||
if (gimple_with_undefined_signed_overflow (gsi_stmt (gsi2)))
|
||||
rewrite_to_defined_overflow (&gsi2);
|
||||
gsi_next (&gsi2);
|
||||
}
|
||||
|
||||
@@ -514,15 +514,9 @@ ifcombine_mark_ssa_name_walk (tree *t, int *, void *data_)
|
||||
static inline void
|
||||
ifcombine_rewrite_to_defined_overflow (gimple_stmt_iterator gsi)
|
||||
{
|
||||
gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi));
|
||||
if (!ass)
|
||||
if (!gimple_with_undefined_signed_overflow (gsi_stmt (gsi)))
|
||||
return;
|
||||
tree lhs = gimple_assign_lhs (ass);
|
||||
if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (ass)))
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1419,11 +1419,7 @@ move_computations_worker (basic_block bb)
|
||||
when the target loop header is executed and the stmt may
|
||||
invoke undefined integer or pointer overflow rewrite it to
|
||||
unsigned arithmetic. */
|
||||
if (is_gimple_assign (stmt)
|
||||
&& INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt)))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (gimple_assign_lhs (stmt)))
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt))
|
||||
if (gimple_with_undefined_signed_overflow (stmt)
|
||||
&& (!ALWAYS_EXECUTED_IN (bb)
|
||||
|| !(ALWAYS_EXECUTED_IN (bb) == level
|
||||
|| flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
|
||||
|
||||
@@ -663,10 +663,7 @@ split_loop (class loop *loop1)
|
||||
gsi = gsi_start (stmts2);
|
||||
while (!gsi_end_p (gsi))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
if (is_gimple_assign (stmt)
|
||||
&& arith_code_with_undefined_signed_overflow
|
||||
(gimple_assign_rhs_code (stmt)))
|
||||
if (gimple_with_undefined_signed_overflow (gsi_stmt (gsi)))
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
gsi_next (&gsi);
|
||||
}
|
||||
|
||||
@@ -2925,30 +2925,22 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange,
|
||||
!gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
gimple *stmt = gsi_stmt (gsi);
|
||||
if (is_gimple_assign (stmt))
|
||||
if (tree lhs = gimple_assign_lhs (stmt))
|
||||
if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|
||||
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs)))
|
||||
{
|
||||
enum tree_code code = gimple_assign_rhs_code (stmt);
|
||||
if (arith_code_with_undefined_signed_overflow (code))
|
||||
{
|
||||
gimple_stmt_iterator gsip = gsi;
|
||||
gimple_stmt_iterator gsin = gsi;
|
||||
gsi_prev (&gsip);
|
||||
gsi_next (&gsin);
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
unsigned uid = gimple_uid (stmt);
|
||||
if (gsi_end_p (gsip))
|
||||
gsip = gsi_after_labels (bb);
|
||||
else
|
||||
gsi_next (&gsip);
|
||||
for (; gsi_stmt (gsip) != gsi_stmt (gsin);
|
||||
gsi_next (&gsip))
|
||||
gimple_set_uid (gsi_stmt (gsip), uid);
|
||||
}
|
||||
}
|
||||
if (gimple_with_undefined_signed_overflow (stmt))
|
||||
{
|
||||
gimple_stmt_iterator gsip = gsi;
|
||||
gimple_stmt_iterator gsin = gsi;
|
||||
gsi_prev (&gsip);
|
||||
gsi_next (&gsin);
|
||||
rewrite_to_defined_overflow (&gsi);
|
||||
unsigned uid = gimple_uid (stmt);
|
||||
if (gsi_end_p (gsip))
|
||||
gsip = gsi_after_labels (bb);
|
||||
else
|
||||
gsi_next (&gsip);
|
||||
for (; gsi_stmt (gsip) != gsi_stmt (gsin);
|
||||
gsi_next (&gsip))
|
||||
gimple_set_uid (gsi_stmt (gsip), uid);
|
||||
}
|
||||
}
|
||||
|
||||
if (opcode == BIT_IOR_EXPR
|
||||
|
||||
Reference in New Issue
Block a user