On Mon, May 5, 2025 at 3:42 AM Andrew Pinski <[email protected]> wrote:
>
> 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 <[email protected]>
> ---
> gcc/gimple-fold.cc | 26 ++++++++++++++++++++++-
> gcc/gimple-fold.h | 2 +-
> gcc/tree-if-conv.cc | 16 +++------------
> gcc/tree-scalar-evolution.cc | 5 +----
> gcc/tree-ssa-ifcombine.cc | 10 ++-------
> gcc/tree-ssa-loop-im.cc | 6 +-----
> gcc/tree-ssa-loop-split.cc | 5 +----
> gcc/tree-ssa-reassoc.cc | 40 +++++++++++++++---------------------
> 8 files changed, 50 insertions(+), 60 deletions(-)
>
> diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
> index 94d5a1ebbd7..c060ef81a42 100644
> --- a/gcc/gimple-fold.cc
> +++ b/gcc/gimple-fold.cc
> @@ -10569,7 +10569,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)
> @@ -10586,6 +10586,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))
Using
gassign *ass = dyn_cast <gassign *> (stmt);
if (!ass)
return false;
and using the gassing below makes the followon tests
cheaper (and eases future wiping off 'gimple *' overloads).
OK with that change.
Richard.
> + 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
> diff --git a/gcc/gimple-fold.h b/gcc/gimple-fold.h
> index 2790d0ffc65..5fcfdcda81b 100644
> --- a/gcc/gimple-fold.h
> +++ b/gcc/gimple-fold.h
> @@ -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);
> diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc
> index 5b63bf67fe0..fe8aee057b3 100644
> --- a/gcc/tree-if-conv.cc
> +++ b/gcc/tree-if-conv.cc
> @@ -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);
> diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
> index 4ca08751a0d..9d64d3a8721 100644
> --- a/gcc/tree-scalar-evolution.cc
> +++ b/gcc/tree-scalar-evolution.cc
> @@ -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);
> }
> diff --git a/gcc/tree-ssa-ifcombine.cc b/gcc/tree-ssa-ifcombine.cc
> index f791994e3b9..19990d67202 100644
> --- a/gcc/tree-ssa-ifcombine.cc
> +++ b/gcc/tree-ssa-ifcombine.cc
> @@ -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);
> }
>
>
> diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
> index 444ee31242f..b395ef6f054 100644
> --- a/gcc/tree-ssa-loop-im.cc
> +++ b/gcc/tree-ssa-loop-im.cc
> @@ -1412,11 +1412,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))))
> diff --git a/gcc/tree-ssa-loop-split.cc b/gcc/tree-ssa-loop-split.cc
> index 5f78c0be207..80f488a4f9a 100644
> --- a/gcc/tree-ssa-loop-split.cc
> +++ b/gcc/tree-ssa-loop-split.cc
> @@ -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);
> }
> diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
> index 4017eea3413..13bb85c4b71 100644
> --- a/gcc/tree-ssa-reassoc.cc
> +++ b/gcc/tree-ssa-reassoc.cc
> @@ -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
> --
> 2.34.1
>