There are a couple of things wrong with this pattern which I missed during the review. First each nop_convert should be nop_convert1 or nop_convert2. Second is we need to the minus in the same type as the minus was originally so we don't introduce extra undefined behavior (signed integer overflow). And we need a convert into the new type too.
pr117363-1.c tests not introducing extra undefined behavior. pr117363-2.c tests the casting to the correct final type, ldist introduces the cond_expr here. Bootstraped and tested on x86_64-linux-gnu. PR tree-optimization/117363 gcc/ChangeLog: * match.pd (`a != 0 ? a - 1 : 0`): Fix type handling and nop_convert handling. gcc/testsuite/ChangeLog: * gcc.dg/torture/pr117363-1.c: New test. * gcc.dg/torture/pr117363-2.c: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/match.pd | 5 +-- gcc/testsuite/gcc.dg/torture/pr117363-1.c | 41 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/torture/pr117363-2.c | 12 +++++++ 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr117363-1.c create mode 100644 gcc/testsuite/gcc.dg/torture/pr117363-2.c diff --git a/gcc/match.pd b/gcc/match.pd index c851ac56e37..9107e6a95ca 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3396,10 +3396,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) simplify (X != 0 ? X + ~0 : 0) to (X - X != 0). */ (simplify (cond (ne@1 @0 integer_zerop) - (nop_convert? (plus (nop_convert? @0) integer_all_onesp)) + (nop_convert1? (plus (nop_convert2?@2 @0) integer_all_onesp)) integer_zerop) (if (INTEGRAL_TYPE_P (type)) - (minus @0 (convert @1)))) + (with { tree itype = TREE_TYPE (@2); } + (convert (minus @2 (convert:itype @1)))))) /* Signed saturation sub, case 1: T minus = (T)((UT)X - (UT)Y); diff --git a/gcc/testsuite/gcc.dg/torture/pr117363-1.c b/gcc/testsuite/gcc.dg/torture/pr117363-1.c new file mode 100644 index 00000000000..b8b5bea76f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr117363-1.c @@ -0,0 +1,41 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fgimple" } */ + +/* PR tree-optimization/117363 */ + +/* a != 0 ? (signed)(((unsigned)a) - 1) : 0 + Should not be transformed into doing the + plus in a signed type which could cause an overflow.` */ + +__attribute__((noinline)) +signed __GIMPLE () +test2 (int n) +{ + unsigned t; + _Bool _4; + if (n_1(D) > 0) goto unreachable; + else goto normal; +normal: + t_2 = (unsigned)n_1(D); + t_3 = t_2 - 1u; + n_5 = (signed) t_3; + _4 = n_1(D) != 0; + n_6 = _4 ? n_5 : 0; + if (n_6 > 0) goto return1; + else goto trap; + +return1: + return n_6; + +unreachable: + __builtin_unreachable(); + +trap: + __builtin_trap (); +} + +int main() +{ + unsigned t = -__INT_MAX__ - 1; + test2(t); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr117363-2.c b/gcc/testsuite/gcc.dg/torture/pr117363-2.c new file mode 100644 index 00000000000..f608380e62f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr117363-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ + +/* PR tree-optimization/117363 */ +/* ldist produces `s != 0 ? s - 1 : 0` (with casts) and that + the match pattern which messed up the converts. */ + +void f(int *array, long t) { + if (!t) return; + unsigned long s = ~t; + for (long i = 0; i < s; i++) + array[i] = 0; +} -- 2.43.0