Handle implicit_defs in the register coalescer. I am still trying to produce
authorRafael Espindola <rafael.espindola@gmail.com>
Sat, 30 Jun 2012 01:45:55 +0000 (01:45 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sat, 30 Jun 2012 01:45:55 +0000 (01:45 +0000)
a reduced testcase, but this fixes pr13209.

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

lib/CodeGen/RegisterCoalescer.cpp

index 19b6ffcb51b3ae23491f376512b60b45e5020e39..6ef098d1a143076546cfd7d874c278926ef9f03a 100644 (file)
@@ -1172,14 +1172,11 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li,
 
   MachineInstr *MI = li.getInstructionFromIndex(VNI->def);
 
-  if (!MI || !MI->isFullCopy() || CP.isPartial() || CP.isPhys())
+  if (!MI || CP.isPartial() || CP.isPhys())
     return false;
 
   unsigned Dst = MI->getOperand(0).getReg();
-  unsigned Src = MI->getOperand(1).getReg();
-
-  if (!TargetRegisterInfo::isVirtualRegister(Src) ||
-      !TargetRegisterInfo::isVirtualRegister(Dst))
+  if (!TargetRegisterInfo::isVirtualRegister(Dst))
     return false;
 
   unsigned A = CP.getDstReg();
@@ -1189,34 +1186,47 @@ static bool RegistersDefinedFromSameValue(LiveIntervals &li,
     std::swap(A, B);
   assert(Dst == A);
 
-  const MachineInstr *OtherMI = li.getInstructionFromIndex(OtherVNI->def);
+  MachineInstr *OtherMI = li.getInstructionFromIndex(OtherVNI->def);
 
-  if (!OtherMI || !OtherMI->isFullCopy())
+  if (!OtherMI)
     return false;
 
   unsigned OtherDst = OtherMI->getOperand(0).getReg();
-  unsigned OtherSrc = OtherMI->getOperand(1).getReg();
-
-  if (!TargetRegisterInfo::isVirtualRegister(OtherSrc) ||
-      !TargetRegisterInfo::isVirtualRegister(OtherDst))
+  if (!TargetRegisterInfo::isVirtualRegister(OtherDst))
     return false;
 
   assert(OtherDst == B);
 
-  if (Src != OtherSrc)
-    return false;
+  if (MI->isImplicitDef()) {
+    DupCopies.push_back(MI);
+    return true;
+  } else {
+    if (!MI->isFullCopy())
+      return false;
+    unsigned Src = MI->getOperand(1).getReg();
+    if (!TargetRegisterInfo::isVirtualRegister(Src))
+      return false;
+    if (!OtherMI->isFullCopy())
+      return false;
+    unsigned OtherSrc = OtherMI->getOperand(1).getReg();
+    if (!TargetRegisterInfo::isVirtualRegister(OtherSrc))
+      return false;
 
-  // If the copies use two different value numbers of X, we cannot merge
-  // A and B.
-  LiveInterval &SrcInt = li.getInterval(Src);
-  // getVNInfoBefore returns NULL for undef copies. In this case, the
-  // optimization is still safe.
-  if (SrcInt.getVNInfoBefore(OtherVNI->def) != SrcInt.getVNInfoBefore(VNI->def))
-    return false;
+    if (Src != OtherSrc)
+      return false;
 
-  DupCopies.push_back(MI);
+    // If the copies use two different value numbers of X, we cannot merge
+    // A and B.
+    LiveInterval &SrcInt = li.getInterval(Src);
+    // getVNInfoBefore returns NULL for undef copies. In this case, the
+    // optimization is still safe.
+    if (SrcInt.getVNInfoBefore(OtherVNI->def) !=
+        SrcInt.getVNInfoBefore(VNI->def))
+      return false;
 
-  return true;
+    DupCopies.push_back(MI);
+    return true;
+  }
 }
 
 /// joinIntervals - Attempt to join these two intervals.  On failure, this
@@ -1254,7 +1264,7 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) {
       continue;
     MachineInstr *MI = LIS->getInstructionFromIndex(VNI->def);
     assert(MI && "Missing def");
-    if (!MI->isCopyLike() // Src not defined by a copy?
+    if (!MI->isCopyLike() && !MI->isImplicitDef()) // Src not defined by a copy?
       continue;
 
     // Figure out the value # from the RHS.
@@ -1283,7 +1293,7 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) {
       continue;
     MachineInstr *MI = LIS->getInstructionFromIndex(VNI->def);
     assert(MI && "Missing def");
-    if (!MI->isCopyLike() // Src not defined by a copy?
+    if (!MI->isCopyLike() && !MI->isImplicitDef()) // Src not defined by a copy?
       continue;
 
     // Figure out the value # from the LHS.
@@ -1429,14 +1439,17 @@ bool RegisterCoalescer::joinIntervals(CoalescerPair &CP) {
     if (!ErasedInstrs.insert(MI))
       continue;
 
-    // We have pretended that the assignment to B in
+    // If MI is a copy, then we have pretended that the assignment to B in
     // A = X
     // B = X
     // was actually a copy from A. Now that we decided to coalesce A and B,
     // transform the code into
     // A = X
-    unsigned Src = MI->getOperand(1).getReg();
-    SourceRegisters.push_back(Src);
+    // In the case of the implicit_def, we just have to remove it.
+    if (!MI->isImplicitDef()) {
+      unsigned Src = MI->getOperand(1).getReg();
+      SourceRegisters.push_back(Src);
+    }
     LIS->RemoveMachineInstrFromMaps(MI);
     MI->eraseFromParent();
   }