| Index: src/IceTargetLoweringX8632.cpp
|
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
|
| index d36ad1695191b49e77d7ad516c33d80eacfbf890..0423e3929c389649fb563dc97f828d5f4ed1468b 100644
|
| --- a/src/IceTargetLoweringX8632.cpp
|
| +++ b/src/IceTargetLoweringX8632.cpp
|
| @@ -22,6 +22,7 @@
|
| #include "IceOperand.h"
|
| #include "IceTargetLoweringX8632.def"
|
| #include "IceTargetLoweringX8632.h"
|
| +#include "llvm/ADT/DenseMap.h"
|
| #include "llvm/Support/CommandLine.h"
|
|
|
| #include <strings.h>
|
| @@ -4164,7 +4165,7 @@ void TargetX8632::postLower() {
|
| return;
|
| // TODO: Avoid recomputing WhiteList every instruction.
|
| RegSetMask RegInclude = RegSet_All;
|
| - RegSetMask RegExclude = RegSet_None;
|
| + RegSetMask RegExclude = RegSet_StackPointer;
|
| if (hasFramePointer())
|
| RegExclude |= RegSet_FramePointer;
|
| llvm::SmallBitVector WhiteList = getRegisterSet(RegInclude, RegExclude);
|
| @@ -4172,11 +4173,25 @@ void TargetX8632::postLower() {
|
| // there was some prior register allocation pass that made register
|
| // assignments, those registers need to be black-listed here as
|
| // well.
|
| + llvm::DenseMap<const Variable *, const Inst *> LastUses;
|
| + // The first pass also keeps track of which instruction is the last
|
| + // use for each infinite-weight variable. After the last use, the
|
| + // variable is released to the free list.
|
| for (InstList::iterator I = Context.getCur(), E = Context.getEnd(); I != E;
|
| ++I) {
|
| const Inst *Inst = *I;
|
| if (Inst->isDeleted())
|
| continue;
|
| + // Don't consider a FakeKill instruction, because (currently) it
|
| + // is only used to kill all scratch registers at a call site, and
|
| + // we don't want to black-list all scratch registers during the
|
| + // call lowering. This could become a problem since it relies on
|
| + // the lowering sequence not keeping any infinite-weight variables
|
| + // live across a call. TODO(stichnot): Consider replacing this
|
| + // whole postLower() implementation with a robust local register
|
| + // allocator, for example compute live ranges only for pre-colored
|
| + // and infinite-weight variables and run the existing linear-scan
|
| + // allocator.
|
| if (llvm::isa<InstFakeKill>(Inst))
|
| continue;
|
| for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) {
|
| @@ -4184,6 +4199,9 @@ void TargetX8632::postLower() {
|
| SizeT NumVars = Src->getNumVars();
|
| for (SizeT J = 0; J < NumVars; ++J) {
|
| const Variable *Var = Src->getVar(J);
|
| + // Track last uses of all variables, regardless of whether
|
| + // they are pre-colored or infinite-weight.
|
| + LastUses[Var] = Inst;
|
| if (!Var->hasReg())
|
| continue;
|
| WhiteList[Var->getRegNum()] = false;
|
| @@ -4192,36 +4210,58 @@ void TargetX8632::postLower() {
|
| }
|
| // The second pass colors infinite-weight variables.
|
| llvm::SmallBitVector AvailableRegisters = WhiteList;
|
| + llvm::SmallBitVector FreedRegisters(WhiteList.size());
|
| for (InstList::iterator I = Context.getCur(), E = Context.getEnd(); I != E;
|
| ++I) {
|
| + FreedRegisters.reset();
|
| const Inst *Inst = *I;
|
| if (Inst->isDeleted())
|
| continue;
|
| - for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) {
|
| - Operand *Src = Inst->getSrc(SrcNum);
|
| + // Skip FakeKill instructions like above.
|
| + if (llvm::isa<InstFakeKill>(Inst))
|
| + continue;
|
| + // Iterate over all variables referenced in the instruction,
|
| + // including the Dest variable (if any). If the variable is
|
| + // marked as infinite-weight, find it a register. If this
|
| + // instruction is the last use of the variable in the lowered
|
| + // sequence, release the register to the free list after this
|
| + // instruction is completely processed. Note that the first pass
|
| + // ignores the Dest operand, under the assumption that a
|
| + // pre-colored Dest will appear as a source operand in some
|
| + // subsequent instruction in the lowered sequence.
|
| + Variable *Dest = Inst->getDest();
|
| + SizeT NumSrcs = Inst->getSrcSize();
|
| + if (Dest)
|
| + ++NumSrcs;
|
| + OperandList Srcs(NumSrcs);
|
| + for (SizeT i = 0; i < Inst->getSrcSize(); ++i)
|
| + Srcs[i] = Inst->getSrc(i);
|
| + if (Dest)
|
| + Srcs[NumSrcs - 1] = Dest;
|
| + for (SizeT SrcNum = 0; SrcNum < NumSrcs; ++SrcNum) {
|
| + Operand *Src = Srcs[SrcNum];
|
| SizeT NumVars = Src->getNumVars();
|
| for (SizeT J = 0; J < NumVars; ++J) {
|
| Variable *Var = Src->getVar(J);
|
| - if (Var->hasReg())
|
| - continue;
|
| - if (!Var->getWeight().isInf())
|
| - continue;
|
| - llvm::SmallBitVector AvailableTypedRegisters =
|
| - AvailableRegisters & getRegisterSetForType(Var->getType());
|
| - if (!AvailableTypedRegisters.any()) {
|
| - // This is a hack in case we run out of physical registers due
|
| - // to an excessively long code sequence, as might happen when
|
| - // lowering arguments in lowerCall().
|
| - AvailableRegisters = WhiteList;
|
| - AvailableTypedRegisters =
|
| + if (!Var->hasReg() && Var->getWeight().isInf()) {
|
| + llvm::SmallBitVector AvailableTypedRegisters =
|
| AvailableRegisters & getRegisterSetForType(Var->getType());
|
| + assert(AvailableTypedRegisters.any());
|
| + int32_t RegNum = AvailableTypedRegisters.find_first();
|
| + Var->setRegNum(RegNum);
|
| + AvailableRegisters[RegNum] = false;
|
| + }
|
| + if (Var->hasReg()) {
|
| + int32_t RegNum = Var->getRegNum();
|
| + assert(!AvailableRegisters[RegNum]);
|
| + if (LastUses[Var] == Inst) {
|
| + if (WhiteList[RegNum])
|
| + FreedRegisters[RegNum] = true;
|
| + }
|
| }
|
| - assert(AvailableTypedRegisters.any());
|
| - int32_t RegNum = AvailableTypedRegisters.find_first();
|
| - Var->setRegNum(RegNum);
|
| - AvailableRegisters[RegNum] = false;
|
| }
|
| }
|
| + AvailableRegisters |= FreedRegisters;
|
| }
|
| }
|
|
|
|
|