From 44e7e4498c3cdc27e087ab80aa76dac41819702f Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 20 Oct 2023 14:08:46 +0200 Subject: 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. --- gcc/testsuite/gcc.dg/torture/pr110243.c | 22 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr111336.c | 25 +++++++++++++++++++++++++ gcc/tree-ssa-loop-ivopts.cc | 31 ++++++++++++++++++++++++++++--- 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr110243.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr111336.c (limited to 'gcc') 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); -- cgit v1.1