Chromium Code Reviews| 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() { |