diff --git a/ir_x86.dasc b/ir_x86.dasc index b728a1f..be1c065 100644 --- a/ir_x86.dasc +++ b/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] } } }