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" } }

Reply via email to