Let callers decide the sub-register index on the def operand of rematerialized instru...
authorEvan Cheng <evan.cheng@apple.com>
Thu, 16 Jul 2009 09:20:10 +0000 (09:20 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 16 Jul 2009 09:20:10 +0000 (09:20 +0000)
Avoid remat'ing instructions whose def have sub-register indices for now. It's just really really hard to get all the cases right.

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

20 files changed:
include/llvm/Target/TargetInstrInfo.h
lib/CodeGen/LiveIntervalAnalysis.cpp
lib/CodeGen/PreAllocSplitting.cpp
lib/CodeGen/SimpleRegisterCoalescing.cpp
lib/CodeGen/SimpleRegisterCoalescing.h
lib/CodeGen/TargetInstrInfoImpl.cpp
lib/CodeGen/TwoAddressInstructionPass.cpp
lib/CodeGen/VirtRegRewriter.cpp
lib/Target/ARM/ARMBaseRegisterInfo.cpp
lib/Target/ARM/ARMBaseRegisterInfo.h
lib/Target/ARM/ARMInstrInfo.cpp
lib/Target/ARM/ARMInstrInfo.h
lib/Target/ARM/Thumb1RegisterInfo.cpp
lib/Target/ARM/Thumb1RegisterInfo.h
lib/Target/ARM/Thumb2RegisterInfo.cpp
lib/Target/ARM/Thumb2RegisterInfo.h
lib/Target/X86/X86InstrInfo.cpp
lib/Target/X86/X86InstrInfo.h
test/CodeGen/X86/2008-08-23-X86-64AsmBug.ll
test/CodeGen/X86/2009-07-16-CoalescerBug.ll [new file with mode: 0644]

index 00f9f5a5220eb0195bf58dc0d02d44705550b80a..0ab57ca08e4c434b17e74fcb6ce2f83157fb652c 100644 (file)
@@ -151,7 +151,7 @@ public:
   /// specific location targeting a new destination register.
   virtual void reMaterialize(MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MI,
-                             unsigned DestReg,
+                             unsigned DestReg, unsigned SubIdx,
                              const MachineInstr *Orig) const = 0;
 
   /// isInvariantLoad - Return true if the specified instruction (which is
@@ -499,7 +499,7 @@ public:
                             const SmallVectorImpl<MachineOperand> &Pred) const;
   virtual void reMaterialize(MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MI,
-                             unsigned DestReg,
+                             unsigned DestReg, unsigned SubReg,
                              const MachineInstr *Orig) const;
   virtual unsigned GetFunctionSizeInBytes(const MachineFunction &MF) const;
 };
index 3887fc81d826ae07fa061ac4c523d23ada8378ed..873e58e5c7b3a42621a98969a6e1bbaf8c4bccd2 100644 (file)
@@ -1157,6 +1157,11 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
   if (DisableReMat)
     return false;
 
+  // FIXME: For now, avoid remating instructions whose definition has a subreg
+  // index. It's just incredibly difficult to get right.
+  if (MI->findRegisterDefOperand(li.reg)->getSubReg())
+    return false;
+
   if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
     return true;
 
