If a copy isn't coalesced, but its src is defined by trivial computation. Re-material...
authorEvan Cheng <evan.cheng@apple.com>
Thu, 28 Aug 2008 07:53:51 +0000 (07:53 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Thu, 28 Aug 2008 07:53:51 +0000 (07:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@55467 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SimpleRegisterCoalescing.cpp
lib/CodeGen/SimpleRegisterCoalescing.h
test/CodeGen/X86/2008-08-23-X86-64AsmBug.ll
test/CodeGen/X86/2008-08-25-AsmRegTypeMismatch.ll

index 897eb7103096f5b3c6840e0424bbc3bd683b9a15..08c0ab3c54b3ac16cb271ee1f1157d0ff0b81269 100644 (file)
@@ -38,6 +38,7 @@ STATISTIC(numJoins    , "Number of interval joins performed");
 STATISTIC(numSubJoins , "Number of subclass joins performed");
 STATISTIC(numCommutes , "Number of instruction commuting performed");
 STATISTIC(numExtends  , "Number of copies extended");
 STATISTIC(numSubJoins , "Number of subclass joins performed");
 STATISTIC(numCommutes , "Number of instruction commuting performed");
 STATISTIC(numExtends  , "Number of copies extended");
+STATISTIC(NumReMats   , "Number of instructions re-materialized");
 STATISTIC(numPeep     , "Number of identity moves eliminated after coalescing");
 STATISTIC(numAborts   , "Number of times interval joining aborted");
 
 STATISTIC(numPeep     , "Number of identity moves eliminated after coalescing");
 STATISTIC(numAborts   , "Number of times interval joining aborted");
 
@@ -426,6 +427,43 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
   return true;
 }
 
   return true;
 }
 
+/// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial
+/// computation, replace the copy by rematerialize the definition.
+bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
+                                                       unsigned DstReg,
+                                                       MachineInstr *CopyMI) {
+  unsigned CopyIdx = li_->getUseIndex(li_->getInstructionIndex(CopyMI));
+  LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx);
+  if (SrcLR == SrcInt.end()) // Should never happen!
+    return false;
+  VNInfo *ValNo = SrcLR->valno;
+  // If other defs can reach uses of this def, then it's not safe to perform
+  // the optimization.
+  if (ValNo->def == ~0U || ValNo->def == ~1U || ValNo->hasPHIKill)
+    return false;
+  MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def);
+  const TargetInstrDesc &TID = DefMI->getDesc();
+  if (!TID.isAsCheapAsAMove())
+    return false;
+  bool SawStore = false;
+  if (!DefMI->isSafeToMove(tii_, SawStore))
+    return false;
+
+  unsigned DefIdx = li_->getDefIndex(CopyIdx);
+  const LiveRange *DLR= li_->getInterval(DstReg).getLiveRangeContaining(DefIdx);
+  DLR->valno->copy = NULL;
+
+  MachineBasicBlock::iterator MII = CopyMI;
+  MachineBasicBlock *MBB = CopyMI->getParent();
+  tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
+  MachineInstr *NewMI = prior(MII);
+  li_->ReplaceMachineInstrInMaps(CopyMI, NewMI);
+  CopyMI->eraseFromParent();
+  ReMatCopies.insert(CopyMI);
+  ++NumReMats;
+  return true;
+}
+
 /// isBackEdgeCopy - Returns true if CopyMI is a back edge copy.
 ///
 bool SimpleRegisterCoalescing::isBackEdgeCopy(MachineInstr *CopyMI,
 /// isBackEdgeCopy - Returns true if CopyMI is a back edge copy.
 ///
 bool SimpleRegisterCoalescing::isBackEdgeCopy(MachineInstr *CopyMI,
@@ -475,6 +513,17 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg,
       unsigned UseDstReg = DstReg;
       if (OldSubIdx)
           UseDstReg = tri_->getSubReg(DstReg, OldSubIdx);
       unsigned UseDstReg = DstReg;
       if (OldSubIdx)
           UseDstReg = tri_->getSubReg(DstReg, OldSubIdx);
+
+      unsigned CopySrcReg, CopyDstReg;
+      if (tii_->isMoveInstr(*UseMI, CopySrcReg, CopyDstReg) &&
+          CopySrcReg != CopyDstReg &&
+          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))
+          continue;
+      }
+
       O.setReg(UseDstReg);
       O.setSubReg(0);
     } else {
       O.setReg(UseDstReg);
       O.setSubReg(0);
     } else {
@@ -865,7 +914,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
   MachineInstr *CopyMI = TheCopy.MI;
 
   Again = false;
   MachineInstr *CopyMI = TheCopy.MI;
 
   Again = false;
-  if (JoinedCopies.count(CopyMI))
+  if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI))
     return false; // Already done.
 
   DOUT << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI;
     return false; // Already done.
 
   DOUT << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI;
