When adjusting the C++ FE code generation for base type copies I noticed the XFAILs on g++.dg/tree-ssa/pr41186.C and investigated things a bit. We can fix the testcase easily iff the frontend emits the MEM_REF variants, thus the following patch.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2011-08-11 Richard Guenther <rguent...@suse.de> * tree-ssa-sccvn.c (vn_reference_lookup_3): Avoid redundant lookups, make looking through aggregate copies stronger. Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 177649) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1351,1367 **** { VEC (vn_reference_op_s, heap) *tem; tree lhs = gimple_assign_lhs (def_stmt); /* Avoid re-allocation overhead. */ VEC_truncate (vn_reference_op_s, lhs_ops, 0); copy_reference_ops_from_ref (lhs, &lhs_ops); tem = lhs_ops; ! lhs_ops = valueize_refs (lhs_ops); gcc_assert (lhs_ops == tem); ! lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref, get_alias_set (lhs), ! TREE_TYPE (lhs), lhs_ops); ! if (lhs_ref_ok ! && !refs_may_alias_p_1 (ref, &lhs_ref, true)) ! return NULL; } base = ao_ref_base (ref); --- 1351,1377 ---- { VEC (vn_reference_op_s, heap) *tem; tree lhs = gimple_assign_lhs (def_stmt); + bool valueized_anything = false; /* Avoid re-allocation overhead. */ VEC_truncate (vn_reference_op_s, lhs_ops, 0); copy_reference_ops_from_ref (lhs, &lhs_ops); tem = lhs_ops; ! lhs_ops = valueize_refs_1 (lhs_ops, &valueized_anything); gcc_assert (lhs_ops == tem); ! if (valueized_anything) ! { ! lhs_ref_ok = ao_ref_init_from_vn_reference (&lhs_ref, ! get_alias_set (lhs), ! TREE_TYPE (lhs), lhs_ops); ! if (lhs_ref_ok ! && !refs_may_alias_p_1 (ref, &lhs_ref, true)) ! return NULL; ! } ! else ! { ! ao_ref_init (&lhs_ref, lhs); ! lhs_ref_ok = true; ! } } base = ao_ref_base (ref); *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1469,1474 **** --- 1479,1498 ---- j--; } + /* ??? The innermost op should always be a MEM_REF and we already + checked that the assignment to the lhs kills vr. Thus for + aggregate copies using char[] types the vn_reference_op_eq + may fail when comparing types for compatibility. But we really + don't care here - further lookups with the rewritten operands + will simply fail if we messed up types too badly. */ + if (j == 0 && i == 0 + && VEC_index (vn_reference_op_s, lhs_ops, 0)->opcode == MEM_REF + && VEC_index (vn_reference_op_s, vr->operands, i)->opcode == MEM_REF + && tree_int_cst_equal + (VEC_index (vn_reference_op_s, lhs_ops, 0)->op0, + VEC_index (vn_reference_op_s, vr->operands, i)->op0)) + i--, j--; + /* i now points to the first additional op. ??? LHS may not be completely contained in VR, one or more VIEW_CONVERT_EXPRs could be in its way. We could at least Index: gcc/testsuite/g++.dg/tree-ssa/pr41186.C =================================================================== *** gcc/testsuite/g++.dg/tree-ssa/pr41186.C (revision 177649) --- gcc/testsuite/g++.dg/tree-ssa/pr41186.C (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O -fdump-tree-fre1-details" } */ struct Foo { Foo() {}; --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */ struct Foo { Foo() {}; *************** int main() *** 30,35 **** } /* { dg-final { scan-tree-dump "Replaced b1.b with 1" "fre1" } } */ ! /* { dg-final { scan-tree-dump "Replaced b1.i with 0" "fre1" { xfail *-*-* } } } */ ! /* { dg-final { scan-tree-dump "Replaced b1.f with 1" "fre1" { xfail *-*-* } } } */ /* { dg-final { cleanup-tree-dump "fre1" } } */ --- 30,35 ---- } /* { dg-final { scan-tree-dump "Replaced b1.b with 1" "fre1" } } */ ! /* { dg-final { scan-tree-dump "Replaced b1.D.\[0-9\]*.i with 0" "fre1" } } */ ! /* { dg-final { scan-tree-dump "Replaced b1.D.\[0-9\]*.f with 1" "fre1" } } */ /* { dg-final { cleanup-tree-dump "fre1" } } */