Update IR

IR commit: 79483000c2a4b918221fa3097ca47b48b3519447
This commit is contained in:
Dmitry Stogov 2024-12-19 20:29:35 +03:00
parent 6666cc83c5
commit 33c12e0776
No known key found for this signature in database
8 changed files with 170 additions and 43 deletions

View file

@ -330,6 +330,7 @@ static ir_ref ir_next_const(ir_ctx *ctx)
static void ir_grow_top(ir_ctx *ctx) static void ir_grow_top(ir_ctx *ctx)
{ {
ir_ref old_insns_limit = ctx->insns_limit;
ir_insn *buf = ctx->ir_base - ctx->consts_limit; ir_insn *buf = ctx->ir_base - ctx->consts_limit;
if (ctx->insns_limit < 1024 * 4) { if (ctx->insns_limit < 1024 * 4) {
@ -341,6 +342,12 @@ static void ir_grow_top(ir_ctx *ctx)
} }
buf = ir_mem_realloc(buf, (ctx->consts_limit + ctx->insns_limit) * sizeof(ir_insn)); buf = ir_mem_realloc(buf, (ctx->consts_limit + ctx->insns_limit) * sizeof(ir_insn));
ctx->ir_base = buf + ctx->consts_limit; ctx->ir_base = buf + ctx->consts_limit;
if (ctx->use_lists) {
ctx->use_lists = ir_mem_realloc(ctx->use_lists, ctx->insns_limit * sizeof(ir_use_list));
memset(ctx->use_lists + old_insns_limit, 0,
(ctx->insns_limit - old_insns_limit) * sizeof(ir_use_list));
}
} }
static ir_ref ir_next_insn(ir_ctx *ctx) static ir_ref ir_next_insn(ir_ctx *ctx)
@ -1152,7 +1159,7 @@ void ir_build_def_use_lists(ir_ctx *ctx)
ir_ref n, i, j, *p, def; ir_ref n, i, j, *p, def;
ir_insn *insn; ir_insn *insn;
uint32_t edges_count; uint32_t edges_count;
ir_use_list *lists = ir_mem_calloc(ctx->insns_count, sizeof(ir_use_list)); ir_use_list *lists = ir_mem_calloc(ctx->insns_limit, sizeof(ir_use_list));
ir_ref *edges; ir_ref *edges;
ir_use_list *use_list; ir_use_list *use_list;
@ -1207,7 +1214,7 @@ void ir_build_def_use_lists(ir_ctx *ctx)
ir_ref n, i, j, *p, def; ir_ref n, i, j, *p, def;
ir_insn *insn; ir_insn *insn;
size_t linked_lists_size, linked_lists_top = 0, edges_count = 0; size_t linked_lists_size, linked_lists_top = 0, edges_count = 0;
ir_use_list *lists = ir_mem_calloc(ctx->insns_count, sizeof(ir_use_list)); ir_use_list *lists = ir_mem_calloc(ctx->insns_limit, sizeof(ir_use_list));
ir_ref *edges; ir_ref *edges;
ir_use_list *use_list; ir_use_list *use_list;
ir_ref *linked_lists; ir_ref *linked_lists;

View file

