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
