On Wed, 18 Oct 2023, Jakub Jelinek wrote: > Hi! > > GCC ICEs on the first testcase. Successful match_uaddc_usubc ends up with > some dead stmts which DCE will remove (hopefully) later all. > The ICE is because one of the dead stmts refers to a freed SSA_NAME. > The code already gsi_removes a couple of stmts in the > /* Remove some statements which can't be kept in the IL because they > use SSA_NAME whose setter is going to be removed too. */ > section for the same reason (the reason for the freed SSA_NAMEs is that > we don't really have a replacement for those cases - all we have after > a match is combined overflow from the addition/subtraction of 2 operands + a > [0, 1] carry in, but not the individual overflows from the former 2 > additions), but for the last (most significant) limb case, where we try > to match x = op1 + op2 + carry1 + carry2; or > x = op1 - op2 - carry1 - carry2; we just gsi_replace the final stmt, but > left around the 2 temporary stmts as dead; if we were unlucky enough that > those referenced the carry flag that went away, it ICEs. > > So, the following patch remembers those temporary statements (rather than > trying to rediscover them more expensively) and removes them before the > final one is replaced. > > While working on it, I've noticed we didn't support all the reassociated > possibilities of writing the addition of 4 operands or subtracting 3 > operands from one, we supported e.g. > x = ((op1 + op2) + op3) + op4; > x = op1 + ((op2 + op3) + op4); > but not > x = (op1 + (op2 + op3)) + op4; > x = op1 + (op2 + (op3 + op4)); > Fixed by the change to inspect also rhs[2] when rhs[1] didn't yield what > we were searching for (if non-NULL) - rhs[0] is inspected in the first > loop and has different handling for the MINUS_EXPR case. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Richard. > 2023-10-18 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/111845 > * tree-ssa-math-opts.cc (match_uaddc_usubc): Remember temporary > statements for the 4 operand addition or subtraction of 3 operands > from 1 operand cases and remove them when successful. Look for > nested additions even from rhs[2], not just rhs[1]. > > * gcc.dg/pr111845.c: New test. > * gcc.target/i386/pr111845.c: New test. > > --- gcc/tree-ssa-math-opts.cc.jj 2023-09-18 10:37:56.180963000 +0200 > +++ gcc/tree-ssa-math-opts.cc 2023-10-17 14:46:39.430139602 +0200 > @@ -4581,6 +4581,7 @@ match_uaddc_usubc (gimple_stmt_iterator > if (!INTEGRAL_TYPE_P (type) || !TYPE_UNSIGNED (type)) > return false; > > + auto_vec<gimple *, 2> temp_stmts; > if (code != BIT_IOR_EXPR && code != BIT_XOR_EXPR) > { > /* If overflow flag is ignored on the MSB limb, we can end up with > @@ -4615,26 +4616,29 @@ match_uaddc_usubc (gimple_stmt_iterator > rhs[0] = gimple_assign_rhs1 (g); > tree &r = rhs[2] ? rhs[3] : rhs[2]; > r = r2; > + temp_stmts.quick_push (g); > } > else > break; > } > - while (TREE_CODE (rhs[1]) == SSA_NAME && !rhs[3]) > - { > - gimple *g = SSA_NAME_DEF_STMT (rhs[1]); > - if (has_single_use (rhs[1]) > - && is_gimple_assign (g) > - && gimple_assign_rhs_code (g) == PLUS_EXPR) > - { > - rhs[1] = gimple_assign_rhs1 (g); > - if (rhs[2]) > - rhs[3] = gimple_assign_rhs2 (g); > - else > - rhs[2] = gimple_assign_rhs2 (g); > - } > - else > - break; > - } > + for (int i = 1; i <= 2; ++i) > + while (rhs[i] && TREE_CODE (rhs[i]) == SSA_NAME && !rhs[3]) > + { > + gimple *g = SSA_NAME_DEF_STMT (rhs[i]); > + if (has_single_use (rhs[i]) > + && is_gimple_assign (g) > + && gimple_assign_rhs_code (g) == PLUS_EXPR) > + { > + rhs[i] = gimple_assign_rhs1 (g); > + if (rhs[2]) > + rhs[3] = gimple_assign_rhs2 (g); > + else > + rhs[2] = gimple_assign_rhs2 (g); > + temp_stmts.quick_push (g); > + } > + else > + break; > + } > /* If there are just 3 addends or one minuend and two subtrahends, > check for UADDC or USUBC being pattern recognized earlier. > Say r = op1 + op2 + ovf1 + ovf2; where the (ovf1 + ovf2) part > @@ -5039,7 +5043,17 @@ match_uaddc_usubc (gimple_stmt_iterator > g = gimple_build_assign (ilhs, IMAGPART_EXPR, > build1 (IMAGPART_EXPR, TREE_TYPE (ilhs), nlhs)); > if (rhs[2]) > - gsi_insert_before (gsi, g, GSI_SAME_STMT); > + { > + gsi_insert_before (gsi, g, GSI_SAME_STMT); > + /* Remove some further statements which can't be kept in the IL because > + they can use SSA_NAMEs whose setter is going to be removed too. */ > + while (temp_stmts.length ()) > + { > + g = temp_stmts.pop (); > + gsi2 = gsi_for_stmt (g); > + gsi_remove (&gsi2, true); > + } > + } > else > gsi_replace (gsi, g, true); > /* Remove some statements which can't be kept in the IL because they > --- gcc/testsuite/gcc.dg/pr111845.c.jj 2023-10-17 16:08:48.561492321 > +0200 > +++ gcc/testsuite/gcc.dg/pr111845.c 2023-10-17 15:04:21.199150290 +0200 > @@ -0,0 +1,16 @@ > +/* PR tree-optimization/111845 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 --param tree-reassoc-width=2" } */ > + > +int a, b; > +unsigned int c, d, e; > + > +void > +foo (int x) > +{ > + b += d; > + c += b < d; > + b += e = a < x; > + c += b; > + c += b < e; > +} > --- gcc/testsuite/gcc.target/i386/pr111845.c.jj 2023-10-17 > 16:11:44.233010594 +0200 > +++ gcc/testsuite/gcc.target/i386/pr111845.c 2023-10-17 16:11:27.944240706 > +0200 > @@ -0,0 +1,47 @@ > +/* PR tree-optimization/111845 */ > +/* { dg-do compile } */ > +/* { dg-options "-O2 -g -masm=att" } */ > +/* { dg-final { scan-assembler-times "\tadcq\t" 8 { target lp64 } } } */ > +/* { dg-final { scan-assembler-times "\tadcl\t" 8 { target ia32 } } } */ > + > +unsigned long l, m; > + > +__attribute__((noipa)) void > +foo (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int > a, int b) > +{ > + unsigned long c, d; > + unsigned long e = __builtin_add_overflow (x, y, &c); > + unsigned long f = __builtin_add_overflow (c, a < b, &d); > + m = ((h + i) + e) + f; > + l = d; > +} > + > +__attribute__((noipa)) void > +bar (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int > a, int b) > +{ > + unsigned long c, d; > + unsigned long e = __builtin_add_overflow (x, y, &c); > + unsigned long f = __builtin_add_overflow (c, a < b, &d); > + m = (h + (i + e)) + f; > + l = d; > +} > + > +__attribute__((noipa)) void > +baz (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int > a, int b) > +{ > + unsigned long c, d; > + unsigned long e = __builtin_add_overflow (x, y, &c); > + unsigned long f = __builtin_add_overflow (c, a < b, &d); > + m = h + (i + (e + f)); > + l = d; > +} > + > +__attribute__((noipa)) void > +qux (unsigned long x, unsigned long y, unsigned long h, unsigned long i, int > a, int b) > +{ > + unsigned long c, d; > + unsigned long e = __builtin_add_overflow (x, y, &c); > + unsigned long f = __builtin_add_overflow (c, a < b, &d); > + m = h + ((i + e) + f); > + l = d; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)