The second test on shared_lookup_references in the block:

      /* We need to pre-pend vr->operands[0..i] to rhs.  */
      vec<vn_reference_op_s> old = vr->operands;
      if (i + 1 + rhs.length () > vr->operands.length ())
        {
          vr->operands.safe_grow (i + 1 + rhs.length ());
          if (old == shared_lookup_references)
            shared_lookup_references = vr->operands;
        }
      else
        vr->operands.truncate (i + 1 + rhs.length ());
      FOR_EACH_VEC_ELT (rhs, j, vro)
        vr->operands[i + 1 + j] = *vro;
      vr->operands = valueize_refs (vr->operands);
      if (old == shared_lookup_references)
        shared_lookup_references = vr->operands;

is bypassed when the first test is true because "old" contains a stalled value 
of shared_lookup_references.  This may result in either memory corruption 
(when checking is disabled) or in the failure of one of the assertions:

      gcc_checking_assert (vr1.operands == shared_lookup_references);

in vn_reference_lookup_pieces or vn_reference_lookup.  This was caught on a 
big proprietary Ada application in LTO mode.

Tested on x86_64-suse-linux, approved privately by Richard B., applied on the 
mainline and 6 branch.


2016-06-13  Eric Botcazou  <ebotca...@adacore.com>

        * tree-ssa-sccvn.c (vn_reference_lookup_3): Use a uniform test and
        update shared_lookup_references only once after changing operands.

-- 
Eric Botcazou
Index: tree-ssa-sccvn.c
===================================================================
--- tree-ssa-sccvn.c	(revision 237323)
+++ tree-ssa-sccvn.c	(working copy)
@@ -2089,11 +2089,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree
       /* We need to pre-pend vr->operands[0..i] to rhs.  */
       vec<vn_reference_op_s> old = vr->operands;
       if (i + 1 + rhs.length () > vr->operands.length ())
-	{
-	  vr->operands.safe_grow (i + 1 + rhs.length ());
-	  if (old == shared_lookup_references)
-	    shared_lookup_references = vr->operands;
-	}
+	vr->operands.safe_grow (i + 1 + rhs.length ());
       else
 	vr->operands.truncate (i + 1 + rhs.length ());
       FOR_EACH_VEC_ELT (rhs, j, vro)
@@ -2244,8 +2240,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree
 	{
 	  vec<vn_reference_op_s> old = vr->operands;
 	  vr->operands.safe_grow_cleared (2);
-	  if (old == shared_lookup_references
-	      && vr->operands != old)
+	  if (old == shared_lookup_references)
 	    shared_lookup_references = vr->operands;
 	}
       else

Reply via email to