https://gcc.gnu.org/g:c31cb13628593fc57779419a806170b6ef2c3b81

commit r17-2217-gc31cb13628593fc57779419a806170b6ef2c3b81
Author: Richard Biener <[email protected]>
Date:   Wed Jul 8 10:06:40 2026 +0200

    tree-optimization/126159 - handle unions in data dependence analysis
    
    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.
    
            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.

Diff:
---
 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(-)

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 000000000000..d364d28d7d24
--- /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 000000000000..8ce4b4acf06d
--- /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 1114903784e5..8e9d78713482 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

Reply via email to