https://gcc.gnu.org/g:7b8104e346cf3949b0ca6eab93106ac860fb3306

commit r17-3988-g7b8104e346cf3949b0ca6eab93106ac860fb3306
Author: Kyrylo Tkachov <[email protected]>
Date:   Sat Sep 5 12:54:56 2026 +0200

    tree-ssa: Canonicalize arithmetic overflow IFN operands
    
    match_arith_overflow can build a commutative overflow internal function
    with noncanonical operands.  For a complement test, it puts the complemented
    operand first.  This can disagree with the canonical order of a related
    addition.
    
    The widening_mul dump before the change contains:
    
      _7 = .ADD_OVERFLOW (b_4(D), a_3(D));
      sum_5 = a_3(D) + b_4(D);
    
    Select the internal function before building the call.  Use
    tree_swap_operands_p to order the operands of addition and multiplication.
    The dump then contains:
    
      _7 = .ADD_OVERFLOW (a_3(D), b_4(D));
      sum_5 = a_3(D) + b_4(D);
    
    This also canonicalizes MUL_OVERFLOW operands.  SUB_OVERFLOW keeps its
    original order because it is not commutative.
    
    Bootstrapped and regression tested on aarch64-unknown-linux-gnu.
    
    gcc/ChangeLog:
    
            * tree-ssa-math-opts.cc (match_arith_overflow): Canonicalize the
            operands of commutative overflow internal functions.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/aarch64/add-overflow-canonical-1.c: New test.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>

Diff:
---
 .../gcc.target/aarch64/add-overflow-canonical-1.c          | 11 +++++++++++
 gcc/tree-ssa-math-opts.cc                                  | 14 +++++++++-----
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/gcc/testsuite/gcc.target/aarch64/add-overflow-canonical-1.c 
b/gcc/testsuite/gcc.target/aarch64/add-overflow-canonical-1.c
new file mode 100644
index 000000000000..5e11c51f3cf0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/add-overflow-canonical-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-widening_mul" } */
+
+unsigned
+f (unsigned a, unsigned b)
+{
+  unsigned sum = a + b;
+  return a <= ~b ? sum : ~0u;
+}
+
+/* { dg-final { scan-tree-dump {ADD_OVERFLOW \(a_[^,]*, b_} "widening_mul" } } 
*/
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index b371b5b7cff9..70ac17c9e2fa 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -4932,12 +4932,16 @@ match_arith_overflow (gimple_stmt_iterator *gsi, gimple 
*stmt,
            }
        }
     }
+  internal_fn ifn = (code == MULT_EXPR
+                    ? IFN_MUL_OVERFLOW
+                    : code != MINUS_EXPR
+                    ? IFN_ADD_OVERFLOW : IFN_SUB_OVERFLOW);
+  if (code != MINUS_EXPR
+      && tree_swap_operands_p (rhs1, rhs2))
+    std::swap (rhs1, rhs2);
+
   tree ctype = build_complex_type (type);
-  gcall *g = gimple_build_call_internal (code == MULT_EXPR
-                                        ? IFN_MUL_OVERFLOW
-                                        : code != MINUS_EXPR
-                                        ? IFN_ADD_OVERFLOW : IFN_SUB_OVERFLOW,
-                                        2, rhs1, rhs2);
+  gcall *g = gimple_build_call_internal (ifn, 2, rhs1, rhs2);
   tree ctmp = make_ssa_name (ctype);
   gimple_call_set_lhs (g, ctmp);
   gsi_insert_before (gsi, g, GSI_SAME_STMT);

Reply via email to