backend/x64: Improve verbose debugging output

This commit is contained in:
Merry 2023-01-20 11:47:49 +00:00
parent c0813cf2a5
commit f0ebdf278c
14 changed files with 97 additions and 78 deletions

View file

@ -148,7 +148,7 @@ A32EmitX64::BlockDescriptor A32EmitX64::Emit(IR::Block& block) {
reg_alloc.EndOfAllocScope(); reg_alloc.EndOfAllocScope();
if (conf.very_verbose_debugging_output) { if (conf.very_verbose_debugging_output) {
EmitVerboseDebuggingOutput(reg_alloc); EmitVerboseDebuggingOutput(reg_alloc, block);
} }
} }

View file

@ -183,6 +183,7 @@ private:
Optimization::ConstantPropagation(ir_block); Optimization::ConstantPropagation(ir_block);
Optimization::DeadCodeElimination(ir_block); Optimization::DeadCodeElimination(ir_block);
} }
Optimization::IdentityRemovalPass(ir_block);
Optimization::VerificationPass(ir_block); Optimization::VerificationPass(ir_block);
return emitter.Emit(ir_block); return emitter.Emit(ir_block);
} }

View file

@ -119,7 +119,7 @@ A64EmitX64::BlockDescriptor A64EmitX64::Emit(IR::Block& block) {
ctx.reg_alloc.EndOfAllocScope(); ctx.reg_alloc.EndOfAllocScope();
if (conf.very_verbose_debugging_output) { if (conf.very_verbose_debugging_output) {
EmitVerboseDebuggingOutput(reg_alloc); EmitVerboseDebuggingOutput(reg_alloc, block);
} }
} }

View file

@ -103,7 +103,7 @@ void EmitX64::PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, I
code.mov(dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32()); code.mov(dword[r15 + code.GetJitStateInfo().offsetof_rsb_ptr], index_reg.cvt32());
} }
void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) { void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc, const IR::Block& block) {
code.sub(rsp, sizeof(RegisterData)); code.sub(rsp, sizeof(RegisterData));
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (rsp.getIdx() == i) { if (rsp.getIdx() == i) {
@ -117,7 +117,7 @@ void EmitX64::EmitVerboseDebuggingOutput(RegAlloc& reg_alloc) {
code.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]); code.lea(rax, ptr[rsp + sizeof(RegisterData) + offsetof(StackLayout, spill)]);
code.mov(xword[rsp + offsetof(RegisterData, spill)], rax); code.mov(xword[rsp + offsetof(RegisterData, spill)], rax);
reg_alloc.EmitVerboseDebuggingOutput(); reg_alloc.EmitVerboseDebuggingOutput(block);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
if (rsp.getIdx() == i) { if (rsp.getIdx() == i) {
@ -143,27 +143,32 @@ void EmitX64::EmitPushRSB(EmitContext& ctx, IR::Inst* inst) {
PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target}); PushRSBHelper(loc_desc_reg, index_reg, IR::LocationDescriptor{unique_hash_of_target});
} }
void EmitX64::EmitGetCarryFromOp(EmitContext&, IR::Inst*) { void EmitX64::EmitGetCarryFromOp(EmitContext& ctx, IR::Inst* inst) {
ASSERT_MSG(false, "should never happen"); ctx.reg_alloc.RegisterPseudoOperation(inst);
} }
void EmitX64::EmitGetOverflowFromOp(EmitContext&, IR::Inst*) { void EmitX64::EmitGetOverflowFromOp(EmitContext& ctx, IR::Inst* inst) {
ASSERT_MSG(false, "should never happen"); ctx.reg_alloc.RegisterPseudoOperation(inst);
} }
void EmitX64::EmitGetGEFromOp(EmitContext&, IR::Inst*) { void EmitX64::EmitGetGEFromOp(EmitContext& ctx, IR::Inst* inst) {
ASSERT_MSG(false, "should never happen"); ctx.reg_alloc.RegisterPseudoOperation(inst);
} }
void EmitX64::EmitGetUpperFromOp(EmitContext&, IR::Inst*) { void EmitX64::EmitGetUpperFromOp(EmitContext& ctx, IR::Inst* inst) {
ASSERT_MSG(false, "should never happen"); ctx.reg_alloc.RegisterPseudoOperation(inst);
} }
void EmitX64::EmitGetLowerFromOp(EmitContext&, IR::Inst*) { void EmitX64::EmitGetLowerFromOp(EmitContext& ctx, IR::Inst* inst) {
ASSERT_MSG(false, "should never happen"); ctx.reg_alloc.RegisterPseudoOperation(inst);
} }
void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) {
if (ctx.reg_alloc.IsValueLive(inst)) {
ctx.reg_alloc.RegisterPseudoOperation(inst);
return;
}
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const int bitsize = [&] { const int bitsize = [&] {
@ -190,6 +195,11 @@ void EmitX64::EmitGetNZFromOp(EmitContext& ctx, IR::Inst* inst) {
} }
void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitGetNZCVFromOp(EmitContext& ctx, IR::Inst* inst) {
if (ctx.reg_alloc.IsValueLive(inst)) {
ctx.reg_alloc.RegisterPseudoOperation(inst);
return;
}
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const int bitsize = [&] { const int bitsize = [&] {

View file

@ -108,7 +108,7 @@ protected:
BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size); BlockDescriptor RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size);
void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target); void PushRSBHelper(Xbyak::Reg64 loc_desc_reg, Xbyak::Reg64 index_reg, IR::LocationDescriptor target);
void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc); void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc, const IR::Block& block);
// Terminal instruction emitters // Terminal instruction emitters
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step); void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);

