Implement some simple IR optimizations (get/set eliminiation and DCE)

This commit is contained in:
MerryMage 2016-07-21 21:48:45 +01:00
parent 90d317b868
commit 5fbfc6c155
16 changed files with 544 additions and 300 deletions

View file

@ -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);

View file

@ -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);
}
};

View file

@ -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 {