On Thu, 16 Jul 2026, Jakub Jelinek wrote:

> Hi!
> 
> We need to avoid overlap between the lhs and input operands of __mulbitint3
> and __divmodbitint4.  This is done in build_bitint_stmt_ssa_conflicts, when
> muldiv_p is set, we call use on all the SSA use operands (including operands
> of stmts on worklist) first and def on the lhs at the end, while for
> !muldiv_p, at least for stmts with a single lhs we call def first and then
> all the use calls.  For MULT_EXPR etc. we already handle it:
>                 case MULT_EXPR:
>                 case TRUNC_DIV_EXPR:
>                 case EXACT_DIV_EXPR:
>                 case TRUNC_MOD_EXPR:
>                   muldiv_p = true;
> Now, for the IFN_*_OVERFLOW, we handle it for bitint_big_endian only
> currently, on big endian there is a problem that if the sizes don't match
> exactly, even in order updates of the limbs can clobber stuff.
> But, for IFN_MUL_OVERFLOW and IFN_UBSAN_CHECK_MUL, we actually use
> __mulbitint3 libgcc call and that function really can't be called with
> overlapping destination and inputs, because it traverses the inputs multiple
> times while writing destination one by one (and it intentionally doesn't
> allocate memory for temporaries).
> 
> So, the following patch fixes it by making IFN_MUL_OVERFLOW and
> IFN_UBSAN_CHECK_MUL calls be always handled as muldiv_p.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and 14+?

OK.

Thanks,
Richard.

> 2026-07-16  Jakub Jelinek  <[email protected]>
> 
>       PR tree-optimization/126262
>       * gimple-lower-bitint.cc (build_bitint_stmt_ssa_conflicts): Treat
>       IFN_MUL_OVERFLOW and IFN_UBSAN_CHECK_MUL like IFN_BSWAP, regardless
>       of bitint_big_endian.
> 
>       * gcc.dg/torture/bitint-102.c: New test.
> 
> --- gcc/gimple-lower-bitint.cc.jj     2026-07-14 10:39:46.547982133 +0200
> +++ gcc/gimple-lower-bitint.cc        2026-07-15 17:51:01.922732017 +0200
> @@ -7028,8 +7028,6 @@ build_bitint_stmt_ssa_conflicts (gimple
>        case IFN_SUB_OVERFLOW:
>        case IFN_UBSAN_CHECK_ADD:
>        case IFN_UBSAN_CHECK_SUB:
> -      case IFN_MUL_OVERFLOW:
> -      case IFN_UBSAN_CHECK_MUL:
>       if (bitint_big_endian)
>         {
>           lhs = gimple_call_lhs (stmt);
> @@ -7037,6 +7035,8 @@ build_bitint_stmt_ssa_conflicts (gimple
>             muldiv_p = true;
>         }
>       break;
> +      case IFN_MUL_OVERFLOW:
> +      case IFN_UBSAN_CHECK_MUL:
>        case IFN_BSWAP:
>        case IFN_BITREVERSE:
>       lhs = gimple_call_lhs (stmt);
> --- gcc/testsuite/gcc.dg/torture/bitint-102.c.jj      2026-07-15 
> 18:43:06.967455017 +0200
> +++ gcc/testsuite/gcc.dg/torture/bitint-102.c 2026-07-15 18:42:51.156653874 
> +0200
> @@ -0,0 +1,33 @@
> +/* PR tree-optimization/126262 */
> +/* { dg-do run { target bitint } } */
> +/* { dg-options "-std=gnu23" } */
> +
> +#if __BITINT_MAXWIDTH__ >= 1024
> +typedef unsigned _BitInt (512) A;
> +typedef _BitInt (1024) B;
> +
> +[[gnu::noipa]] int
> +foo (signed char x, A y)
> +{
> +  B b = -(B) y;
> +  A c;
> +  if (__builtin_mul_overflow (1, b, &c))
> +    c = 42;
> +  B f;
> +  if (__builtin_mul_overflow (x, 9, &f))
> +    f = 42;
> +  int i;
> +  if (__builtin_mul_overflow (f, 1, &i))
> +    i = 42;
> +  return c + i;
> +}
> +#endif
> +
> +int
> +main ()
> +{
> +#if __BITINT_MAXWIDTH__ >= 1024
> +  if (foo (1, -2) != 51)
> +    __builtin_abort ();
> +#endif
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to