This patch deletes REG_EQUAL note when a src register is replaced by a constant in an assignment. This is to prevent spurious equivalences between the constant and the expression in the REG_EQUAL note. In the bug reported in PR 62146, an assignment in one branch (which is actually dead) of an IF statement has a REG_EQUAL note equating a register with an expression. Conditional copy propagation replaces the register with 0. The instruction is hoisted above the branch subsequently and then the value 0 is equated with the expression in the REG_EQUAL. Is this ok for 4.9 branch if all tests pass?
This patch looks applicable to trunk as well, but I don't have a test case to reproduce the issue in trunk. ChangeLog: 2014-08-25 Easwaran Raman <era...@google.com> PR rtl-optimization/62146 * cprop.c (try_replace_reg): Remove REG_EQUAL note when a constant is propagated into the src of an assignment. testsuite/ChangeLog 2014-08-25 Easwaran Raman <era...@google.com> PR rtl-optimization/62146 * testsuite/g++.dg/opt/pr62146.C: New.
Index: gcc/testsuite/g++.dg/opt/pr62146.C =================================================================== --- gcc/testsuite/g++.dg/opt/pr62146.C (revision 0) +++ gcc/testsuite/g++.dg/opt/pr62146.C (revision 0) @@ -0,0 +1,51 @@ +/* PR rtl-optimization/62146 */ +/* { dg-do compile } */ +/* { dg-options "-O2 " } */ +class F +{ +public: + virtual ~ F (); +}; +template < class CL > class G:public F +{ + int *member_; +public: + G ( int *b): member_ (0) + { + } +}; + +class D +{ +public: + template < class CL > void RegisterNonTagCallback (int, + void (CL:: + *p3) ()) + { + InternalRegisterNonTag (p3 ? new G < CL > ( 0) : 0); + } void InternalRegisterNonTag (F *); +}; + +void fn1 (); +class C1 +{ + void foo(); + class TokenType + { + public: + void AddToken () + { + } + }; + C1::TokenType bar_t; +}; +D a; +void C1::foo() +{ + if (&bar_t) + fn1 (); + for (int i = 0; i < sizeof 0; ++i) + a.RegisterNonTagCallback (0, &TokenType::AddToken); +} + +/* { dg-final { scan-assembler-not "mov.*_ZN2C19TokenType8AddTokenEv, .\\\(" } } */ Index: gcc/cprop.c =================================================================== --- gcc/cprop.c (revision 214472) +++ gcc/cprop.c (working copy) @@ -790,8 +790,11 @@ try_replace_reg (rtx from, rtx to, rtx insn) /* REG_EQUAL may get simplified into register. We don't allow that. Remove that note. This code ought not to happen, because previous code ought to synthesize - reg-reg move, but be on the safe side. */ - if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0))) + reg-reg move, but be on the safe side. The REG_EQUAL note is + also removed when the source is a constant. */ + if (note && REG_NOTE_KIND (note) == REG_EQUAL + && (REG_P (XEXP (note, 0)) + || (set && CONSTANT_P (SET_SRC (set))))) remove_note (insn, note); return success;