emit_x64_data_processing: EmitSub: Use cmp where possible

This commit is contained in:
MerryMage 2021-01-01 19:37:47 +00:00
parent e926f0b393
commit 8c4463a0c1
2 changed files with 17 additions and 7 deletions

View file

@ -1080,19 +1080,28 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& carry_in = args[2]; auto& carry_in = args[2];
const bool is_cmp = inst->UseCount() == !!carry_inst + !!overflow_inst + !!nzcv_inst && carry_in.IsImmediate() && carry_in.GetImmediateU1();
const Xbyak::Reg64 nzcv = DoNZCV(code, ctx.reg_alloc, nzcv_inst); const Xbyak::Reg64 nzcv = DoNZCV(code, ctx.reg_alloc, nzcv_inst);
const Xbyak::Reg result = ctx.reg_alloc.UseScratchGpr(args[0]).changeBit(bitsize); const Xbyak::Reg result = (is_cmp ? ctx.reg_alloc.UseGpr(args[0]) : ctx.reg_alloc.UseScratchGpr(args[0])).changeBit(bitsize);
const Xbyak::Reg8 carry = DoCarry(ctx.reg_alloc, carry_in, carry_inst); const Xbyak::Reg8 carry = DoCarry(ctx.reg_alloc, carry_in, carry_inst);
const Xbyak::Reg8 overflow = overflow_inst ? ctx.reg_alloc.ScratchGpr().cvt8() : Xbyak::Reg8{-1}; const Xbyak::Reg8 overflow = overflow_inst ? ctx.reg_alloc.ScratchGpr().cvt8() : Xbyak::Reg8{-1};
// TODO: Consider using LEA. // TODO: Consider using LEA.
// TODO: Optimize CMP case.
// Note that x64 CF is inverse of what the ARM carry flag is here. // Note that x64 CF is inverse of what the ARM carry flag is here.
bool invert_output_carry = true; bool invert_output_carry = true;
if (is_cmp) {
if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) { if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
const u32 op_arg = args[1].GetImmediateU32();
code.cmp(result, op_arg);
} else {
OpArg op_arg = ctx.reg_alloc.UseOpArg(args[1]);
op_arg.setBit(bitsize);
code.cmp(result, *op_arg);
}
} else if (args[1].IsImmediate() && args[1].GetType() == IR::Type::U32) {
const u32 op_arg = args[1].GetImmediateU32(); const u32 op_arg = args[1].GetImmediateU32();
if (carry_in.IsImmediate()) { if (carry_in.IsImmediate()) {
if (carry_in.GetImmediateU1()) { if (carry_in.GetImmediateU1()) {
@ -1146,9 +1155,10 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
ctx.reg_alloc.DefineValue(overflow_inst, overflow); ctx.reg_alloc.DefineValue(overflow_inst, overflow);
ctx.EraseInstruction(overflow_inst); ctx.EraseInstruction(overflow_inst);
} }
if (!is_cmp) {
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
}
void EmitX64::EmitSub32(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitSub32(EmitContext& ctx, IR::Inst* inst) {
EmitSub(code, ctx, inst, 32); EmitSub(code, ctx, inst, 32);

View file

@ -27,7 +27,7 @@ bool TranslatorVisitor::CCMP_reg(bool sf, Reg Rm, Cond cond, Reg Rn, Imm<4> nzcv
const IR::U32U64 operand1 = X(datasize, Rn); const IR::U32U64 operand1 = X(datasize, Rn);
const IR::U32U64 operand2 = X(datasize, Rm); const IR::U32U64 operand2 = X(datasize, Rm);
const IR::NZCV then_flags = ir.NZCVFrom(ir.AddWithCarry(operand1, ir.Not(operand2), ir.Imm1(1))); const IR::NZCV then_flags = ir.NZCVFrom(ir.SubWithCarry(operand1, operand2, ir.Imm1(1)));
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags)); const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags)); ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
return true; return true;
@ -53,7 +53,7 @@ bool TranslatorVisitor::CCMP_imm(bool sf, Imm<5> imm5, Cond cond, Reg Rn, Imm<4>
const IR::U32U64 operand1 = X(datasize, Rn); const IR::U32U64 operand1 = X(datasize, Rn);
const IR::U32U64 operand2 = I(datasize, imm5.ZeroExtend<u32>()); const IR::U32U64 operand2 = I(datasize, imm5.ZeroExtend<u32>());
const IR::NZCV then_flags = ir.NZCVFrom(ir.AddWithCarry(operand1, ir.Not(operand2), ir.Imm1(1))); const IR::NZCV then_flags = ir.NZCVFrom(ir.SubWithCarry(operand1, operand2, ir.Imm1(1)));
const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags)); const IR::NZCV else_flags = ir.NZCVFromPackedFlags(ir.Imm32(flags));
ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags)); ir.SetNZCV(ir.ConditionalSelect(cond, then_flags, else_flags));
return true; return true;