From: Kyrylo Tkachov <[email protected]>
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
first_commutative_argument and tree_swap_operands_p to order its operands.
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 tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
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]>
---
.../gcc.target/aarch64/add-overflow-canonical-1.c | 11 +++++++++++
gcc/tree-ssa-math-opts.cc | 14 +++++++++-----
2 files changed, 20 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/add-overflow-canonical-1.c
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 00000000000..5e11c51f3cf
--- /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 b371b5b7cff..e5d4575eed2 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 (first_commutative_argument (ifn) == 0
+ && 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);
--
2.50.1 (Apple Git-155)