| Index: src/IceRegAlloc.cpp
|
| diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
|
| index e6f3f560e4ad6fe5470d109ba0233a197abd57c0..57b0a3a27c67945b88384f5ee284e1cc771cc388 100644
|
| --- a/src/IceRegAlloc.cpp
|
| +++ b/src/IceRegAlloc.cpp
|
| @@ -49,19 +49,20 @@ void dumpDisableOverlap(const Cfg *Func, const Variable *Var,
|
| const char *Reason) {
|
| if (!BuildDefs::dump())
|
| return;
|
| - if (Func->isVerbose(IceV_LinearScan)) {
|
| - VariablesMetadata *VMetadata = Func->getVMetadata();
|
| - Ostream &Str = Func->getContext()->getStrDump();
|
| - Str << "Disabling Overlap due to " << Reason << " " << *Var
|
| - << " LIVE=" << Var->getLiveRange() << " Defs=";
|
| - if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
|
| - Str << FirstDef->getNumber();
|
| - const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
|
| - for (size_t i = 0; i < Defs.size(); ++i) {
|
| - Str << "," << Defs[i]->getNumber();
|
| - }
|
| - Str << "\n";
|
| + if (!Func->isVerbose(IceV_LinearScan))
|
| + return;
|
| +
|
| + VariablesMetadata *VMetadata = Func->getVMetadata();
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + Str << "Disabling Overlap due to " << Reason << " " << *Var
|
| + << " LIVE=" << Var->getLiveRange() << " Defs=";
|
| + if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var))
|
| + Str << FirstDef->getNumber();
|
| + const InstDefList &Defs = VMetadata->getLatterDefinitions(Var);
|
| + for (size_t i = 0; i < Defs.size(); ++i) {
|
| + Str << "," << Defs[i]->getNumber();
|
| }
|
| + Str << "\n";
|
| }
|
|
|
| void dumpLiveRange(const Variable *Var, const Cfg *Func) {
|
| @@ -160,9 +161,8 @@ bool LinearScan::livenessValidateIntervals(
|
| return false;
|
| }
|
|
|
| -// Prepare for very simple register allocation of only infinite-weight
|
| -// Variables while respecting pre-colored Variables. Some properties we take
|
| -// advantage of:
|
| +// Prepare for very simple register allocation of only infinite-weight Variables
|
| +// while respecting pre-colored Variables. Some properties we take advantage of:
|
| //
|
| // * Live ranges of interest consist of a single segment.
|
| //
|
| @@ -172,9 +172,9 @@ bool LinearScan::livenessValidateIntervals(
|
| // lowered, or they don't contain any pre-colored or infinite-weight
|
| // Variables.
|
| //
|
| -// * We don't need to renumber instructions before computing live ranges
|
| -// because all the high-level ICE instructions are deleted prior to lowering,
|
| -// and the low-level instructions are added in monotonically increasing order.
|
| +// * We don't need to renumber instructions before computing live ranges because
|
| +// all the high-level ICE instructions are deleted prior to lowering, and the
|
| +// low-level instructions are added in monotonically increasing order.
|
| //
|
| // * There are no opportunities for register preference or allowing overlap.
|
| //
|
| @@ -183,8 +183,7 @@ bool LinearScan::livenessValidateIntervals(
|
| // * Because live ranges are a single segment, the Inactive set will always be
|
| // empty, and the live range trimming operation is unnecessary.
|
| //
|
| -// * Calculating overlap of single-segment live ranges could be optimized a
|
| -// bit.
|
| +// * Calculating overlap of single-segment live ranges could be optimized a bit.
|
| void LinearScan::initForInfOnly() {
|
| TimerMarker T(TimerStack::TT_initUnhandled, Func);
|
| FindPreference = false;
|
| @@ -350,10 +349,10 @@ void LinearScan::init(RegAllocKind Kind) {
|
| }
|
|
|
| // This is called when Cur must be allocated a register but no registers are
|
| -// available across Cur's live range. To handle this, we find a register that
|
| -// is not explicitly used during Cur's live range, spill that register to a
|
| -// stack location right before Cur's live range begins, and fill (reload) the
|
| -// register from the stack location right after Cur's live range ends.
|
| +// available across Cur's live range. To handle this, we find a register that is
|
| +// not explicitly used during Cur's live range, spill that register to a stack
|
| +// location right before Cur's live range begins, and fill (reload) the register
|
| +// from the stack location right after Cur's live range ends.
|
| void LinearScan::addSpillFill(IterationState &Iter) {
|
| // Identify the actual instructions that begin and end Iter.Cur's live range.
|
| // Iterate through Iter.Cur's node's instruction list until we find the actual
|
| @@ -385,9 +384,9 @@ void LinearScan::addSpillFill(IterationState &Iter) {
|
| if (I->getNumber() == End)
|
| FillPoint = I;
|
| if (SpillPoint != E) {
|
| - // Remove from RegMask any physical registers referenced during Cur's
|
| - // live range. Start looking after SpillPoint gets set, i.e. once Cur's
|
| - // live range begins.
|
| + // Remove from RegMask any physical registers referenced during Cur's live
|
| + // range. Start looking after SpillPoint gets set, i.e. once Cur's live
|
| + // range begins.
|
| FOREACH_VAR_IN_INST(Var, *I) {
|
| if (!Var->hasRegTmp())
|
| continue;
|
| @@ -407,9 +406,8 @@ void LinearScan::addSpillFill(IterationState &Iter) {
|
| assert(RegNum != -1);
|
| Iter.Cur->setRegNumTmp(RegNum);
|
| Variable *Preg = Target->getPhysicalRegister(RegNum, Iter.Cur->getType());
|
| - // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that
|
| - // SpillLoc is correctly identified as !isMultiBlock(), reducing stack frame
|
| - // size.
|
| + // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc
|
| + // is correctly identified as !isMultiBlock(), reducing stack frame size.
|
| Variable *SpillLoc = Func->makeVariable(Iter.Cur->getType());
|
| // Add "reg=FakeDef;spill=reg" before SpillPoint
|
| Target->lowerInst(Node, SpillPoint, InstFakeDef::create(Func, Preg));
|
| @@ -475,68 +473,67 @@ void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
|
| }
|
|
|
| // Infer register preference and allowable overlap. Only form a preference when
|
| -// the current Variable has an unambiguous "first" definition. The preference
|
| -// is some source Variable of the defining instruction that either is assigned
|
| -// a register that is currently free, or that is assigned a register that is
|
| -// not free but overlap is allowed. Overlap is allowed when the Variable under
|
| -// consideration is single-definition, and its definition is a simple
|
| -// assignment - i.e., the register gets copied/aliased but is never modified.
|
| -// Furthermore, overlap is only allowed when preferred Variable definition
|
| -// instructions do not appear within the current Variable's live range.
|
| +// the current Variable has an unambiguous "first" definition. The preference is
|
| +// some source Variable of the defining instruction that either is assigned a
|
| +// register that is currently free, or that is assigned a register that is not
|
| +// free but overlap is allowed. Overlap is allowed when the Variable under
|
| +// consideration is single-definition, and its definition is a simple assignment
|
| +// - i.e., the register gets copied/aliased but is never modified. Furthermore,
|
| +// overlap is only allowed when preferred Variable definition instructions do
|
| +// not appear within the current Variable's live range.
|
| void LinearScan::findRegisterPreference(IterationState &Iter) {
|
| Iter.Prefer = nullptr;
|
| Iter.PreferReg = Variable::NoRegister;
|
| Iter.AllowOverlap = false;
|
|
|
| - if (FindPreference) {
|
| - VariablesMetadata *VMetadata = Func->getVMetadata();
|
| - if (const Inst *DefInst =
|
| - VMetadata->getFirstDefinitionSingleBlock(Iter.Cur)) {
|
| - assert(DefInst->getDest() == Iter.Cur);
|
| - bool IsAssign = DefInst->isVarAssign();
|
| - bool IsSingleDef = !VMetadata->isMultiDef(Iter.Cur);
|
| - FOREACH_VAR_IN_INST(SrcVar, *DefInst) {
|
| - // Only consider source variables that have (so far) been assigned a
|
| - // register. That register must be one in the RegMask set, e.g. don't
|
| - // try to prefer the stack pointer as a result of the stacksave
|
| - // intrinsic.
|
| - if (SrcVar->hasRegTmp()) {
|
| - const llvm::SmallBitVector &Aliases =
|
| - *RegAliases[SrcVar->getRegNumTmp()];
|
| - const int32_t SrcReg = (Iter.RegMask & Aliases).find_first();
|
| - const bool IsAliasAvailable = (SrcReg != -1);
|
| - if (IsAliasAvailable) {
|
| - if (FindOverlap && !Iter.Free[SrcReg]) {
|
| - // Don't bother trying to enable AllowOverlap if the register is
|
| - // already free.
|
| - Iter.AllowOverlap = IsSingleDef && IsAssign &&
|
| - !overlapsDefs(Func, Iter.Cur, SrcVar);
|
| - }
|
| - if (Iter.AllowOverlap || Iter.Free[SrcReg]) {
|
| - Iter.Prefer = SrcVar;
|
| - Iter.PreferReg = SrcReg;
|
| - // Stop looking for a preference after the first valid preference
|
| - // is found. One might think that we should look at all
|
| - // instruction variables to find the best <Prefer,AllowOverlap>
|
| - // combination, but note that AllowOverlap can only be true for a
|
| - // simple assignment statement which can have only one source
|
| - // operand, so it's not possible for AllowOverlap to be true
|
| - // beyond the first source operand.
|
| - FOREACH_VAR_IN_INST_BREAK;
|
| - }
|
| - }
|
| - }
|
| - }
|
| - if (Verbose && Iter.Prefer) {
|
| - Ostream &Str = Ctx->getStrDump();
|
| - Str << "Initial Iter.Prefer=";
|
| - Iter.Prefer->dump(Func);
|
| - Str << " R=" << Iter.PreferReg
|
| - << " LIVE=" << Iter.Prefer->getLiveRange()
|
| - << " Overlap=" << Iter.AllowOverlap << "\n";
|
| - }
|
| + if (!FindPreference)
|
| + return;
|
| +
|
| + VariablesMetadata *VMetadata = Func->getVMetadata();
|
| + const Inst *DefInst = VMetadata->getFirstDefinitionSingleBlock(Iter.Cur);
|
| + if (DefInst == nullptr)
|
| + return;
|
| +
|
| + assert(DefInst->getDest() == Iter.Cur);
|
| + const bool IsSingleDefAssign =
|
| + DefInst->isVarAssign() && !VMetadata->isMultiDef(Iter.Cur);
|
| + FOREACH_VAR_IN_INST(SrcVar, *DefInst) {
|
| + // Only consider source variables that have (so far) been assigned a
|
| + // register.
|
| + if (!SrcVar->hasRegTmp())
|
| + continue;
|
| +
|
| + // That register must be one in the RegMask set, e.g. don't try to prefer
|
| + // the stack pointer as a result of the stacksave intrinsic.
|
| + const llvm::SmallBitVector &Aliases = *RegAliases[SrcVar->getRegNumTmp()];
|
| + const int32_t SrcReg = (Iter.RegMask & Aliases).find_first();
|
| + if (SrcReg == -1)
|
| + continue;
|
| +
|
| + if (FindOverlap && IsSingleDefAssign && !Iter.Free[SrcReg]) {
|
| + // Don't bother trying to enable AllowOverlap if the register is already
|
| + // free (hence the test on Iter.Free[SrcReg]).
|
| + Iter.AllowOverlap = !overlapsDefs(Func, Iter.Cur, SrcVar);
|
| + }
|
| + if (Iter.AllowOverlap || Iter.Free[SrcReg]) {
|
| + Iter.Prefer = SrcVar;
|
| + Iter.PreferReg = SrcReg;
|
| + // Stop looking for a preference after the first valid preference is
|
| + // found. One might think that we should look at all instruction
|
| + // variables to find the best <Prefer,AllowOverlap> combination, but note
|
| + // that AllowOverlap can only be true for a simple assignment statement
|
| + // which can have only one source operand, so it's not possible for
|
| + // AllowOverlap to be true beyond the first source operand.
|
| + FOREACH_VAR_IN_INST_BREAK;
|
| }
|
| }
|
| + if (BuildDefs::dump() && Verbose && Iter.Prefer) {
|
| + Ostream &Str = Ctx->getStrDump();
|
| + Str << "Initial Iter.Prefer=";
|
| + Iter.Prefer->dump(Func);
|
| + Str << " R=" << Iter.PreferReg << " LIVE=" << Iter.Prefer->getLiveRange()
|
| + << " Overlap=" << Iter.AllowOverlap << "\n";
|
| + }
|
| }
|
|
|
| // Remove registers from the Free[] list where an Inactive range overlaps with
|
| @@ -554,8 +551,7 @@ void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) {
|
| // AllowOverlap.
|
| Iter.Free[RegAlias] = false;
|
| // Disable AllowOverlap if an Inactive variable, which is not Prefer,
|
| - // shares Prefer's register, and has a definition within Cur's live
|
| - // range.
|
| + // shares Prefer's register, and has a definition within Cur's live range.
|
| if (Iter.AllowOverlap && Item != Iter.Prefer &&
|
| RegAlias == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) {
|
| Iter.AllowOverlap = false;
|
| @@ -567,28 +563,28 @@ void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) {
|
|
|
| // Remove registers from the Free[] list where an Unhandled pre-colored range
|
| // overlaps with the current range, and set those registers to infinite weight
|
| -// so that they aren't candidates for eviction. Cur->rangeEndsBefore(Item) is
|
| -// an early exit check that turns a guaranteed O(N^2) algorithm into expected
|
| +// so that they aren't candidates for eviction. Cur->rangeEndsBefore(Item) is an
|
| +// early exit check that turns a guaranteed O(N^2) algorithm into expected
|
| // linear complexity.
|
| void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) {
|
| for (Variable *Item : reverse_range(UnhandledPrecolored)) {
|
| assert(Item->hasReg());
|
| if (Iter.Cur->rangeEndsBefore(Item))
|
| break;
|
| - if (Item->rangeOverlaps(Iter.Cur)) {
|
| - const llvm::SmallBitVector &Aliases =
|
| - *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
|
| - for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
|
| - RegAlias = Aliases.find_next(RegAlias)) {
|
| - Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
|
| - Iter.Free[RegAlias] = false;
|
| - Iter.PrecoloredUnhandledMask[RegAlias] = true;
|
| - // Disable Iter.AllowOverlap if the preferred register is one of these
|
| - // pre-colored unhandled overlapping ranges.
|
| - if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) {
|
| - Iter.AllowOverlap = false;
|
| - dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
|
| - }
|
| + if (!Item->rangeOverlaps(Iter.Cur))
|
| + continue;
|
| + const llvm::SmallBitVector &Aliases =
|
| + *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
|
| + for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
|
| + RegAlias = Aliases.find_next(RegAlias)) {
|
| + Iter.Weights[RegAlias].setWeight(RegWeight::Inf);
|
| + Iter.Free[RegAlias] = false;
|
| + Iter.PrecoloredUnhandledMask[RegAlias] = true;
|
| + // Disable Iter.AllowOverlap if the preferred register is one of these
|
| + // pre-colored unhandled overlapping ranges.
|
| + if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) {
|
| + Iter.AllowOverlap = false;
|
| + dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
|
| }
|
| }
|
| }
|
| @@ -664,8 +660,7 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
|
| }
|
| }
|
|
|
| - // All the weights are now calculated. Find the register with smallest
|
| - // weight.
|
| + // All the weights are now calculated. Find the register with smallest weight.
|
| int32_t MinWeightIndex = Iter.RegMask.find_first();
|
| // MinWeightIndex must be valid because of the initial RegMask.any() test.
|
| assert(MinWeightIndex >= 0);
|
| @@ -713,10 +708,10 @@ void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
|
| // Note: The Item->rangeOverlaps(Cur) clause is not part of the
|
| // description of AssignMemLoc() in the original paper. But there doesn't
|
| // seem to be any need to evict an inactive live range that doesn't
|
| - // overlap with the live range currently being considered. It's
|
| - // especially bad if we would end up evicting an infinite-weight but
|
| - // currently-inactive live range. The most common situation for this
|
| - // would be a scratch register kill set for call instructions.
|
| + // overlap with the live range currently being considered. It's especially
|
| + // bad if we would end up evicting an infinite-weight but
|
| + // currently-inactive live range. The most common situation for this would
|
| + // be a scratch register kill set for call instructions.
|
| if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) {
|
| dumpLiveRangeTrace("Evicting I ", Item);
|
| Item->setRegNumTmp(Variable::NoRegister);
|
| @@ -762,7 +757,7 @@ void LinearScan::assignFinalRegisters(
|
| if (Randomized && Item->hasRegTmp() && !Item->hasReg()) {
|
| AssignedRegNum = Permutation[RegNum];
|
| }
|
| - if (Verbose) {
|
| + if (BuildDefs::dump() && Verbose) {
|
| Ostream &Str = Ctx->getStrDump();
|
| if (!Item->hasRegTmp()) {
|
| Str << "Not assigning ";
|
| @@ -785,8 +780,8 @@ void LinearScan::assignFinalRegisters(
|
| // Allocation in the Context of SSA Form and Register Constraints" by Hanspeter
|
| // Mössenböck and Michael Pfeiffer,
|
| // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF. This implementation is
|
| -// modified to take affinity into account and allow two interfering variables
|
| -// to share the same register in certain cases.
|
| +// modified to take affinity into account and allow two interfering variables to
|
| +// share the same register in certain cases.
|
| //
|
| // Requires running Cfg::liveness(Liveness_Intervals) in preparation. Results
|
| // are assigned to Variable::RegNum for each Variable.
|
| @@ -809,12 +804,11 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
|
| LiveRange KillsRange(Kills);
|
| KillsRange.untrim();
|
|
|
| - // Reset the register use count
|
| + // Reset the register use count.
|
| RegUses.resize(NumRegisters);
|
| std::fill(RegUses.begin(), RegUses.end(), 0);
|
|
|
| - // Unhandled is already set to all ranges in increasing order of start
|
| - // points.
|
| + // Unhandled is already set to all ranges in increasing order of start points.
|
| assert(Active.empty());
|
| assert(Inactive.empty());
|
| assert(Handled.empty());
|
| @@ -824,7 +818,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
|
| const llvm::SmallBitVector KillsMask =
|
| Target->getRegisterSet(RegsInclude, RegsExclude);
|
|
|
| - // Allocate memory once outside the loop
|
| + // Allocate memory once outside the loop.
|
| IterationState Iter;
|
| Iter.Weights.reserve(NumRegisters);
|
| Iter.PrecoloredUnhandledMask.reserve(NumRegisters);
|
| @@ -894,7 +888,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
|
| }
|
|
|
| // Print info about physical register availability.
|
| - if (Verbose) {
|
| + if (BuildDefs::dump() && Verbose) {
|
| Ostream &Str = Ctx->getStrDump();
|
| for (SizeT i = 0; i < Iter.RegMask.size(); ++i) {
|
| if (Iter.RegMask[i]) {
|
| @@ -907,15 +901,15 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
|
| }
|
|
|
| if (Iter.Prefer && (Iter.AllowOverlap || Iter.Free[Iter.PreferReg])) {
|
| - // First choice: a preferred register that is either free or is allowed
|
| - // to overlap with its linked variable.
|
| + // First choice: a preferred register that is either free or is allowed to
|
| + // overlap with its linked variable.
|
| allocatePreferredRegister(Iter);
|
| } else if (Iter.Free.any()) {
|
| // Second choice: any free register.
|
| allocateFreeRegister(Iter);
|
| } else {
|
| - // Fallback: there are no free registers, so we look for the
|
| - // lowest-weight register and see if Cur has higher weight.
|
| + // Fallback: there are no free registers, so we look for the lowest-weight
|
| + // register and see if Cur has higher weight.
|
| handleNoFreeRegisters(Iter);
|
| }
|
| dump(Func);
|
| @@ -930,16 +924,6 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
|
|
|
| assignFinalRegisters(RegMaskFull, PreDefinedRegisters, Randomized);
|
|
|
| - // TODO: Consider running register allocation one more time, with infinite
|
| - // registers, for two reasons. First, evicted live ranges get a second chance
|
| - // for a register. Second, it allows coalescing of stack slots. If there is
|
| - // no time budget for the second register allocation run, each unallocated
|
| - // variable just gets its own slot.
|
| - //
|
| - // Another idea for coalescing stack slots is to initialize the Unhandled
|
| - // list with just the unallocated variables, saving time but not offering
|
| - // second-chance opportunities.
|
| -
|
| if (Verbose)
|
| Ctx->unlockStr();
|
| }
|
| @@ -961,7 +945,7 @@ void LinearScan::dumpLiveRangeTrace(const char *Label, const Variable *Item) {
|
| void LinearScan::dump(Cfg *Func) const {
|
| if (!BuildDefs::dump())
|
| return;
|
| - if (!Func->isVerbose(IceV_LinearScan))
|
| + if (!Verbose)
|
| return;
|
| Ostream &Str = Func->getContext()->getStrDump();
|
| Func->resetCurrentNode();
|
|
|