View file

@ -71,7 +71,6 @@ void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Reg64 carry = ctx.reg_alloc.ScratchGpr(); const Xbyak::Reg64 carry = ctx.reg_alloc.ScratchGpr();
code.setc(carry.cvt8()); code.setc(carry.cvt8());
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
} }
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
@ -332,7 +331,6 @@ void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} else { } else {
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
@ -350,7 +348,6 @@ void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
code.shr(result.cvt64(), 32); code.shr(result.cvt64(), 32);
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
} }
@ -469,7 +466,6 @@ void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} else { } else {
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
@ -486,7 +482,6 @@ void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
code.setc(carry.cvt8()); code.setc(carry.cvt8());
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
} }
@ -603,7 +598,6 @@ void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} else { } else {
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
@ -620,7 +614,6 @@ void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
code.setc(carry.cvt8()); code.setc(carry.cvt8());
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
} }
@ -718,7 +711,6 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} else { } else {
ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX); ctx.reg_alloc.UseScratch(shift_arg, HostLoc::RCX);
@ -737,7 +729,6 @@ void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
code.L(end); code.L(end);
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
} }
@ -788,7 +779,6 @@ void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) {
code.setc(carry); code.setc(carry);
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
} }
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
@ -974,17 +964,14 @@ static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
code.lahf(); code.lahf();
code.seto(code.al); code.seto(code.al);
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv); ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
ctx.EraseInstruction(nzcv_inst);
} }
if (carry_inst) { if (carry_inst) {
code.setc(carry); code.setc(carry);
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
} }
if (overflow_inst) { if (overflow_inst) {
code.seto(overflow); code.seto(overflow);
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst);
} }
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
@ -1064,7 +1051,6 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
code.lahf(); code.lahf();
code.seto(code.al); code.seto(code.al);
ctx.reg_alloc.DefineValue(nzcv_inst, nzcv); ctx.reg_alloc.DefineValue(nzcv_inst, nzcv);
ctx.EraseInstruction(nzcv_inst);
} }
if (carry_inst) { if (carry_inst) {
if (invert_output_carry) { if (invert_output_carry) {
@ -1073,12 +1059,10 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
code.setc(carry); code.setc(carry);
} }
ctx.reg_alloc.DefineValue(carry_inst, carry); ctx.reg_alloc.DefineValue(carry_inst, carry);
ctx.EraseInstruction(carry_inst);
} }
if (overflow_inst) { if (overflow_inst) {
code.seto(overflow); code.seto(overflow);
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst);
} }
if (!is_cmp) { if (!is_cmp) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);

View file