@@ -1108,6 +1157,12 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
 
   if (!isEmpty && !JoinIntervals(DstInt, SrcInt, Swapped)) {
     // Coalescing failed.
 
   if (!isEmpty && !JoinIntervals(DstInt, SrcInt, Swapped)) {
     // Coalescing failed.
+
+    // If definition of source is defined by trivial computation, try
+    // rematerializing it.
+    if (!isExtSubReg && !isInsSubReg &&
+        ReMaterializeTrivialDef(SrcInt, DstInt.reg, CopyMI))
+      return true;
     
     // If we can eliminate the copy without merging the live ranges, do so now.
     if (!isExtSubReg && !isInsSubReg &&
     
     // If we can eliminate the copy without merging the live ranges, do so now.
     if (!isExtSubReg && !isInsSubReg &&
@@ -1211,9 +1266,6 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
   if (TargetRegisterInfo::isVirtualRegister(DstReg))
     RemoveUnnecessaryKills(DstReg, *ResDstInt);
 
   if (TargetRegisterInfo::isVirtualRegister(DstReg))
     RemoveUnnecessaryKills(DstReg, *ResDstInt);
 
-  // SrcReg is guarateed to be the register whose live interval that is
-  // being merged.
-  li_->removeInterval(SrcReg);
   if (isInsSubReg)
     // Avoid:
     // r1024 = op
   if (isInsSubReg)
     // Avoid:
     // r1024 = op
@@ -1223,6 +1275,10 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
     RemoveDeadImpDef(DstReg, *ResDstInt);
   UpdateRegDefsUses(SrcReg, DstReg, SubIdx);
 
     RemoveDeadImpDef(DstReg, *ResDstInt);
   UpdateRegDefsUses(SrcReg, DstReg, SubIdx);
 
+  // SrcReg is guarateed to be the register whose live interval that is
+  // being merged.
+  li_->removeInterval(SrcReg);
+
   if (isEmpty) {
     // Now the copy is being coalesced away, the val# previously defined
     // by the copy is being defined by an IMPLICIT_DEF which defines a zero
   if (isEmpty) {
     // Now the copy is being coalesced away, the val# previously defined
     // by the copy is being defined by an IMPLICIT_DEF which defines a zero
@@ -2018,6 +2074,7 @@ void SimpleRegisterCoalescing::printRegName(unsigned reg) const {
 
 void SimpleRegisterCoalescing::releaseMemory() {
   JoinedCopies.clear();
 
 void SimpleRegisterCoalescing::releaseMemory() {
   JoinedCopies.clear();
+  ReMatCopies.clear();
 }
 
 static bool isZeroLengthInterval(LiveInterval *li) {
 }
 
 static bool isZeroLengthInterval(LiveInterval *li) {
index bb21515a3546e1406ed39964138e8ee689d682e7..62738952aa2ce5b7304fa08e710095b373e1b092 100644 (file)
@@ -96,6 +96,10 @@ namespace llvm {
     ///
     SmallPtrSet<MachineInstr*, 32> JoinedCopies;
 
     ///
     SmallPtrSet<MachineInstr*, 32> JoinedCopies;
 
+    /// ReMatCopies - Keep track of copies eliminated due to remat.
+    ///
+    SmallPtrSet<MachineInstr*, 32> ReMatCopies;
+
   public:
     static char ID; // Pass identifcation, replacement for typeid
     SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}
   public:
     static char ID; // Pass identifcation, replacement for typeid
     SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}
@@ -194,6 +198,9 @@ namespace llvm {
     bool RemoveCopyByCommutingDef(LiveInterval &IntA, LiveInterval &IntB,
                                   MachineInstr *CopyMI);
 
     bool RemoveCopyByCommutingDef(LiveInterval &IntA, LiveInterval &IntB,
                                   MachineInstr *CopyMI);
 
+    bool ReMaterializeTrivialDef(LiveInterval &SrcInt, unsigned DstReg,
+                                 MachineInstr *CopyMI);
+
     /// TurnCopyIntoImpDef - If source of the specified copy is an implicit def,
     /// turn the copy into an implicit def.
     bool TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
     /// TurnCopyIntoImpDef - If source of the specified copy is an implicit def,
     /// turn the copy into an implicit def.
     bool TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
index 2b9f96e188d5dbed1c1cc1b0e119514aeec9ba71..b50f2b0a608790f3e73744d91be9ee8f78f2a4c8 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | not grep movd
+; 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
 
 ; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin | grep movq
 ; PR2677
 
index 8d987b5011fd5a97025bb2bbfd27563a24614a5d..61240979ac3b6b66fb94ef6c8b33c5218d824c70 100644 (file)
@@ -1,5 +1,7 @@
-; RUN: llvm-as < %s | llc -mcpu=yonah
+; RUN: llvm-as < %s | llc -mcpu=yonah | grep pxor | count 2
+; RUN: llvm-as < %s | llc -mcpu=yonah | not grep movapd
 ; PR2715
 ; PR2715
+
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
 target triple = "x86_64-unknown-linux-gnu"
        %struct.XPTTypeDescriptorPrefix = type { i8 }
 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
 target triple = "x86_64-unknown-linux-gnu"
        %struct.XPTTypeDescriptorPrefix = type { i8 }