Fix ARM vector copies of overlapping register tuples.
authorAndrew Trick <atrick@apple.com>
Wed, 29 Aug 2012 01:58:55 +0000 (01:58 +0000)
committerAndrew Trick <atrick@apple.com>
Wed, 29 Aug 2012 01:58:55 +0000 (01:58 +0000)
I have tested the fix, but have not been successfull in generating
a robust unit test. This can only be exposed through particular
register assignments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@162821 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMBaseInstrInfo.cpp

index 5191c3eabeadcaada7b4305d38f27dd8c8821c8b..f3c9cf4e434c933dab4d8a01c18ec2d9e6685c2b 100644 (file)
@@ -710,10 +710,23 @@ void ARMBaseInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 
   const TargetRegisterInfo *TRI = &getRegisterInfo();
   MachineInstrBuilder Mov;
+
+  // Copy register tuples backward when the first Dest reg overlaps with SrcReg.
+  if (TRI->regsOverlap(SrcReg, TRI->getSubReg(DestReg, BeginIdx))) {
+    BeginIdx = BeginIdx + ((SubRegs-1)*Spacing);
+    Spacing = -Spacing;
+  }
+#ifndef NDEBUG
+  SmallSet<unsigned, 4> DstRegs;
+#endif
   for (unsigned i = 0; i != SubRegs; ++i) {
     unsigned Dst = TRI->getSubReg(DestReg, BeginIdx + i*Spacing);
     unsigned Src = TRI->getSubReg(SrcReg,  BeginIdx + i*Spacing);
     assert(Dst && Src && "Bad sub-register");
+#ifndef NDEBUG
+    DstRegs.insert(Dst);
+    assert(!DstRegs.count(Src) && "destructive vector copy");
+#endif
     Mov = BuildMI(MBB, I, I->getDebugLoc(), get(Opc), Dst)
       .addReg(Src);
     // VORR takes two source operands.