Commit bb8b624e by Jim Stichnoth

Subzero: Improve the representation and handling of the FakeKill instruction.

The FakeKill instruction is always used for killing scratch registers, and a fair amount of effort is spent building new copies of the same scratch register list each time (i.e., for each lowered call instruction). As such, we can create one master list of scratch registers and share it among all FakeKill instructions. Also, in all situations where an instruction's Srcs[] were considered for liveness, we had to either explicitly ignore an InstFakeKill instruction, or treat it specially. Now that InstFakeKill lacks any Srcs[] (or Dest), it doesn't need to be specially ignored, and the code is simplified. In addition, the text asm emitter no longer clutters the output with FakeKill comments (and FakeUse as well). BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/691693003
parent 2daadb78
...@@ -316,8 +316,6 @@ bool Cfg::validateLiveness() const { ...@@ -316,8 +316,6 @@ bool Cfg::validateLiveness() const {
for (Inst *Inst : Node->getInsts()) { for (Inst *Inst : Node->getInsts()) {
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
if (llvm::isa<InstFakeKill>(Inst))
continue;
if (FirstInst == NULL) if (FirstInst == NULL)
FirstInst = Inst; FirstInst = Inst;
InstNumberT InstNumber = Inst->getNumber(); InstNumberT InstNumber = Inst->getNumber();
......
...@@ -667,9 +667,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) { ...@@ -667,9 +667,7 @@ void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
if (Mode == Liveness_Intervals) { if (Mode == Liveness_Intervals) {
if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) {
if (!Kill->getLinked()->isDeleted()) { if (!Kill->getLinked()->isDeleted()) {
SizeT NumSrcs = I->getSrcSize(); for (Variable *Var : Kill->getKilledRegs()) {
for (SizeT Src = 0; Src < NumSrcs; ++Src) {
Variable *Var = llvm::cast<Variable>(I->getSrc(Src));
InstNumberT InstNumber = I->getNumber(); InstNumberT InstNumber = I->getNumber();
Var->addLiveRange(InstNumber, InstNumber, 1); Var->addLiveRange(InstNumber, InstNumber, 1);
} }
......
...@@ -454,11 +454,8 @@ InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) ...@@ -454,11 +454,8 @@ InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src)
InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs,
const Inst *Linked) const Inst *Linked)
: InstHighLevel(Func, Inst::FakeKill, KilledRegs.size(), NULL), : InstHighLevel(Func, Inst::FakeKill, 0, NULL), KilledRegs(KilledRegs),
Linked(Linked) { Linked(Linked) {}
for (Variable *Var : KilledRegs)
addSource(Var);
}
// ======================== Dump routines ======================== // // ======================== Dump routines ======================== //
...@@ -730,6 +727,8 @@ void InstUnreachable::dump(const Cfg *Func) const { ...@@ -730,6 +727,8 @@ void InstUnreachable::dump(const Cfg *Func) const {
} }
void InstFakeDef::emit(const Cfg *Func) const { void InstFakeDef::emit(const Cfg *Func) const {
// Go ahead and "emit" these for now, since they are relatively
// rare.
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t# "; Str << "\t# ";
getDest()->emit(Func); getDest()->emit(Func);
...@@ -744,12 +743,7 @@ void InstFakeDef::dump(const Cfg *Func) const { ...@@ -744,12 +743,7 @@ void InstFakeDef::dump(const Cfg *Func) const {
dumpSources(Func); dumpSources(Func);
} }
void InstFakeUse::emit(const Cfg *Func) const { void InstFakeUse::emit(const Cfg *Func) const { (void)Func; }
Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t# ";
Str << "use.pseudo ";
emitSources(Func);
}
void InstFakeUse::dump(const Cfg *Func) const { void InstFakeUse::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
...@@ -757,21 +751,20 @@ void InstFakeUse::dump(const Cfg *Func) const { ...@@ -757,21 +751,20 @@ void InstFakeUse::dump(const Cfg *Func) const {
dumpSources(Func); dumpSources(Func);
} }
void InstFakeKill::emit(const Cfg *Func) const { void InstFakeKill::emit(const Cfg *Func) const { (void)Func; }
Ostream &Str = Func->getContext()->getStrEmit();
Str << "\t# ";
if (Linked->isDeleted())
Str << "// ";
Str << "kill.pseudo ";
emitSources(Func);
}
void InstFakeKill::dump(const Cfg *Func) const { void InstFakeKill::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump(); Ostream &Str = Func->getContext()->getStrDump();
if (Linked->isDeleted()) if (Linked->isDeleted())
Str << "// "; Str << "// ";
Str << "kill.pseudo "; Str << "kill.pseudo ";
dumpSources(Func); bool First = true;
for (Variable *Var : KilledRegs) {
if (!First)
Str << ", ";
First = false;
Var->dump(Func);
}
} }
void InstTarget::dump(const Cfg *Func) const { void InstTarget::dump(const Cfg *Func) const {
......
...@@ -801,6 +801,7 @@ public: ...@@ -801,6 +801,7 @@ public:
return new (Func->allocateInst<InstFakeKill>()) return new (Func->allocateInst<InstFakeKill>())
InstFakeKill(Func, KilledRegs, Linked); InstFakeKill(Func, KilledRegs, Linked);
} }
const VarList &getKilledRegs() const { return KilledRegs; }
const Inst *getLinked() const { return Linked; } const Inst *getLinked() const { return Linked; }
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
void emitIAS(const Cfg * /* Func */) const override {} void emitIAS(const Cfg * /* Func */) const override {}
...@@ -811,6 +812,7 @@ private: ...@@ -811,6 +812,7 @@ private:
InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked); InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked);
~InstFakeKill() override {} ~InstFakeKill() override {}
const VarList &KilledRegs;
// This instruction is ignored if Linked->isDeleted() is true. // This instruction is ignored if Linked->isDeleted() is true.
const Inst *Linked; const Inst *Linked;
}; };
......
...@@ -350,18 +350,8 @@ void VariablesMetadata::addNode(CfgNode *Node) { ...@@ -350,18 +350,8 @@ void VariablesMetadata::addNode(CfgNode *Node) {
for (Inst *I : Node->getInsts()) { for (Inst *I : Node->getInsts()) {
if (I->isDeleted()) if (I->isDeleted())
continue; continue;
if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { // Note: The implicit definitions (and uses) from InstFakeKill are
// A FakeKill instruction indicates certain Variables (usually // deliberately ignored.
// physical scratch registers) are redefined, so we register
// them as defs.
for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) {
Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum));
SizeT VarNum = Var->getIndex();
assert(VarNum < Metadata.size());
Metadata[VarNum].markDef(Kind, Kill, Node);
}
continue; // no point in executing the rest
}
if (Variable *Dest = I->getDest()) { if (Variable *Dest = I->getDest()) {
SizeT DestNum = Dest->getIndex(); SizeT DestNum = Dest->getIndex();
assert(DestNum < Metadata.size()); assert(DestNum < Metadata.size());
......
...@@ -316,6 +316,8 @@ TargetX8632::TargetX8632(Cfg *Func) ...@@ -316,6 +316,8 @@ TargetX8632::TargetX8632(Cfg *Func)
void TargetX8632::translateO2() { void TargetX8632::translateO2() {
TimerMarker T(TimerStack::TT_O2, Func); TimerMarker T(TimerStack::TT_O2, Func);
initFakeKilledScratchRegisters();
if (!Ctx->getFlags().PhiEdgeSplit) { if (!Ctx->getFlags().PhiEdgeSplit) {
// Lower Phi instructions. // Lower Phi instructions.
Func->placePhiLoads(); Func->placePhiLoads();
...@@ -411,6 +413,9 @@ void TargetX8632::translateO2() { ...@@ -411,6 +413,9 @@ void TargetX8632::translateO2() {
void TargetX8632::translateOm1() { void TargetX8632::translateOm1() {
TimerMarker T(TimerStack::TT_Om1, Func); TimerMarker T(TimerStack::TT_Om1, Func);
initFakeKilledScratchRegisters();
Func->placePhiLoads(); Func->placePhiLoads();
if (Func->hasError()) if (Func->hasError())
return; return;
...@@ -1869,12 +1874,9 @@ void TargetX8632::lowerCall(const InstCall *Instr) { ...@@ -1869,12 +1874,9 @@ void TargetX8632::lowerCall(const InstCall *Instr) {
} }
// Insert a register-kill pseudo instruction. // Insert a register-kill pseudo instruction.
VarList KilledRegs; assert(!FakeKilledScratchRegisters.empty());
for (SizeT i = 0; i < ScratchRegs.size(); ++i) { Context.insert(
if (ScratchRegs[i]) InstFakeKill::create(Func, FakeKilledScratchRegisters, NewCall));
KilledRegs.push_back(Func->getTarget()->getPhysicalRegister(i));
}
Context.insert(InstFakeKill::create(Func, KilledRegs, NewCall));
// Generate a FakeUse to keep the call live if necessary. // Generate a FakeUse to keep the call live if necessary.
if (Instr->hasSideEffects() && ReturnReg) { if (Instr->hasSideEffects() && ReturnReg) {
...@@ -4540,8 +4542,7 @@ void TargetX8632::postLower() { ...@@ -4540,8 +4542,7 @@ void TargetX8632::postLower() {
// allocator, for example compute live ranges only for pre-colored // allocator, for example compute live ranges only for pre-colored
// and infinite-weight variables and run the existing linear-scan // and infinite-weight variables and run the existing linear-scan
// allocator. // allocator.
if (llvm::isa<InstFakeKill>(Inst)) assert(!llvm::isa<InstFakeKill>(Inst) || Inst->getSrcSize() == 0);
continue;
for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) { for (SizeT SrcNum = 0; SrcNum < Inst->getSrcSize(); ++SrcNum) {
Operand *Src = Inst->getSrc(SrcNum); Operand *Src = Inst->getSrc(SrcNum);
SizeT NumVars = Src->getNumVars(); SizeT NumVars = Src->getNumVars();
...@@ -4563,9 +4564,6 @@ void TargetX8632::postLower() { ...@@ -4563,9 +4564,6 @@ void TargetX8632::postLower() {
FreedRegisters.reset(); FreedRegisters.reset();
if (Inst->isDeleted()) if (Inst->isDeleted())
continue; continue;
// Skip FakeKill instructions like above.
if (llvm::isa<InstFakeKill>(Inst))
continue;
// Iterate over all variables referenced in the instruction, // Iterate over all variables referenced in the instruction,
// including the Dest variable (if any). If the variable is // including the Dest variable (if any). If the variable is
// marked as infinite-weight, find it a register. If this // marked as infinite-weight, find it a register. If this
...@@ -4579,6 +4577,8 @@ void TargetX8632::postLower() { ...@@ -4579,6 +4577,8 @@ void TargetX8632::postLower() {
SizeT NumSrcs = Inst->getSrcSize(); SizeT NumSrcs = Inst->getSrcSize();
if (Dest) if (Dest)
++NumSrcs; ++NumSrcs;
if (NumSrcs == 0)
continue;
OperandList Srcs(NumSrcs); OperandList Srcs(NumSrcs);
for (SizeT i = 0; i < Inst->getSrcSize(); ++i) for (SizeT i = 0; i < Inst->getSrcSize(); ++i)
Srcs[i] = Inst->getSrc(i); Srcs[i] = Inst->getSrc(i);
......
...@@ -484,10 +484,20 @@ protected: ...@@ -484,10 +484,20 @@ protected:
SizeT NextLabelNumber; SizeT NextLabelNumber;
bool ComputedLiveRanges; bool ComputedLiveRanges;
VarList PhysicalRegisters[IceType_NUM]; VarList PhysicalRegisters[IceType_NUM];
VarList FakeKilledScratchRegisters;
static IceString RegNames[]; static IceString RegNames[];
private: private:
~TargetX8632() override {} ~TargetX8632() override {}
// Ideally, this initialization would be done in the constructor,
// but we need to defer it until after the initial CFG is built,
// because some of the bitcode reader tests rely on the order that
// Variables are created and their default printable names.
void initFakeKilledScratchRegisters() {
for (SizeT I = 0; I < ScratchRegs.size(); ++I)
if (ScratchRegs[I])
FakeKilledScratchRegisters.push_back(getPhysicalRegister(I));
}
template <typename T> void emitConstantPool() const; template <typename T> void emitConstantPool() const;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment