This fixes copy-propagation (in DOM in this case) which breaks
virtual SSA form by introducing overlapping life-ranges which
in turn breaks CFG transforms that rely on that property.

The patch disables copy-propagation of virtuals in general
(for all passes checking may_propagate_copy) because that
predicate cannot decide if the propagation would be valid.

Instead the patch special-cases propagation of virtual operands
across PHI nodes (the only relevant case of virtual operand
copy propagation) in phi_only_cprop.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2013-05-28  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/57411
        * tree-ssa-copy.c (may_propagate_copy): Cannot propagate
        virtual operands.
        * tree-ssa-dom.c (eliminate_const_or_copy): Special-case
        virtual operand propagation.

        * g++.dg/opt/pr57411.C: New testcase.

Index: gcc/tree-ssa-copy.c
===================================================================
*** gcc/tree-ssa-copy.c (revision 199356)
--- gcc/tree-ssa-copy.c (working copy)
*************** may_propagate_copy (tree dest, tree orig
*** 73,86 ****
    if (!useless_type_conversion_p (type_d, type_o))
      return false;
  
!   /* Propagating virtual operands is always ok.  */
    if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest))
!     {
!       /* But only between virtual operands.  */
!       gcc_assert (TREE_CODE (orig) == SSA_NAME && virtual_operand_p (orig));
! 
!       return true;
!     }
  
    /* Anything else is OK.  */
    return true;
--- 73,82 ----
    if (!useless_type_conversion_p (type_d, type_o))
      return false;
  
!   /* Generally propagating virtual operands is not ok as that may
!      create overlapping life-ranges.  */
    if (TREE_CODE (dest) == SSA_NAME && virtual_operand_p (dest))
!     return false;
  
    /* Anything else is OK.  */
    return true;
Index: gcc/testsuite/g++.dg/opt/pr57411.C
===================================================================
*** gcc/testsuite/g++.dg/opt/pr57411.C  (revision 0)
--- gcc/testsuite/g++.dg/opt/pr57411.C  (working copy)
***************
*** 0 ****
--- 1,23 ----
+ // { dg-do compile }
+ // { dg-options "-O -fno-tree-dce -ftree-vectorize" }
+ 
+ static inline void
+ iota (int *__first, int *__last, int __value)
+ {
+   for (; __first != __last; ++__first)
+     {
+       *__first = __value;
+     }
+ }
+ 
+ void assert_fail ();
+ 
+ int A[] = { 0, 0, 0 };
+ 
+ void
+ test01 (int equal)
+ {
+   iota (A, A + 3, 1);
+   if (equal)
+     assert_fail ();
+ }
Index: gcc/tree-ssa-dom.c
===================================================================
*** gcc/tree-ssa-dom.c  (revision 199355)
--- gcc/tree-ssa-dom.c  (working copy)
*************** eliminate_const_or_copy (gimple stmt, bi
*** 2936,2942 ****
        return;
      }
  
!   propagate_rhs_into_lhs (stmt, lhs, rhs, interesting_names);
  
    /* Note that STMT may well have been deleted by now, so do
       not access it, instead use the saved version # to clear
--- 2936,2957 ----
        return;
      }
  
!   if (!virtual_operand_p (lhs))
!     propagate_rhs_into_lhs (stmt, lhs, rhs, interesting_names);
!   else
!     {
!       gimple use_stmt;
!       imm_use_iterator iter;
!       use_operand_p use_p;
!       /* For virtual operands we have to propagate into all uses as
!          otherwise we will create overlapping life-ranges.  */
!       FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
!       FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
!         SET_USE (use_p, rhs);
!       if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
!       SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs) = 1;
!       remove_stmt_or_phi (stmt);
!     }
  
    /* Note that STMT may well have been deleted by now, so do
       not access it, instead use the saved version # to clear

Reply via email to