@@ -1595,7 +1600,7 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
             
     if (CreatedNewVReg) {
       if (DefIsReMat) {
-        vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI/*, CanDelete*/);
+        vrm.setVirtIsReMaterialized(NewVReg, ReMatDefMI);
         if (ReMatIds[VNI->id] == VirtRegMap::MAX_STACK_SLOT) {
           // Each valnum may have its own remat id.
           ReMatIds[VNI->id] = vrm.assignVirtReMatId(NewVReg);
index c49575bade65d21363aaf87d92ae8e7e068e43fe..580a6d1d9d8e6605f3cf04f9cfe90503d27015fd 100644 (file)
@@ -867,7 +867,7 @@ void PreAllocSplitting::RenumberValno(VNInfo* VN) {
   NumRenumbers++;
 }
 
-bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
+bool PreAllocSplitting::Rematerialize(unsigned VReg, VNInfo* ValNo,
                                       MachineInstr* DefMI,
                                       MachineBasicBlock::iterator RestorePt,
                                       unsigned RestoreIdx,
@@ -884,7 +884,7 @@ bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
   if (KillPt == DefMI->getParent()->end())
     return false;
   
-  TII->reMaterialize(MBB, RestorePt, vreg, DefMI);
+  TII->reMaterialize(MBB, RestorePt, VReg, 0, DefMI);
   LIs->InsertMachineInstrInMaps(prior(RestorePt), RestoreIdx);
   
   ReconstructLiveInterval(CurrLI);
index 94a275a21a137eab4c55e86653d22bd7892db25d..444952f330cc057208a3ecfe546a8b0442dae112 100644 (file)
@@ -590,6 +590,7 @@ SimpleRegisterCoalescing::TrimLiveIntervalToLastUse(unsigned CopyIdx,
 /// computation, replace the copy by rematerialize the definition.
 bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
                                                        unsigned DstReg,
+                                                       unsigned DstSubIdx,
                                                        MachineInstr *CopyMI) {
   unsigned CopyIdx = li_->getUseIndex(li_->getInstructionIndex(CopyMI));
   LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx);
@@ -647,7 +648,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
     }
 
   MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI));
-  tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
+  tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI);
   MachineInstr *NewMI = prior(MII);
 
   if (checkForDeadDef) {
@@ -738,7 +739,8 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg,
           CopySrcReg == SrcReg && CopyDstReg != UseDstReg) {
         // If the use is a copy and it won't be coalesced away, and its source
         // is defined by a trivial computation, try to rematerialize it instead.
-        if (ReMaterializeTrivialDef(li_->getInterval(SrcReg), CopyDstReg,UseMI))
+        if (ReMaterializeTrivialDef(li_->getInterval(SrcReg), CopyDstReg,
+                                    CopyDstSubIdx, UseMI))
           continue;
       }
 
@@ -950,10 +952,9 @@ SimpleRegisterCoalescing::ShortenDeadCopySrcLiveRange(LiveInterval &li,
   if (LR->valno->def == RemoveStart) {
     // If the def MI defines the val# and this copy is the only kill of the
     // val#, then propagate the dead marker.
-    if (li.isOnlyLROfValNo(LR)) {
-      PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
-      ++numDeadValNo;
-    }
+    PropagateDeadness(li, CopyMI, RemoveStart, li_, tri_);
+    ++numDeadValNo;
+
     if (li.isKill(LR->valno, RemoveEnd))
       li.removeKill(LR->valno, RemoveEnd);
   }
@@ -1679,7 +1680,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
     // If definition of source is defined by trivial computation, try
     // rematerializing it.
     if (!isExtSubReg && !isInsSubReg && !isSubRegToReg &&
-        ReMaterializeTrivialDef(SrcInt, DstInt.reg, CopyMI))
+        ReMaterializeTrivialDef(SrcInt, DstReg, DstSubIdx, CopyMI))
       return true;
     
     // If we can eliminate the copy without merging the live ranges, do so now.
index d2c55810f60cb6e453624db940edfe2c72bdb890..b1810ed413ac63c08b52e1a618db081a2980e509 100644 (file)
@@ -206,7 +206,7 @@ namespace llvm {
     /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial
     /// computation, replace the copy by rematerialize the definition.
     bool ReMaterializeTrivialDef(LiveInterval &SrcInt, unsigned DstReg,
-                                 MachineInstr *CopyMI);
+                                 unsigned DstSubIdx, MachineInstr *CopyMI);
 
     /// TurnCopyIntoImpDef - If source of the specified copy is an implicit def,
     /// turn the copy into an implicit def.
index 97de901f4313807b05692e11f234cbf3dd52ff95..0b791e4a71f5ae605278ce46ece740f9e8c789e5 100644 (file)
@@ -130,9 +130,12 @@ bool TargetInstrInfoImpl::PredicateInstruction(MachineInstr *MI,
 void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator I,
                                         unsigned DestReg,
+                                        unsigned SubIdx,
                                         const MachineInstr *Orig) const {
   MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
-  MI->getOperand(0).setReg(DestReg);
+  MachineOperand &MO = MI->getOperand(0);
+  MO.setReg(DestReg);
+  MO.setSubReg(SubIdx);
   MBB.insert(I, MI);
 }
 