@ -528,11 +528,12 @@ void ir_strtab_free(ir_strtab *strtab);
#define IR_OPT_INLINE (1<<16) #define IR_OPT_INLINE (1<<16)
#define IR_OPT_FOLDING (1<<17) #define IR_OPT_FOLDING (1<<17)
#define IR_OPT_CFG (1<<18) /* merge BBs, by remove END->BEGIN nodes during CFG construction */ #define IR_OPT_CFG (1<<18) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
#define IR_OPT_CODEGEN (1<<19) #define IR_OPT_MEM2SSA (1<<19)
#define IR_GEN_NATIVE (1<<20) #define IR_OPT_CODEGEN (1<<20)
#define IR_GEN_CODE (1<<21) /* C or LLVM */ #define IR_GEN_NATIVE (1<<21)
#define IR_GEN_CODE (1<<22) /* C or LLVM */
#define IR_GEN_CACHE_DEMOTE (1<<22) /* Demote the generated code from closest CPU caches */ #define IR_GEN_CACHE_DEMOTE (1<<23) /* Demote the generated code from closest CPU caches */
/* debug related */ /* debug related */
#ifdef IR_DEBUG #ifdef IR_DEBUG
@ -751,13 +752,15 @@ ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref);
/* Def -> Use lists */ /* Def -> Use lists */
void ir_build_def_use_lists(ir_ctx *ctx); void ir_build_def_use_lists(ir_ctx *ctx);
/* SSA Construction */
int ir_mem2ssa(ir_ctx *ctx);
/* CFG - Control Flow Graph (implementation in ir_cfg.c) */ /* CFG - Control Flow Graph (implementation in ir_cfg.c) */
int ir_build_cfg(ir_ctx *ctx); int ir_build_cfg(ir_ctx *ctx);
int ir_remove_unreachable_blocks(ir_ctx *ctx);
int ir_build_dominators_tree(ir_ctx *ctx); int ir_build_dominators_tree(ir_ctx *ctx);
int ir_find_loops(ir_ctx *ctx); int ir_find_loops(ir_ctx *ctx);
int ir_schedule_blocks(ir_ctx *ctx); int ir_schedule_blocks(ir_ctx *ctx);
void ir_build_prev_refs(ir_ctx *ctx); void ir_reset_cfg(ir_ctx *ctx);
/* SCCP - Sparse Conditional Constant Propagation (implementation in ir_sccp.c) */ /* SCCP - Sparse Conditional Constant Propagation (implementation in ir_sccp.c) */
int ir_sccp(ir_ctx *ctx); int ir_sccp(ir_ctx *ctx);
@ -929,7 +932,7 @@ IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
} }
return ir_emit_code(ctx, size); return ir_emit_code(ctx, size);
} else if (opt_level == 1 || opt_level == 2) { } else if (opt_level > 0) {
if (!(ctx->flags & IR_OPT_FOLDING)) { if (!(ctx->flags & IR_OPT_FOLDING)) {
// IR_ASSERT(0 && "IR_OPT_FOLDING must be set in ir_init() for -O1 and -O2"); // IR_ASSERT(0 && "IR_OPT_FOLDING must be set in ir_init() for -O1 and -O2");
return NULL; return NULL;
@ -938,14 +941,29 @@ IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
ir_build_def_use_lists(ctx); ir_build_def_use_lists(ctx);
if (opt_level == 2 if (ctx->flags & IR_OPT_MEM2SSA) {
&& !ir_sccp(ctx)) {
return NULL;
}
if (!ir_build_cfg(ctx) if (!ir_build_cfg(ctx)
|| !ir_build_dominators_tree(ctx) || !ir_build_dominators_tree(ctx)
|| !ir_find_loops(ctx) || !ir_mem2ssa(ctx)) {
return NULL;
}
}
if (opt_level > 1) {
ir_reset_cfg(ctx);
if (!ir_sccp(ctx)) {
return NULL;
}
}
if (!ctx->cfg_blocks) {
if (!ir_build_cfg(ctx)
|| !ir_build_dominators_tree(ctx)) {
return NULL;
}
}
if (!ir_find_loops(ctx)
|| !ir_gcm(ctx) || !ir_gcm(ctx)
|| !ir_schedule(ctx) || !ir_schedule(ctx)
|| !ir_match(ctx) || !ir_match(ctx)

View file

@ -1095,6 +1095,8 @@ binop_fp:
} }
} }
return IR_SKIPPED | IR_NOP; return IR_SKIPPED | IR_NOP;
case IR_NOP:
return IR_SKIPPED | IR_NOP;
default: default:
break; break;
} }
@ -5603,7 +5605,8 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
} else if (def_flags & IR_USE_MUST_BE_IN_REG) { } else if (def_flags & IR_USE_MUST_BE_IN_REG) {
if (insn->op == IR_VLOAD if (insn->op == IR_VLOAD
&& ctx->live_intervals[ctx->vregs[i]] && ctx->live_intervals[ctx->vregs[i]]
&& ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1) { && ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1
&& ir_is_same_mem_var(ctx, i, ctx->ir_base[insn->op2].op3)) {
/* pass */ /* pass */
} else if (insn->op != IR_PARAM) { } else if (insn->op != IR_PARAM) {
reg = ir_get_free_reg(insn->type, available); reg = ir_get_free_reg(insn->type, available);
@ -5704,7 +5707,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) {
IR_REGSET_EXCL(available, reg); IR_REGSET_EXCL(available, reg);
ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD; ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD;
} else if (j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) { } else if (IR_IS_FOLDABLE_OP(insn->op) && j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) {
ctx->regs[i][j] = ctx->regs[i][1]; ctx->regs[i][j] = ctx->regs[i][1];
} else if (use_flags & IR_USE_MUST_BE_IN_REG) { } else if (use_flags & IR_USE_MUST_BE_IN_REG) {
reg = ir_get_free_reg(ctx->ir_base[input].type, available); reg = ir_get_free_reg(ctx->ir_base[input].type, available);

View file

@ -8,6 +8,8 @@
#include "ir.h" #include "ir.h"
#include "ir_private.h" #include "ir_private.h"
static int ir_remove_unreachable_blocks(ir_ctx *ctx);
IR_ALWAYS_INLINE void _ir_add_successors(const ir_ctx *ctx, ir_ref ref, ir_worklist *worklist) IR_ALWAYS_INLINE void _ir_add_successors(const ir_ctx *ctx, ir_ref ref, ir_worklist *worklist)
{ {
ir_use_list *use_list = &ctx->use_lists[ref]; ir_use_list *use_list = &ctx->use_lists[ref];
@ -57,6 +59,24 @@ IR_ALWAYS_INLINE void _ir_add_predecessors(const ir_insn *insn, ir_worklist *wor
} }
} }
void ir_reset_cfg(ir_ctx *ctx)
{
ctx->cfg_blocks_count = 0;
ctx->cfg_edges_count = 0;
if (ctx->cfg_blocks) {
ir_mem_free(ctx->cfg_blocks);
ctx->cfg_blocks = NULL;
if (ctx->cfg_edges) {
ir_mem_free(ctx->cfg_edges);
ctx->cfg_edges = NULL;
}
if (ctx->cfg_map) {
ir_mem_free(ctx->cfg_map);
ctx->cfg_map = NULL;
}
}
}
int ir_build_cfg(ir_ctx *ctx) int ir_build_cfg(ir_ctx *ctx)
{ {
ir_ref n, *p, ref, start, end; ir_ref n, *p, ref, start, end;
@ -330,11 +350,15 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
} }
} }
i--; i--;
for (j = i + 1; j <= n; j++) {
ir_insn_set_op(insn, j, IR_UNUSED);
}
if (i == 1) { if (i == 1) {
insn->op = IR_BEGIN; insn->op = IR_BEGIN;
insn->inputs_count = 1; insn->inputs_count = 1;
use_list = &ctx->use_lists[merge]; use_list = &ctx->use_lists[merge];
if (use_list->count > 1) { if (use_list->count > 1) {
n++;
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) { for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
use = *p; use = *p;
use_insn = &ctx->ir_base[use]; use_insn = &ctx->ir_base[use];
@ -347,12 +371,14 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
if (ir_bitset_in(life_inputs, j - 1)) { if (ir_bitset_in(life_inputs, j - 1)) {
use_insn->op1 = ir_insn_op(use_insn, j); use_insn->op1 = ir_insn_op(use_insn, j);
} else if (input > 0) { } else if (input > 0) {
ir_use_list_remove_all(ctx, input, use); ir_use_list_remove_one(ctx, input, use);
} }
} }
use_insn->op = IR_COPY; use_insn->op = IR_COPY;
use_insn->op2 = IR_UNUSED; use_insn->inputs_count = 1;
use_insn->op3 = IR_UNUSED; for (j = 2; j <= n; j++) {
ir_insn_set_op(use_insn, j, IR_UNUSED);
}
ir_use_list_remove_all(ctx, merge, use); ir_use_list_remove_all(ctx, merge, use);
} }
} }
@ -360,9 +386,9 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
} else { } else {
insn->inputs_count = i; insn->inputs_count = i;
n++;
use_list = &ctx->use_lists[merge]; use_list = &ctx->use_lists[merge];
if (use_list->count > 1) { if (use_list->count > 1) {
n++;
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) { for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
use = *p; use = *p;
use_insn = &ctx->ir_base[use]; use_insn = &ctx->ir_base[use];
@ -378,9 +404,13 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
} }
i++; i++;
} else if (input > 0) { } else if (input > 0) {
ir_use_list_remove_all(ctx, input, use); ir_use_list_remove_one(ctx, input, use);
} }
} }
use_insn->inputs_count = i - 1;
for (j = i; j <= n; j++) {
ir_insn_set_op(use_insn, j, IR_UNUSED);
}
} }
} }
} }
@ -390,7 +420,7 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
} }
/* CFG constructed after SCCP pass doesn't have unreachable BBs, otherwise they should be removed */ /* CFG constructed after SCCP pass doesn't have unreachable BBs, otherwise they should be removed */
int ir_remove_unreachable_blocks(ir_ctx *ctx) static int ir_remove_unreachable_blocks(ir_ctx *ctx)
{ {
uint32_t b, *p, i; uint32_t b, *p, i;
uint32_t unreachable_count = 0; uint32_t unreachable_count = 0;

View file

@ -362,6 +362,10 @@ bool ir_check(const ir_ctx *ctx)
break; break;
} }
} }
if (count == 0 && (insn->op == IR_END || insn->op == IR_LOOP_END)) {
/* Dead block */
break;
}
fprintf(stderr, "ir_base[%d].op (%s) must have 1 successor (%d)\n", fprintf(stderr, "ir_base[%d].op (%s) must have 1 successor (%d)\n",
i, ir_op_name[insn->op], count); i, ir_op_name[insn->op], count);
ok = 0; ok = 0;

