Compound assignment instruction fusion

This commit is contained in:
Dmitry Stogov 2022-06-21 17:33:57 +03:00
parent 082bcf89c9
commit 9b25587eb6
3 changed files with 105 additions and 9 deletions

View File

@ -582,6 +582,7 @@ typedef enum _ir_rule {
IR_MEM_BINOP_INT,
IR_MEM_SHIFT,
IR_MEM_SHIFT_CONST,
IR_REG_BINOP_INT,
IR_SKIP_BINOP_INT,
IR_SKIP_SHIFT,
IR_VSTORE_INT,
@ -1521,7 +1522,9 @@ store_int:
if (!ctx->rules[insn->op3]) {
ctx->rules[insn->op3] = ir_match_insn(ctx, insn->op3, bb);
}
if (ctx->rules[insn->op3] == IR_BINOP_INT && op_insn->op != IR_MUL) {
if ((ctx->rules[insn->op3] == IR_BINOP_INT && op_insn->op != IR_MUL) ||
ctx->rules[insn->op3] == IR_LEA_OB ||
ctx->rules[insn->op3] == IR_LEA_IB) {
if (ctx->ir_base[op_insn->op1].op == load_op
&& ctx->ir_base[op_insn->op1].op2 == insn->op2) {
if (op_insn->op1 > bb->start
@ -1656,6 +1659,36 @@ store_int:
return IR_STORE_FP;
}
break;
case IR_RSTORE:
if (IR_IS_TYPE_INT(ctx->ir_base[insn->op2].type)) {
if ((ctx->flags & IR_OPT_CODEGEN) && insn->op2 > bb->start && insn->op2 < ref && ctx->use_lists[insn->op2].count == 1) {
ir_insn *op_insn = &ctx->ir_base[insn->op2];
if (!ctx->rules[insn->op2]) {
ctx->rules[insn->op2] = ir_match_insn(ctx, insn->op2, bb);
}
if ((ctx->rules[insn->op2] == IR_BINOP_INT && op_insn->op != IR_MUL) ||
ctx->rules[insn->op2] == IR_LEA_OB ||
ctx->rules[insn->op2] == IR_LEA_IB) {
if (ctx->ir_base[op_insn->op1].op == IR_RLOAD
&& ctx->ir_base[op_insn->op1].op2 == insn->op3) {
ctx->rules[insn->op2] = IR_SKIP_BINOP_INT;
ctx->rules[op_insn->op1] = IR_SKIP;
return IR_REG_BINOP_INT;
} else if ((ir_op_flags[op_insn->op] & IR_OP_FLAG_COMMUTATIVE)
&& ctx->ir_base[op_insn->op2].op == IR_RLOAD
&& ctx->ir_base[op_insn->op2].op2 == insn->op3) {
ir_ref tmp = op_insn->op1;
op_insn->op1 = op_insn->op2;
op_insn->op2 = tmp;
ctx->rules[insn->op2] = IR_SKIP_BINOP_INT;
ctx->rules[op_insn->op1] = IR_SKIP;
return IR_REG_BINOP_INT;
}
}
}
}
return IR_RSTORE;
case IR_START:
case IR_BEGIN:
// case IR_END:
@ -2326,6 +2359,71 @@ static void ir_emit_mem_binop_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
}
}
static void ir_emit_reg_binop_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
{
ir_backend_data *data = ctx->data;
dasm_State **Dst = &data->dasm_state;
ir_insn *op_insn = &ctx->ir_base[insn->op2];
ir_type type = op_insn->type;
ir_ref op2 = op_insn->op2;
ir_reg op2_reg = ctx->regs[insn->op2][2];
ir_reg reg;
IR_ASSERT(insn->op == IR_RSTORE);
reg = insn->op3;
if (op2_reg == IR_REG_NONE) {
ir_val *val = &ctx->ir_base[op2].val;
IR_ASSERT(IR_IS_CONST_REF(op2) && (ir_type_size[type] != 8 || IR_IS_32BIT(type, ctx->ir_base[op2].val)));
switch (op_insn->op) {
case IR_ADD:
| ASM_REG_IMM_OP add, type, reg, val->i32
break;
case IR_SUB:
| ASM_REG_IMM_OP sub, type, reg, val->i32
break;
case IR_OR:
| ASM_REG_IMM_OP or, type, reg, val->i32
break;
case IR_AND:
| ASM_REG_IMM_OP and, type, reg, val->i32
break;
case IR_XOR:
| ASM_REG_IMM_OP xor, type, reg, val->i32
break;
default:
IR_ASSERT(0 && "NIY binary op");
break;
}
} else {
if ((op2_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(op2)) {
op2_reg &= ~IR_REG_SPILL_LOAD;
ir_emit_load(ctx, type, op2_reg, op2);
}
switch (op_insn->op) {
case IR_ADD:
| ASM_REG_REG_OP add, type, reg, op2_reg
break;
case IR_SUB:
| ASM_REG_REG_OP sub, type, reg, op2_reg
break;
case IR_OR:
| ASM_REG_REG_OP or, type, reg, op2_reg
break;
case IR_AND:
| ASM_REG_REG_OP and, type, reg, op2_reg
break;
case IR_XOR:
| ASM_REG_REG_OP xor, type, reg, op2_reg
break;
default:
IR_ASSERT(0 && "NIY binary op");
break;
}
}
}
static void ir_emit_mul_div_mod_pwr2(ir_ctx *ctx, ir_ref def, ir_insn *insn)
{
ir_backend_data *data = ctx->data;
@ -6853,6 +6951,9 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
case IR_MEM_SHIFT_CONST:
ir_emit_mem_shift_const(ctx, i, insn);
break;
case IR_REG_BINOP_INT:
ir_emit_reg_binop_int(ctx, i, insn);
break;
case IR_VADDR:
ir_emit_vaddr(ctx, i, insn);
break;

View File

@ -94,9 +94,7 @@ test:
movq %rsp, %rax
movl $0, (%rax)
.L1:
movl (%rax), %ecx
leal 1(%rcx), %ecx
movl %ecx, (%rax)
addl $1, (%rax)
movsd -0x20(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
movapd %xmm1, %xmm2
@ -131,7 +129,6 @@ test:
popq %rbp
retq
.rodata
.db 0x90, 0x90, 0x90, 0x90
.L3:
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f
.L4:

View File

@ -85,9 +85,7 @@ test:
movsd %xmm0, 0x18(%rsp)
movl $0, 0x20(%rsp)
.L1:
movl 0x20(%rsp), %eax
leal 1(%rax), %eax
movl %eax, 0x20(%rsp)
addl $1, 0x20(%rsp)
movsd 0x18(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
movapd %xmm1, %xmm2
@ -119,7 +117,7 @@ test:
addq $0x40, %rsp
retq
.rodata
.db 0x90, 0x90, 0x90
.db 0x90, 0x90, 0x90, 0x90, 0x90
.L3:
.db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f
.L4: