@@ -685,6 +685,11 @@ IR_ALWAYS_INLINE ir_mem IR_MEM(ir_reg base, int32_t offset, ir_reg index, int32_
685685|| }
686686|.endmacro
687687
688+ /* Zero a register. A 32-bit xor has a shorter encoding and also clears the upper 32 bits. */
689+ |.macro ASM_REG_ZERO, type, reg
690+ | xor Rd(reg), Rd(reg)
691+ |.endmacro
692+
688693|.macro ASM_REG_REG_OP2, op, type, op1, op2
689694|| switch (ir_type_size[type]) {
690695|| default:
@@ -1851,9 +1856,10 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
18511856 break;
18521857 case IR_SHIFT:
18531858 if (rule & IR_FUSED) {
1854- flags = IR_OP2_MUST_BE_IN_REG;
1859+ flags = IR_OP2_MUST_BE_IN_REG | IR_OP2_HINT_NEEDS_HOLE ;
18551860 } else {
1856- flags = IR_DEF_REUSES_OP1_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
1861+ flags = IR_DEF_REUSES_OP1_REG | IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG |
1862+ IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG | IR_OP2_HINT_NEEDS_HOLE;
18571863 }
18581864 constraints->hints[1] = IR_REG_NONE;
18591865 constraints->hints[2] = IR_REG_RCX;
@@ -3268,6 +3274,15 @@ static bool ir_match_has_flags_deps(ir_ctx *ctx, ir_ref ref, ir_ref root)
32683274 return pos != ref;
32693275}
32703276
3277+ static uint32_t ir_match_fuse_load_const_addr(ir_ctx *ctx, ir_ref ref, const ir_insn *addr_insn)
3278+ {
3279+ if (ir_may_fuse_addr(ctx, addr_insn)) {
3280+ return IR_FUSED | IR_SIMPLE | IR_LOAD;
3281+ }
3282+ /* The address doesn't fit into the displacement. Load it into a temporary register. */
3283+ return IR_FUSED | (IR_IS_TYPE_INT(ctx->ir_base[ref].type) ? IR_LOAD_INT : IR_LOAD_FP);
3284+ }
3285+
32713286static void ir_match_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
32723287{
32733288 if (ir_in_same_block(ctx, ref) &&
@@ -3279,10 +3294,8 @@ static void ir_match_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
32793294 ir_insn *addr_insn = &ctx->ir_base[addr_ref];
32803295
32813296 if (IR_IS_CONST_REF(addr_ref)) {
3282- if (ir_may_fuse_addr(ctx, addr_insn)) {
3283- ctx->rules[ref] = IR_FUSED | IR_SIMPLE | IR_LOAD;
3284- return;
3285- }
3297+ ctx->rules[ref] = ir_match_fuse_load_const_addr(ctx, ref, addr_insn);
3298+ return;
32863299 } else if (addr_insn->op == IR_TLS_ADDR) {
32873300 // TODO: try to fuse static TLS addr ???
32883301 return;
@@ -3307,10 +3320,8 @@ static bool ir_match_try_fuse_load(ir_ctx *ctx, ir_ref ref, ir_ref root)
33073320 ir_insn *addr_insn = &ctx->ir_base[addr_ref];
33083321
33093322 if (IR_IS_CONST_REF(addr_ref)) {
3310- if (ir_may_fuse_addr(ctx, addr_insn)) {
3311- ctx->rules[ref] = IR_FUSED | IR_SIMPLE | IR_LOAD;
3312- return 1;
3313- }
3323+ ctx->rules[ref] = ir_match_fuse_load_const_addr(ctx, ref, addr_insn);
3324+ return 1;
33143325 } else if (addr_insn->op == IR_TLS_ADDR) {
33153326 // TODO: try to fuse static TLS addr ???
33163327 return 0;
@@ -5348,7 +5359,11 @@ static void ir_match_insn2(ir_ctx *ctx, ir_ref ref, uint32_t rule)
53485359 if (rule == IR_LEA_IB) {
53495360 if (!ir_match_try_revert_lea_to_add(ctx, ref) && !(ctx->flags & IR_OPT_CODEGEN)) {
53505361 /* revert to ADD to avoid extra register spill load with -O0 */
5351- ctx->rules[ref] = IR_BINOP_INT | IR_MAY_SWAP;
5362+ ir_insn *insn = &ctx->ir_base[ref];
5363+
5364+ if (ctx->ir_base[insn->op1].op != IR_ALLOCA && ctx->ir_base[insn->op2].op != IR_ALLOCA) {
5365+ ctx->rules[ref] = IR_BINOP_INT | IR_MAY_SWAP;
5366+ }
53525367 }
53535368 }
53545369}
@@ -5458,7 +5473,7 @@ static void ir_emit_load_imm_int(ir_ctx *ctx, ir_type type, ir_reg reg, int64_t
54585473
54595474 IR_ASSERT(IR_IS_TYPE_INT(type));
54605475 if (val == 0) {
5461- | ASM_REG_REG_OP xor, type, reg , reg
5476+ | ASM_REG_ZERO type, reg
54625477 } else {
54635478 ir_emit_mov_imm_int(ctx, type, reg, val);
54645479 }
@@ -8234,7 +8249,7 @@ static void ir_emit_mul_div_mod(ir_ctx *ctx, ir_ref def, ir_insn *insn)
82348249 if (ir_type_size[type] == 1) {
82358250 | movzx ax, al
82368251 } else {
8237- | ASM_REG_REG_OP xor, type, IR_REG_RDX , IR_REG_RDX
8252+ | ASM_REG_ZERO type, IR_REG_RDX
82388253 }
82398254 if (op2_reg != IR_REG_NONE) {
82408255 | ASM_REG_OP div, type, op2_reg
@@ -8801,7 +8816,7 @@ static void ir_emit_cmp_int(ir_ctx *ctx, ir_ref def, ir_insn *insn)
88018816 if (IR_IS_CONST_REF(op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2].op) && ctx->ir_base[op2].val.u64 == 0) {
88028817 if (op == IR_ULT) {
88038818 /* always false */
8804- | xor Ra (def_reg), Ra (def_reg)
8819+ | xor Rd (def_reg), Rd (def_reg)
88058820 if (IR_REG_SPILLED(ctx->regs[def][0])) {
88068821 ir_emit_store(ctx, insn->type, def, def_reg);
88078822 }
@@ -14572,7 +14587,7 @@ static void ir_emit_cmp_i64(ir_ctx *ctx, ir_ref def, ir_insn *insn)
1457214587 if (IR_IS_CONST_REF(op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2].op) && ctx->ir_base[op2].val.u64 == 0) {
1457314588 if (op == IR_ULT) {
1457414589 /* always false */
14575- | xor Ra (def_reg), Ra (def_reg)
14590+ | xor Rd (def_reg), Rd (def_reg)
1457614591 if (IR_REG_SPILLED(ctx->regs[def][0])) {
1457714592 ir_emit_store(ctx, insn->type, def, def_reg);
1457814593 }
@@ -22205,7 +22220,7 @@ static void ir_emit_vector_binop_expand(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2220522220 } else if (element_size == 1) {
2220622221 | movzx ax, al
2220722222 } else {
22208- | ASM_REG_REG_OP xor, element_type, IR_REG_RDX , IR_REG_RDX
22223+ | ASM_REG_ZERO element_type, IR_REG_RDX
2220922224 }
2221022225 if (IR_IS_TYPE_SIGNED(element_type)) {
2221122226 | ASM_REG_OP idiv, element_type, tmp2_reg
@@ -22652,7 +22667,7 @@ static void ir_emit_vector_binop_expand(ir_ctx *ctx, ir_ref def, ir_insn *insn)
2265222667 } else if (element_size == 1) {
2265322668 | movzx ax, al
2265422669 } else {
22655- | ASM_REG_REG_OP xor, element_type, IR_REG_RDX , IR_REG_RDX
22670+ | ASM_REG_ZERO element_type, IR_REG_RDX
2265622671 }
2265722672 if (IR_IS_TYPE_SIGNED(element_type)) {
2265822673 | ASM_MEM_OP idiv, element_type, mem
@@ -25988,8 +26003,10 @@ void ir_fix_stack_frame(ir_ctx *ctx)
2598826003
2598926004#ifdef IR_TARGET_X86
2599026005 if (ctx->flags2 & IR_HAS_MEMCPY) {
25991- IR_REGSET_INCL(ctx->used_preserved_regs, IR_REG_RSI);
25992- IR_REGSET_INCL(ctx->used_preserved_regs, IR_REG_RDI);
26006+ ir_regset tmp = ctx->used_preserved_regs;
26007+ IR_REGSET_INCL(tmp, IR_REG_RSI);
26008+ IR_REGSET_INCL(tmp, IR_REG_RDI);
26009+ ctx->used_preserved_regs = tmp;
2599326010 }
2599426011#endif
2599526012
0 commit comments