Commit b82baf2f by Jim Stichnoth

Subzero: More asm-verbose fixes.

It turns out that code deleted in 9a05aea8 actually had a legitimate purpose, so it is added back, this time with more extensive comments justifying it. Also, takes the instruction's IsDestNonKillable flag into account when updating the live register usage count (along with extra comments on why that is necessary). Furthermore, removes an unnecessary assert that otherwise fails when --asm-verbose is used with --filetype=iasm or --filetype-obj. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/1158113002
parent 0d9faeac
...@@ -495,7 +495,6 @@ void Cfg::emit() { ...@@ -495,7 +495,6 @@ void Cfg::emit() {
void Cfg::emitIAS() { void Cfg::emitIAS() {
TimerMarker T(TimerStack::TT_emit, this); TimerMarker T(TimerStack::TT_emit, this);
assert(!Ctx->getFlags().getDecorateAsm());
// The emitIAS() routines emit into the internal assembler buffer, // The emitIAS() routines emit into the internal assembler buffer,
// so there's no need to lock the streams. // so there's no need to lock the streams.
for (CfgNode *Node : Nodes) for (CfgNode *Node : Nodes)
......
...@@ -828,21 +828,26 @@ void emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr, ...@@ -828,21 +828,26 @@ void emitLiveRangesEnded(Ostream &Str, const Cfg *Func, const Inst *Instr,
return; return;
bool First = true; bool First = true;
Variable *Dest = Instr->getDest(); Variable *Dest = Instr->getDest();
if (Dest && Dest->hasReg()) // Normally we increment the live count for the dest register. But
// we shouldn't if the instruction's IsDestNonKillable flag is set,
// because this means that the target lowering created this
// instruction as a non-SSA assignment; i.e., a different, previous
// instruction started the dest variable's live range.
if (!Instr->isDestNonKillable() && Dest && Dest->hasReg())
++LiveRegCount[Dest->getRegNum()]; ++LiveRegCount[Dest->getRegNum()];
for (SizeT I = 0; I < Instr->getSrcSize(); ++I) { for (SizeT I = 0; I < Instr->getSrcSize(); ++I) {
Operand *Src = Instr->getSrc(I); Operand *Src = Instr->getSrc(I);
SizeT NumVars = Src->getNumVars(); SizeT NumVars = Src->getNumVars();
for (SizeT J = 0; J < NumVars; ++J) { for (SizeT J = 0; J < NumVars; ++J) {
const Variable *Var = Src->getVar(J); const Variable *Var = Src->getVar(J);
bool ShouldEmit = Instr->isLastUse(Var); bool ShouldReport = Instr->isLastUse(Var);
if (Var->hasReg()) { if (ShouldReport && Var->hasReg()) {
// Don't report end of live range until the live count reaches 0. // Don't report end of live range until the live count reaches 0.
SizeT NewCount = --LiveRegCount[Var->getRegNum()]; SizeT NewCount = --LiveRegCount[Var->getRegNum()];
if (NewCount) if (NewCount)
ShouldEmit = false; ShouldReport = false;
} }
if (ShouldEmit) { if (ShouldReport) {
if (First) if (First)
Str << " \t# END="; Str << " \t# END=";
else else
...@@ -885,6 +890,10 @@ void CfgNode::emit(Cfg *Func) const { ...@@ -885,6 +890,10 @@ void CfgNode::emit(Cfg *Func) const {
bool DecorateAsm = bool DecorateAsm =
Liveness && Func->getContext()->getFlags().getDecorateAsm(); Liveness && Func->getContext()->getFlags().getDecorateAsm();
Str << getAsmName() << ":\n"; Str << getAsmName() << ":\n";
// LiveRegCount keeps track of the number of currently live
// variables that each register is assigned to. Normally that would
// be only 0 or 1, but the register allocator's AllowOverlap
// inference allows it to be greater than 1 for short periods.
std::vector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters()); std::vector<SizeT> LiveRegCount(Func->getTarget()->getNumRegisters());
if (DecorateAsm) { if (DecorateAsm) {
const bool IsLiveIn = true; const bool IsLiveIn = true;
...@@ -900,8 +909,21 @@ void CfgNode::emit(Cfg *Func) const { ...@@ -900,8 +909,21 @@ void CfgNode::emit(Cfg *Func) const {
for (const Inst &I : Insts) { for (const Inst &I : Insts) {
if (I.isDeleted()) if (I.isDeleted())
continue; continue;
if (I.isRedundantAssign()) if (I.isRedundantAssign()) {
// Usually, redundant assignments end the live range of the src
// variable and begin the live range of the dest variable, with
// no net effect on the liveness of their register. However, if
// the register allocator infers the AllowOverlap condition,
// then this may be a redundant assignment that does not end the
// src variable's live range, in which case the active variable
// count for that register needs to be bumped. That normally
// would have happened as part of emitLiveRangesEnded(), but
// that isn't called for redundant assignments.
Variable *Dest = I.getDest();
if (DecorateAsm && Dest->hasReg() && !I.isLastUse(I.getSrc(0)))
++LiveRegCount[Dest->getRegNum()];
continue; continue;
}
I.emit(Func); I.emit(Func);
if (DecorateAsm) if (DecorateAsm)
emitLiveRangesEnded(Str, Func, &I, LiveRegCount); emitLiveRangesEnded(Str, Func, &I, LiveRegCount);
......
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