aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-03-17 09:27:35 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-03-17 09:27:35 +0000
commitba1a3df608a14ca37ca944f4c942c202e919ea80 (patch)
tree5191a09840c794e5d7f7ddb5c7da926761637b8e
parentdb264ae07f451cbd5bb33d528ae00e4910ce386b (diff)
Joining a live interval of a physical register with a virtual one can turn out
to be really bad. Once they are joined they are not broken apart. Also, physical intervals cannot be spilled! Added a heuristic as a workaround for this. Be careful coalescing with a physical register if the virtual register uses are "far". Check if there are uses in the same loop as the source (copy instruction). Check if it is in the loop preheader, etc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35134 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index f8713cc1da..72b8bacb0a 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -41,6 +41,8 @@ STATISTIC(numIntervalsAfter, "Number of intervals after coalescing");
STATISTIC(numJoins , "Number of interval joins performed");
STATISTIC(numPeep , "Number of identity moves eliminated after coalescing");
STATISTIC(numFolded , "Number of loads/stores folded into instructions");
+STATISTIC(numAborts , "Number of times interval joining aborted");
+static cl::opt<bool> ReduceJoinPhys("reduce-joining-phy-regs", cl::Hidden);
namespace {
RegisterPass<LiveIntervals> X("liveintervals", "Live Interval Analysis");
@@ -931,6 +933,58 @@ bool LiveIntervals::JoinCopy(MachineInstr *CopyMI,
isShorten = true;
}
+ // We need to be careful about coalescing a source physical register with a
+ // virtual register. Once the coalescing is done, it cannot be broken and
+ // these are not spillable! If the destination interval uses are far away,
+ // think twice about coalescing them!
+ if (ReduceJoinPhys && !isDead &&
+ MRegisterInfo::isPhysicalRegister(repSrcReg)) {
+ // Small function. No need to worry!
+ if (r2iMap_.size() <= allocatableRegs_.size() * 2)
+ goto TryJoin;
+
+ LiveVariables::VarInfo& dvi = lv_->getVarInfo(repDstReg);
+ // Is the value used in the current BB or any immediate successroe BB?
+ MachineBasicBlock *SrcBB = CopyMI->getParent();
+ if (!dvi.UsedBlocks[SrcBB->getNumber()]) {
+ for (MachineBasicBlock::succ_iterator SI = SrcBB->succ_begin(),
+ SE = SrcBB->succ_end(); SI != SE; ++SI) {
+ MachineBasicBlock *SuccMBB = *SI;
+ if (dvi.UsedBlocks[SuccMBB->getNumber()])
+ goto TryJoin;
+ }
+ }
+
+ // Ok, no use in this BB and no use in immediate successor BB's. Be really
+ // careful now!
+ // It's only used in one BB, forget about it!
+ if (dvi.UsedBlocks.count() <= 1) {
+ ++numAborts;
+ return false;
+ }
+
+ // Examine all the blocks where the value is used. If any is in the same
+ // loop, then it's ok. Or if the current BB is a preheader of any of the
+ // loop that uses this value, that's ok as well.
+ const LoopInfo &LI = getAnalysis<LoopInfo>();
+ const Loop *L = LI.getLoopFor(SrcBB->getBasicBlock());
+ int UseBBNum = dvi.UsedBlocks.find_first();
+ while (UseBBNum != -1) {
+ MachineBasicBlock *UseBB = mf_->getBlockNumbered(UseBBNum);
+ const Loop *UL = LI.getLoopFor(UseBB->getBasicBlock());
+ if ((UL && UL == L) || // A use in the same loop
+ (UL && L && // A use in a loop and this BB is the preheader
+ UL->getLoopPreheader() == SrcBB->getBasicBlock()))
+ goto TryJoin;
+ UseBBNum = dvi.UsedBlocks.find_next(UseBBNum);
+ }
+
+ // Don't do it!
+ ++numAborts;
+ return false;
+ }
+
+TryJoin:
// Okay, attempt to join these two intervals. On failure, this returns false.
// Otherwise, if one of the intervals being joined is a physreg, this method
// always canonicalizes DestInt to be it. The output "SrcInt" will not have