View file

@ -356,10 +356,12 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b)
} }
} else { } else {
j = i = ctx->cfg_map[use]; j = i = ctx->cfg_map[use];
if (i) {
IR_ASSERT(i > 0); IR_ASSERT(i > 0);
while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) { while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) {
j = ctx->cfg_blocks[j].idom; j = ctx->cfg_blocks[j].idom;
} }
}
clone = ir_hashtab_find(&hash, j); clone = ir_hashtab_find(&hash, j);
if (clone == IR_INVALID_VAL) { if (clone == IR_INVALID_VAL) {
clone = clones_count++; clone = clones_count++;
@ -941,8 +943,9 @@ int ir_schedule(ir_ctx *ctx)
for (p = &ctx->use_edges[use_list->refs]; count > 0; p++, count--) { for (p = &ctx->use_edges[use_list->refs]; count > 0; p++, count--) {
ir_ref use = *p; ir_ref use = *p;
if (!_xlat[use]) {
ir_insn *use_insn = &ctx->ir_base[use]; ir_insn *use_insn = &ctx->ir_base[use];
if (!_xlat[use] && (_blocks[use] || use_insn->op == IR_PARAM)) {
IR_ASSERT(_blocks[use] == b || use_insn->op == IR_PARAM);
if (use_insn->op == IR_PARAM if (use_insn->op == IR_PARAM
|| use_insn->op == IR_VAR || use_insn->op == IR_VAR
|| use_insn->op == IR_PI || use_insn->op == IR_PI

View file

@ -1120,6 +1120,7 @@ struct _ir_block {
uint32_t loop_depth; uint32_t loop_depth;
}; };
void ir_build_prev_refs(ir_ctx *ctx);
uint32_t ir_skip_empty_target_blocks(const ir_ctx *ctx, uint32_t b); uint32_t ir_skip_empty_target_blocks(const ir_ctx *ctx, uint32_t b);
uint32_t ir_next_block(const ir_ctx *ctx, uint32_t b); uint32_t ir_next_block(const ir_ctx *ctx, uint32_t b);
void ir_get_true_false_blocks(const ir_ctx *ctx, uint32_t b, uint32_t *true_block, uint32_t *false_block); void ir_get_true_false_blocks(const ir_ctx *ctx, uint32_t b, uint32_t *true_block, uint32_t *false_block);

View file

@ -1456,11 +1456,29 @@ op2_const:
case IR_SEXT: case IR_SEXT:
case IR_ZEXT: case IR_ZEXT:
case IR_TRUNC: case IR_TRUNC:
case IR_BITCAST:
case IR_PROTO: case IR_PROTO:
case IR_FP2FP: case IR_FP2FP:
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG; flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
break; break;
case IR_BITCAST:
insn = &ctx->ir_base[ref];
if (IR_IS_TYPE_INT(insn->type) && IR_IS_TYPE_INT(ctx->ir_base[insn->op1].type)) {
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
} else {
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
}
break;
case IR_FP2INT:
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
break;
case IR_INT2FP:
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
insn = &ctx->ir_base[ref];
if (IR_IS_CONST_REF(insn->op1)) {
constraints->tmp_regs[0] = IR_TMP_REG(1, ctx->ir_base[insn->op1].type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
n = 1;
}
break;
case IR_ABS_INT: case IR_ABS_INT:
flags = IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG; flags = IR_DEF_CONFLICTS_WITH_INPUT_REGS | IR_USE_MUST_BE_IN_REG | IR_OP1_MUST_BE_IN_REG;
break; break;
@ -2878,6 +2896,8 @@ store_int:
} }
} }
return IR_SKIPPED | IR_NOP; return IR_SKIPPED | IR_NOP;
case IR_NOP:
return IR_SKIPPED | IR_NOP;
default: default:
break; break;
} }
@ -6202,23 +6222,36 @@ static void ir_emit_cond(ir_ctx *ctx, ir_ref def, ir_insn *insn)
IR_ASSERT(def_reg != IR_REG_NONE); IR_ASSERT(def_reg != IR_REG_NONE);
if (op2 != op3) {
if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) { if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
op2_reg = IR_REG_NUM(op2_reg); op2_reg = IR_REG_NUM(op2_reg);
ir_emit_load(ctx, type, op2_reg, op2); ir_emit_load(ctx, type, op2_reg, op2);
if (op1 == op2) { if (op1 == op2) {
op1_reg = op2_reg; op1_reg = op2_reg;
} }
if (op3 == op2) {
op3_reg = op2_reg;
} }
} if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
if (op3_reg != IR_REG_NONE && op3 != op2 && IR_REG_SPILLED(op3_reg)) {
op3_reg = IR_REG_NUM(op3_reg); op3_reg = IR_REG_NUM(op3_reg);
ir_emit_load(ctx, type, op3_reg, op3); ir_emit_load(ctx, type, op3_reg, op3);
if (op1 == op2) { if (op1 == op2) {
op1_reg = op3_reg; op1_reg = op3_reg;
} }
} }
} else if (op2_reg != IR_REG_NONE && IR_REG_SPILLED(op2_reg)) {
op2_reg = IR_REG_NUM(op2_reg);
ir_emit_load(ctx, type, op2_reg, op2);
op3_reg = op2_reg;
if (op1 == op2) {
op1_reg = op2_reg;
}
} else if (op3_reg != IR_REG_NONE && IR_REG_SPILLED(op3_reg)) {
op3_reg = IR_REG_NUM(op3_reg);
ir_emit_load(ctx, type, op3_reg, op3);
op2_reg = op3_reg;
if (op1 == op3) {
op1_reg = op3_reg;
}
}
if (op1_reg != IR_REG_NONE && op1 != op2 && op1 != op3 && IR_REG_SPILLED(op1_reg)) { if (op1_reg != IR_REG_NONE && op1 != op2 && op1 != op3 && IR_REG_SPILLED(op1_reg)) {
op1_reg = IR_REG_NUM(op1_reg); op1_reg = IR_REG_NUM(op1_reg);
ir_emit_load(ctx, op1_type, op1_reg, op1); ir_emit_load(ctx, op1_type, op1_reg, op1);
@ -6710,7 +6743,19 @@ static void ir_emit_sext(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|.endif |.endif
} }
} else if (IR_IS_CONST_REF(insn->op1)) { } else if (IR_IS_CONST_REF(insn->op1)) {
IR_ASSERT(0); int64_t val;
if (ir_type_size[src_type] == 1) {
val = ctx->ir_base[insn->op1].val.i8;
} else if (ir_type_size[src_type] == 2) {
val = ctx->ir_base[insn->op1].val.i16;
} else if (ir_type_size[src_type] == 4) {
val = ctx->ir_base[insn->op1].val.i32;
} else {
IR_ASSERT(ir_type_size[src_type] == 8);
val = ctx->ir_base[insn->op1].val.i64;
}
ir_emit_mov_imm_int(ctx, dst_type, def_reg, val);
} else { } else {
ir_mem mem; ir_mem mem;
@ -6809,7 +6854,19 @@ static void ir_emit_zext(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|.endif |.endif
} }
} else if (IR_IS_CONST_REF(insn->op1)) { } else if (IR_IS_CONST_REF(insn->op1)) {
IR_ASSERT(0); uint64_t val;
if (ir_type_size[src_type] == 1) {
val = ctx->ir_base[insn->op1].val.u8;
} else if (ir_type_size[src_type] == 2) {
val = ctx->ir_base[insn->op1].val.u16;
} else if (ir_type_size[src_type] == 4) {
val = ctx->ir_base[insn->op1].val.u32;
} else {
IR_ASSERT(ir_type_size[src_type] == 8);
val = ctx->ir_base[insn->op1].val.u64;
}
ir_emit_mov_imm_int(ctx, dst_type, def_reg, val);
} else { } else {
ir_mem mem; ir_mem mem;
@ -7117,6 +7174,8 @@ static void ir_emit_int2fp(ir_ctx *ctx, ir_ref def, ir_insn *insn)
} }
|.endif |.endif
} }
} else if (IR_IS_CONST_REF(insn->op1)) {
IR_ASSERT(0);
} else { } else {
ir_mem mem; ir_mem mem;
bool src64 = ir_type_size[src_type] == 8; bool src64 = ir_type_size[src_type] == 8;
@ -9559,7 +9618,7 @@ static void ir_emit_sse_sqrt(ir_ctx *ctx, ir_ref def, ir_insn *insn)
if (IR_REG_SPILLED(op3_reg)) { if (IR_REG_SPILLED(op3_reg)) {
op3_reg = IR_REG_NUM(op3_reg); op3_reg = IR_REG_NUM(op3_reg);
ir_emit_load(ctx, IR_ADDR, op3_reg, insn->op3); ir_emit_load(ctx, insn->type, op3_reg, insn->op3);
} }
| ASM_FP_REG_REG_OP sqrts, insn->type, def_reg, op3_reg | ASM_FP_REG_REG_OP sqrts, insn->type, def_reg, op3_reg
@ -9581,7 +9640,7 @@ static void ir_emit_sse_round(ir_ctx *ctx, ir_ref def, ir_insn *insn, int round_
if (IR_REG_SPILLED(op3_reg)) { if (IR_REG_SPILLED(op3_reg)) {
op3_reg = IR_REG_NUM(op3_reg); op3_reg = IR_REG_NUM(op3_reg);
ir_emit_load(ctx, IR_ADDR, op3_reg, insn->op3); ir_emit_load(ctx, insn->type, op3_reg, insn->op3);
} }
if (ctx->mflags & IR_X86_AVX) { if (ctx->mflags & IR_X86_AVX) {
@ -10019,7 +10078,8 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
} else if (def_flags & IR_USE_MUST_BE_IN_REG) { } else if (def_flags & IR_USE_MUST_BE_IN_REG) {
if (insn->op == IR_VLOAD if (insn->op == IR_VLOAD
&& ctx->live_intervals[ctx->vregs[i]] && ctx->live_intervals[ctx->vregs[i]]
&& ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1) { && ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1
&& ir_is_same_mem_var(ctx, i, ctx->ir_base[insn->op2].op3)) {
/* pass */ /* pass */
} else if (insn->op != IR_PARAM) { } else if (insn->op != IR_PARAM) {
reg = ir_get_free_reg(insn->type, available); reg = ir_get_free_reg(insn->type, available);
@ -10120,7 +10180,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) { if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) {
IR_REGSET_EXCL(available, reg); IR_REGSET_EXCL(available, reg);
ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD; ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD;
} else if (j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) { } else if (IR_IS_FOLDABLE_OP(insn->op) && j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) {
ctx->regs[i][j] = ctx->regs[i][1]; ctx->regs[i][j] = ctx->regs[i][1];
} else if (use_flags & IR_USE_MUST_BE_IN_REG) { } else if (use_flags & IR_USE_MUST_BE_IN_REG) {
reg = ir_get_free_reg(ctx->ir_base[input].type, available); reg = ir_get_free_reg(ctx->ir_base[input].type, available);
@ -11018,7 +11078,8 @@ void ir_fix_thunk(void *thunk_entry, void *addr)
addr_ptr = (void**)(code + 6 + *offset_ptr); addr_ptr = (void**)(code + 6 + *offset_ptr);
*addr_ptr = addr; *addr_ptr = addr;
} else { } else {
int32_t *addr_ptr; typedef IR_SET_ALIGNED(1, int32_t unaligned_int32_t);
unaligned_int32_t *addr_ptr;
code[0] = 0xe9; code[0] = 0xe9;
addr_ptr = (int32_t*)(code + 1); addr_ptr = (int32_t*)(code + 1);