@ -33,7 +33,6 @@ void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
code.pxor(xmm_ge, ones); code.pxor(xmm_ge, ones);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
@ -56,7 +55,6 @@ void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
code.pcmpgtb(xmm_ge, xmm0); code.pcmpgtb(xmm_ge, xmm0);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
code.paddb(xmm_a, xmm_b); code.paddb(xmm_a, xmm_b);
@ -86,7 +84,6 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
code.pxor(xmm_ge, ones); code.pxor(xmm_ge, ones);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} else { } else {
const Xbyak::Xmm tmp_a = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm tmp_a = ctx.reg_alloc.ScratchXmm();
const Xbyak::Xmm tmp_b = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm tmp_b = ctx.reg_alloc.ScratchXmm();
@ -99,7 +96,6 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
code.pcmpgtw(tmp_b, tmp_a); // *Signed* comparison! code.pcmpgtw(tmp_b, tmp_a); // *Signed* comparison!
ctx.reg_alloc.DefineValue(ge_inst, tmp_b); ctx.reg_alloc.DefineValue(ge_inst, tmp_b);
ctx.EraseInstruction(ge_inst);
} }
} }
@ -123,7 +119,6 @@ void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
code.pcmpgtw(xmm_ge, xmm0); code.pcmpgtw(xmm_ge, xmm0);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
code.paddw(xmm_a, xmm_b); code.paddw(xmm_a, xmm_b);
@ -146,7 +141,6 @@ void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
code.pcmpeqb(xmm_ge, xmm_a); code.pcmpeqb(xmm_ge, xmm_a);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
code.psubb(xmm_a, xmm_b); code.psubb(xmm_a, xmm_b);
@ -171,7 +165,6 @@ void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
code.pcmpgtb(xmm_ge, xmm0); code.pcmpgtb(xmm_ge, xmm0);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
code.psubb(xmm_a, xmm_b); code.psubb(xmm_a, xmm_b);
@ -205,7 +198,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
code.psubw(xmm_a, xmm_b); code.psubw(xmm_a, xmm_b);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
return; return;
} }
@ -226,7 +218,6 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
code.psubw(xmm_a, xmm_b); code.psubw(xmm_a, xmm_b);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
ctx.reg_alloc.DefineValue(inst, xmm_a); ctx.reg_alloc.DefineValue(inst, xmm_a);
} }
@ -247,7 +238,6 @@ void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
code.pcmpgtw(xmm_ge, xmm0); code.pcmpgtw(xmm_ge, xmm0);
ctx.reg_alloc.DefineValue(ge_inst, xmm_ge); ctx.reg_alloc.DefineValue(ge_inst, xmm_ge);
ctx.EraseInstruction(ge_inst);
} }
code.psubw(xmm_a, xmm_b); code.psubw(xmm_a, xmm_b);
@ -554,7 +544,6 @@ static void EmitPackedSubAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst
code.or_(ge_sum, ge_diff); code.or_(ge_sum, ge_diff);
ctx.reg_alloc.DefineValue(ge_inst, ge_sum); ctx.reg_alloc.DefineValue(ge_inst, ge_sum);
ctx.EraseInstruction(ge_inst);
} }
if (is_halving) { if (is_halving) {

View file

@ -64,7 +64,6 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
if constexpr (has_overflow_inst) { if constexpr (has_overflow_inst) {
if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) { if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) {
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst);
} }
} else { } else {
code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8()); code.or_(code.byte[code.r15 + code.GetJitStateInfo().offsetof_fpsr_qc], overflow.cvt8());
@ -155,7 +154,6 @@ void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
code.seta(overflow.cvt8()); code.seta(overflow.cvt8());
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst);
} }
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
@ -185,7 +183,6 @@ void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
code.seta(overflow.cvt8()); code.seta(overflow.cvt8());
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst);
} }
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);

View file

