A recent match patterns were added that introduce signed integer overflow where
there was none before. `cmp + (-cmp ^ x)` has no signed integer overflow when
x is INT_MIN when cmp is 0. This gets translated into cmp ? -x : x.
But this has now introduced an signed integer overflow for INT_MIN.
The fix is to use unsigned type for the negative.
Bootstrapped and tested on x86_64-linux-gnu.
Changes since v1:
* v2: Remove the abs patterns since a signed integer overflow would have
happened anyways.
PR tree-optimization/126418
gcc/ChangeLog:
* match.pd (`(A ^ -cmp) + cmp`): Cast to unsigned type
before taking the negative.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/pr126418-1.c: New test.
Signed-off-by: Andrea Pinski <[email protected]>
---
gcc/match.pd | 8 +++++++-
gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c | 11 +++++++++++
2 files changed, 18 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 5da1e372f10..945fcabf956 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4942,7 +4942,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (INTEGRAL_TYPE_P (type)
&& !TYPE_SATURATING (type)
&& (GIMPLE || !TREE_SIDE_EFFECTS (@0)))
- (cond (convert:boolean_type_node @1) (negate @0) @0)))
+ /* Do the negate in unsigned type always; otherwise
+ we would be introducing an overflow. */
+ (with { tree utype = unsigned_type_for (type); }
+ (cond
+ (convert:boolean_type_node @1)
+ (convert:type (negate (convert:utype @0)))
+ @0))))
/* Transform A & (B*cmp) into (A&B)*cmp. */
(simplify
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
new file mode 100644
index 00000000000..3714069b43f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr126418-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" } */
+
+int f_cmp_gt_commuted(int x, int y)
+{
+ int cmp = x > y;
+ return cmp + (-cmp ^ x);
+}
+
+/* { dg-final { scan-tree-dump-times "\\(unsigned int\\) " 1 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "\\(int\\) " 1 "forwprop1" } } */
--
2.43.0