This backports the fix to the GCC 8 branch where we have a different way of determining availability.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2019-02-13 Richard Biener <rguent...@suse.de> Backport from mainline 2019-01-08 Richard Biener <rguent...@suse.de> PR tree-optimization/86554 * tree-ssa-sccvn.c (visit_nary_op): When value-numbering to expressions with different overflow behavior make sure there's an available expression on the path. * gcc.dg/torture/pr86554-1.c: New testcase. * gcc.dg/torture/pr86554-2.c: Likewise. Index: gcc/testsuite/gcc.dg/torture/pr86554-1.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr86554-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr86554-1.c (working copy) @@ -0,0 +1,35 @@ +/* { dg-do run } */ + +struct foo +{ + unsigned x; +}; +typedef struct foo foo; + +static inline int zot(foo *f) +{ + int ret; + + if (f->x > 0x7FFFFFFF) + ret = (int)(f->x - 0x7FFFFFFF); + else + ret = (int)f->x - 0x7FFFFFFF; + return ret; +} + +void __attribute__((noinline,noclone)) bar(foo *f) +{ + int ret = zot(f); + volatile int x = ret; + if (ret < 1) + __builtin_abort (); +} + +int main() +{ + foo f; + f.x = 0x800003f8; + + bar(&f); + return 0; +} Index: gcc/testsuite/gcc.dg/torture/pr86554-2.c =================================================================== --- gcc/testsuite/gcc.dg/torture/pr86554-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/torture/pr86554-2.c (working copy) @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +struct s { __INT64_TYPE__ e; }; + +static void f (struct s *ps) +{ + volatile __INT64_TYPE__ m = 9223372036854775807; + const char *str = "11E"; + int r; + __INT64_TYPE__ sum; + + ps->e = 0; + + for (;;) + { + if (*str++ != '1') + break; + ps->e ++; + } + + r = 1; + sum = m; + + if (sum >= 0 && ps->e >= 0) + { + __UINT64_TYPE__ uc; + uc = (__UINT64_TYPE__) sum + (__UINT64_TYPE__) ps->e; + if (uc > 9223372036854775807) + r = 2; + else + sum = 17; + } + else + sum = sum + ps->e; + + if (sum != 9223372036854775807) + __builtin_abort (); + if (r != 2) + __builtin_abort (); + ps->e = sum; +} + +int main (void) +{ + struct s s; + f (&s); + return 0; +} Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 268838) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -3619,7 +3619,17 @@ visit_nary_op (tree lhs, gassign *stmt) ops[0] = vn_nary_op_lookup_pieces (2, gimple_assign_rhs_code (def), type, ops, NULL); /* We have wider operation available. */ - if (ops[0]) + if (ops[0] + /* If the leader is a wrapping operation we can + insert it for code hoisting w/o introducing + undefined overflow. If it is not it has to + be available. See PR86554. */ + && (TYPE_OVERFLOW_WRAPS (TREE_TYPE (ops[0])) + || TREE_CODE (ops[0]) != SSA_NAME + || SSA_NAME_IS_DEFAULT_DEF (ops[0]) + || dominated_by_p_w_unex + (gimple_bb (stmt), + gimple_bb (SSA_NAME_DEF_STMT (ops[0]))))) { unsigned lhs_prec = TYPE_PRECISION (type); unsigned rhs_prec = TYPE_PRECISION (TREE_TYPE (rhs1));