Re: [PATCH] Fold unfolded constants from initializers

2019-05-03 Thread Richard Biener
On Wed, Mar 13, 2019 at 12:35 PM Richard Biener  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  
>
> 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 = 
> +  void* vp = dynamic_cast(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
> +//  to the argument of bar
> +// { dg-final { scan-tree-dump "bar \\\(" "fre1" } }


[PATCH] Fold unfolded constants from initializers

2019-03-13 Thread Richard Biener


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.

Richard.

2019-03-14  Richard Biener  

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 = 
+  void* vp = dynamic_cast(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
+//  to the argument of bar
+// { dg-final { scan-tree-dump "bar \\\(" "fre1" } }