[llvm-commits] [PATCH] Fix MachineCSE bug causing miscompile of oggenc on PowerPC

Evan Cheng evan.cheng at apple.com
Tue Nov 13 10:22:42 PST 2012


LGTM

Evan
On Nov 8, 2012, at 6:03 AM, Ulrich Weigand <Ulrich.Weigand at de.ibm.com> wrote:

> 
> Hello,
> 
> as described in this email a while back:
> http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20121008/152920.html
> the oggenc test case is currently miscompiled on PowerPC, because
> MachineCSE merges two DYNALLOC8 nodes representing two separate alloca
> calls into a single node:
> 		 %vreg5<def> = DYNALLOC8 %vreg4, 0, <fi#-1>, %X1<imp-def,dead>,
> %X1<imp-use>; G8RC:%vreg5,%vreg4
> 		 %vreg6<def> = DYNALLOC8 %vreg4, 0, <fi#-1>, %X1<imp-def,dead>,
> %X1<imp-use>; G8RC:%vreg6,%vreg4
> into
> 		 %vreg5<def> = DYNALLOC8 %vreg4, 0, <fi#-1>, %X1<imp-def,dead>,
> %X1<imp-use>; G8RC:%vreg5,%vreg4
> 
> In the email back in October, I noted that this problem disappears when
> marking the DYNALLOC8 node as "mayStore".  However, there seemed to be some
> concern that this would just paper over the problem, and in fact even
> without mayStore, CSE ought not to merge these two nodes.
> 
> Thus I went back and had a closer look at the CSE algorithm.  The code does
> in fact notice that %X1 is used by the node, and it attempts to verify that
> this is still safe:
> 
>    // If the instruction defines physical registers and the values *may*
> be
>    // used, then it's not safe to replace it with a common subexpression.
>    // It's also not safe if the instruction uses physical registers.
>    bool CrossMBBPhysDef = false;
>    SmallSet<unsigned, 8> PhysRefs;
>    SmallVector<unsigned, 2> PhysDefs;
>    if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs, PhysDefs)) {
>      FoundCSE = false;
> 
>      // ... Unless the CS is local or is in the sole predecessor block
>      // and it also defines the physical register which is not clobbered
>      // in between and the physical register uses were not clobbered.
>      unsigned CSVN = VNT.lookup(MI);
>      MachineInstr *CSMI = Exps[CSVN];
>      if (PhysRegDefsReach(CSMI, MI, PhysRefs, PhysDefs, CrossMBBPhysDef))
>        FoundCSE = true;
>    }
> 
> 
> So the code tries to check that "the physical register uses were not
> clobbered" in PhysRegDefsReach.   However, it does that by scanning all
> instructions *between* the first and second DYNALLOC8 node, and checking
> that none of those modifies %X1.  This is in fact trivially true, since
> there are no instructions between those two.  What the code neglects to
> notice is that the first DYNALLOC8 node itself already modifies %X1 ...
> 
> So I thought to modify PhysRegDefsReach to include that initial instruction
> in its scan.  And this does indeed prevent those two DYNALLOC8 instructions
> being merged.  Unfortunately, it prevents a lot more: since "PhysRefs"
> above holds not just physical registers used, but also physical registers
> *defined* by the instruction, *any* instruction that defines a physical
> register now no longer can be CSE'd.  This is not what we want (e.g. it
> prevent any instruction that sets %eflags from being CSE'd).
> 
> What we really want is to distinguish between physical register defs and
> uses:  for a use in MI, a def by CSMI is problematic, but for a def in MI,
> it is not.  Unfortunately, as defs and uses are mixed up in PhysRefs and
> cannot be separated out any more, this is not really feasible to do in
> PhysRegDefsReach.
> 
> On the other hand, since CSMI is a copy of MI anyway, we can check an
> equivalent simpler condition: if MI both defines and uses the same physical
> register, it is not suitable for CSE.   This condition can in fact be
> checked in hasLivePhysRegDefUses already; we do not need to walk any
> instructions to find out.
> 
> The attached patch implements this check.  This fixes the oggenc test case,
> and does not introduce any regressions in the full test suite (e.g. due to
> missed optimizations) either.
> 
> OK to commit?
> 
> Bye,
> Ulrich
> 
> (See attached file: diff-llvm-dynalloc-csefix)<diff-llvm-dynalloc-csefix>_______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list