Hi, this patch makes stmt_may_be_vtbl_ptr_store to skip clobbers as discussed previously. Martin, I do not fully follow the logic of this function. Can't we just ignore all stores that are not of pointer type that looks like vptr type? All those tores are compiler generated and we probably can just annotate them, right?
Bootstrapped/regtested x86_64-linux, comitted. Honza * ipa-prop.c (stmt_may_be_vtbl_ptr_store): Skip clobbers. * g++.dg/ipa/devirt-19.C: New testcase. Index: ipa-prop.c =================================================================== --- ipa-prop.c (revision 205987) +++ ipa-prop.c (working copy) @@ -560,6 +560,8 @@ stmt_may_be_vtbl_ptr_store (gimple stmt) { if (is_gimple_call (stmt)) return false; + else if (gimple_clobber_p (stmt)) + return false; else if (is_gimple_assign (stmt)) { tree lhs = gimple_assign_lhs (stmt); Index: testsuite/g++.dg/ipa/devirt-19.C =================================================================== --- testsuite/g++.dg/ipa/devirt-19.C (revision 0) +++ testsuite/g++.dg/ipa/devirt-19.C (revision 0) @@ -0,0 +1,32 @@ +/* We should specialize for &b and devirtualize the call. + Previously we were failing by considering CLOBBER statement to be + a type change. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-ipa-cp" } */ +struct A { + void operator==(const A &); +}; +class B { +public: + A m_fn1(); + A m_fn2(); +}; +template <typename T, typename M> class C { +public: + T Key; + const M &m_fn2(const T &); + virtual void m_fn1() {} + B _map; +}; + +C<int, int> b; +template <typename T, typename M> const M &C<T, M>::m_fn2(const T &) { + A a = _map.m_fn2(); + a == _map.m_fn1(); + m_fn1(); +} + +void fn1() { b.m_fn2(0); } +/* { dg-final { scan-ipa-dump-times "Discovered a virtual call to a known target" 1 "cp" } } */ +/* { dg-final { cleanup-ipa-dump "cp" } } */ +