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 <[email protected]>
>
> 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 <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)