@ -3633,7 +3633,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(upper_inst, result); ctx.reg_alloc.DefineValue(upper_inst, result);
ctx.EraseInstruction(upper_inst);
} }
if (lower_inst) { if (lower_inst) {
@ -3645,7 +3644,6 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
code.pmullw(result, y); code.pmullw(result, y);
} }
ctx.reg_alloc.DefineValue(lower_inst, result); ctx.reg_alloc.DefineValue(lower_inst, result);
ctx.EraseInstruction(lower_inst);
} }
} }
@ -3663,7 +3661,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
code.vpmulld(result, x, y); code.vpmulld(result, x, y);
ctx.reg_alloc.DefineValue(lower_inst, result); ctx.reg_alloc.DefineValue(lower_inst, result);
ctx.EraseInstruction(lower_inst);
return; return;
} }
@ -3675,7 +3672,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
code.vpmulld(lower_result, x, y); code.vpmulld(lower_result, x, y);
ctx.reg_alloc.DefineValue(lower_inst, lower_result); ctx.reg_alloc.DefineValue(lower_inst, lower_result);
ctx.EraseInstruction(lower_inst);
} }
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
@ -3687,7 +3683,6 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
code.shufps(result, x, 0b11011101); code.shufps(result, x, 0b11011101);
ctx.reg_alloc.DefineValue(upper_inst, result); ctx.reg_alloc.DefineValue(upper_inst, result);
ctx.EraseInstruction(upper_inst);
return; return;
} }
@ -3730,11 +3725,9 @@ void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
if (upper_inst) { if (upper_inst) {
ctx.reg_alloc.DefineValue(upper_inst, upper_result); ctx.reg_alloc.DefineValue(upper_inst, upper_result);
ctx.EraseInstruction(upper_inst);
} }
if (lower_inst) { if (lower_inst) {
ctx.reg_alloc.DefineValue(lower_inst, lower_result); ctx.reg_alloc.DefineValue(lower_inst, lower_result);
ctx.EraseInstruction(lower_inst);
} }
} }
@ -5139,7 +5132,6 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
} }
ctx.reg_alloc.DefineValue(upper_inst, result); ctx.reg_alloc.DefineValue(upper_inst, result);
ctx.EraseInstruction(upper_inst);
} }
if (lower_inst) { if (lower_inst) {
@ -5151,7 +5143,6 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
code.pmullw(result, y); code.pmullw(result, y);
} }
ctx.reg_alloc.DefineValue(lower_inst, result); ctx.reg_alloc.DefineValue(lower_inst, result);
ctx.EraseInstruction(lower_inst);
} }
} }
@ -5169,7 +5160,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
code.vpmulld(result, x, y); code.vpmulld(result, x, y);
ctx.reg_alloc.DefineValue(lower_inst, result); ctx.reg_alloc.DefineValue(lower_inst, result);
ctx.EraseInstruction(lower_inst);
return; return;
} }
@ -5181,7 +5171,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm lower_result = ctx.reg_alloc.ScratchXmm();
code.vpmulld(lower_result, x, y); code.vpmulld(lower_result, x, y);
ctx.reg_alloc.DefineValue(lower_inst, lower_result); ctx.reg_alloc.DefineValue(lower_inst, lower_result);
ctx.EraseInstruction(lower_inst);
} }
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
@ -5193,7 +5182,6 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
code.shufps(result, x, 0b11011101); code.shufps(result, x, 0b11011101);
ctx.reg_alloc.DefineValue(upper_inst, result); ctx.reg_alloc.DefineValue(upper_inst, result);
ctx.EraseInstruction(upper_inst);
return; return;
} }
@ -5224,11 +5212,9 @@ void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
if (upper_inst) { if (upper_inst) {
ctx.reg_alloc.DefineValue(upper_inst, upper_result); ctx.reg_alloc.DefineValue(upper_inst, upper_result);
ctx.EraseInstruction(upper_inst);
} }
if (lower_inst) { if (lower_inst) {
ctx.reg_alloc.DefineValue(lower_inst, lower_result); ctx.reg_alloc.DefineValue(lower_inst, lower_result);
ctx.EraseInstruction(lower_inst);
} }
} }

View file

