fix constant folding from array CTORs
authorRichard Biener <rguenther@suse.de>
Thu, 9 Jul 2020 14:03:45 +0000 (16:03 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 10 Jul 2020 08:52:47 +0000 (10:52 +0200)
This fixes the case where we try to fold a read from an
array initalizer and happen to cross the boundary of
multiple CTORs which isn't really supported.  For the
interesting cases like the testcase we actually handle
the folding by encoding the whole initializer.

2020-07-10  Richard Biener  <rguenther@suse.de>

PR tree-optimization/96133
* gimple-fold.c (fold_array_ctor_reference): Do not
recurse to folding a CTOR that does not fully cover the
asked for object.

* gcc.dg/torture/pr96133.c: New testcase.

gcc/gimple-fold.c
gcc/testsuite/gcc.dg/torture/pr96133.c [new file with mode: 0644]

index 41b84ba..dfda6db 100644 (file)
@@ -6875,10 +6875,17 @@ fold_array_ctor_reference (tree type, tree ctor,
             SIZE to the size of the accessed element.  */
          inner_offset = 0;
          type = TREE_TYPE (val);
-         size = elt_size.to_uhwi () * BITS_PER_UNIT;
+         size = elt_sz * BITS_PER_UNIT;
        }
+      else if (size && access_index < CONSTRUCTOR_NELTS (ctor) - 1
+              && TREE_CODE (val) == CONSTRUCTOR
+              && (elt_sz * BITS_PER_UNIT - inner_offset) < size)
+       /* If this isn't the last element in the CTOR and a CTOR itself
+          and it does not cover the whole object we are requesting give up
+          since we're not set up for combining from multiple CTORs.  */
+       return NULL_TREE;
 
-      *suboff += (access_index * elt_size * BITS_PER_UNIT).to_uhwi ();
+      *suboff += access_index.to_uhwi () * elt_sz * BITS_PER_UNIT;
       return fold_ctor_reference (type, val, inner_offset, size, from_decl,
                                  suboff);
     }
diff --git a/gcc/testsuite/gcc.dg/torture/pr96133.c b/gcc/testsuite/gcc.dg/torture/pr96133.c
new file mode 100644 (file)
index 0000000..8d051ce
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do run } */
+
+typedef int T;
+static const T a[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
+typedef T v2 __attribute__((vector_size(2*sizeof(T))));
+
+int
+main()
+{
+  const T *p = &a[0][2];
+  v2 x = *(const v2 *)p;
+  T z = x[1];
+  if (z != 4)
+    __builtin_abort ();
+  return 0;
+}