diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h | 2 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/LiveIntervalAnalysis.cpp | 46 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/VirtRegMap.cpp | 2 | 
3 files changed, 46 insertions, 4 deletions
diff --git a/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h b/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h index da521dbc535..bf7469093a8 100644 --- a/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/llvm/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -252,7 +252,7 @@ namespace llvm {      /// addKillFlags - Add kill flags to any instruction that kills a virtual      /// register. -    void addKillFlags(); +    void addKillFlags(const VirtRegMap*);      /// handleMove - call this method to notify LiveIntervals that      /// instruction 'mi' has been moved within a basic block. This will update diff --git a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp b/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp index bdf4f2dfffc..b447c3c2d70 100644 --- a/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/llvm/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -34,6 +34,7 @@  #include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/STLExtras.h"  #include "LiveRangeCalc.h" +#include "VirtRegMap.h"  #include <algorithm>  #include <limits>  #include <cmath> @@ -733,12 +734,28 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li,  // Register allocator hooks.  // -void LiveIntervals::addKillFlags() { +void LiveIntervals::addKillFlags(const VirtRegMap *VRM) { +  // Keep track of regunit ranges. +  SmallVector<std::pair<LiveInterval*, LiveInterval::iterator>, 8> RU; +    for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {      unsigned Reg = TargetRegisterInfo::index2VirtReg(i);      if (MRI->reg_nodbg_empty(Reg))        continue;      LiveInterval *LI = &getInterval(Reg); +    if (LI->empty()) +      continue; + +    // Find the regunit intervals for the assigned register. They may overlap +    // the virtual register live range, cancelling any kills. +    RU.clear(); +    for (MCRegUnitIterator Units(VRM->getPhys(Reg), TRI); Units.isValid(); +         ++Units) { +      LiveInterval *RUInt = &getRegUnit(*Units); +      if (RUInt->empty()) +        continue; +      RU.push_back(std::make_pair(RUInt, RUInt->find(LI->begin()->end))); +    }      // Every instruction that kills Reg corresponds to a live range end point.      for (LiveInterval::iterator RI = LI->begin(), RE = LI->end(); RI != RE; @@ -749,7 +766,32 @@ void LiveIntervals::addKillFlags() {        MachineInstr *MI = getInstructionFromIndex(RI->end);        if (!MI)          continue; -      MI->addRegisterKilled(Reg, NULL); + +      // Check if any of the reguints are live beyond the end of RI. That could +      // happen when a physreg is defined as a copy of a virtreg: +      // +      //   %EAX = COPY %vreg5 +      //   FOO %vreg5         <--- MI, cancel kill because %EAX is live. +      //   BAR %EAX<kill> +      // +      // There should be no kill flag on FOO when %vreg5 is rewritten as %EAX. +      bool CancelKill = false; +      for (unsigned u = 0, e = RU.size(); u != e; ++u) { +        LiveInterval *RInt = RU[u].first; +        LiveInterval::iterator &I = RU[u].second; +        if (I == RInt->end()) +          continue; +        I = RInt->advanceTo(I, RI->end); +        if (I == RInt->end() || I->start >= RI->end) +          continue; +        // I is overlapping RI. +        CancelKill = true; +        break; +      } +      if (CancelKill) +        MI->clearRegisterKills(Reg, NULL); +      else +        MI->addRegisterKilled(Reg, NULL);      }    }  } diff --git a/llvm/lib/CodeGen/VirtRegMap.cpp b/llvm/lib/CodeGen/VirtRegMap.cpp index a1cac7c5b2a..6343e8a3529 100644 --- a/llvm/lib/CodeGen/VirtRegMap.cpp +++ b/llvm/lib/CodeGen/VirtRegMap.cpp @@ -200,7 +200,7 @@ bool VirtRegRewriter::runOnMachineFunction(MachineFunction &fn) {    DEBUG(VRM->dump());    // Add kill flags while we still have virtual registers. -  LIS->addKillFlags(); +  LIS->addKillFlags(VRM);    // Live-in lists on basic blocks are required for physregs.    addMBBLiveIns();  | 

