Index: src/IceTargetLowering.cpp |
diff --git a/src/IceTargetLowering.cpp b/src/IceTargetLowering.cpp |
index 1b9ca23bfe49eb96b1bc0dcc5ad38d72965c9adf..c4f3336c25329bc5c253ce0bf15c6dd2d75061cf 100644 |
--- a/src/IceTargetLowering.cpp |
+++ b/src/IceTargetLowering.cpp |
@@ -26,6 +26,7 @@ |
#include "IceInstVarIter.h" |
#include "IceOperand.h" |
#include "IceRegAlloc.h" |
+#include "IceLiveness.h" |
Jim Stichnoth
2016/07/29 17:04:07
sort
manasijm
2016/08/01 22:20:04
Done.
|
#include <string> |
#include <vector> |
@@ -511,6 +512,156 @@ void TargetLowering::regAlloc(RegAllocKind Kind) { |
// set of Variables that have no register and a non-empty live range, and |
// model an infinite number of registers. Maybe use the register aliasing |
// mechanism to get better packing of narrower slots. |
+ if (getFlags().getGlobalSplitting()) |
+ postRegallocSplitting(LinearScan, RegMask); |
+} |
Jim Stichnoth
2016/07/29 19:14:31
blank line after this
manasijm
2016/08/01 22:20:04
Done.
|
+namespace { |
+CfgVector<Inst *> GetInstructionsInRange(CfgNode *Node, InstNumberT Start, |
Jim Stichnoth
2016/07/29 19:14:31
Does this function assume that instruction numbers
Jim Stichnoth
2016/07/29 19:14:31
lowercase getInstructionsInRange per coding style
manasijm
2016/08/01 22:20:04
Done.
|
+ InstNumberT End) { |
+ CfgVector<Inst *> Result; |
+ bool Started = false; |
+ auto Process = [&](InstList &Insts) { |
+ for (auto &Inst : Insts) { |
Jim Stichnoth
2016/07/29 19:14:32
Name this Instr instead of Inst which is a type na
manasijm
2016/08/01 22:20:04
Done.
|
+ if (!Started) { |
Jim Stichnoth
2016/07/29 19:14:31
Restructure as "if (Started) ... else ..."
manasijm
2016/08/01 22:20:05
Acknowledged.
|
+ if (Inst.getNumber() == Start) { |
+ if (!Inst.isDeleted()) { |
+ Result.push_back(&Inst); |
+ } |
+ Started = true; |
+ } else { |
Jim Stichnoth
2016/07/29 19:14:31
Is the "else continue" necessary? It doesn't look
manasijm
2016/08/01 22:20:04
Acknowledged.
|
+ continue; |
+ } |
+ } else { |
+ if (Inst.getNumber() == End) { |
+ break; |
+ } else { |
+ if (!Inst.isDeleted()) { |
+ Result.push_back(&Inst); |
+ } |
+ } |
+ } |
+ } |
+ }; |
+ Process(Node->getPhis()); |
+ Process(Node->getInsts()); |
+ return Result; |
+} |
+} |
+void TargetLowering::postRegallocSplitting(LinearScan &RegAllocator, |
Jim Stichnoth
2016/07/29 17:04:07
These days we avoid passing by non-const ref, so m
manasijm
2016/08/01 22:20:04
Not passing a LinearScan object anymore.
|
+ const SmallBitVector &RegMask) { |
+ TimerMarker T(TimerStack::TT_globalSplitting, Func->getContext()); |
Jim Stichnoth
2016/07/29 19:14:31
Newer Subzero style is to name this "_" instead of
manasijm
2016/08/01 22:20:04
Done.
|
+ CfgSet<Variable *> SplitCandidates; |
+ for (Variable *Var : Func->getVariables()) { |
Jim Stichnoth
2016/07/29 19:14:31
Please add some documentation in the code as to wh
manasijm
2016/08/01 22:20:05
Done.
|
+ if (!Var->mustNotHaveReg() && !Var->hasReg()) { |
+ if (Var->getLiveRange().getNumSegments() > 1) |
+ SplitCandidates.insert(Var); |
+ } |
+ } |
+ if (SplitCandidates.empty()) |
+ return; |
+ |
+ CfgSet<Variable *> ExtraVars; |
+ |
+ struct UseInfo { |
+ Variable *Replacing = nullptr; |
+ Inst *FirstUse = nullptr; |
+ Inst *LastDef = nullptr; |
+ SizeT UseCount = 0; |
+ }; |
+ CfgUnorderedMap<Variable *, UseInfo> VarInfo; |
+ for (auto *Var : SplitCandidates) { |
+ for (auto &Segment : Var->getLiveRange().getSegments()) { |
+ UseInfo Info; |
+ Info.Replacing = Var; |
+ auto *Node = Var->getLiveRange().getNodeForSegment(Segment.first); |
+ |
+ for (auto *Instr : |
+ GetInstructionsInRange(Node, Segment.first, Segment.second)) { |
Jim Stichnoth
2016/07/29 19:14:32
(This might be too much to ask for an initial feat
manasijm
2016/08/01 22:20:04
Acknowledged.
|
+ for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { |
+ for (SizeT j = 0; j < Instr->getSrc(i)->getNumVars(); ++j) { |
+ auto *Var = Instr->getSrc(i)->getVar(j); |
+ if (Var == Info.Replacing) { |
+ if (Info.FirstUse == nullptr && !llvm::isa<InstPhi>(Instr)) { |
+ Info.FirstUse = Instr; |
+ } |
+ Info.UseCount++; |
+ } |
+ } |
+ } |
+ if (Instr->getDest() == Info.Replacing && !llvm::isa<InstPhi>(Instr)) { |
+ Info.LastDef = Instr; |
+ } |
+ } |
+ if (Info.UseCount < 3) |
Jim Stichnoth
2016/07/29 19:14:31
Use a static constexpr variable to self-document t
manasijm
2016/08/01 22:20:04
Done.
|
+ continue; |
+ |
+ if (!Info.FirstUse && !Info.LastDef) { |
+ continue; |
+ } |
+ |
+ LiveRange LR; |
+ LR.addSegment(Segment); |
+ Variable *NewVar = Variable::create( |
+ Func, Var->getType(), Func->getNumVariables() + ExtraVars.size()); |
+ NewVar->setLiveRange(LR); |
+ |
+ VarInfo[NewVar] = Info; |
+ |
+ ExtraVars.insert(NewVar); |
+ } |
+ } |
+ RegAllocator.init(RAK_Global, ExtraVars, SplitCandidates); |
+ RegAllocator.setSplittingMode(); |
+ RegAllocator.scan(RegMask, getFlags().getRandomizeRegisterAllocation()); |
+ |
+ for (auto *ExtraVar : ExtraVars) { |
+ if (ExtraVar->hasReg()) { |
Jim Stichnoth
2016/07/29 19:14:31
how about:
if (!ExtraVar->hasReg())
continu
manasijm
2016/08/01 22:20:05
Done.
|
+ Func->addVariable(ExtraVar); |
Jim Stichnoth
2016/07/29 19:14:31
I'm not thrilled about how these extra variables a
manasijm
2016/08/01 22:20:04
Done.
|
+ |
+ auto &Info = VarInfo[ExtraVar]; |
+ |
+ assert(ExtraVar->getLiveRange().getSegments().size() == 1); |
+ auto Segment = ExtraVar->getLiveRange().getSegments()[0]; |
+ |
+ auto *Node = |
+ Info.Replacing->getLiveRange().getNodeForSegment(Segment.first); |
+ |
+ auto RelevantInsts = |
+ GetInstructionsInRange(Node, Segment.first, Segment.second); |
+ |
+ if (RelevantInsts.empty()) |
+ continue; |
+ |
+ for (auto *Instr : RelevantInsts) { |
+ if (llvm::isa<InstPhi>(Instr)) |
+ continue; |
+ for (SizeT i = 0; i < Instr->getSrcSize(); ++i) { |
Jim Stichnoth
2016/07/29 19:14:31
Document that it's safe to iterate over the top-le
manasijm
2016/08/01 22:20:05
Copied this as is. :)
|
+ if (auto *Var = llvm::dyn_cast<Variable>(Instr->getSrc(i))) { |
+ if (Var == Info.Replacing) { |
+ Instr->replaceSource(i, ExtraVar); |
+ } |
+ } |
+ } |
+ if (Instr->getDest() == Info.Replacing) { |
+ Instr->replaceDest(ExtraVar); |
+ } |
+ } |
+ |
+ assert(Info.FirstUse != Info.LastDef); |
+ assert(Info.FirstUse || Info.LastDef); |
+ |
+ if (Info.FirstUse != nullptr) { |
+ auto *NewInst = |
+ Func->getTarget()->createLoweredMove(ExtraVar, Info.Replacing); |
+ Node->getInsts().insert(instToIterator(Info.FirstUse), NewInst); |
+ } |
+ if (Info.LastDef != nullptr) { |
+ auto *NewInst = |
+ Func->getTarget()->createLoweredMove(Info.Replacing, ExtraVar); |
+ Node->getInsts().insertAfter(instToIterator(Info.LastDef), NewInst); |
+ } |
+ } |
+ } |
} |
void TargetLowering::markRedefinitions() { |