On Wed, Mar 13, 2019 at 12:35 PM Richard Biener <rguent...@suse.de> wrote: > > > This fixes a missed optimization in the testcase in PR89698 > where we fail to fold an access to a virtual table slot because > it is (int (*) ()) 0 - yes, an unfolded INTEGER_CST. Callers > are not happy with this so the following makes sure to > return a properly folded constant via canonicalize_constructor_val. > > This avoids the dynamic_cast<> runtime overhead in the testcase. > > Bootstrap & regtest running on x86_64-unknown-linux-gnu, queued for GCC > 10.
Applied as r270833. Richard. > Richard. > > 2019-03-14 Richard Biener <rguent...@suse.de> > > PR tree-optimization/89698 > * gimple-fold.c (canonicalize_constructor_val): Early out > for constants, handle unfolded INTEGER_CSTs as they appear in > C++ virtual table ctors. > > * g++.dg/tree-ssa/pr89698.C: New testcase. > > Index: gcc/gimple-fold.c > =================================================================== > --- gcc/gimple-fold.c (revision 269641) > +++ gcc/gimple-fold.c (working copy) > @@ -207,6 +207,9 @@ create_tmp_reg_or_ssa_name (tree type, g > tree > canonicalize_constructor_val (tree cval, tree from_decl) > { > + if (CONSTANT_CLASS_P (cval)) > + return cval; > + > tree orig_cval = cval; > STRIP_NOPS (cval); > if (TREE_CODE (cval) == POINTER_PLUS_EXPR > @@ -257,8 +260,15 @@ canonicalize_constructor_val (tree cval, > cval = fold_convert (TREE_TYPE (orig_cval), cval); > return cval; > } > - if (TREE_OVERFLOW_P (cval)) > - return drop_tree_overflow (cval); > + /* In CONSTRUCTORs we may see unfolded constants like (int (*) ()) 0. */ > + if (TREE_CODE (cval) == INTEGER_CST) > + { > + if (TREE_OVERFLOW_P (cval)) > + cval = drop_tree_overflow (cval); > + if (!useless_type_conversion_p (TREE_TYPE (orig_cval), TREE_TYPE > (cval))) > + cval = fold_convert (TREE_TYPE (orig_cval), cval); > + return cval; > + } > return orig_cval; > } > > Index: gcc/testsuite/g++.dg/tree-ssa/pr89698.C > =================================================================== > --- gcc/testsuite/g++.dg/tree-ssa/pr89698.C (nonexistent) > +++ gcc/testsuite/g++.dg/tree-ssa/pr89698.C (working copy) > @@ -0,0 +1,29 @@ > +// { dg-do compile } > +// { dg-options "-O -fdump-tree-fre1" } > + > +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) {}; > +}; > + > +void bar(void *); > +void test() > +{ > + B b(2); > + A* bp = &b; > + void* vp = dynamic_cast<void*>(bp); > + bar (vp); > +} > + > +// We should be able to constant fold from the virtual table > +// the offset added to bp for the dynamic cast and forward > +// &b to the argument of bar > +// { dg-final { scan-tree-dump "bar \\\(&b" "fre1" } }