Message ID | ZbwfF+oAgCCq002P@tucnak |
---|---|
State | New |
Headers | show |
Series | tree-ssa-math-opts: Fix is_widening_mult_rhs_p - unbreak bootstrap [PR113705] | expand |
> Am 01.02.2024 um 23:46 schrieb Jakub Jelinek <jakub@redhat.com>: > > On Tue, Jan 30, 2024 at 07:33:10AM -0000, Roger Sayle wrote: > + wide_int bits = wide_int::from (tree_nonzero_bits (rhs), > + prec, > + TYPE_SIGN (TREE_TYPE (rhs))); > ... >> + if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR >> + && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST >> + && wi::to_wide (gimple_assign_rhs2 (stmt)) >> + == wi::mask (hprec, false, prec)) > > This change broke bootstrap on aarch64-linux. > The problem can be seen even on the reduced testcase. > > The IL on the unreduced testcase before widening_mul has: > # val_583 = PHI <val_26(13), val_164(40)> > ... > pretmp_266 = MEM[(const struct wide_int_storage *)&D.160657].len; > _264 = pretmp_266 & 65535; > ... > _176 = (sizetype) val_583; > _439 = (sizetype) _264; > _284 = _439 * 8; > _115 = _176 + _284; > where 583/266/264 have unsigned int type and 176/439/284/115 have sizetype. > widening_mul first turns that into: > # val_583 = PHI <val_26(13), val_164(40)> > ... > pretmp_266 = MEM[(const struct wide_int_storage *)&D.160657].len; > _264 = pretmp_266 & 65535; > ... > _176 = (sizetype) val_583; > _439 = (sizetype) _264; > _284 = _264 w* 8; > _115 = _176 + _284; > and then is_widening_mult_rhs_p is called, with type sizetype (64-bit), > rhs _264, hprec 32 and prec 64. Now tree_nonzero_bits (rhs) is > 65535, so bits is 64-bit wide_int 65535, stmt is BIT_AND_EXPR, > but we ICE on the > wi::to_wide (gimple_assign_rhs2 (stmt)) == wi::mask (hprec, false, prec) > comparison because wi::to_wide on gimple_assign_rhs2 (stmt) - unsigned int > 65535 gives 32-bit wide_int 65535, while wi::mask (hprec, false, prec) > gives 64-bit wide_int 0xffffffff and comparison between different precision > wide_ints is forbidden. > > The following patch fixes it the same way how bits is computed earlier, > by calling wide_int::from on the wi::to_wide (gimple_assign_rhs2 (stmt)), > so we compare 64-bit 65535 with 64-bit 0xffffffff. > > Bootstrapped/regtested on x86_64-linux and i686-linux plus tested on the > testcase using cross to aarch64-linux, ok for trunk? Ok Richard > 2024-02-01 Jakub Jelinek <jakub@redhat.com> > > PR middle-end/113705 > * tree-ssa-math-opts.cc (is_widening_mult_rhs_p): Use wide_int_from > around wi::to_wide in order to compare value in prec precision. > > * g++.dg/opt/pr113705.C: New test. > > --- gcc/tree-ssa-math-opts.cc.jj 2024-02-01 09:14:16.623549514 +0100 > +++ gcc/tree-ssa-math-opts.cc 2024-02-01 17:48:59.151771177 +0100 > @@ -2572,7 +2572,8 @@ is_widening_mult_rhs_p (tree type, tree > if (is_gimple_assign (stmt) > && gimple_assign_rhs_code (stmt) == BIT_AND_EXPR > && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST > - && wi::to_wide (gimple_assign_rhs2 (stmt)) > + && wide_int::from (wi::to_wide (gimple_assign_rhs2 (stmt)), > + prec, TYPE_SIGN (TREE_TYPE (rhs))) > == wi::mask (hprec, false, prec)) > *new_rhs_out = gimple_assign_rhs1 (stmt); > else > --- gcc/testsuite/g++.dg/opt/pr113705.C.jj 2024-02-01 19:02:29.181388575 +0100 > +++ gcc/testsuite/g++.dg/opt/pr113705.C 2024-02-01 19:03:03.211918152 +0100 > @@ -0,0 +1,68 @@ > +// PR middle-end/113705 > +// { dg-do compile { target c++17 } } > +// { dg-options "-O2 -w" } > + > +void foo (); > +template <typename T> struct A : T { long bar () const; }; > +int a; > + > +template <typename T> > +long > +A<T>::bar () const > +{ > + return this->baz ()[a]; > +} > + > +struct B { > + struct { long b[1]; long c; } u; > + unsigned d; > + int e; > + B (const B &); > + ~B (); > + const long *baz () const; > + unsigned qux () const; > +}; > + > +B::B (const B &) > +{ > + if (__builtin_expect (e, 0)) > + u.c = 0; > +} > + > +B::~B () > +{ > + if (__builtin_expect (e, 0)) > + foo (); > +} > + > +const long * > +B::baz () const > +{ > + return u.b; > +} > + > +unsigned > +B::qux () const > +{ > + return d; > +} > + > +struct C { A<B> corge () const; A<B> *f; }; > + > +A<B> > +C::corge () const > +{ > + return f[1]; > +} > + > +void > +test (C r, long *h, unsigned short *d) > +{ > + for (int j = 0; j < 8; ++j) > + { > + A g = r.corge (); > + *d = g.qux (); > + for (unsigned i = 0; i < *d; ++i) > + *h++ = g.bar (); > + } > +} > > > Jakub >
--- gcc/tree-ssa-math-opts.cc.jj 2024-02-01 09:14:16.623549514 +0100 +++ gcc/tree-ssa-math-opts.cc 2024-02-01 17:48:59.151771177 +0100 @@ -2572,7 +2572,8 @@ is_widening_mult_rhs_p (tree type, tree if (is_gimple_assign (stmt) && gimple_assign_rhs_code (stmt) == BIT_AND_EXPR && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST - && wi::to_wide (gimple_assign_rhs2 (stmt)) + && wide_int::from (wi::to_wide (gimple_assign_rhs2 (stmt)), + prec, TYPE_SIGN (TREE_TYPE (rhs))) == wi::mask (hprec, false, prec)) *new_rhs_out = gimple_assign_rhs1 (stmt); else --- gcc/testsuite/g++.dg/opt/pr113705.C.jj 2024-02-01 19:02:29.181388575 +0100 +++ gcc/testsuite/g++.dg/opt/pr113705.C 2024-02-01 19:03:03.211918152 +0100 @@ -0,0 +1,68 @@ +// PR middle-end/113705 +// { dg-do compile { target c++17 } } +// { dg-options "-O2 -w" } + +void foo (); +template <typename T> struct A : T { long bar () const; }; +int a; + +template <typename T> +long +A<T>::bar () const +{ + return this->baz ()[a]; +} + +struct B { + struct { long b[1]; long c; } u; + unsigned d; + int e; + B (const B &); + ~B (); + const long *baz () const; + unsigned qux () const; +}; + +B::B (const B &) +{ + if (__builtin_expect (e, 0)) + u.c = 0; +} + +B::~B () +{ + if (__builtin_expect (e, 0)) + foo (); +} + +const long * +B::baz () const +{ + return u.b; +} + +unsigned +B::qux () const +{ + return d; +} + +struct C { A<B> corge () const; A<B> *f; }; + +A<B> +C::corge () const +{ + return f[1]; +} + +void +test (C r, long *h, unsigned short *d) +{ + for (int j = 0; j < 8; ++j) + { + A g = r.corge (); + *d = g.qux (); + for (unsigned i = 0; i < *d; ++i) + *h++ = g.bar (); + } +}