On Wed, 16 Apr 2025, Jakub Jelinek wrote: > Hi! > > The following testcase is miscompiled, because we emit a CLOBBER in a place > where it shouldn't be emitted. > Before lowering we have: > b_5 = 0; > b.0_6 = b_5; > b.1_1 = (unsigned _BitInt(129)) b.0_6; > ... > <retval> = b_5; > The bitint coalescing assigns the same partition/underlying variable > for both b_5 and b.0_6 (possible because there is a copy assignment) > and of course a different one for b.1_1 (and other SSA_NAMEs in between). > This is -O0 so stmts aren't DCEd and aren't propagated that much etc. > It is -O0 so we also don't try to optimize and omit some names from m_names > and handle multiple stmts at once, so the expansion emits essentially > bitint.4 = {}; > bitint.4 = bitint.4; > bitint.2 = cast of bitint.4; > bitint.4 = CLOBBER; > ... > <retval> = bitint.4; > and the CLOBBER is the problem because bitint.4 is still live afterwards. > We emit the clobbers to improve code generation, but do it only for > (initially) has_single_use SSA_NAMEs (remembered in m_single_use_names) > being used, if they don't have the same partition on the lhs and a few > other conditions. > The problem above is that b.0_6 which is used in the cast has_single_use > and so was in m_single_use_names bitmask and the lhs in that case is > bitint.2, so a different partition. But there is gimple_assign_copy_p > with SSA_NAME rhs1 and the partitioning special cases those and while > b.0_6 is single use, b_5 has multiple uses. I believe this ought to be > a problem solely in the case of such copy stmts and its special case > by the partitioning, if instead of b.0_6 = b_5; there would be > b.0_6 = b_5 + 1; or whatever other stmts that performs or may perform > changes on the value, partitioning couldn't assign the same partition > to b.0_6 and b_5 if b_5 is used later, it couldn't have two different > (or potentially different) values in the same bitint.N var. With > copy that is possible though. > > So the following patch fixes it by being more careful when we set > m_single_use_names, don't set it if it is a has_single_use SSA_NAME > but SSA_NAME_DEF_STMT of it is a copy stmt with SSA_NAME rhs1 and that > rhs1 doesn't have single use, or has_single_use but SSA_NAME_DEF_STMT of it > is a copy stmt etc. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > Just to make sure it doesn't change code generation too much, I've gathered > statistics how many times > if (m_first > && m_single_use_names > && m_vars[p] != m_lhs > && m_after_stmt > && bitmap_bit_p (m_single_use_names, SSA_NAME_VERSION (op))) > { > tree clobber = build_clobber (TREE_TYPE (m_vars[p]), > CLOBBER_STORAGE_END); > g = gimple_build_assign (m_vars[p], clobber); > gimple_stmt_iterator gsi = gsi_for_stmt (m_after_stmt); > gsi_insert_after (&gsi, g, GSI_SAME_STMT); > } > emits a clobber on > make check-gcc GCC_TEST_RUN_EXPENSIVE=1 > RUNTESTFLAGS="--target_board=unix\{-m64,-m32\} GCC_TEST_RUN_EXPENSIVE=1 > dg.exp='*bitint* pr112673.c builtin-stdc-bit-*.c pr112566-2.c pr112511.c > pr116588.c pr116003.c pr113693.c pr113602.c flex-array-counted-by-7.c' > dg-torture.exp='*bitint* pr116480-2.c pr114312.c pr114121.c' dfp.exp=*bitint* > i386.exp='pr118017.c pr117946.c apx-ndd-x32-2a.c' > vect.exp='vect-early-break_99-pr113287.c' tree-ssa.exp=pr113735.c" > and before this patch it was 41010 clobbers and after it is 40968, > so difference is 42 clobbers, 0.1% fewer.
OK. Richard. > 2025-04-16 Jakub Jelinek <ja...@redhat.com> > > PR middle-end/119808 > * gimple-lower-bitint.cc (gimple_lower_bitint): Don't set > m_single_use_names bits for SSA_NAMEs which have single use but > their SSA_NAME_DEF_STMT is a copy from another SSA_NAME which doesn't > have a single use, or single use which is such a copy etc. > > * gcc.dg/bitint-121.c: New test. > > --- gcc/gimple-lower-bitint.cc.jj 2025-04-12 13:13:47.543814860 +0200 > +++ gcc/gimple-lower-bitint.cc 2025-04-15 21:00:32.779348865 +0200 > @@ -6647,10 +6647,28 @@ gimple_lower_bitint (void) > bitmap_set_bit (large_huge.m_names, SSA_NAME_VERSION (s)); > if (has_single_use (s)) > { > - if (!large_huge.m_single_use_names) > - large_huge.m_single_use_names = BITMAP_ALLOC (NULL); > - bitmap_set_bit (large_huge.m_single_use_names, > - SSA_NAME_VERSION (s)); > + tree s2 = s; > + /* The coalescing hook special cases SSA_NAME copies. > + Make sure not to mark in m_single_use_names single > + use SSA_NAMEs copied from non-single use SSA_NAMEs. */ > + while (gimple_assign_copy_p (SSA_NAME_DEF_STMT (s2))) > + { > + s2 = gimple_assign_rhs1 (SSA_NAME_DEF_STMT (s2)); > + if (TREE_CODE (s2) != SSA_NAME) > + break; > + if (!has_single_use (s2)) > + { > + s2 = NULL_TREE; > + break; > + } > + } > + if (s2) > + { > + if (!large_huge.m_single_use_names) > + large_huge.m_single_use_names = BITMAP_ALLOC (NULL); > + bitmap_set_bit (large_huge.m_single_use_names, > + SSA_NAME_VERSION (s)); > + } > } > if (SSA_NAME_VAR (s) > && ((TREE_CODE (SSA_NAME_VAR (s)) == PARM_DECL > --- gcc/testsuite/gcc.dg/bitint-121.c.jj 2025-04-15 21:03:30.314955543 > +0200 > +++ gcc/testsuite/gcc.dg/bitint-121.c 2025-04-15 21:03:12.704192945 +0200 > @@ -0,0 +1,24 @@ > +/* PR middle-end/119808 */ > +/* { dg-do run { target { bitint && fstack_protector } } } */ > +/* { dg-options "-O0 -ftree-coalesce-vars -fstack-protector-strong" } */ > + > +#if __BITINT_MAXWIDTH__ >= 129 > +_BitInt(129) > +foo () > +{ > + _BitInt(129) b = 0; > + _BitInt(8) a > + =__builtin_stdc_rotate_right (0x8c82111b5d2d37c57e9ada7213ed95a49uwb, b); > + return b; > +} > +#endif > + > +int > +main () > +{ > +#if __BITINT_MAXWIDTH__ >= 129 > + _BitInt(129) x = foo (); > + if (x) > + __builtin_abort (); > +#endif > +} > > 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)