microinstruction: Make use_count private (#53)
Makes the operation a part of the direct interface.
This commit is contained in:
parent
3621a925b2
commit
de1f831d79
6 changed files with 31 additions and 32 deletions
|
@ -473,7 +473,7 @@ void EmitX64::EmitMostSignificantWord(IR::Block& block, IR::Inst* inst) {
|
||||||
|
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
Xbyak::Reg64 carry = reg_alloc.DefGpr(carry_inst);
|
Xbyak::Reg64 carry = reg_alloc.DefGpr(carry_inst);
|
||||||
|
|
||||||
code->setc(carry.cvt8());
|
code->setc(carry.cvt8());
|
||||||
|
@ -524,7 +524,7 @@ void EmitX64::EmitLogicalShiftLeft(IR::Block& block, IR::Inst* inst) {
|
||||||
if (!carry_inst) {
|
if (!carry_inst) {
|
||||||
if (!inst->GetArg(2).IsImmediate()) {
|
if (!inst->GetArg(2).IsImmediate()) {
|
||||||
// TODO: Remove redundant argument.
|
// TODO: Remove redundant argument.
|
||||||
reg_alloc.DecrementRemainingUses(inst->GetArg(2).GetInst());
|
inst->GetArg(2).GetInst()->DecrementRemainingUses();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
@ -553,7 +553,7 @@ void EmitX64::EmitLogicalShiftLeft(IR::Block& block, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ void EmitX64::EmitLogicalShiftRight(IR::Block& block, IR::Inst* inst) {
|
||||||
if (!carry_inst) {
|
if (!carry_inst) {
|
||||||
if (!inst->GetArg(2).IsImmediate()) {
|
if (!inst->GetArg(2).IsImmediate()) {
|
||||||
// TODO: Remove redundant argument.
|
// TODO: Remove redundant argument.
|
||||||
reg_alloc.DecrementRemainingUses(inst->GetArg(2).GetInst());
|
inst->GetArg(2).GetInst()->DecrementRemainingUses();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
@ -646,7 +646,7 @@ void EmitX64::EmitLogicalShiftRight(IR::Block& block, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
|
||||||
|
@ -722,7 +722,7 @@ void EmitX64::EmitArithmeticShiftRight(IR::Block& block, IR::Inst* inst) {
|
||||||
if (!carry_inst) {
|
if (!carry_inst) {
|
||||||
if (!inst->GetArg(2).IsImmediate()) {
|
if (!inst->GetArg(2).IsImmediate()) {
|
||||||
// TODO: Remove redundant argument.
|
// TODO: Remove redundant argument.
|
||||||
reg_alloc.DecrementRemainingUses(inst->GetArg(2).GetInst());
|
inst->GetArg(2).GetInst()->DecrementRemainingUses();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
@ -749,7 +749,7 @@ void EmitX64::EmitArithmeticShiftRight(IR::Block& block, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
|
||||||
|
@ -805,7 +805,7 @@ void EmitX64::EmitRotateRight(IR::Block& block, IR::Inst* inst) {
|
||||||
if (!carry_inst) {
|
if (!carry_inst) {
|
||||||
if (!inst->GetArg(2).IsImmediate()) {
|
if (!inst->GetArg(2).IsImmediate()) {
|
||||||
// TODO: Remove redundant argument.
|
// TODO: Remove redundant argument.
|
||||||
reg_alloc.DecrementRemainingUses(inst->GetArg(2).GetInst());
|
inst->GetArg(2).GetInst()->DecrementRemainingUses();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
@ -824,7 +824,7 @@ void EmitX64::EmitRotateRight(IR::Block& block, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
|
|
||||||
auto shift_arg = inst->GetArg(1);
|
auto shift_arg = inst->GetArg(1);
|
||||||
|
|
||||||
|
@ -886,7 +886,7 @@ void EmitX64::EmitRotateRightExtended(IR::Block& block, IR::Inst* inst) {
|
||||||
|
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
code->setc(carry);
|
code->setc(carry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -946,12 +946,12 @@ void EmitX64::EmitAddWithCarry(IR::Block& block, IR::Inst* inst) {
|
||||||
|
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
code->setc(carry);
|
code->setc(carry);
|
||||||
}
|
}
|
||||||
if (overflow_inst) {
|
if (overflow_inst) {
|
||||||
EraseInstruction(block, overflow_inst);
|
EraseInstruction(block, overflow_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
code->seto(overflow);
|
code->seto(overflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,12 +1015,12 @@ void EmitX64::EmitSubWithCarry(IR::Block& block, IR::Inst* inst) {
|
||||||
|
|
||||||
if (carry_inst) {
|
if (carry_inst) {
|
||||||
EraseInstruction(block, carry_inst);
|
EraseInstruction(block, carry_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
code->setnc(carry);
|
code->setnc(carry);
|
||||||
}
|
}
|
||||||
if (overflow_inst) {
|
if (overflow_inst) {
|
||||||
EraseInstruction(block, overflow_inst);
|
EraseInstruction(block, overflow_inst);
|
||||||
reg_alloc.DecrementRemainingUses(inst);
|
inst->DecrementRemainingUses();
|
||||||
code->seto(overflow);
|
code->seto(overflow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ void RegAlloc::RegisterAddDef(IR::Inst* def_inst, const IR::Value& use_inst) {
|
||||||
DEBUG_ASSERT_MSG(ValueLocation(use_inst.GetInst()), "use_inst must already be defined");
|
DEBUG_ASSERT_MSG(ValueLocation(use_inst.GetInst()), "use_inst must already be defined");
|
||||||
HostLoc location = *ValueLocation(use_inst.GetInst());
|
HostLoc location = *ValueLocation(use_inst.GetInst());
|
||||||
LocInfo(location).values.emplace_back(def_inst);
|
LocInfo(location).values.emplace_back(def_inst);
|
||||||
DecrementRemainingUses(use_inst.GetInst());
|
use_inst.GetInst()->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(location).IsIdle());
|
DEBUG_ASSERT(LocInfo(location).IsIdle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ HostLoc RegAlloc::UseScratchHostLocReg(IR::Inst* use_inst, HostLocList desired_l
|
||||||
if (HostLocIsSpill(current_location)) {
|
if (HostLocIsSpill(current_location)) {
|
||||||
EmitMove(new_location, current_location);
|
EmitMove(new_location, current_location);
|
||||||
LocInfo(new_location).is_being_used = true;
|
LocInfo(new_location).is_being_used = true;
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(new_location).IsScratch());
|
DEBUG_ASSERT(LocInfo(new_location).IsScratch());
|
||||||
return new_location;
|
return new_location;
|
||||||
} else if (HostLocIsRegister(current_location)) {
|
} else if (HostLocIsRegister(current_location)) {
|
||||||
|
@ -249,7 +249,7 @@ HostLoc RegAlloc::UseScratchHostLocReg(IR::Inst* use_inst, HostLocList desired_l
|
||||||
|
|
||||||
LocInfo(new_location).is_being_used = true;
|
LocInfo(new_location).is_being_used = true;
|
||||||
LocInfo(new_location).values.clear();
|
LocInfo(new_location).values.clear();
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(new_location).IsScratch());
|
DEBUG_ASSERT(LocInfo(new_location).IsScratch());
|
||||||
return new_location;
|
return new_location;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +348,7 @@ bool RegAlloc::IsRegisterAllocated(HostLoc loc) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RegAlloc::IsLastUse(const IR::Inst* inst) const {
|
bool RegAlloc::IsLastUse(const IR::Inst* inst) const {
|
||||||
if (inst->use_count > 1)
|
if (inst->UseCount() > 1)
|
||||||
return false;
|
return false;
|
||||||
return LocInfo(*ValueLocation(inst)).values.size() == 1;
|
return LocInfo(*ValueLocation(inst)).values.size() == 1;
|
||||||
}
|
}
|
||||||
|
@ -390,11 +390,6 @@ void RegAlloc::EndOfAllocScope() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegAlloc::DecrementRemainingUses(IR::Inst* value) {
|
|
||||||
ASSERT_MSG(value->HasUses(), "value doesn't have any remaining uses");
|
|
||||||
value->use_count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegAlloc::AssertNoMoreUses() {
|
void RegAlloc::AssertNoMoreUses() {
|
||||||
ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i){ return i.values.empty(); }));
|
ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i){ return i.values.empty(); }));
|
||||||
}
|
}
|
||||||
|
@ -446,14 +441,14 @@ std::tuple<HostLoc, bool> RegAlloc::UseHostLoc(IR::Inst* use_inst, HostLocList d
|
||||||
EmitMove(new_location, current_location);
|
EmitMove(new_location, current_location);
|
||||||
LocInfo(new_location).is_being_used = true;
|
LocInfo(new_location).is_being_used = true;
|
||||||
LocInfo(new_location).values.emplace_back(use_inst);
|
LocInfo(new_location).values.emplace_back(use_inst);
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(new_location).IsUse());
|
DEBUG_ASSERT(LocInfo(new_location).IsUse());
|
||||||
return std::make_tuple(new_location, false);
|
return std::make_tuple(new_location, false);
|
||||||
} else {
|
} else {
|
||||||
bool was_being_used = LocInfo(current_location).is_being_used;
|
bool was_being_used = LocInfo(current_location).is_being_used;
|
||||||
ASSERT(LocInfo(current_location).IsUse() || LocInfo(current_location).IsIdle());
|
ASSERT(LocInfo(current_location).IsUse() || LocInfo(current_location).IsIdle());
|
||||||
LocInfo(current_location).is_being_used = true;
|
LocInfo(current_location).is_being_used = true;
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(current_location).IsUse());
|
DEBUG_ASSERT(LocInfo(current_location).IsUse());
|
||||||
return std::make_tuple(current_location, was_being_used);
|
return std::make_tuple(current_location, was_being_used);
|
||||||
}
|
}
|
||||||
|
@ -462,7 +457,7 @@ std::tuple<HostLoc, bool> RegAlloc::UseHostLoc(IR::Inst* use_inst, HostLocList d
|
||||||
if (HostLocIsSpill(current_location)) {
|
if (HostLocIsSpill(current_location)) {
|
||||||
bool was_being_used = LocInfo(current_location).is_being_used;
|
bool was_being_used = LocInfo(current_location).is_being_used;
|
||||||
LocInfo(current_location).is_being_used = true;
|
LocInfo(current_location).is_being_used = true;
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(current_location).IsUse());
|
DEBUG_ASSERT(LocInfo(current_location).IsUse());
|
||||||
return std::make_tuple(current_location, was_being_used);
|
return std::make_tuple(current_location, was_being_used);
|
||||||
} else if (HostLocIsRegister(current_location)) {
|
} else if (HostLocIsRegister(current_location)) {
|
||||||
|
@ -471,7 +466,7 @@ std::tuple<HostLoc, bool> RegAlloc::UseHostLoc(IR::Inst* use_inst, HostLocList d
|
||||||
EmitExchange(new_location, current_location);
|
EmitExchange(new_location, current_location);
|
||||||
std::swap(LocInfo(new_location), LocInfo(current_location));
|
std::swap(LocInfo(new_location), LocInfo(current_location));
|
||||||
LocInfo(new_location).is_being_used = true;
|
LocInfo(new_location).is_being_used = true;
|
||||||
DecrementRemainingUses(use_inst);
|
use_inst->DecrementRemainingUses();
|
||||||
DEBUG_ASSERT(LocInfo(new_location).IsUse());
|
DEBUG_ASSERT(LocInfo(new_location).IsUse());
|
||||||
return std::make_tuple(new_location, false);
|
return std::make_tuple(new_location, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,8 +143,6 @@ public:
|
||||||
|
|
||||||
// TODO: Values in host flags
|
// TODO: Values in host flags
|
||||||
|
|
||||||
void DecrementRemainingUses(IR::Inst* value);
|
|
||||||
|
|
||||||
void EndOfAllocScope();
|
void EndOfAllocScope();
|
||||||
|
|
||||||
void AssertNoMoreUses();
|
void AssertNoMoreUses();
|
||||||
|
|
|
@ -217,7 +217,11 @@ bool Inst::MayHaveSideEffects() const {
|
||||||
WritesToFPSCR() ||
|
WritesToFPSCR() ||
|
||||||
AltersExclusiveState() ||
|
AltersExclusiveState() ||
|
||||||
IsMemoryWrite();
|
IsMemoryWrite();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Inst::DecrementRemainingUses() {
|
||||||
|
ASSERT_MSG(HasUses(), "Microinstruction doesn't have any remaining uses");
|
||||||
|
use_count--;
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
|
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
|
||||||
|
|
|
@ -73,7 +73,10 @@ public:
|
||||||
/// Determines whether or not this instruction may have side-effects.
|
/// Determines whether or not this instruction may have side-effects.
|
||||||
bool MayHaveSideEffects() const;
|
bool MayHaveSideEffects() const;
|
||||||
|
|
||||||
|
size_t UseCount() const { return use_count; }
|
||||||
bool HasUses() const { return use_count > 0; }
|
bool HasUses() const { return use_count > 0; }
|
||||||
|
void DecrementRemainingUses();
|
||||||
|
|
||||||
/// Gets a pseudo-operation associated with this instruction.
|
/// Gets a pseudo-operation associated with this instruction.
|
||||||
Inst* GetAssociatedPseudoOperation(Opcode opcode);
|
Inst* GetAssociatedPseudoOperation(Opcode opcode);
|
||||||
|
|
||||||
|
@ -91,13 +94,12 @@ public:
|
||||||
|
|
||||||
void ReplaceUsesWith(Value& replacement);
|
void ReplaceUsesWith(Value& replacement);
|
||||||
|
|
||||||
size_t use_count = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Use(Value& value);
|
void Use(Value& value);
|
||||||
void UndoUse(Value& value);
|
void UndoUse(Value& value);
|
||||||
|
|
||||||
Opcode op;
|
Opcode op;
|
||||||
|
size_t use_count = 0;
|
||||||
std::array<Value, 3> args;
|
std::array<Value, 3> args;
|
||||||
|
|
||||||
Inst* carry_inst = nullptr;
|
Inst* carry_inst = nullptr;
|
||||||
|
|
|
@ -37,7 +37,7 @@ void VerificationPass(const IR::Block& block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& pair : actual_uses) {
|
for (const auto& pair : actual_uses) {
|
||||||
ASSERT(pair.first->use_count == pair.second);
|
ASSERT(pair.first->UseCount() == pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue