mirror of
https://git.suyu.dev/suyu/dynarmic.git
synced 2026-01-07 06:58:15 +01:00
Implement some simple IR optimizations (get/set eliminiation and DCE)
This commit is contained in:
parent
90d317b868
commit
5fbfc6c155
16 changed files with 544 additions and 300 deletions
|
|
@ -137,7 +137,7 @@ void EmitX64::EmitGetNFlag(IR::Value* value_) {
|
|||
void EmitX64::EmitSetNFlag(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg to_store = reg_alloc.UseRegister(value->GetArg(0).get());
|
||||
X64Reg to_store = reg_alloc.UseScratchRegister(value->GetArg(0).get());
|
||||
|
||||
// TODO: Flag optimization
|
||||
|
||||
|
|
@ -161,7 +161,7 @@ void EmitX64::EmitGetZFlag(IR::Value* value_) {
|
|||
void EmitX64::EmitSetZFlag(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg to_store = reg_alloc.UseRegister(value->GetArg(0).get());
|
||||
X64Reg to_store = reg_alloc.UseScratchRegister(value->GetArg(0).get());
|
||||
|
||||
// TODO: Flag optimization
|
||||
|
||||
|
|
@ -185,7 +185,7 @@ void EmitX64::EmitGetCFlag(IR::Value* value_) {
|
|||
void EmitX64::EmitSetCFlag(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg to_store = reg_alloc.UseRegister(value->GetArg(0).get());
|
||||
X64Reg to_store = reg_alloc.UseScratchRegister(value->GetArg(0).get());
|
||||
|
||||
// TODO: Flag optimization
|
||||
|
||||
|
|
@ -209,7 +209,7 @@ void EmitX64::EmitGetVFlag(IR::Value* value_) {
|
|||
void EmitX64::EmitSetVFlag(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg to_store = reg_alloc.UseRegister(value->GetArg(0).get());
|
||||
X64Reg to_store = reg_alloc.UseScratchRegister(value->GetArg(0).get());
|
||||
|
||||
// TODO: Flag optimization
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ void EmitX64::EmitSetVFlag(IR::Value* value_) {
|
|||
void EmitX64::EmitBXWritePC(IR::Value* value_) {
|
||||
auto value = reinterpret_cast<IR::Inst*>(value_);
|
||||
|
||||
X64Reg new_pc = reg_alloc.UseRegister(value->GetArg(0).get());
|
||||
X64Reg new_pc = reg_alloc.UseScratchRegister(value->GetArg(0).get());
|
||||
X64Reg tmp1 = reg_alloc.ScratchRegister();
|
||||
X64Reg tmp2 = reg_alloc.ScratchRegister();
|
||||
|
||||
|
|
@ -312,6 +312,7 @@ void EmitX64::EmitLogicalShiftLeft(IR::Value* value_) {
|
|||
X64Reg shift = reg_alloc.UseRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
X64Reg zero = reg_alloc.ScratchRegister();
|
||||
reg_alloc.DecrementRemainingUses(value->GetArg(2).get());
|
||||
|
||||
// The 32-bit x64 SHL instruction masks the shift count by 0x1F before performing the shift.
|
||||
// ARM differs from the behaviour: It does not mask the count, so shifts above 31 result in zeros.
|
||||
|
|
@ -363,6 +364,7 @@ void EmitX64::EmitLogicalShiftRight(IR::Value* value_) {
|
|||
X64Reg shift = reg_alloc.UseRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
X64Reg zero = reg_alloc.ScratchRegister();
|
||||
reg_alloc.DecrementRemainingUses(value->GetArg(2).get());
|
||||
|
||||
// The 32-bit x64 SHR instruction masks the shift count by 0x1F before performing the shift.
|
||||
// ARM differs from the behaviour: It does not mask the count, so shifts above 31 result in zeros.
|
||||
|
|
@ -414,9 +416,10 @@ void EmitX64::EmitArithmeticShiftRight(IR::Value* value_) {
|
|||
auto carry_inst = FindUseWithOpcode(value, IR::Opcode::GetCarryFromOp);
|
||||
|
||||
if (!carry_inst) {
|
||||
X64Reg shift = reg_alloc.UseRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg shift = reg_alloc.UseScratchRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
X64Reg const31 = reg_alloc.ScratchRegister();
|
||||
reg_alloc.DecrementRemainingUses(value->GetArg(2).get());
|
||||
|
||||
// The 32-bit x64 SAR instruction masks the shift count by 0x1F before performing the shift.
|
||||
// ARM differs from the behaviour: It does not mask the count.
|
||||
|
|
@ -425,7 +428,7 @@ void EmitX64::EmitArithmeticShiftRight(IR::Value* value_) {
|
|||
code->MOV(32, R(const31), Imm32(31));
|
||||
code->MOVZX(32, 8, shift, R(shift));
|
||||
code->CMP(32, R(shift), Imm32(31));
|
||||
code->CMOVcc(32, shift, R(const31), CC_L);
|
||||
code->CMOVcc(32, shift, R(const31), CC_G);
|
||||
code->SAR(32, R(result), R(shift));
|
||||
} else {
|
||||
inhibit_emission.insert(carry_inst);
|
||||
|
|
@ -465,13 +468,14 @@ void EmitX64::EmitRotateRight(IR::Value* value_) {
|
|||
if (!carry_inst) {
|
||||
X64Reg shift = reg_alloc.UseRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
reg_alloc.DecrementRemainingUses(value->GetArg(2).get());
|
||||
|
||||
// x64 ROR instruction does (shift & 0x1F) for us.
|
||||
code->ROR(32, R(result), R(shift));
|
||||
} else {
|
||||
inhibit_emission.insert(carry_inst);
|
||||
|
||||
X64Reg shift = reg_alloc.UseRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg shift = reg_alloc.UseScratchRegister(value->GetArg(1).get(), {HostLoc::RCX});
|
||||
X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value);
|
||||
X64Reg carry = reg_alloc.UseDefRegister(value->GetArg(2).get(), carry_inst);
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include "frontend/arm_types.h"
|
||||
#include "frontend/translate/translate.h"
|
||||
#include "interface/interface.h"
|
||||
#include "ir_opt/passes.h"
|
||||
|
||||
namespace Dynarmic {
|
||||
|
||||
|
|
@ -53,6 +54,9 @@ private:
|
|||
return code_ptr;
|
||||
|
||||
IR::Block ir_block = Arm::Translate(descriptor, callbacks.MemoryRead32);
|
||||
Optimization::GetSetElimination(ir_block);
|
||||
Optimization::DeadCodeElimination(ir_block);
|
||||
Optimization::VerificationPass(ir_block);
|
||||
return emitter.Emit(descriptor, ir_block);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -141,10 +141,13 @@ Gen::X64Reg RegAlloc::UseScratchRegister(IR::Value* use_value, std::initializer_
|
|||
|
||||
if (IsRegisterOccupied(new_location)) {
|
||||
SpillRegister(new_location);
|
||||
if (current_location != new_location) {
|
||||
code->MOV(32, Gen::R(hostloc_to_x64.at(new_location)), Gen::R(hostloc_to_x64.at(current_location)));
|
||||
}
|
||||
} else {
|
||||
code->MOV(32, Gen::R(hostloc_to_x64.at(new_location)), Gen::R(hostloc_to_x64.at(current_location)));
|
||||
}
|
||||
|
||||
code->MOV(32, Gen::R(hostloc_to_x64.at(new_location)), Gen::R(hostloc_to_x64.at(current_location)));
|
||||
|
||||
hostloc_state[new_location] = HostLocState::Scratch;
|
||||
remaining_uses[use_value]--;
|
||||
} else {
|
||||
|
|
@ -203,6 +206,9 @@ void RegAlloc::HostCall(IR::Value* result_def, IR::Value* arg0_use, IR::Value* a
|
|||
ScratchRegister({AbiArgs[i]});
|
||||
}
|
||||
}
|
||||
|
||||
ScratchRegister({HostLoc::RSP});
|
||||
code->MOV(64, Gen::R(Gen::RSP), Gen::MDisp(Gen::R15, offsetof(JitState, save_host_RSP)));
|
||||
}
|
||||
|
||||
HostLoc RegAlloc::SelectARegister(std::initializer_list<HostLoc> desired_locations) const {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue