summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2012-09-06 18:15:18 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2012-09-06 18:15:18 +0000
commite617ccb80da76821379bbff4a2fdcd09e8401e8b (patch)
tree83ab7c91cdf9ce34b1d5413b4482624e621e4393
parentf9dff0e0e4e8aa9fd99c5f069e431fe6de98c1c9 (diff)
downloadllvm-e617ccb80da76821379bbff4a2fdcd09e8401e8b.tar.gz
llvm-e617ccb80da76821379bbff4a2fdcd09e8401e8b.tar.bz2
llvm-e617ccb80da76821379bbff4a2fdcd09e8401e8b.tar.xz
Handle overlapping regunit intervals in LiveIntervals::addKillFlags().
We will soon allow virtual register live ranges to overlap regunit live ranges when the physreg is defined as a copy of the virtreg: %EAX = COPY %vreg5 FOO %vreg5 BAR %EAX<kill> There is no real interference since %vreg5 and %EAX have the same value where they overlap. This patch prevents addKillFlags from adding virtreg kill flags to FOO where the assigned physreg is overlapping the virtual register live range. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@163335 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h2
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp46
-rw-r--r--lib/CodeGen/VirtRegMap.cpp2
3 files changed, 46 insertions, 4 deletions
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index da521dbc53..bf7469093a 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/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/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index bdf4f2dfff..b447c3c2d7 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/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/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index a1cac7c5b2..6343e8a352 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/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();