@ -17,6 +17,7 @@
#include "dynarmic/backend/x64/abi.h" #include "dynarmic/backend/x64/abi.h"
#include "dynarmic/backend/x64/stack_layout.h" #include "dynarmic/backend/x64/stack_layout.h"
#include "dynarmic/backend/x64/verbose_debugging_output.h" #include "dynarmic/backend/x64/verbose_debugging_output.h"
#include "dynarmic/ir/basic_block.h"
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
@ -157,12 +158,14 @@ void HostLocInfo::AddValue(IR::Inst* inst) {
max_bit_width = std::max(max_bit_width, GetBitWidth(inst->GetType())); max_bit_width = std::max(max_bit_width, GetBitWidth(inst->GetType()));
} }
void HostLocInfo::EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const { void HostLocInfo::EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index, const IR::Block& block) const {
using namespace Xbyak::util; using namespace Xbyak::util;
for (IR::Inst* value : values) { for (IR::Inst* value : values) {
const auto inst_offset = std::distance(block.begin(), IR::Block::const_iterator(value));
code.mov(code.ABI_PARAM1, rsp); code.mov(code.ABI_PARAM1, rsp);
code.mov(code.ABI_PARAM2, host_loc_index); code.mov(code.ABI_PARAM2, host_loc_index);
code.mov(code.ABI_PARAM3, mcl::bit_cast<u64>(value)); code.mov(code.ABI_PARAM3, mcl::bit_cast<u64>(inst_offset));
code.mov(code.ABI_PARAM4, GetBitWidth(value->GetType()));
code.CallFunction(PrintVerboseDebuggingOutputLine); code.CallFunction(PrintVerboseDebuggingOutputLine);
} }
} }
@ -271,6 +274,24 @@ RegAlloc::ArgumentInfo RegAlloc::GetArgumentInfo(IR::Inst* inst) {
return ret; return ret;
} }
void RegAlloc::RegisterPseudoOperation(IR::Inst* inst) {
ASSERT(IsValueLive(inst));
for (size_t i = 0; i < inst->NumArgs(); i++) {
const IR::Value arg = inst->GetArg(i);
if (!arg.IsImmediate() && !IsValuelessType(arg.GetType())) {
if (const auto loc = ValueLocation(arg.GetInst())) {
// May not necessarily have a value (e.g. CMP variant of Sub32).
LocInfo(*loc).AddArgReference();
}
}
}
}
bool RegAlloc::IsValueLive(IR::Inst* inst) const {
return !!ValueLocation(inst);
}
Xbyak::Reg64 RegAlloc::UseGpr(Argument& arg) { Xbyak::Reg64 RegAlloc::UseGpr(Argument& arg) {
ASSERT(!arg.allocated); ASSERT(!arg.allocated);
arg.allocated = true; arg.allocated = true;
@ -494,9 +515,9 @@ void RegAlloc::AssertNoMoreUses() {
ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i) { return i.IsEmpty(); })); ASSERT(std::all_of(hostloc_info.begin(), hostloc_info.end(), [](const auto& i) { return i.IsEmpty(); }));
} }
void RegAlloc::EmitVerboseDebuggingOutput() { void RegAlloc::EmitVerboseDebuggingOutput(const IR::Block& block) {
for (size_t i = 0; i < hostloc_info.size(); i++) { for (size_t i = 0; i < hostloc_info.size(); i++) {
hostloc_info[i].EmitVerboseDebuggingOutput(code, i); hostloc_info[i].EmitVerboseDebuggingOutput(code, i, block);
} }
} }

View file

