Message ID | ZcpZkb/MOU8rzXAH@tucnak |
---|---|
State | New |
Headers | show |
Series | lower-bitint: Fix handle_cast when used e.g. in comparisons of precisions multiple of limb_prec [PR113849] | expand |
> Am 12.02.2024 um 18:47 schrieb Jakub Jelinek <jakub@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 <jakub@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 >
--- 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; +}