summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c21
-rw-r--r--gcc/tree-ssa-sccvn.c51
4 files changed, 81 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3891393d604..e6bf96d9c92 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38885
+ * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle partial reads
+ from constants.
+
2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
* doc/invoke.texi (-fshrink-wrap): Document.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6ddbccda88a..4a09d43266d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-10-05 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/38885
+ * gcc.dg/tree-ssa/ssa-fre-33.c: New testcase.
+
2011-10-05 Bernd Schmidt <bernds@codesourcery.com>
* gcc.target/i386/sw-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
new file mode 100644
index 00000000000..daba77d9822
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+#define vector __attribute__((vector_size(16) ))
+
+struct {
+ float i;
+ vector float global_res;
+} s;
+float x;
+int main(int argc)
+{
+ vector float res = (vector float){0.0f,0.0f,0.0f,1.0f};
+ res += (vector float){1.0f,2.0f,3.0f,4.0f};
+ s.global_res = res;
+ x = *((float*)&s.global_res + 1);
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump "Replaced BIT_FIELD_REF.*with 2" "fre1" } } */
+/* { dg-final { cleanup-tree-dump "fre1" } } */
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 4b5d388cf31..3b1ad3da269 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1442,7 +1442,54 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
}
}
- /* 3) For aggregate copies translate the reference through them if
+ /* 3) Assignment from a constant. We can use folds native encode/interpret
+ routines to extract the assigned bits. */
+ else if (CHAR_BIT == 8 && BITS_PER_UNIT == 8
+ && ref->size == maxsize
+ && maxsize % BITS_PER_UNIT == 0
+ && offset % BITS_PER_UNIT == 0
+ && is_gimple_reg_type (vr->type)
+ && gimple_assign_single_p (def_stmt)
+ && is_gimple_min_invariant (gimple_assign_rhs1 (def_stmt)))
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2;
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2);
+ if (maxsize2 != -1
+ && maxsize2 == size2
+ && size2 % BITS_PER_UNIT == 0
+ && offset2 % BITS_PER_UNIT == 0
+ && operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ /* We support up to 512-bit values (for V8DFmode). */
+ unsigned char buffer[64];
+ int len;
+
+ len = native_encode_expr (gimple_assign_rhs1 (def_stmt),
+ buffer, sizeof (buffer));
+ if (len > 0)
+ {
+ tree val = native_interpret_expr (vr->type,
+ buffer
+ + ((offset - offset2)
+ / BITS_PER_UNIT),
+ ref->size / BITS_PER_UNIT);
+ if (val)
+ {
+ unsigned int value_id = get_or_alloc_constant_value_id (val);
+ return vn_reference_insert_pieces
+ (vuse, vr->set, vr->type,
+ VEC_copy (vn_reference_op_s, heap, vr->operands),
+ val, value_id);
+ }
+ }
+ }
+ }
+
+ /* 4) For aggregate copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& gimple_assign_single_p (def_stmt)
@@ -1540,7 +1587,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
return NULL;
}
- /* 4) For memcpy copies translate the reference through them if
+ /* 5) For memcpy copies translate the reference through them if
the copy kills ref. */
else if (vn_walk_kind == VN_WALKREWRITE
&& is_gimple_reg_type (vr->type)