microinstruction: Optimize storage of associated pseudooperation

This commit is contained in:
Merry 2022-07-17 09:03:33 +01:00
parent 91d1f944e3
commit ac19912fe7
2 changed files with 30 additions and 97 deletions

View file

@ -583,40 +583,19 @@ bool Inst::AreAllArgsImmediates() const {
}
bool Inst::HasAssociatedPseudoOperation() const {
return carry_inst
|| overflow_inst
|| ge_inst
|| nzcv_inst
|| upper_inst
|| lower_inst;
return next_pseudoop && !IsAPseudoOperation();
}
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
// This is faster than doing a search through the block.
switch (opcode) {
case Opcode::GetCarryFromOp:
ASSERT(!carry_inst || carry_inst->GetOpcode() == Opcode::GetCarryFromOp);
return carry_inst;
case Opcode::GetOverflowFromOp:
ASSERT(!overflow_inst || overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp);
return overflow_inst;
case Opcode::GetGEFromOp:
ASSERT(!ge_inst || ge_inst->GetOpcode() == Opcode::GetGEFromOp);
return ge_inst;
case Opcode::GetNZCVFromOp:
ASSERT(!nzcv_inst || nzcv_inst->GetOpcode() == Opcode::GetNZCVFromOp);
return nzcv_inst;
case Opcode::GetUpperFromOp:
ASSERT(!upper_inst || upper_inst->GetOpcode() == Opcode::GetUpperFromOp);
return upper_inst;
case Opcode::GetLowerFromOp:
ASSERT(!lower_inst || lower_inst->GetOpcode() == Opcode::GetLowerFromOp);
return lower_inst;
default:
break;
Inst* pseudoop = next_pseudoop;
while (pseudoop) {
if (pseudoop->GetOpcode() == opcode) {
ASSERT(pseudoop->GetArg(0).GetInst() == this);
return pseudoop;
}
ASSERT_FALSE("Not a valid pseudo-operation");
pseudoop = pseudoop->next_pseudoop;
}
return nullptr;
}
Type Inst::GetType() const {
@ -679,67 +658,31 @@ void Inst::ReplaceUsesWith(Value replacement) {
void Inst::Use(const Value& value) {
value.GetInst()->use_count++;
switch (op) {
case Opcode::GetCarryFromOp:
ASSERT_MSG(!value.GetInst()->carry_inst, "Only one of each type of pseudo-op allowed");
value.GetInst()->carry_inst = this;
break;
case Opcode::GetOverflowFromOp:
ASSERT_MSG(!value.GetInst()->overflow_inst, "Only one of each type of pseudo-op allowed");
value.GetInst()->overflow_inst = this;
break;
case Opcode::GetGEFromOp:
ASSERT_MSG(!value.GetInst()->ge_inst, "Only one of each type of pseudo-op allowed");
value.GetInst()->ge_inst = this;
break;
case Opcode::GetNZCVFromOp:
ASSERT_MSG(!value.GetInst()->nzcv_inst, "Only one of each type of pseudo-op allowed");
if (IsAPseudoOperation()) {
if (op == Opcode::GetNZCVFromOp) {
ASSERT_MSG(value.GetInst()->MayGetNZCVFromOp(), "This value doesn't support the GetNZCVFromOp pseduo-op");
value.GetInst()->nzcv_inst = this;
break;
case Opcode::GetUpperFromOp:
ASSERT_MSG(!value.GetInst()->upper_inst, "Only one of each type of pseudo-op allowed");
value.GetInst()->upper_inst = this;
break;
case Opcode::GetLowerFromOp:
ASSERT_MSG(!value.GetInst()->lower_inst, "Only one of each type of pseudo-op allowed");
value.GetInst()->lower_inst = this;
break;
default:
break;
}
Inst* insert_point = value.GetInst();
while (insert_point->next_pseudoop) {
insert_point = insert_point->next_pseudoop;
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
}
insert_point->next_pseudoop = this;
}
}
void Inst::UndoUse(const Value& value) {
value.GetInst()->use_count--;
switch (op) {
case Opcode::GetCarryFromOp:
ASSERT(value.GetInst()->carry_inst->GetOpcode() == Opcode::GetCarryFromOp);
value.GetInst()->carry_inst = nullptr;
break;
case Opcode::GetOverflowFromOp:
ASSERT(value.GetInst()->overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp);
value.GetInst()->overflow_inst = nullptr;
break;
case Opcode::GetGEFromOp:
ASSERT(value.GetInst()->ge_inst->GetOpcode() == Opcode::GetGEFromOp);
value.GetInst()->ge_inst = nullptr;
break;
case Opcode::GetNZCVFromOp:
ASSERT(value.GetInst()->nzcv_inst->GetOpcode() == Opcode::GetNZCVFromOp);
value.GetInst()->nzcv_inst = nullptr;
break;
case Opcode::GetUpperFromOp:
ASSERT(value.GetInst()->upper_inst->GetOpcode() == Opcode::GetUpperFromOp);
value.GetInst()->upper_inst = nullptr;
break;
case Opcode::GetLowerFromOp:
ASSERT(value.GetInst()->lower_inst->GetOpcode() == Opcode::GetLowerFromOp);
value.GetInst()->lower_inst = nullptr;
break;
default:
break;
if (IsAPseudoOperation()) {
Inst* insert_point = value.GetInst();
while (insert_point->next_pseudoop != this) {
insert_point = insert_point->next_pseudoop;
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
}
insert_point->next_pseudoop = next_pseudoop;
next_pseudoop = nullptr;
}
}

View file

@ -149,18 +149,8 @@ private:
size_t use_count = 0;
std::array<Value, max_arg_count> args;
// Pointers to related pseudooperations:
// Since not all combinations are possible, we use a union to save space
union {
Inst* carry_inst = nullptr;
Inst* ge_inst;
Inst* upper_inst;
};
Inst* overflow_inst = nullptr;
union {
Inst* nzcv_inst = nullptr;
Inst* lower_inst;
};
// Linked list of pseudooperations associated with this instruction.
Inst* next_pseudoop = nullptr;
};
} // namespace Dynarmic::IR