diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c | 21 | ||||
-rw-r--r-- | gcc/tree-ssa-sccvn.c | 51 |
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) |