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