> Am 12.02.2024 um 18:47 schrieb Jakub Jelinek <ja...@redhat.com>:
>
> Hi!
>
> handle_cast handles the simple way all narrowing large/huge bitint to
> large/huge bitint conversions and also such widening conversions if we can
> assume that the most significant limb is processed using constant index
> and both lhs and rhs have same number of limbs.
> But, the condition whether we can rely on the most significant limb
> being processed using constant index is incorrect.
> For m_upwards_2limb it was correct (m_upwards_2limb then is the number
> of limbs handled by the loop, so if lhs_type has larger precision than
> that, it is handled with constant index), similarly if m_var_msb is set
> (on left shifts), it is never handled with constant idx. But in other
> cases, like right shifts or non-equality comparisons, or bitquery operations
> which operate from most significant to least significant limb, all those
> can handle even the most significant limb in a loop when lhs_type has
> precision which is a multiple of limb_prec.
>
> So, the following patch punts on the optimization in that case and goes for
> the conditionals in the loop for that case.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok
Richard
> 2024-02-12 Jakub Jelinek <ja...@redhat.com>
>
> PR tree-optimization/113849
> * gimple-lower-bitint.cc (bitint_large_huge::handle_cast): Don't use
> fast path for widening casts where !m_upwards_2limb and lhs_type
> has precision which is a multiple of limb_prec.
>
> * gcc.dg/torture/bitint-58.c: New test.
>
> --- gcc/gimple-lower-bitint.cc.jj 2024-02-10 12:52:10.015925212 +0100
> +++ gcc/gimple-lower-bitint.cc 2024-02-12 14:51:58.717472624 +0100
> @@ -1267,13 +1267,17 @@ bitint_large_huge::handle_cast (tree lhs
> the most significant limb is handled in straight
> line code. If m_var_msb (on left shifts) or
> if m_upwards_2limb * limb_prec is equal to
> - lhs precision that is not the case. */
> + lhs precision or if not m_upwards_2limb and lhs_type
> + has precision which is multiple of limb_prec that is
> + not the case. */
> || (!m_var_msb
> && (CEIL (TYPE_PRECISION (lhs_type), limb_prec)
> == CEIL (TYPE_PRECISION (rhs_type), limb_prec))
> - && (!m_upwards_2limb
> - || (m_upwards_2limb * limb_prec
> - < TYPE_PRECISION (lhs_type)))))
> + && ((!m_upwards_2limb
> + && (TYPE_PRECISION (lhs_type) % limb_prec != 0))
> + || (m_upwards_2limb
> + && (m_upwards_2limb * limb_prec
> + < TYPE_PRECISION (lhs_type))))))
> {
> rhs1 = handle_operand (rhs1, idx);
> if (tree_fits_uhwi_p (idx))
> --- gcc/testsuite/gcc.dg/torture/bitint-58.c.jj 2024-02-12
> 14:58:42.105944347 +0100
> +++ gcc/testsuite/gcc.dg/torture/bitint-58.c 2024-02-12 14:44:33.280575269
> +0100
> @@ -0,0 +1,25 @@
> +/* PR tree-optimization/113849 */
> +/* { dg-do run { target bitint } } */
> +/* { dg-options "-std=c23 -pedantic-errors" } */
> +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
> +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
> +
> +signed char c;
> +unsigned _BitInt(512) b;
> +
> +__attribute__((noipa)) void
> +foo (unsigned _BitInt(511) a, int *x)
> +{
> + int z = (a << 510) <= b;
> + *x = z + c;
> +}
> +
> +int
> +main ()
> +{
> + int x;
> + foo (2, &x);
> + if (x != 1)
> + __builtin_abort ();
> + return 0;
> +}
>
> Jakub
>