I'm testing a pair of patches to fix PR38885 (for constants) and PR38884 (for non-constants) stores to complex/vector memory and CSE of component accesses from SCCVN.
This is the piece that handles stores from constants and partial reads of it. We can conveniently re-use fold-const native encode/interpret code for this. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2011-10-05 Richard Guenther <rguent...@suse.de> PR tree-optimization/38885 * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle partial reads from constants. * gcc.dg/tree-ssa/ssa-fre-33.c: New testcase. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 179549) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1442,1448 **** } } ! /* 3) 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) --- 1442,1495 ---- } } ! /* 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) *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1540,1546 **** return NULL; } ! /* 4) 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) --- 1587,1593 ---- return NULL; } ! /* 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) Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-33.c (revision 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" } } */