The following implements minimal handling of union accesses in
data reference analysis, namely accesses to non-aggregate fields,
in particular those we are not adding additional subsetting on.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/126159
        * tree-data-ref.cc (dr_analyze_indices): Handle non-aggregate
        union field accesses.
        (access_fn_component_p): Adjust.

        * gcc.dg/vect/vect-pr126159-1.c: New testcase.
        * gcc.dg/vect/vect-pr126159-2.c: Likewise.
---
 gcc/testsuite/gcc.dg/vect/vect-pr126159-1.c | 16 +++++++++++
 gcc/testsuite/gcc.dg/vect/vect-pr126159-2.c | 16 +++++++++++
 gcc/tree-data-ref.cc                        | 30 ++++++++++++++-------
 3 files changed, 53 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/vect-pr126159-1.c
 create mode 100644 gcc/testsuite/gcc.dg/vect/vect-pr126159-2.c

diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr126159-1.c 
b/gcc/testsuite/gcc.dg/vect/vect-pr126159-1.c
new file mode 100644
index 00000000000..d364d28d7d2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr126159-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+typedef union { int i; float f; } RtreeCoord;
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+void cellUnion_f(RtreeCoord *a1, RtreeCoord *a2, int n) {
+  int ii = 0;
+  do {
+    a1[ii].f   = MIN(a1[ii].f,   a2[ii].f);
+    a1[ii+1].f = MAX(a1[ii+1].f, a2[ii+1].f);
+    ii += 2;
+  } while (ii < n);
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 1 "vect" { 
target { vect_float } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr126159-2.c 
b/gcc/testsuite/gcc.dg/vect/vect-pr126159-2.c
new file mode 100644
index 00000000000..8ce4b4acf06
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-pr126159-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+typedef union { int i; float f; } RtreeCoord;
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+void cellUnion_i(RtreeCoord *a1, RtreeCoord *a2, int n) {
+  int ii = 0;
+  do {
+    a1[ii].i   = MIN(a1[ii].i,   a2[ii].i);
+    a1[ii+1].i = MAX(a1[ii+1].i, a2[ii+1].i);
+    ii += 2;
+  } while (ii < n);
+}
+
+/* { dg-final { scan-tree-dump-times "optimized: loop vectorized" 1 "vect" { 
target { vect_int && { ! vect_no_int_min_max } } } } } */
diff --git a/gcc/tree-data-ref.cc b/gcc/tree-data-ref.cc
index 1114903784e..8e9d7871348 100644
--- a/gcc/tree-data-ref.cc
+++ b/gcc/tree-data-ref.cc
@@ -1295,7 +1295,9 @@ access_fn_component_p (tree op)
       return true;
 
     case COMPONENT_REF:
-      return TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == RECORD_TYPE;
+      return (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == RECORD_TYPE
+             || (!AGGREGATE_TYPE_P (TREE_TYPE (op))
+                 && TREE_CODE (TREE_TYPE (op)) != COMPLEX_TYPE));
 
     default:
       return false;
@@ -1363,17 +1365,27 @@ dr_analyze_indices (struct indices *dri, tree ref, edge 
nest, loop_p loop)
          access_fns.safe_push (access_fn);
        }
       else if (TREE_CODE (ref) == COMPONENT_REF
-              && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+              && (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE
+                  || (!AGGREGATE_TYPE_P (TREE_TYPE (ref))
+                      && TREE_CODE (TREE_TYPE (ref)) != COMPLEX_TYPE)))
        {
          /* For COMPONENT_REFs of records (but not unions!) use the
             FIELD_DECL offset as constant access function so we can
-            disambiguate a[i].f1 and a[i].f2.  */
-         tree off = component_ref_field_offset (ref);
-         off = size_binop (PLUS_EXPR,
-                           size_binop (MULT_EXPR,
-                                       fold_convert (bitsizetype, off),
-                                       bitsize_int (BITS_PER_UNIT)),
-                           DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1)));
+            disambiguate a[i].f1 and a[i].f2.  For unions and accesses
+            we do not create further access functions for just use
+            zero.  */
+         tree off;
+         if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+           {
+             off = component_ref_field_offset (ref);
+             off = size_binop (PLUS_EXPR,
+                               size_binop (MULT_EXPR,
+                                           fold_convert (bitsizetype, off),
+                                           bitsize_int (BITS_PER_UNIT)),
+                               DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1)));
+           }
+         else
+           off = bitsize_zero_node;
          access_fns.safe_push (off);
        }
       else
-- 
2.51.0

Reply via email to