index b67f84b0f943704e7e1d9dc633a150ee1f8cdf63..83468d9273d594a2cce93332b22ad89d0138cfe8 100644 (file)
@@ -798,6 +798,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
           //     a = a op c
           unsigned regA = mi->getOperand(ti).getReg();
           unsigned regB = mi->getOperand(si).getReg();
+          unsigned regASubIdx = mi->getOperand(ti).getSubReg();
 
           assert(TargetRegisterInfo::isVirtualRegister(regB) &&
                  "cannot update physical register live information");
@@ -946,7 +947,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) {
               DefMI->isSafeToReMat(TII, regB) &&
               isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){
             DEBUG(cerr << "2addr: REMATTING : " << *DefMI << "\n");
-            TII->reMaterialize(*mbbi, mi, regA, DefMI);
+            TII->reMaterialize(*mbbi, mi, regA, regASubIdx, DefMI);
             ReMatRegs.set(regB);
             ++NumReMats;
           } else {
index 69f640ea11fef70ee9dd4414ccda0cc14743cdc6..800cdd625f9e5855aeaf0b116e19dd4bf394d5e0 100644 (file)
@@ -490,7 +490,7 @@ static void ReMaterialize(MachineBasicBlock &MBB,
                           const TargetInstrInfo *TII,
                           const TargetRegisterInfo *TRI,
                           VirtRegMap &VRM) {
-  TII->reMaterialize(MBB, MII, DestReg, VRM.getReMaterializedMI(Reg));
+  TII->reMaterialize(MBB, MII, DestReg, 0, VRM.getReMaterializedMI(Reg));
   MachineInstr *NewMI = prior(MII);
   for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
     MachineOperand &MO = NewMI->getOperand(i);
index 37ba0efae73731cebcf47ce93fc791291e584c66..55db6c9e7d9d54361b465770324123c1667f2dcc 100644 (file)
@@ -887,7 +887,7 @@ void ARMBaseRegisterInfo::
 emitLoadConstPool(MachineBasicBlock &MBB,
                   MachineBasicBlock::iterator &MBBI,
                   DebugLoc dl,
-                  unsigned DestReg, int Val,
+                  unsigned DestReg, unsigned SubIdx, int Val,
                   ARMCC::CondCodes Pred,
                   unsigned PredReg) const {
   MachineFunction &MF = *MBB.getParent();
@@ -896,7 +896,8 @@ emitLoadConstPool(MachineBasicBlock &MBB,
              MF.getFunction()->getContext()->getConstantInt(Type::Int32Ty, Val);
   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
 
-  BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp), DestReg)
+  BuildMI(MBB, MBBI, dl, TII.get(ARM::LDRcp))
+    .addReg(DestReg, getDefRegState(true), SubIdx)
     .addConstantPoolIndex(Idx)
     .addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
 }
index f427b97cc8b4ffbd51ba1fa0881b63310257773b..92ecc783c7f8da97a13b211c6ab984c70adbb0a7 100644 (file)
@@ -112,7 +112,8 @@ public:
   virtual void emitLoadConstPool(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator &MBBI,
                                  DebugLoc dl,
-                                 unsigned DestReg, int Val,
+                                 unsigned DestReg, unsigned SubIdx,
+                                 int Val,
                                  ARMCC::CondCodes Pred = ARMCC::AL,
                                  unsigned PredReg = 0) const;
 
index ab0a39177ab3ebe3f6b59a4280967df503c639f5..688dc31c1393047791085bc6fbccb78be3154f15 100644 (file)
@@ -117,12 +117,12 @@ BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
 void ARMInstrInfo::
 reMaterialize(MachineBasicBlock &MBB,
               MachineBasicBlock::iterator I,
-              unsigned DestReg,
+              unsigned DestReg, unsigned SubIdx,
               const MachineInstr *Orig) const {
   DebugLoc dl = Orig->getDebugLoc();
   if (Orig->getOpcode() == ARM::MOVi2pieces) {
     RI.emitLoadConstPool(MBB, I, dl,
-                         DestReg,
+                         DestReg, SubIdx,
                          Orig->getOperand(1).getImm(),
                          (ARMCC::CondCodes)Orig->getOperand(2).getImm(),
                          Orig->getOperand(3).getReg());
index 286b5b702f5fdc5eec7d629af140556b521c67b4..3e9f0204fe01d83301aefe974995dd6abb5e32cf 100644 (file)
@@ -45,7 +45,8 @@ public:
   const ARMRegisterInfo &getRegisterInfo() const { return RI; }
 
   void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                     unsigned DestReg, const MachineInstr *Orig) const;
+                     unsigned DestReg, unsigned SubIdx,
+                     const MachineInstr *Orig) const;
 };
 
 }