@ -23,6 +23,7 @@
namespace Dynarmic::IR { namespace Dynarmic::IR {
enum class AccType; enum class AccType;
class Block;
} // namespace Dynarmic::IR } // namespace Dynarmic::IR
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
@ -48,7 +49,7 @@ public:
void AddValue(IR::Inst* inst); void AddValue(IR::Inst* inst);
void EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index) const; void EmitVerboseDebuggingOutput(BlockOfCode& code, size_t host_loc_index, const IR::Block& block) const;
private: private:
// Current instruction state // Current instruction state
@ -110,6 +111,8 @@ public:
explicit RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order); explicit RegAlloc(BlockOfCode& code, std::vector<HostLoc> gpr_order, std::vector<HostLoc> xmm_order);
ArgumentInfo GetArgumentInfo(IR::Inst* inst); ArgumentInfo GetArgumentInfo(IR::Inst* inst);
void RegisterPseudoOperation(IR::Inst* inst);
bool IsValueLive(IR::Inst* inst) const;
Xbyak::Reg64 UseGpr(Argument& arg); Xbyak::Reg64 UseGpr(Argument& arg);
Xbyak::Xmm UseXmm(Argument& arg); Xbyak::Xmm UseXmm(Argument& arg);
@ -145,7 +148,7 @@ public:
void AssertNoMoreUses(); void AssertNoMoreUses();
void EmitVerboseDebuggingOutput(); void EmitVerboseDebuggingOutput(const IR::Block& block);
private: private:
friend struct Argument; friend struct Argument;

View file

@ -5,25 +5,52 @@
#include "dynarmic/backend/x64/verbose_debugging_output.h" #include "dynarmic/backend/x64/verbose_debugging_output.h"
#include <iterator>
#include <fmt/format.h> #include <fmt/format.h>
#include "dynarmic/backend/x64/hostloc.h" #include "dynarmic/backend/x64/hostloc.h"
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr) { void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, size_t inst_index, size_t bitsize) {
if (HostLocIsGPR(hostloc)) { fmt::print("dynarmic debug: %{:05} = ", inst_index);
const u64 value = reg_data.gprs[HostLocToReg64(hostloc).getIdx()];
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, 0, value); Vector value = [&]() -> Vector {
} else if (HostLocIsXMM(hostloc)) { if (HostLocIsGPR(hostloc)) {
const Vector value = reg_data.xmms[HostLocToXmm(hostloc).getIdx()]; return {reg_data.gprs[HostLocToReg64(hostloc).getIdx()], 0};
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]); } else if (HostLocIsXMM(hostloc)) {
} else if (HostLocIsSpill(hostloc)) { return reg_data.xmms[HostLocToXmm(hostloc).getIdx()];
const Vector value = (*reg_data.spill)[static_cast<size_t>(hostloc) - static_cast<size_t>(HostLoc::FirstSpill)]; } else if (HostLocIsSpill(hostloc)) {
fmt::print("dynarmic debug: {:016x} = {:016x}{:016x}\n", inst_addr, value[1], value[0]); return (*reg_data.spill)[static_cast<size_t>(hostloc) - static_cast<size_t>(HostLoc::FirstSpill)];
} else { } else {
fmt::print("dynarmic debug: Invalid hostloc\n"); fmt::print("invalid hostloc! ");
return {0, 0};
}
}();
switch (bitsize) {
case 8:
fmt::print("{:02x}", value[0] & 0xff);
break;
case 16:
fmt::print("{:04x}", value[0] & 0xffff);
break;
case 32:
fmt::print("{:08x}", value[0] & 0xffffffff);
break;
case 64:
fmt::print("{:016x}", value[0]);
break;
case 128:
fmt::print("{:016x}{:016x}", value[1], value[0]);
break;
default:
fmt::print("invalid bitsize!");
break;
} }
fmt::print("\n");
} }
} // namespace Dynarmic::Backend::X64 } // namespace Dynarmic::Backend::X64

View file

@ -31,6 +31,6 @@ struct alignas(16) RegisterData {
# pragma warning(pop) # pragma warning(pop)
#endif #endif
void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, u64 inst_addr); void PrintVerboseDebuggingOutputLine(RegisterData& reg_data, HostLoc hostloc, size_t inst_index, size_t bitsize);
} // namespace Dynarmic::Backend::X64 } // namespace Dynarmic::Backend::X64

View file

@ -663,6 +663,7 @@ static std::optional<size_t> str2sz(char const* s) {
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc != 5) { if (argc != 5) {
fmt::print("Usage: {} <thumb|arm|a64> <seed> <instruction_count> <iteration_count>\n", argv[0]); fmt::print("Usage: {} <thumb|arm|a64> <seed> <instruction_count> <iteration_count>\n", argv[0]);
return 1;
} }
const auto seed = str2sz(argv[2]); const auto seed = str2sz(argv[2]);