Not because it might be terribly important but the recent change
triggered a latent(?) issue on AIX which broke bootstrap.  Let's
try if another change mitigates that.

The change basically allows devirt-to-const/pure to be taken
into account during the value-numbering rather than only in
followup passes (after we committed the devirtualization).

Bootstrap / regtest running on x86_64-unknown-linux-gnu.

Richard.

2016-09-22  Richard Biener  <rguent...@suse.de>

        * tree-ssa-sccvn.c (visit_reference_op_call): Value number
        virtual definition to virtual use if the call devirtualizes
        to a const or pure function.
        (visit_use): Also visit calls we can devirtualize to a
        const or pure function.

Index: gcc/tree-ssa-sccvn.c
===================================================================
*** gcc/tree-ssa-sccvn.c        (revision 240353)
--- gcc/tree-ssa-sccvn.c        (working copy)
*************** visit_reference_op_call (tree lhs, gcall
*** 3486,3492 ****
        vn_reference_t vr2;
        vn_reference_s **slot;
        if (vdef)
!       changed |= set_ssa_val_to (vdef, vdef);
        if (lhs)
        changed |= set_ssa_val_to (lhs, lhs);
        vr2 = current_info->references_pool->allocate ();
--- 3593,3615 ----
        vn_reference_t vr2;
        vn_reference_s **slot;
        if (vdef)
!       {
!         /* If we value numbered an indirect functions function to
!            one not clobbering memory value number its VDEF to its
!            VUSE.  */
!         tree fn = gimple_call_fn (stmt);
!         tree vdef_val = vdef;
!         if (fn && TREE_CODE (fn) == SSA_NAME)
!           {
!             fn = SSA_VAL (fn);
!             if (TREE_CODE (fn) == ADDR_EXPR
!                 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
!                 && (flags_from_decl_or_type (TREE_OPERAND (fn, 0))
!                     & (ECF_CONST | ECF_PURE)))
!               vdef_val = vuse_ssa_val (gimple_vuse (stmt));
!           }
!         changed |= set_ssa_val_to (vdef, vdef_val);
!       }
        if (lhs)
        changed |= set_ssa_val_to (lhs, lhs);
        vr2 = current_info->references_pool->allocate ();
*************** visit_use (tree use)
*** 3913,3923 ****
            }
        }
  
        if (!gimple_call_internal_p (call_stmt)
          && (/* Calls to the same function with the same vuse
                 and the same operands do not necessarily return the same
                 value, unless they're pure or const.  */
!             gimple_call_flags (call_stmt) & (ECF_PURE | ECF_CONST)
              /* If calls have a vdef, subsequent calls won't have
                 the same incoming vuse.  So, if 2 calls with vdef have the
                 same vuse, we know they're not subsequent.
--- 4035,4056 ----
            }
        }
  
+       /* Pick up flags from a devirtualization target.  */
+       tree fn = gimple_call_fn (stmt);
+       int extra_fnflags = 0;
+       if (fn && TREE_CODE (fn) == SSA_NAME)
+       {
+         fn = SSA_VAL (fn);
+         if (TREE_CODE (fn) == ADDR_EXPR
+             && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+           extra_fnflags = flags_from_decl_or_type (TREE_OPERAND (fn, 0));
+       }
        if (!gimple_call_internal_p (call_stmt)
          && (/* Calls to the same function with the same vuse
                 and the same operands do not necessarily return the same
                 value, unless they're pure or const.  */
!             ((gimple_call_flags (call_stmt) | extra_fnflags)
!              & (ECF_PURE | ECF_CONST))
              /* If calls have a vdef, subsequent calls won't have
                 the same incoming vuse.  So, if 2 calls with vdef have the
                 same vuse, we know they're not subsequent.
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c  (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-56.c  (working copy)
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O -fdump-tree-fre1" } */
+ 
+ int x = 1;
+ int __attribute__((noinline,noclone)) fn ()
+ {
+   return x;
+ }
+ int (*f)();
+ int main ()
+ {
+   int res;
+   f = fn;
+   x = 0;
+   res = f ();
+   res += x;
+   if (res != 0)
+     __builtin_abort ();
+   return 0;
+ }
+ 
+ /* We should be able to optimize the load from x in main and thus the
+    addition.  */
+ 
+ /* { dg-final { scan-tree-dump-times "= x;" 1 "fre1" } } */
+ /* { dg-final { scan-tree-dump-times " \\\+ " 0 "fre1" } } */

Reply via email to