index 8374090bd3f6c1b531dfd3f8c2a4f55277dda487..9c933063230a3ea5aad2563ed49de21cef214bf8 100644 (file)
@@ -62,7 +62,8 @@ const MachineInstrBuilder &AddDefaultCC(const MachineInstrBuilder &MIB) {
 void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
                                            MachineBasicBlock::iterator &MBBI,
                                            DebugLoc dl,
-                                           unsigned DestReg, int Val,
+                                           unsigned DestReg, unsigned SubIdx,
+                                           int Val,
                                            ARMCC::CondCodes Pred,
                                            unsigned PredReg) const {
   MachineFunction &MF = *MBB.getParent();
@@ -71,8 +72,9 @@ void Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
              MF.getFunction()->getContext()->getConstantInt(Type::Int32Ty, Val);
   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
 
-  BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp), DestReg)
-    .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg);
+  BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRcp))
+          .addReg(DestReg, getDefRegState(true), SubIdx)
+          .addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg);
 }
 
 const TargetRegisterClass*
@@ -149,7 +151,7 @@ void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
       AddDefaultCC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
         .addReg(LdReg, RegState::Kill);
     } else
-      MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, NumBytes);
+      MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes);
 
     // Emit add / sub.
     int Opc = (isSub) ? ARM::tSUBrr : (isHigh ? ARM::tADDhirr : ARM::tADDrr);
@@ -570,7 +572,7 @@ void Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
         emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,
                                  Offset, false, TII, *this, dl);
       else {
-        emitLoadConstPool(MBB, II, dl, TmpReg, Offset);
+        emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
         UseRR = true;
       }
     } else {
@@ -610,7 +612,7 @@ void Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
         emitThumbRegPlusImmInReg(MBB, II, TmpReg, FrameReg,
                                  Offset, false, TII, *this, dl);
       else {
-        emitLoadConstPool(MBB, II, dl, TmpReg, Offset);
+        emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
         UseRR = true;
       }
     } else
index 6e8dd3d6dab13ba30583d45919ce93792861304a..31e0df235033d1009b91560e8e6d049c774b8cbe 100644 (file)
@@ -32,7 +32,7 @@ public:
  void emitLoadConstPool(MachineBasicBlock &MBB,
                         MachineBasicBlock::iterator &MBBI,
                         DebugLoc dl,
-                        unsigned DestReg, int Val,
+                        unsigned DestReg, unsigned SubIdx, int Val,
                         ARMCC::CondCodes Pred = ARMCC::AL,
                         unsigned PredReg = 0) const;
 
index bf7149722ec4fb3e6484fab631206b925fb89118..482fdce519e3c8abe0533ec2167d4af293bcdadc 100644 (file)
@@ -46,7 +46,8 @@ Thumb2RegisterInfo::Thumb2RegisterInfo(const ARMBaseInstrInfo &tii,
 void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
                                            MachineBasicBlock::iterator &MBBI,
                                            DebugLoc dl,
-                                           unsigned DestReg, int Val,
+                                           unsigned DestReg, unsigned SubIdx,
+                                           int Val,
                                            ARMCC::CondCodes Pred,
                                            unsigned PredReg) const {
   MachineFunction &MF = *MBB.getParent();
@@ -55,7 +56,8 @@ void Thumb2RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
              MF.getFunction()->getContext()->getConstantInt(Type::Int32Ty, Val);
   unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
 
-  BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci), DestReg)
+  BuildMI(MBB, MBBI, dl, TII.get(ARM::t2LDRpci))
+    .addReg(DestReg, getDefRegState(true), SubIdx)
     .addConstantPoolIndex(Idx).addImm((int64_t)ARMCC::AL).addReg(0);
 }
 
