mirror of
https://github.com/danog/ir.git
synced 2025-01-22 05:31:32 +01:00
Load fusion for MUL/DIV/MOD
This commit is contained in:
parent
dbb382224d
commit
1f657fd4d7
49
ir_x86.dasc
49
ir_x86.dasc
@ -99,14 +99,6 @@
|
||||
|| }
|
||||
|.endmacro
|
||||
|
||||
|.macro ASM_MREF_OP, op, type, ref
|
||||
|| do {
|
||||
|| int32_t offset = ir_ref_spill_slot(ctx, ref);
|
||||
|| ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
| ASM_MEM_OP op, type, [Ra(fp)+offset]
|
||||
|| } while (0);
|
||||
|.endmacro
|
||||
|
||||
|.macro ASM_REG_REG_OP, op, type, dst, src
|
||||
|| switch (ir_type_size[type]) {
|
||||
|| case 1:
|
||||
@ -231,18 +223,6 @@
|
||||
|| }
|
||||
|.endmacro
|
||||
|
||||
|.macro ASM_REG_MREF_OP, _op, type, dst, src
|
||||
|| if (IR_IS_CONST_REF(src)) {
|
||||
|| ir_insn *_insn = &ctx->ir_base[src];
|
||||
|| IR_ASSERT(IR_IS_32BIT(_insn->type, _insn->val));
|
||||
| ASM_REG_IMM_OP _op, type, dst, _insn->val.i32
|
||||
|| } else {
|
||||
|| int32_t offset = ir_ref_spill_slot(ctx, src);
|
||||
|| ir_reg fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
| ASM_REG_MEM_OP _op, type, dst, [Ra(fp)+offset]
|
||||
|| }
|
||||
|.endmacro
|
||||
|
||||
|.macro ASM_MREF_REG_OP, op, type, dst, src
|
||||
|| do {
|
||||
|| int32_t offset = ir_ref_spill_slot(ctx, dst);
|
||||
@ -1399,7 +1379,11 @@ binop_fp:
|
||||
return IR_MUL_PWR2; // shl op1, IR_LOG2(op2_insn->val.u64)
|
||||
}
|
||||
}
|
||||
return (IR_IS_TYPE_SIGNED(insn->type) && ir_type_size[insn->type] != 1) ? IR_BINOP_INT : IR_MUL_INT;
|
||||
if (IR_IS_TYPE_SIGNED(insn->type) && ir_type_size[insn->type] != 1) {
|
||||
goto binop_int;
|
||||
}
|
||||
ir_match_fuse_load(ctx, insn->op2, bb);
|
||||
return IR_MUL_INT;
|
||||
} else {
|
||||
goto binop_fp;
|
||||
}
|
||||
@ -1412,9 +1396,9 @@ binop_fp:
|
||||
IR_ASSERT(IR_IS_TYPE_INT(insn->type));
|
||||
if (IR_IS_TYPE_SIGNED(insn->type) && ir_type_size[insn->type] != 1) {
|
||||
goto binop_int;
|
||||
} else {
|
||||
return IR_MUL_INT;
|
||||
}
|
||||
ir_match_fuse_load(ctx, insn->op2, bb);
|
||||
return IR_MUL_INT;
|
||||
case IR_DIV:
|
||||
if (IR_IS_TYPE_INT(insn->type)) {
|
||||
if ((ctx->flags & IR_OPT_CODEGEN) && IR_IS_CONST_REF(insn->op2)) {
|
||||
@ -1427,6 +1411,7 @@ binop_fp:
|
||||
return IR_DIV_PWR2; // shr op1, IR_LOG2(op2_insn->val.u64)
|
||||
}
|
||||
}
|
||||
ir_match_fuse_load(ctx, insn->op2, bb);
|
||||
return IR_DIV_INT;
|
||||
} else {
|
||||
goto binop_fp;
|
||||
@ -1443,6 +1428,7 @@ binop_fp:
|
||||
return IR_MOD_PWR2; // and op1, op2_insn->val.u64-1
|
||||
}
|
||||
}
|
||||
ir_match_fuse_load(ctx, insn->op2, bb);
|
||||
return IR_MOD_INT;
|
||||
case IR_BSWAP:
|
||||
case IR_NOT:
|
||||
@ -3043,6 +3029,8 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
|
||||
ir_reg op1_reg = ctx->regs[def][1];
|
||||
ir_reg op2_reg = ctx->regs[def][2];
|
||||
ir_reg base_reg = IR_REG_NONE;
|
||||
int32_t offset = 0;
|
||||
|
||||
IR_ASSERT(def_reg != IR_REG_NONE);
|
||||
|
||||
@ -3071,12 +3059,21 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
ir_emit_load(ctx, type, op2_reg, op2);
|
||||
}
|
||||
if (op2_reg == IR_REG_NONE) {
|
||||
if (ctx->rules[op2] == IR_SKIP_MEM) {
|
||||
base_reg = ir_fuse_load(ctx, op2, &offset);
|
||||
IR_ASSERT(base_reg != IR_REG_NONE);
|
||||
} else {
|
||||
base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
|
||||
offset = ir_ref_spill_slot(ctx, op2);
|
||||
}
|
||||
}
|
||||
if (insn->op == IR_MUL || insn->op == IR_MUL_OV) {
|
||||
IR_ASSERT(!IR_IS_TYPE_SIGNED(insn->type));
|
||||
if (op2_reg != IR_REG_NONE) {
|
||||
| ASM_REG_OP mul, type, op2_reg
|
||||
} else {
|
||||
| ASM_MREF_OP mul, type, op2
|
||||
| ASM_MEM_OP mul, type, [Ra(base_reg)+offset]
|
||||
}
|
||||
} else {
|
||||
if (IR_IS_TYPE_SIGNED(type)) {
|
||||
@ -3090,14 +3087,14 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
if (op2_reg != IR_REG_NONE) {
|
||||
| ASM_REG_OP idiv, type, op2_reg
|
||||
} else {
|
||||
| ASM_MREF_OP idiv, type, op2
|
||||
| ASM_MEM_OP idiv, type, [Ra(base_reg)+offset]
|
||||
}
|
||||
} else {
|
||||
| ASM_REG_REG_OP xor, type, IR_REG_RDX, IR_REG_RDX
|
||||
if (op2_reg != IR_REG_NONE) {
|
||||
| ASM_REG_OP div, type, op2_reg
|
||||
} else {
|
||||
| ASM_MREF_OP div, type, op2
|
||||
| ASM_MEM_OP div, type, [Ra(base_reg)+offset]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user