microinstruction: Optimize storage of associated pseudooperation
This commit is contained in:
parent
91d1f944e3
commit
ac19912fe7
2 changed files with 30 additions and 97 deletions
|
@ -583,40 +583,19 @@ bool Inst::AreAllArgsImmediates() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inst::HasAssociatedPseudoOperation() const {
|
bool Inst::HasAssociatedPseudoOperation() const {
|
||||||
return carry_inst
|
return next_pseudoop && !IsAPseudoOperation();
|
||||||
|| overflow_inst
|
|
||||||
|| ge_inst
|
|
||||||
|| nzcv_inst
|
|
||||||
|| upper_inst
|
|
||||||
|| lower_inst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
|
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
|
||||||
// This is faster than doing a search through the block.
|
Inst* pseudoop = next_pseudoop;
|
||||||
switch (opcode) {
|
while (pseudoop) {
|
||||||
case Opcode::GetCarryFromOp:
|
if (pseudoop->GetOpcode() == opcode) {
|
||||||
ASSERT(!carry_inst || carry_inst->GetOpcode() == Opcode::GetCarryFromOp);
|
ASSERT(pseudoop->GetArg(0).GetInst() == this);
|
||||||
return carry_inst;
|
return pseudoop;
|
||||||
case Opcode::GetOverflowFromOp:
|
}
|
||||||
ASSERT(!overflow_inst || overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp);
|
pseudoop = pseudoop->next_pseudoop;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
ASSERT_FALSE("Not a valid pseudo-operation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type Inst::GetType() const {
|
Type Inst::GetType() const {
|
||||||
|
@ -679,67 +658,31 @@ void Inst::ReplaceUsesWith(Value replacement) {
|
||||||
void Inst::Use(const Value& value) {
|
void Inst::Use(const Value& value) {
|
||||||
value.GetInst()->use_count++;
|
value.GetInst()->use_count++;
|
||||||
|
|
||||||
switch (op) {
|
if (IsAPseudoOperation()) {
|
||||||
case Opcode::GetCarryFromOp:
|
if (op == Opcode::GetNZCVFromOp) {
|
||||||
ASSERT_MSG(!value.GetInst()->carry_inst, "Only one of each type of pseudo-op allowed");
|
ASSERT_MSG(value.GetInst()->MayGetNZCVFromOp(), "This value doesn't support the GetNZCVFromOp pseduo-op");
|
||||||
value.GetInst()->carry_inst = this;
|
}
|
||||||
break;
|
|
||||||
case Opcode::GetOverflowFromOp:
|
Inst* insert_point = value.GetInst();
|
||||||
ASSERT_MSG(!value.GetInst()->overflow_inst, "Only one of each type of pseudo-op allowed");
|
while (insert_point->next_pseudoop) {
|
||||||
value.GetInst()->overflow_inst = this;
|
insert_point = insert_point->next_pseudoop;
|
||||||
break;
|
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
|
||||||
case Opcode::GetGEFromOp:
|
}
|
||||||
ASSERT_MSG(!value.GetInst()->ge_inst, "Only one of each type of pseudo-op allowed");
|
insert_point->next_pseudoop = this;
|
||||||
value.GetInst()->ge_inst = this;
|
|
||||||
break;
|
|
||||||
case Opcode::GetNZCVFromOp:
|
|
||||||
ASSERT_MSG(!value.GetInst()->nzcv_inst, "Only one of each type of pseudo-op allowed");
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inst::UndoUse(const Value& value) {
|
void Inst::UndoUse(const Value& value) {
|
||||||
value.GetInst()->use_count--;
|
value.GetInst()->use_count--;
|
||||||
|
|
||||||
switch (op) {
|
if (IsAPseudoOperation()) {
|
||||||
case Opcode::GetCarryFromOp:
|
Inst* insert_point = value.GetInst();
|
||||||
ASSERT(value.GetInst()->carry_inst->GetOpcode() == Opcode::GetCarryFromOp);
|
while (insert_point->next_pseudoop != this) {
|
||||||
value.GetInst()->carry_inst = nullptr;
|
insert_point = insert_point->next_pseudoop;
|
||||||
break;
|
DEBUG_ASSERT(insert_point->GetArg(0).GetInst() == this);
|
||||||
case Opcode::GetOverflowFromOp:
|
}
|
||||||
ASSERT(value.GetInst()->overflow_inst->GetOpcode() == Opcode::GetOverflowFromOp);
|
insert_point->next_pseudoop = next_pseudoop;
|
||||||
value.GetInst()->overflow_inst = nullptr;
|
next_pseudoop = 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -149,18 +149,8 @@ private:
|
||||||
size_t use_count = 0;
|
size_t use_count = 0;
|
||||||
std::array<Value, max_arg_count> args;
|
std::array<Value, max_arg_count> args;
|
||||||
|
|
||||||
// Pointers to related pseudooperations:
|
// Linked list of pseudooperations associated with this instruction.
|
||||||
// Since not all combinations are possible, we use a union to save space
|
Inst* next_pseudoop = nullptr;
|
||||||
union {
|
|
||||||
Inst* carry_inst = nullptr;
|
|
||||||
Inst* ge_inst;
|
|
||||||
Inst* upper_inst;
|
|
||||||
};
|
|
||||||
Inst* overflow_inst = nullptr;
|
|
||||||
union {
|
|
||||||
Inst* nzcv_inst = nullptr;
|
|
||||||
Inst* lower_inst;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Dynarmic::IR
|
} // namespace Dynarmic::IR
|
||||||
|
|
Loading…
Reference in a new issue