index 61ee531c76aa1de8b74681c6df695417a4907394..0a9a15aa1ee34b964e7c08e075119c0089cdd952 100644 (file)
@@ -32,7 +32,7 @@ public:
  void emitLoadConstPool(MachineBasicBlock &MBB,
                         MachineBasicBlock::iterator &MBBI,
                         DebugLoc dl,
-                        unsigned DestReg, int Val,
+                        unsigned DestReg, unsigned SubIdx, int Val,
                         ARMCC::CondCodes Pred = ARMCC::AL,
                         unsigned PredReg = 0) const;
 
index 6f5e717384fea6bdad537944bbbbafa012669c42..6e1d0791ec338bc064da9c09df9771bf5d8d71ed 100644 (file)
@@ -916,14 +916,11 @@ static bool isSafeToClobberEFLAGS(MachineBasicBlock &MBB,
 
 void X86InstrInfo::reMaterialize(MachineBasicBlock &MBB,
                                  MachineBasicBlock::iterator I,
-                                 unsigned DestReg,
+                                 unsigned DestReg, unsigned SubIdx,
                                  const MachineInstr *Orig) const {
   DebugLoc DL = DebugLoc::getUnknownLoc();
   if (I != MBB.end()) DL = I->getDebugLoc();
 
-  unsigned SubIdx = Orig->getOperand(0).isReg()
-    ? Orig->getOperand(0).getSubReg() : 0;
-  bool ChangeSubIdx = SubIdx != 0;
   if (SubIdx && TargetRegisterInfo::isPhysicalRegister(DestReg)) {
     DestReg = RI.getSubReg(DestReg, SubIdx);
     SubIdx = 0;
@@ -931,37 +928,36 @@ void X86InstrInfo::reMaterialize(MachineBasicBlock &MBB,
 
   // MOV32r0 etc. are implemented with xor which clobbers condition code.
   // Re-materialize them as movri instructions to avoid side effects.
-  bool Emitted = false;
-  switch (Orig->getOpcode()) {
+  bool Clone = true;
+  unsigned Opc = Orig->getOpcode();
+  switch (Opc) {
   default: break;
   case X86::MOV8r0:
   case X86::MOV16r0:
   case X86::MOV32r0: {
     if (!isSafeToClobberEFLAGS(MBB, I)) {
-      unsigned Opc = 0;
-      switch (Orig->getOpcode()) {
+      switch (Opc) {
       default: break;
       case X86::MOV8r0:  Opc = X86::MOV8ri;  break;
       case X86::MOV16r0: Opc = X86::MOV16ri; break;
       case X86::MOV32r0: Opc = X86::MOV32ri; break;
       }
-      BuildMI(MBB, I, DL, get(Opc), DestReg).addImm(0);
-      Emitted = true;
+      Clone = false;
     }
     break;
   }
   }
 
-  if (!Emitted) {
+  if (Clone) {
     MachineInstr *MI = MBB.getParent()->CloneMachineInstr(Orig);
     MI->getOperand(0).setReg(DestReg);
     MBB.insert(I, MI);
+  } else {
+    BuildMI(MBB, I, DL, get(Opc), DestReg).addImm(0);
   }
 
-  if (ChangeSubIdx) {
-    MachineInstr *NewMI = prior(I);
-    NewMI->getOperand(0).setSubReg(SubIdx);
-  }
+  MachineInstr *NewMI = prior(I);
+  NewMI->getOperand(0).setSubReg(SubIdx);
 }
 
 /// isInvariantLoad - Return true if the specified instruction (which is marked
index 5ad52cff3a4243a245af17a8d223fc88bfe0fced..0fb2052202751a9cd0cc9df8913e51b090d93474 100644 (file)
@@ -456,7 +456,8 @@ public:
 
   bool isReallyTriviallyReMaterializable(const MachineInstr *MI) const;
   void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                     unsigned DestReg, const MachineInstr *Orig) const;
+                     unsigned DestReg, unsigned SubIdx,
+                     const MachineInstr *Orig) const;
 
   bool isInvariantLoad(const MachineInstr *MI) const;
 
index 4e3533287dbce173321eeb6a3ab2a9a1364927ec..518e8ccd5dc1eb90252f1a020ec41226c6836b42 100644 (file)
@@ -1,7 +1,11 @@
-; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | grep movd | count 1
 ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | grep movq
 ; PR2677
 
+; FIXME: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | grep movd | count 1
+; We now no longer allow instruction whose def has a sub-reg index to be
+; rematerialized.
+
+
        %struct.Bigint = type { %struct.Bigint*, i32, i32, i32, i32, [1 x i32] }
 
 define double @_Z7qstrtodPKcPS0_Pb(i8* %s00, i8** %se, i8* %ok) nounwind {
diff --git a/test/CodeGen/X86/2009-07-16-CoalescerBug.ll b/test/CodeGen/X86/2009-07-16-CoalescerBug.ll
new file mode 100644 (file)
index 0000000..f79b3da
--- /dev/null
@@ -0,0 +1,210 @@
+; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin10
+; rdar://7059496
+
+       %struct.brinfo = type <{ %struct.brinfo*, %struct.brinfo*, i8*, i32, i32, i32, i8, i8, i8, i8 }>
+       %struct.cadata = type <{ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i32, %struct.cmatcher*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8, i8, i8, i8 }>
+       %struct.cline = type <{ %struct.cline*, i32, i8, i8, i8, i8, i8*, i32, i8, i8, i8, i8, i8*, i32, i8, i8, i8, i8, i8*, i32, i32, %struct.cline*, %struct.cline*, i32, i32 }>
+       %struct.cmatch = type <{ i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i32, i8, i8, i8, i8, i32*, i32*, i8*, i8*, i32, i32, i32, i32, i16, i8, i8, i16, i8, i8 }>
+       %struct.cmatcher = type <{ i32, i8, i8, i8, i8, %struct.cmatcher*, i32, i8, i8, i8, i8, %struct.cpattern*, i32, i8, i8, i8, i8, %struct.cpattern*, i32, i8, i8, i8, i8, %struct.cpattern*, i32, i8, i8, i8, i8, %struct.cpattern*, i32, i8, i8, i8, i8 }>
+       %struct.cpattern = type <{ %struct.cpattern*, i32, i8, i8, i8, i8, %union.anon }>
+       %struct.patprog = type <{ i64, i64, i64, i64, i32, i32, i32, i32, i8, i8, i8, i8, i8, i8, i8, i8 }>
+       %union.anon = type <{ [8 x i8] }>
+
+define i32 @addmatches(%struct.cadata* %dat, i8** nocapture %argv) nounwind ssp {
+entry:
+       br i1 undef, label %if.else, label %if.then91
+
+if.then91:             ; preds = %entry
+       br label %if.end96
+
+if.else:               ; preds = %entry
+       br label %if.end96
+
+if.end96:              ; preds = %if.else, %if.then91
+       br i1 undef, label %lor.lhs.false, label %if.then105
+
+lor.lhs.false:         ; preds = %if.end96
+       br i1 undef, label %if.else139, label %if.then105
+
+if.then105:            ; preds = %lor.lhs.false, %if.end96
+       unreachable
+
+if.else139:            ; preds = %lor.lhs.false
+       br i1 undef, label %land.end, label %land.rhs
+
+land.rhs:              ; preds = %if.else139
+       unreachable
+
+land.end:              ; preds = %if.else139
+       br i1 undef, label %land.lhs.true285, label %if.then315
+
+land.lhs.true285:              ; preds = %land.end
+       br i1 undef, label %if.end324, label %if.then322
+
+if.then315:            ; preds = %land.end
+       unreachable
+
+if.then322:            ; preds = %land.lhs.true285
+       unreachable
+
+if.end324:             ; preds = %land.lhs.true285
+       br i1 undef, label %if.end384, label %if.then358
+
+if.then358:            ; preds = %if.end324
+       unreachable
+
+if.end384:             ; preds = %if.end324
+       br i1 undef, label %if.end394, label %land.lhs.true387
+
+land.lhs.true387:              ; preds = %if.end384
+       unreachable
+
+if.end394:             ; preds = %if.end384
+       br i1 undef, label %if.end498, label %land.lhs.true399
+
+land.lhs.true399:              ; preds = %if.end394
+       br i1 undef, label %if.end498, label %if.then406
+
+if.then406:            ; preds = %land.lhs.true399
+       unreachable
+
+if.end498:             ; preds = %land.lhs.true399, %if.end394
+       br i1 undef, label %if.end514, label %if.then503
+
+if.then503:            ; preds = %if.end498
+       unreachable
+
+if.end514:             ; preds = %if.end498
+       br i1 undef, label %if.end585, label %if.then520
+
+if.then520:            ; preds = %if.end514
+       br i1 undef, label %lor.lhs.false547, label %if.then560
+
+lor.lhs.false547:              ; preds = %if.then520
+       unreachable
+
+if.then560:            ; preds = %if.then520
+       br i1 undef, label %if.end585, label %land.lhs.true566
+
+land.lhs.true566:              ; preds = %if.then560
+       br i1 undef, label %if.end585, label %if.then573
+
+if.then573:            ; preds = %land.lhs.true566
+       unreachable
+
+if.end585:             ; preds = %land.lhs.true566, %if.then560, %if.end514
+       br i1 undef, label %cond.true593, label %cond.false599
+
+cond.true593:          ; preds = %if.end585
+       unreachable
+
+cond.false599:         ; preds = %if.end585
+       br i1 undef, label %if.end647, label %if.then621
+
+if.then621:            ; preds = %cond.false599
+       br i1 undef, label %cond.true624, label %cond.false630
+
+cond.true624:          ; preds = %if.then621
+       br label %if.end647
+
+cond.false630:         ; preds = %if.then621
+       unreachable
+
+if.end647:             ; preds = %cond.true624, %cond.false599
+       br i1 undef, label %if.end723, label %if.then701
+
+if.then701:            ; preds = %if.end647
+       br label %if.end723
+
+if.end723:             ; preds = %if.then701, %if.end647
+       br i1 undef, label %if.else1090, label %if.then729
+
+if.then729:            ; preds = %if.end723
+       br i1 undef, label %if.end887, label %if.then812
+
+if.then812:            ; preds = %if.then729
+       unreachable
+
+if.end887:             ; preds = %if.then729
+       br i1 undef, label %if.end972, label %if.then893
+
+if.then893:            ; preds = %if.end887
+       br i1 undef, label %if.end919, label %if.then903
+
+if.then903:            ; preds = %if.then893
+       unreachable
+
+if.end919:             ; preds = %if.then893
+       br label %if.end972
+
+if.end972:             ; preds = %if.end919, %if.end887
+       %sline.0 = phi %struct.cline* [ undef, %if.end919 ], [ null, %if.end887 ]               ; <%struct.cline*> [#uses=5]
+       %bcs.0 = phi i32 [ undef, %if.end919 ], [ 0, %if.end887 ]               ; <i32> [#uses=5]
+       br i1 undef, label %if.end1146, label %land.lhs.true975
+
+land.lhs.true975:              ; preds = %if.end972
+       br i1 undef, label %if.end1146, label %if.then980
+
+if.then980:            ; preds = %land.lhs.true975
+       br i1 undef, label %cond.false1025, label %cond.false1004
+
+cond.false1004:                ; preds = %if.then980
+       unreachable
+
+cond.false1025:                ; preds = %if.then980
+       br i1 undef, label %if.end1146, label %if.then1071
+
+if.then1071:           ; preds = %cond.false1025
+       br i1 undef, label %if.then1074, label %if.end1081
+
+if.then1074:           ; preds = %if.then1071
+       br label %if.end1081
+
+if.end1081:            ; preds = %if.then1074, %if.then1071
+       %call1083 = call %struct.patprog* @patcompile(i8* undef, i32 0, i8** null) nounwind ssp         ; <%struct.patprog*> [#uses=2]
+       br i1 undef, label %if.end1146, label %if.then1086
+
+if.then1086:           ; preds = %if.end1081
+       br label %if.end1146
+
+if.else1090:           ; preds = %if.end723
+       br i1 undef, label %if.end1146, label %land.lhs.true1093
+
+land.lhs.true1093:             ; preds = %if.else1090
+       br i1 undef, label %if.end1146, label %if.then1098
+
+if.then1098:           ; preds = %land.lhs.true1093
+       unreachable
+
+if.end1146:            ; preds = %land.lhs.true1093, %if.else1090, %if.then1086, %if.end1081, %cond.false1025, %land.lhs.true975, %if.end972
+       %cp.0 = phi %struct.patprog* [ %call1083, %if.then1086 ], [ null, %if.end972 ], [ null, %land.lhs.true975 ], [ null, %cond.false1025 ], [ %call1083, %if.end1081 ], [ null, %if.else1090 ], [ null, %land.lhs.true1093 ]                ; <%struct.patprog*> [#uses=1]
+       %sline.1 = phi %struct.cline* [ %sline.0, %if.then1086 ], [ %sline.0, %if.end972 ], [ %sline.0, %land.lhs.true975 ], [ %sline.0, %cond.false1025 ], [ %sline.0, %if.end1081 ], [ null, %if.else1090 ], [ null, %land.lhs.true1093 ]             ; <%struct.cline*> [#uses=1]
+       %bcs.1 = phi i32 [ %bcs.0, %if.then1086 ], [ %bcs.0, %if.end972 ], [ %bcs.0, %land.lhs.true975 ], [ %bcs.0, %cond.false1025 ], [ %bcs.0, %if.end1081 ], [ 0, %if.else1090 ], [ 0, %land.lhs.true1093 ]          ; <i32> [#uses=1]
+       br i1 undef, label %if.end1307, label %do.body1270
+
+do.body1270:           ; preds = %if.end1146
+       unreachable
+
+if.end1307:            ; preds = %if.end1146
+       br i1 undef, label %if.end1318, label %if.then1312
+
+if.then1312:           ; preds = %if.end1307
+       unreachable
+
+if.end1318:            ; preds = %if.end1307
+       br i1 undef, label %for.cond1330.preheader, label %if.then1323
+
+if.then1323:           ; preds = %if.end1318
+       unreachable
+
+for.cond1330.preheader:                ; preds = %if.end1318
+       %call1587 = call i8* @comp_match(i8* undef, i8* undef, i8* undef, %struct.patprog* %cp.0, %struct.cline** undef, i32 0, %struct.brinfo** undef, i32 0, %struct.brinfo** undef, i32 %bcs.1, i32* undef) nounwind ssp             ; <i8*> [#uses=0]
+       %call1667 = call %struct.cmatch* @add_match_data(i32 0, i8* undef, i8* undef, %struct.cline* undef, i8* undef, i8* null, i8* undef, i8* undef, i8* undef, i8* undef, %struct.cline* null, i8* undef, %struct.cline* %sline.1, i8* undef, i32 undef, i32 undef) ssp              ; <%struct.cmatch*> [#uses=0]
+       unreachable
+}
+
+declare %struct.patprog* @patcompile(i8*, i32, i8**) ssp
+
+declare i8* @comp_match(i8*, i8*, i8*, %struct.patprog*, %struct.cline**, i32, %struct.brinfo**, i32, %struct.brinfo**, i32, i32*) ssp
+
+declare %struct.cmatch* @add_match_data(i32, i8*, i8*, %struct.cline*, i8*, i8*, i8*, i8*, i8*, i8*, %struct.cline*, i8*, %struct.cline*, i8*, i32, i32) nounwind ssp