mirror of
https://github.com/danog/ir.git
synced 2024-12-02 17:55:40 +01:00
Avoid code generation for useless loads and stores
This commit is contained in:
parent
eaaf487600
commit
3de6c5126a
@ -2920,6 +2920,12 @@ static void ir_emit_load_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
||||||
|
|
||||||
if (op2_reg == IR_REG_NONE) {
|
if (op2_reg == IR_REG_NONE) {
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op1_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
ir_emit_load_mem_int(ctx, type, def_reg, op1_reg, offset);
|
ir_emit_load_mem_int(ctx, type, def_reg, op1_reg, offset);
|
||||||
} else {
|
} else {
|
||||||
switch (ir_type_size[type]) {
|
switch (ir_type_size[type]) {
|
||||||
@ -2981,6 +2987,12 @@ static void ir_emit_load_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
||||||
|
|
||||||
if (op2_reg == IR_REG_NONE) {
|
if (op2_reg == IR_REG_NONE) {
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op1_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
ir_emit_load_mem_fp(ctx, type, def_reg, op1_reg, offset);
|
ir_emit_load_mem_fp(ctx, type, def_reg, op1_reg, offset);
|
||||||
} else {
|
} else {
|
||||||
if (type == IR_DOUBLE) {
|
if (type == IR_DOUBLE) {
|
||||||
@ -3016,20 +3028,33 @@ static void ir_emit_store_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
ir_reg op2_reg = ctx->regs[ref][2];
|
ir_reg op2_reg = ctx->regs[ref][2];
|
||||||
ir_reg op3_reg = ctx->regs[ref][3];
|
ir_reg op3_reg = ctx->regs[ref][3];
|
||||||
|
|
||||||
if (op3_reg == IR_REG_NONE) {
|
|
||||||
IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0);
|
|
||||||
op3_reg = IR_REG_ZR;
|
|
||||||
} else if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
|
||||||
op3_reg &= ~IR_REG_SPILL_LOAD;
|
|
||||||
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
|
||||||
}
|
|
||||||
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
||||||
ir_reg op1_reg;
|
ir_reg op1_reg;
|
||||||
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
||||||
|
|
||||||
if (op2_reg == IR_REG_NONE) {
|
if (op2_reg == IR_REG_NONE) {
|
||||||
|
if (!IR_IS_CONST_REF(insn->op3) && (op3_reg & IR_REG_SPILL_LOAD)) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op1_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op3_reg == IR_REG_NONE) {
|
||||||
|
IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0);
|
||||||
|
op3_reg = IR_REG_ZR;
|
||||||
|
} else if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
ir_emit_store_mem_int(ctx, type, op1_reg, offset, op3_reg);
|
ir_emit_store_mem_int(ctx, type, op1_reg, offset, op3_reg);
|
||||||
} else {
|
} else {
|
||||||
|
if (op3_reg == IR_REG_NONE) {
|
||||||
|
IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0);
|
||||||
|
op3_reg = IR_REG_ZR;
|
||||||
|
} else if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
switch (ir_type_size[type]) {
|
switch (ir_type_size[type]) {
|
||||||
case 8:
|
case 8:
|
||||||
| str Rx(op3_reg), [Rx(op1_reg), Rx(op2_reg)]
|
| str Rx(op3_reg), [Rx(op1_reg), Rx(op2_reg)]
|
||||||
@ -3054,6 +3079,13 @@ static void ir_emit_store_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
|
if (op3_reg == IR_REG_NONE) {
|
||||||
|
IR_ASSERT(IR_IS_CONST_REF(insn->op3) && ctx->ir_base[insn->op3].val.i64 == 0);
|
||||||
|
op3_reg = IR_REG_ZR;
|
||||||
|
} else if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
ir_emit_store_mem_int(ctx, type, op2_reg, 0, op3_reg);
|
ir_emit_store_mem_int(ctx, type, op2_reg, 0, op3_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3067,17 +3099,27 @@ static void ir_emit_store_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
ir_reg op3_reg = ctx->regs[ref][3];
|
ir_reg op3_reg = ctx->regs[ref][3];
|
||||||
|
|
||||||
IR_ASSERT(op3_reg != IR_REG_NONE);
|
IR_ASSERT(op3_reg != IR_REG_NONE);
|
||||||
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
|
||||||
op3_reg &= ~IR_REG_SPILL_LOAD;
|
|
||||||
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
|
||||||
}
|
|
||||||
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
||||||
ir_reg op1_reg;
|
ir_reg op1_reg;
|
||||||
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
int32_t offset = ir_fuse_addr(ctx, insn->op2, &op1_reg, &op2_reg);
|
||||||
|
|
||||||
if (op2_reg == IR_REG_NONE) {
|
if (op2_reg == IR_REG_NONE) {
|
||||||
|
if (!IR_IS_CONST_REF(insn->op3) && (op3_reg & IR_REG_SPILL_LOAD)) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op1_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
ir_emit_store_mem_fp(ctx, type, op1_reg, offset, op3_reg);
|
ir_emit_store_mem_fp(ctx, type, op1_reg, offset, op3_reg);
|
||||||
} else {
|
} else {
|
||||||
|
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
if (type == IR_DOUBLE) {
|
if (type == IR_DOUBLE) {
|
||||||
| str Rd(op3_reg-IR_REG_FP_FIRST), [Rx(op1_reg), Rx(op2_reg)]
|
| str Rd(op3_reg-IR_REG_FP_FIRST), [Rx(op1_reg), Rx(op2_reg)]
|
||||||
} else {
|
} else {
|
||||||
@ -3091,6 +3133,10 @@ static void ir_emit_store_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
|
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
ir_emit_store_mem_fp(ctx, type, op2_reg, 0, op3_reg);
|
ir_emit_store_mem_fp(ctx, type, op2_reg, 0, op3_reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
ir_x86.dasc
56
ir_x86.dasc
@ -5269,6 +5269,9 @@ static void ir_emit_load_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
if (sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(addr)) {
|
if (sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(addr)) {
|
||||||
int32_t addr32 = (int32_t)(intptr_t)addr;
|
int32_t addr32 = (int32_t)(intptr_t)addr;
|
||||||
| ASM_REG_MEM_OP mov, type, def_reg, [addr32]
|
| ASM_REG_MEM_OP mov, type, def_reg, [addr32]
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_emit_store(ctx, type, def, def_reg);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5277,18 +5280,18 @@ static void ir_emit_load_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
}
|
}
|
||||||
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
if (!IR_IS_CONST_REF(insn->op2) && (ir_rule(ctx, insn->op2) & IR_FUSED)) {
|
||||||
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if ((op2_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op2)) {
|
} else if ((op2_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op2)) {
|
||||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
|
||||||
ir_reg fp;
|
|
||||||
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ir_emit_load_mem_int(ctx, type, def_reg, op2_reg, offset);
|
ir_emit_load_mem_int(ctx, type, def_reg, op2_reg, offset);
|
||||||
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
ir_emit_store(ctx, type, def, def_reg);
|
ir_emit_store(ctx, type, def, def_reg);
|
||||||
@ -5315,24 +5318,27 @@ static void ir_emit_load_fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
|||||||
|
|
||||||
IR_ASSERT(sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(ctx->ir_base[insn->op2].val.i64));
|
IR_ASSERT(sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(ctx->ir_base[insn->op2].val.i64));
|
||||||
| ASM_FP_REG_MEM_OP movss, movsd, vmovss, vmovsd, type, def_reg, [addr32]
|
| ASM_FP_REG_MEM_OP movss, movsd, vmovss, vmovsd, type, def_reg, [addr32]
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_emit_store(ctx, type, def, def_reg);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
} else if (op2_reg == IR_REG_NONE) {
|
} else if (op2_reg == IR_REG_NONE) {
|
||||||
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
||||||
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
|
||||||
ir_reg fp;
|
|
||||||
if (ir_ref_spill_slot(ctx, def, &fp) == offset && op2_reg == fp) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ir_emit_load_mem_fp(ctx, type, def_reg, op2_reg, offset);
|
ir_emit_load_mem_fp(ctx, type, def_reg, op2_reg, offset);
|
||||||
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
if (ctx->regs[def][0] & IR_REG_SPILL_STORE) {
|
||||||
ir_emit_store(ctx, type, def, def_reg);
|
ir_emit_store(ctx, type, def, def_reg);
|
||||||
@ -5371,6 +5377,12 @@ static void ir_emit_store_int(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
}
|
}
|
||||||
} else if (op2_reg == IR_REG_NONE) {
|
} else if (op2_reg == IR_REG_NONE) {
|
||||||
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
||||||
|
if (!IR_IS_CONST_REF(insn->op3) && (op3_reg & IR_REG_SPILL_LOAD)) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op2_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
@ -5399,28 +5411,38 @@ static void ir_emit_store_fp(ir_ctx *ctx, ir_ref ref, ir_insn *insn)
|
|||||||
int32_t offset = 0;
|
int32_t offset = 0;
|
||||||
|
|
||||||
IR_ASSERT(op3_reg != IR_REG_NONE);
|
IR_ASSERT(op3_reg != IR_REG_NONE);
|
||||||
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
|
||||||
op3_reg &= ~IR_REG_SPILL_LOAD;
|
|
||||||
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
|
||||||
}
|
|
||||||
if (IR_IS_CONST_REF(insn->op2)) {
|
if (IR_IS_CONST_REF(insn->op2)) {
|
||||||
if (op2_reg == IR_REG_NONE) {
|
if (op2_reg == IR_REG_NONE) {
|
||||||
int32_t addr32 = ctx->ir_base[insn->op2].val.i32;
|
int32_t addr32 = ctx->ir_base[insn->op2].val.i32;
|
||||||
|
|
||||||
IR_ASSERT(sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(ctx->ir_base[insn->op2].val.i64));
|
IR_ASSERT(sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(ctx->ir_base[insn->op2].val.i64));
|
||||||
| ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [addr32], op2_reg
|
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
|
| ASM_FP_MEM_REG_OP movss, movsd, vmovss, vmovsd, type, [addr32], op3_reg
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
} else if (op2_reg == IR_REG_NONE) {
|
} else if (op2_reg == IR_REG_NONE) {
|
||||||
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
offset = ir_fuse_addr(ctx, insn->op2, &op2_reg);
|
||||||
|
if (!IR_IS_CONST_REF(insn->op3) && (op3_reg & IR_REG_SPILL_LOAD)) {
|
||||||
|
ir_reg fp;
|
||||||
|
if (ir_ref_spill_slot(ctx, insn->op3, &fp) == offset && op2_reg == fp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
} else if (op2_reg & IR_REG_SPILL_LOAD) {
|
||||||
op2_reg &= ~IR_REG_SPILL_LOAD;
|
op2_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
IR_ASSERT(ctx->ir_base[insn->op2].type == IR_ADDR);
|
||||||
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((op3_reg & IR_REG_SPILL_LOAD) || IR_IS_CONST_REF(insn->op3)) {
|
||||||
|
op3_reg &= ~IR_REG_SPILL_LOAD;
|
||||||
|
ir_emit_load(ctx, type, op3_reg, insn->op3);
|
||||||
|
}
|
||||||
ir_emit_store_mem_fp(ctx, type, op2_reg, offset, op3_reg);
|
ir_emit_store_mem_fp(ctx, type, op2_reg, offset, op3_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user