On Wed, 27 Mar 2019, Richard Sandiford wrote: > Richard Biener <rguent...@suse.de> writes: > > Our beloved condition combining code to BIT_FIELD_REFs miscompiles > > the testcase because it relies on operand_equal_p to detect equal > > bases. For some reason that very same operand_equal_p is > > treating any dereference of a pointer based on the same pointer > > or decl the same - idependent on the actual type used for the > > access (in this case, two different sized structs). Weirdly > > it already checks alignment... > > > > The following patch makes operand_equal_p behave and more > > in line with what it does for MEM_REF handling. > > > > Bootstrap & regtest running on x86_64-unknown-linux-gnu. > > > > Richard. > > > > 2019-03-14 Richard Biener <rguent...@suse.de> > > > > PR middle-end/89698 > > * fold-const.c (operand_equal_p): For INDIRECT_REF check > > that the access types are similar. > > > > * g++.dg/torture/pr89698.C: New testcase. > > > > Index: gcc/fold-const.c > > =================================================================== > > --- gcc/fold-const.c (revision 269641) > > +++ gcc/fold-const.c (working copy) > > @@ -3220,10 +3220,16 @@ operand_equal_p (const_tree arg0, const_ > > switch (TREE_CODE (arg0)) > > { > > case INDIRECT_REF: > > - if (!(flags & OEP_ADDRESS_OF) > > - && (TYPE_ALIGN (TREE_TYPE (arg0)) > > - != TYPE_ALIGN (TREE_TYPE (arg1)))) > > - return 0; > > + if (!(flags & OEP_ADDRESS_OF)) > > + { > > + if (TYPE_ALIGN (TREE_TYPE (arg0)) > > + != TYPE_ALIGN (TREE_TYPE (arg1))) > > + return 0; > > + /* Verify that the access types are compatible. */ > > + if (TYPE_MAIN_VARIANT (TREE_TYPE (arg0)) > > + != TYPE_MAIN_VARIANT (TREE_TYPE (arg1))) > > + return 0; > > Question from the peanut gallery, sorry, but: why's TYPE_MAIN_VARIANT > rather than types_compatible_p the right check here? E.g. if the > dereferenced types are both pointers, but pointers to different types, > wouldn't they normally be equivalent in gimple?
But this is GENERIC where the above is the usual check for "same type". In GIMPLE you never see an INDIRECT_REF. Richard. > Thanks, > Richard > > > > + } > > flags &= ~OEP_ADDRESS_OF; > > return OP_SAME (0); > > > > Index: gcc/testsuite/g++.dg/torture/pr89698.C > > =================================================================== > > --- gcc/testsuite/g++.dg/torture/pr89698.C (nonexistent) > > +++ gcc/testsuite/g++.dg/torture/pr89698.C (working copy) > > @@ -0,0 +1,28 @@ > > +/* { dg-do run } */ > > + > > +extern "C" void abort (void); > > + > > +class A { > > + virtual void f(){}; > > +public: > > + int x; > > + A(int in): x(in) {}; > > +}; > > + > > +class B: public A { > > +public: > > + int y; > > + B(int in):A(in-1), y(in) {}; > > +}; > > + > > +int test(void) > > +{ > > + int res; > > + B b(2); > > + A* bp = &b; > > + void* vp = dynamic_cast<void*>(bp); > > + if (((A*)vp)->x == 1 && ((B*)vp)->y == 2) > > + return 1; > > + return 0; > > +} > > +int main() { if (test() != 1) abort (); return 0; } > -- Richard Biener <rguent...@suse.de> SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)