emit_x64_data_processing: Emit lea where possible in EmitAdd and EmitSub
This commit is contained in:
parent
30f1a3c628
commit
ca2cc2c4ba
1 changed files with 32 additions and 3 deletions
|
@ -924,13 +924,32 @@ static void EmitAdd(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];
|
||||||
|
|
||||||
|
// Consider using LEA.
|
||||||
|
if (!carry_inst && !overflow_inst && !nzcv_inst && carry_in.IsImmediate() && !carry_in.GetImmediateU1()) {
|
||||||
|
if (args[1].IsImmediate() && args[1].FitsInImmediateS32()) {
|
||||||
|
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||||
|
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr().changeBit(bitsize);
|
||||||
|
|
||||||
|
code.lea(result, code.ptr[op1 + args[1].GetImmediateS32()]);
|
||||||
|
|
||||||
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
} else {
|
||||||
|
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||||
|
const Xbyak::Reg op2 = ctx.reg_alloc.UseGpr(args[1]).changeBit(bitsize);
|
||||||
|
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr().changeBit(bitsize);
|
||||||
|
|
||||||
|
code.lea(result, code.ptr[op1 + op2]);
|
||||||
|
|
||||||
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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 = 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.
|
|
||||||
|
|
||||||
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();
|
const u32 op_arg = args[1].GetImmediateU32();
|
||||||
if (carry_in.IsImmediate()) {
|
if (carry_in.IsImmediate()) {
|
||||||
|
@ -994,12 +1013,22 @@ static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bit
|
||||||
auto& carry_in = args[2];
|
auto& carry_in = args[2];
|
||||||
const bool is_cmp = inst->UseCount() == size_t(!!carry_inst + !!overflow_inst + !!nzcv_inst) && carry_in.IsImmediate() && carry_in.GetImmediateU1();
|
const bool is_cmp = inst->UseCount() == size_t(!!carry_inst + !!overflow_inst + !!nzcv_inst) && carry_in.IsImmediate() && carry_in.GetImmediateU1();
|
||||||
|
|
||||||
|
// Consider using LEA.
|
||||||
|
if (!carry_inst && !overflow_inst && !nzcv_inst && carry_in.IsImmediate() && carry_in.GetImmediateU1() && args[1].IsImmediate() && args[1].FitsInImmediateS32()) {
|
||||||
|
const Xbyak::Reg op1 = ctx.reg_alloc.UseGpr(args[0]).changeBit(bitsize);
|
||||||
|
const Xbyak::Reg result = ctx.reg_alloc.ScratchGpr().changeBit(bitsize);
|
||||||
|
|
||||||
|
code.lea(result, code.ptr[op1 - args[1].GetImmediateS32()]);
|
||||||
|
|
||||||
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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 = (is_cmp ? ctx.reg_alloc.UseGpr(args[0]) : 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.
|
|
||||||
// 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;
|
||||||
|
|
Loading…
Reference in a new issue