This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR81884


This PR shows an issue in the must-alias oracle (stmt_kills_ref_p) which
when determining must-alias by finding a common base in two reference
trees doesn't handle trailing arrays correctly.  The fix is to do
array-at-struct-end detection on-the-fly by recording the innermost
ARRAY_REF we drop when searching for the common base and not allow
that to be an array_at_struct_end_p.  Similar to trunk 
array_at_struct_end_p this doesn't allow sub-arrays to be flexible,
for (*)[2'][3''] only ' is allowed to expand below the declared bound
(the artificial case of ' having just one element and thus effectively
not being an array and '' being a flexible array is not supported by
GCC).

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

Poking more holes appreciated ;)

Richard.

2017-08-21  Richard Biener  <rguenther@suse.de>

	PR middle-end/81884
	* tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses
	at struct end conservatively when comparing common bases.

	* g++.dg/torture/pr81884.C: New testcase.

Index: gcc/tree-ssa-alias.c
===================================================================
--- gcc/tree-ssa-alias.c	(revision 251103)
+++ gcc/tree-ssa-alias.c	(working copy)
@@ -2415,6 +2415,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *
       if (ref->ref)
 	{
 	  tree base = ref->ref;
+	  tree innermost_dropped_array_ref = NULL_TREE;
 	  if (handled_component_p (base))
 	    {
 	      tree saved_lhs0 = NULL_TREE;
@@ -2434,6 +2435,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *
 		  TREE_OPERAND (base, 0) = saved_base0;
 		  if (res)
 		    break;
+		  /* Remember if we drop an array-ref that we need to
+		     double-check not being at struct end.  */ 
+		  if (TREE_CODE (base) == ARRAY_REF
+		      || TREE_CODE (base) == ARRAY_RANGE_REF)
+		    innermost_dropped_array_ref = base;
 		  /* Otherwise drop handled components of the access.  */
 		  base = saved_base0;
 		}
@@ -2442,15 +2448,22 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *
 		TREE_OPERAND (lhs, 0) = saved_lhs0;
 	    }
 	  /* Finally check if the lhs has the same address and size as the
-	     base candidate of the access.  */
-	  if (lhs == base
-	      || (((TYPE_SIZE (TREE_TYPE (lhs))
-		    == TYPE_SIZE (TREE_TYPE (base)))
-		   || (TYPE_SIZE (TREE_TYPE (lhs))
-		       && TYPE_SIZE (TREE_TYPE (base))
-		       && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
-					   TYPE_SIZE (TREE_TYPE (base)), 0)))
-		  && operand_equal_p (lhs, base, OEP_ADDRESS_OF)))
+	     base candidate of the access.  Watch out if we have dropped
+	     an array-ref that was at struct end, this means ref->ref may
+	     be outside of the TYPE_SIZE of its base.  */
+	  if ((! innermost_dropped_array_ref
+	       || ! array_at_struct_end_p (innermost_dropped_array_ref, false))
+	      && (lhs == base
+		  || (((TYPE_SIZE (TREE_TYPE (lhs))
+			== TYPE_SIZE (TREE_TYPE (base)))
+		       || (TYPE_SIZE (TREE_TYPE (lhs))
+			   && TYPE_SIZE (TREE_TYPE (base))
+			   && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
+					       TYPE_SIZE (TREE_TYPE (base)),
+					       0)))
+		      && operand_equal_p (lhs, base,
+					  OEP_ADDRESS_OF
+					  | OEP_MATCH_SIDE_EFFECTS))))
 	    return true;
 	}
 
Index: gcc/testsuite/g++.dg/torture/pr81884.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr81884.C	(nonexistent)
+++ gcc/testsuite/g++.dg/torture/pr81884.C	(working copy)
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+
+typedef unsigned long uint64_t;
+
+struct value_t {
+    uint64_t _count;
+    value_t(uint64_t c) : _count(c) {}
+};
+
+struct X {
+    value_t eventTime;
+    uint64_t arr[0];
+};
+
+X* x;
+
+__attribute__((noclone, noinline))
+void initialize()
+{
+  x->arr[0] = 11;
+  x->arr[1] = 12;
+  x->eventTime = value_t(10);
+  x->arr[2] = 13;
+  x->arr[3] = 14;
+}
+
+int main()
+{
+  char buffer[sizeof(X) + sizeof(uint64_t)*4];
+  x = (X*)buffer;
+  x->eventTime = value_t(999);
+  x->arr[0] = 1;
+  x->arr[1] = 2;
+  x->arr[2] = 3;
+  x->arr[3] = 4;
+  initialize();
+  if (x->arr[0] != 11 || x->arr[1] != 12 || x->arr[2] != 13 || x->arr[3] != 14)
+    __builtin_abort ();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]