This handles the case of CSEing part of an SSA name that is stored to memory and defined with a composition like COMPLEX_EXPR or CONSTRUCTOR. This fixes the remaining pieces of PR38884 and PR38885.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-10-06 Richard Guenther <rguent...@suse.de> PR tree-optimization/38884 * tree-ssa-sccvn.c (vn_reference_lookup_3): Handle partial reads from aggregate SSA names. * gcc.dg/tree-ssa/ssa-fre-34.c: New testcase. * gcc.dg/tree-ssa/ssa-fre-35.c: Likewise. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 179556) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1489,1495 **** } } ! /* 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) --- 1489,1554 ---- } } ! /* 4) Assignment from an SSA name which definition we may be able ! to access pieces from. */ ! else if (ref->size == maxsize ! && is_gimple_reg_type (vr->type) ! && gimple_assign_single_p (def_stmt) ! && TREE_CODE (gimple_assign_rhs1 (def_stmt)) == SSA_NAME) ! { ! tree rhs1 = gimple_assign_rhs1 (def_stmt); ! gimple def_stmt2 = SSA_NAME_DEF_STMT (rhs1); ! if (is_gimple_assign (def_stmt2) ! && (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR ! || gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR) ! && types_compatible_p (vr->type, TREE_TYPE (TREE_TYPE (rhs1)))) ! { ! tree base2; ! HOST_WIDE_INT offset2, size2, maxsize2, off; ! base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt), ! &offset2, &size2, &maxsize2); ! off = offset - offset2; ! if (maxsize2 != -1 ! && maxsize2 == size2 ! && operand_equal_p (base, base2, 0) ! && offset2 <= offset ! && offset2 + size2 >= offset + maxsize) ! { ! tree val = NULL_TREE; ! HOST_WIDE_INT elsz ! = TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (TREE_TYPE (rhs1)))); ! if (gimple_assign_rhs_code (def_stmt2) == COMPLEX_EXPR) ! { ! if (off == 0) ! val = gimple_assign_rhs1 (def_stmt2); ! else if (off == elsz) ! val = gimple_assign_rhs2 (def_stmt2); ! } ! else if (gimple_assign_rhs_code (def_stmt2) == CONSTRUCTOR ! && off % elsz == 0) ! { ! tree ctor = gimple_assign_rhs1 (def_stmt2); ! unsigned i = off / elsz; ! if (i < CONSTRUCTOR_NELTS (ctor)) ! { ! constructor_elt *elt = CONSTRUCTOR_ELT (ctor, i); ! if (compare_tree_int (elt->index, i) == 0) ! val = elt->value; ! } ! } ! 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); ! } ! } ! } ! } ! ! /* 5) 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 *** 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) --- 1646,1652 ---- return NULL; } ! /* 6) 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-34.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-34.c (revision 0) *************** *** 0 **** --- 1,18 ---- + /* { 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 foo(float f) + { + vector float res = (vector float){0.0f,f,0.0f,1.0f}; + s.global_res = res; + return *((float*)&s.global_res + 1); + } + + /* { dg-final { scan-tree-dump "Replaced BIT_FIELD_REF.*with f" "fre1" } } */ + /* { dg-final { cleanup-tree-dump "fre1" } } */ Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c =================================================================== *** gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c (revision 0) --- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-35.c (revision 0) *************** *** 0 **** --- 1,17 ---- + /* { dg-do compile } */ + /* { dg-options "-O -fdump-tree-fre1-details" } */ + + struct s { _Complex float i; }; + void g(struct s *); + + float a1 (float dd) + { + struct s sv; + sv.i = dd; + float d = __real__ sv.i; + g(&sv); + return d; + } + + /* { dg-final { scan-tree-dump "Replaced REALPART_EXPR.*with dd" "fre1" } } */ + /* { dg-final { cleanup-tree-dump "fre1" } } */