aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2023-10-20 14:08:46 +0200
committerRichard Biener <rguenther@suse.de>2023-10-20 15:15:25 +0200
commit44e7e4498c3cdc27e087ab80aa76dac41819702f (patch)
tree2be66de4baf22f4ae5d32daf147f5ee9a1e771e4 /gcc
parentd70575f542f575133eb4c49eda89ab61eedf83b8 (diff)
downloadgcc-44e7e4498c3cdc27e087ab80aa76dac41819702f.zip
gcc-44e7e4498c3cdc27e087ab80aa76dac41819702f.tar.gz
gcc-44e7e4498c3cdc27e087ab80aa76dac41819702f.tar.bz2
tree-optimization/110243 - IVOPTs introducing undefined overflow
The following addresses IVOPTs rewriting expressions in its strip_offset without caring for definedness of overflow. Rather than the earlier attempt of just using the proper split_constant_offset from data-ref analysis the following adjusts IVOPTs helper trying to minimize changes from this fix, possibly easing backports. PR tree-optimization/110243 PR tree-optimization/111336 * tree-ssa-loop-ivopts.cc (strip_offset_1): Rewrite operations with undefined behavior on overflow to unsigned arithmetic. * gcc.dg/torture/pr110243.c: New testcase. * gcc.dg/torture/pr111336.c: Likewise.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr110243.c22
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr111336.c25
-rw-r--r--gcc/tree-ssa-loop-ivopts.cc31
3 files changed, 75 insertions, 3 deletions
diff --git a/gcc/testsuite/gcc.dg/torture/pr110243.c b/gcc/testsuite/gcc.dg/torture/pr110243.c
new file mode 100644
index 0000000..07dffd9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr110243.c
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
+
+#define X 1100000000
+unsigned char a;
+long b = X;
+int c[9][1];
+unsigned d;
+static long *e = &b, *f = &b;
+int g() {
+ if (a && a <= '9')
+ return '0';
+ if (a)
+ return 10;
+ return -1;
+}
+int main() {
+ d = 0;
+ for (; (int)*f -(X-1) + d < 9; d++)
+ c[g() + (int)*f + ((int)*e - X) -(X-1) + d]
+ [0] = 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr111336.c b/gcc/testsuite/gcc.dg/torture/pr111336.c
new file mode 100644
index 0000000..a2fa122
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr111336.c
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-require-effective-target lp64 } */
+
+extern void abort (void);
+int a, b;
+long c = 3521733542;
+int d[2];
+int e(int f, int g) {
+ if (f == 0)
+ return 0;
+ if (f > 200)
+ return 0;
+ if (g)
+ return 5 * f;
+ return 0;
+}
+int main()
+{
+ int h = 0;
+ for (; e((int)c + 773233762, c + 60) + 773163185 + h < 2; h++)
+ d[h] = b;
+ if (a != 0)
+ abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-loop-ivopts.cc b/gcc/tree-ssa-loop-ivopts.cc
index 2c1f084..98e5b30 100644
--- a/gcc/tree-ssa-loop-ivopts.cc
+++ b/gcc/tree-ssa-loop-ivopts.cc
@@ -2829,12 +2829,29 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
else if (integer_zerop (op0))
{
if (code == MINUS_EXPR)
- expr = fold_build1 (NEGATE_EXPR, type, op1);
+ {
+ if (TYPE_OVERFLOW_UNDEFINED (type))
+ {
+ type = unsigned_type_for (type);
+ op1 = fold_convert (type, op1);
+ }
+ expr = fold_build1 (NEGATE_EXPR, type, op1);
+ }
else
expr = op1;
}
else
- expr = fold_build2 (code, type, op0, op1);
+ {
+ if (TYPE_OVERFLOW_UNDEFINED (type))
+ {
+ type = unsigned_type_for (type);
+ if (code == POINTER_PLUS_EXPR)
+ code = PLUS_EXPR;
+ op0 = fold_convert (type, op0);
+ op1 = fold_convert (type, op1);
+ }
+ expr = fold_build2 (code, type, op0, op1);
+ }
return fold_convert (orig_type, expr);
@@ -2852,7 +2869,15 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
if (integer_zerop (op0))
expr = op0;
else
- expr = fold_build2 (MULT_EXPR, type, op0, op1);
+ {
+ if (TYPE_OVERFLOW_UNDEFINED (type))
+ {
+ type = unsigned_type_for (type);
+ op0 = fold_convert (type, op0);
+ op1 = fold_convert (type, op1);
+ }
+ expr = fold_build2 (MULT_EXPR, type, op0, op1);
+ }
return fold_convert (orig_type, expr);