diff mbox

RFA: Fix PR53688

Message ID Pine.LNX.4.64.1206181649480.29474@wotan.suse.de
State New
Headers show

Commit Message

Michael Matz June 18, 2012, 2:59 p.m. UTC
Hi,

now that we regard MEM_EXPR as a conservative approximation for MEM_SIZE 
(and MEM_OFFSET) we must ensure that this is really the case.  It isn't 
currently for the string expanders, as they use the MEM_REF (whose address 
was taken) directly as the one to use for MEM_EXPR on the MEM rtx.  That's 
wrong, on gimple side we take the address only and hence its size is 
arbitrary.

So, we have to build a memref always and rewrite its type to one 
representing the real size.  Note that TYPE_MAX_VALUE may be NULL, so we 
don't need to check for 'len' being null or not.

This fixes the C testcase (don't know about fma 3d), and is in 
regstrapping on x86_64-linux.  Okay if that passes?


Ciao,
Michael.
	PR middle-end/53688
	* builtins.c (get_memory_rtx): Always build a MEM_REF and override
	its type with one of correct range.

testsuite/
	* gcc.c-torture/execute/pr53688.c: New test.
diff mbox

Patch

Index: builtins.c
===================================================================
--- builtins.c	(revision 188734)
+++ builtins.c	(working copy)
@@ -1274,11 +1274,11 @@  get_memory_rtx (tree exp, tree len)
       && TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
       && host_integerp (TREE_OPERAND (exp, 1), 0)
       && (off = tree_low_cst (TREE_OPERAND (exp, 1), 0)) > 0)
-    exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+    exp = build_simple_mem_ref (TREE_OPERAND (exp, 0));
   else if (TREE_CODE (exp) == ADDR_EXPR)
-    exp = TREE_OPERAND (exp, 0);
+    exp = build_simple_mem_ref (exp);
   else if (POINTER_TYPE_P (TREE_TYPE (exp)))
-    exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
+    exp = build_simple_mem_ref (exp);
   else
     exp = NULL;
 
@@ -1287,6 +1287,11 @@  get_memory_rtx (tree exp, tree len)
      (as stringops may access multiple array elements).  */
   if (exp)
     {
+      /* Reset the type to something spanning the whole thing.  EXP
+         is always a MEM_REF, hence unshared.  */
+      TREE_TYPE (exp)
+	= build_array_type (char_type_node,
+			    build_range_type (sizetype, size_one_node, len));
       set_mem_attributes (mem, exp, 0);
 
       if (off)
Index: testsuite/gcc.c-torture/execute/pr53688.c
===================================================================
--- testsuite/gcc.c-torture/execute/pr53688.c	(revision 0)
+++ testsuite/gcc.c-torture/execute/pr53688.c	(revision 0)
@@ -0,0 +1,32 @@ 
+char headline[256];
+struct hdr {
+  char part1[9];
+  char part2[8];
+} p;
+
+void __attribute__((noinline,noclone))
+init()
+{
+  __builtin_memcpy (p.part1, "FOOBARFOO", sizeof (p.part1));
+  __builtin_memcpy (p.part2, "SPEC CPU", sizeof (p.part2));
+}
+
+int main()
+{
+  char *x;
+  int c;
+  init();
+  __builtin_memcpy (&headline[0], p.part1, 9);
+  c = 9;
+  x = &headline[0];
+  x = x + c;
+  __builtin_memset (x, ' ', 245);
+  __builtin_memcpy (&headline[10], p.part2, 8);
+  c = 18;
+  x = &headline[0];
+  x = x + c;
+  __builtin_memset (x, ' ', 238);
+  if (headline[10] != 'S')
+    __builtin_abort ();
+  return 0;
+}