http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56988
Bug #: 56988 Summary: ipa-cp incorrectly propagates a field of an aggregate Classification: Unclassified Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end AssignedTo: unassig...@gcc.gnu.org ReportedBy: era...@google.com Created attachment 29890 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=29890 Reduced test case $ trunk_g++ --version trunk_g++ (GCC) 4.9.0 20130416 (experimental) $ trunk_g++ -S -O2 -std=c++11 -fno-exceptions upstream_test_case.ii && grep "mov.* _ZTVN12_GLOBAL__N_18RCTesterE" upstream_test_case.s movq %rax, _ZTVN12_GLOBAL__N_18RCTesterE+24(%rip) The generated assembly attempts to write into RCTester class's vtable. >From the dump generated by -fdump-ipa-whole-program-all (just before ipa-cp), the caller has the following code: # .MEM_11 = VDEF <.MEM_10> obj_3->D.2045._vptr.ReferenceCountedD.2013 = &MEM[(voidD.45 *)&_ZTVN12_GLOBAL__N_18RCTesterED.2049 + 16B]; # .MEM_12 = VDEF <.MEM_11> obj_3->destructed_D.2025 = 0B; # .MEM_13 = VDEF <.MEM_12> obj_3->owner_D.2026 = 0B; # .MEM_5 = VDEF <.MEM_13> # USE = nonlocal null { D.2015 D.2049 } (glob) # CLB = nonlocal null { D.2015 D.2049 } (glob) _ZN12_GLOBAL__N_19TestResetEPNS_8RCTesterED.2068 (obj_3); At the callee, we see: void {anonymous}::TestReset({anonymous}::RCTester*) (struct RCTesterD.2017 * objD.2067) { const struct AssertionResultD.1962 gtest_arD.2071; boolD.1899 destructedD.2070; struct RCTesterD.2017 * obj.3D.2179; # .MEM_2 = VDEF <.MEM_1(D)> destructedD.2070 = 0; # VUSE <.MEM_2> # PT = nonlocal escaped obj.3_3 = objD.2067; # .MEM_8 = VDEF <.MEM_2> MEM[(boolD.1899 * *)obj.3_3 + 8B] = &destructedD.2070; ipa-cp mistakenly thinks that the move statement obj.3_3 = objD.2067; actually loads from offset 0 of objD.2067 and hence propagates &MEM[(voidD.45 *)&_ZTVN12_GLOBAL__N_18RCTesterED.2049 + 16B] into obj.3_3 which then subsequently gets propagated to the store of &destructedD.2070. The following patch fixes this, but not sure if this could be too restrictive: Index: gcc/ipa-prop.c =================================================================== --- gcc/ipa-prop.c (revision 197495) +++ gcc/ipa-prop.c (working copy) @@ -3892,7 +3892,7 @@ ipcp_transform_function (struct cgraph_node *node) { struct ipa_agg_replacement_value *v; gimple stmt = gsi_stmt (gsi); - tree rhs, val, t; + tree rhs, lhs, val, t; HOST_WIDE_INT offset; int index; bool by_ref, vce; @@ -3900,6 +3900,7 @@ ipcp_transform_function (struct cgraph_node *node) if (!gimple_assign_load_p (stmt)) continue; rhs = gimple_assign_rhs1 (stmt); + lhs = gimple_assign_lhs (stmt); if (!is_gimple_reg_type (TREE_TYPE (rhs))) continue; @@ -3924,7 +3925,8 @@ ipcp_transform_function (struct cgraph_node *node) continue; for (v = aggval; v; v = v->next) if (v->index == index - && v->offset == offset) + && v->offset == offset + && TREE_TYPE (v->value) == TREE_TYPE (lhs)) break; if (!v) continue;