mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Update IR
IR commit: 34aeda97a5febe81fb53a679800f8c6cd802c847
This commit is contained in:
@@ -1730,7 +1730,7 @@ static ir_ref ir_find_aliasing_load(ir_ctx *ctx, ir_ref ref, ir_type type, ir_re
|
||||
}
|
||||
} else if (insn->op == IR_RSTORE) {
|
||||
modified_regset |= (1 << insn->op3);
|
||||
} else if (insn->op >= IR_START || insn->op == IR_CALL) {
|
||||
} else if (insn->op >= IR_START || insn->op == IR_CALL || insn->op == IR_VSTORE) {
|
||||
return IR_UNUSED;
|
||||
}
|
||||
ref = insn->op1;
|
||||
|
||||
@@ -94,6 +94,13 @@ static bool aarch64_may_encode_logical_imm(uint64_t value, uint32_t type_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool aarch64_may_encode_imm7_addr_offset(const int64_t offset, uint32_t type_size)
|
||||
{
|
||||
return (uintptr_t)(offset) % type_size == 0
|
||||
&& offset < 63 * (int32_t)type_size
|
||||
&& offset >= -64 * (int32_t)type_size;
|
||||
}
|
||||
|
||||
static bool aarch64_may_encode_addr_offset(int64_t offset, uint32_t type_size)
|
||||
{
|
||||
return (uintptr_t)(offset) % type_size == 0 && (uintptr_t)(offset) < 0xfff * type_size;
|
||||
@@ -352,7 +359,20 @@ int ir_get_target_constraints(const ir_ctx *ctx, ir_ref ref, ir_target_constrain
|
||||
constraints->tmp_regs[n] = IR_TMP_REG(1, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
||||
n++;
|
||||
}
|
||||
if (rule == IR_SHIFT && insn->op == IR_ROL) {
|
||||
if (rule == IR_SHIFT_CONST
|
||||
&& (insn->op == IR_ROL || insn->op == IR_ROR)
|
||||
&& ir_type_size[insn->type] < 4) {
|
||||
constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
||||
n++;
|
||||
} else if (rule == IR_SHIFT
|
||||
&& (insn->op == IR_ROL || insn->op == IR_ROR)
|
||||
&& ir_type_size[insn->type] < 4) {
|
||||
if (insn->op == IR_ROL) {
|
||||
flags |= IR_DEF_CONFLICTS_WITH_INPUT_REGS;
|
||||
}
|
||||
constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_LOAD_SUB_REF, IR_SAVE_SUB_REF);
|
||||
n++;
|
||||
} else if (rule == IR_SHIFT && insn->op == IR_ROL) {
|
||||
constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
|
||||
n++;
|
||||
}
|
||||
@@ -1341,9 +1361,16 @@ static void ir_emit_prologue(ir_ctx *ctx)
|
||||
{
|
||||
ir_backend_data *data = ctx->data;
|
||||
dasm_State **Dst = &data->dasm_state;
|
||||
int offset;
|
||||
|
||||
if (ctx->flags & IR_USE_FRAME_POINTER) {
|
||||
| stp x29, x30, [sp, # (-(ctx->stack_frame_size+16))]!
|
||||
offset = -(ctx->stack_frame_size+16);
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| stp x29, x30, [sp, #offset]!
|
||||
} else {
|
||||
| sub sp, sp, #(ctx->stack_frame_size+16)
|
||||
| stp x29, x30, [sp]
|
||||
}
|
||||
| mov x29, sp
|
||||
if (ctx->call_stack_size) {
|
||||
| sub sp, sp, #(ctx->call_stack_size)
|
||||
@@ -1357,7 +1384,6 @@ static void ir_emit_prologue(ir_ctx *ctx)
|
||||
}
|
||||
if (ctx->used_preserved_regs) {
|
||||
ir_reg fp;
|
||||
int offset;
|
||||
uint32_t i;
|
||||
ir_reg prev = IR_REG_NONE;
|
||||
ir_regset used_preserved_regs = (ir_regset)ctx->used_preserved_regs;
|
||||
@@ -1375,7 +1401,13 @@ static void ir_emit_prologue(ir_ctx *ctx)
|
||||
prev = i;
|
||||
} else if (i < IR_REG_FP_FIRST) {
|
||||
offset -= sizeof(void*) * 2;
|
||||
| stp Rx(prev), Rx(i), [Rx(fp), #offset]
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| stp Rx(prev), Rx(i), [Rx(fp), #offset]
|
||||
} else {
|
||||
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
|
||||
| str Rx(prev), [Rx(fp), #offset]
|
||||
| str Rx(i), [Rx(fp), #(offset+8)]
|
||||
}
|
||||
prev = IR_REG_NONE;
|
||||
} else {
|
||||
if (prev < IR_REG_FP_FIRST) {
|
||||
@@ -1385,7 +1417,13 @@ static void ir_emit_prologue(ir_ctx *ctx)
|
||||
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
} else {
|
||||
offset -= sizeof(void*) * 2;
|
||||
| stp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| stp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
} else {
|
||||
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
|
||||
| str Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
| str Rd(i-IR_REG_FP_FIRST), [Rx(fp), #(offset+8)]
|
||||
}
|
||||
}
|
||||
prev = IR_REG_NONE;
|
||||
}
|
||||
@@ -1425,7 +1463,13 @@ static void ir_emit_prologue(ir_ctx *ctx)
|
||||
offset += sizeof(void*) * ctx->gp_reg_params;
|
||||
for (i = ctx->gp_reg_params; i < IR_REG_INT_ARGS; i++) {
|
||||
if (prev != IR_REG_NONE) {
|
||||
| stp Rx(prev), Rx(int_reg_params[i]), [Rx(fp), #offset]
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| stp Rx(prev), Rx(int_reg_params[i]), [Rx(fp), #offset]
|
||||
} else {
|
||||
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
|
||||
| str Rx(prev), [Rx(fp), #offset]
|
||||
| str Rx(int_reg_params[i]), [Rx(fp), #(offset+8)]
|
||||
}
|
||||
prev = IR_REG_NONE;
|
||||
offset += sizeof(void*) * 2;
|
||||
} else {
|
||||
@@ -1473,7 +1517,13 @@ static void ir_emit_epilogue(ir_ctx *ctx)
|
||||
prev = i;
|
||||
} else if (i < IR_REG_FP_FIRST) {
|
||||
offset -= sizeof(void*) * 2;
|
||||
| ldp Rx(prev), Rx(i), [Rx(fp), #offset]
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| ldp Rx(prev), Rx(i), [Rx(fp), #offset]
|
||||
} else {
|
||||
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
|
||||
| ldr Rx(prev), [Rx(fp), #offset]
|
||||
| ldr Rx(i), [Rx(fp), #(offset+8)]
|
||||
}
|
||||
prev = IR_REG_NONE;
|
||||
} else {
|
||||
if (prev < IR_REG_FP_FIRST) {
|
||||
@@ -1483,7 +1533,13 @@ static void ir_emit_epilogue(ir_ctx *ctx)
|
||||
| ldr Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
} else {
|
||||
offset -= sizeof(void*) * 2;
|
||||
| ldp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
if (aarch64_may_encode_imm7_addr_offset(offset, 8)) {
|
||||
| ldp Rd(prev-IR_REG_FP_FIRST), Rd(i-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
} else {
|
||||
IR_ASSERT(aarch64_may_encode_addr_offset(offset, 8));
|
||||
| ldr Rd(prev-IR_REG_FP_FIRST), [Rx(fp), #offset]
|
||||
| ldr Rd(i-IR_REG_FP_FIRST), [Rx(fp), #(offset+8)]
|
||||
}
|
||||
}
|
||||
prev = IR_REG_NONE;
|
||||
}
|
||||
@@ -1504,7 +1560,12 @@ static void ir_emit_epilogue(ir_ctx *ctx)
|
||||
if (ctx->call_stack_size || (ctx->flags2 & IR_HAS_ALLOCA)) {
|
||||
| mov sp, x29
|
||||
}
|
||||
| ldp x29, x30, [sp], # (ctx->stack_frame_size+16)
|
||||
if (aarch64_may_encode_imm7_addr_offset(ctx->stack_frame_size+16, 8)) {
|
||||
| ldp x29, x30, [sp], #(ctx->stack_frame_size+16)
|
||||
} else {
|
||||
| ldp x29, x30, [sp]
|
||||
| add sp, sp, #(ctx->stack_frame_size+16)
|
||||
}
|
||||
} else if (ctx->stack_frame_size + ctx->call_stack_size) {
|
||||
if (ctx->fixed_stack_red_zone) {
|
||||
IR_ASSERT(ctx->stack_frame_size + ctx->call_stack_size <= ctx->fixed_stack_red_zone);
|
||||
@@ -1922,18 +1983,55 @@ static void ir_emit_shift(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case IR_SHL:
|
||||
| ASM_REG_REG_REG_OP lsl, type, def_reg, op1_reg, op2_reg
|
||||
if (ir_type_size[type] == 1) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xff
|
||||
| lsl Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xffff
|
||||
| lsl Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else {
|
||||
| ASM_REG_REG_REG_OP lsl, type, def_reg, op1_reg, op2_reg
|
||||
}
|
||||
break;
|
||||
case IR_SHR:
|
||||
| ASM_REG_REG_REG_OP lsr, type, def_reg, op1_reg, op2_reg
|
||||
if (ir_type_size[type] == 1) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xff
|
||||
| lsr Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xffff
|
||||
| lsr Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else {
|
||||
| ASM_REG_REG_REG_OP lsr, type, def_reg, op1_reg, op2_reg
|
||||
}
|
||||
break;
|
||||
case IR_SAR:
|
||||
| ASM_REG_REG_REG_OP asr, type, def_reg, op1_reg, op2_reg
|
||||
if (ir_type_size[type] == 1) {
|
||||
| sxtb Rw(def_reg), Rw(op1_reg)
|
||||
| asr Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| sxth Rw(def_reg), Rw(op1_reg)
|
||||
| asr Rw(def_reg), Rw(def_reg), Rw(op2_reg)
|
||||
} else {
|
||||
| ASM_REG_REG_REG_OP asr, type, def_reg, op1_reg, op2_reg
|
||||
}
|
||||
break;
|
||||
case IR_ROL:
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
IR_ASSERT(tmp_reg != IR_REG_NONE);
|
||||
if (ir_type_size[type] == 8) {
|
||||
if (ir_type_size[type] == 1) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xff
|
||||
| add Rw(def_reg), Rw(def_reg), Rw(def_reg), lsl #8
|
||||
| add Rw(def_reg), Rw(def_reg), Rw(def_reg), lsl #16
|
||||
| neg Rw(tmp_reg), Rw(op2_reg)
|
||||
| ror Rw(def_reg), Rw(def_reg), Rw(tmp_reg)
|
||||
| and Rw(def_reg), Rw(def_reg), #0xff
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| and Rw(def_reg), Rw(op1_reg), #0xffff
|
||||
| add Rw(def_reg), Rw(def_reg), Rw(def_reg), lsl #16
|
||||
| neg Rw(tmp_reg), Rw(op2_reg)
|
||||
| ror Rw(def_reg), Rw(def_reg), Rw(tmp_reg)
|
||||
| and Rw(def_reg), Rw(def_reg), #0xffff
|
||||
} else if (ir_type_size[type] == 8) {
|
||||
| neg Rx(tmp_reg), Rx(op2_reg)
|
||||
| ror Rx(def_reg), Rx(op1_reg), Rx(tmp_reg)
|
||||
} else {
|
||||
@@ -1942,7 +2040,24 @@ static void ir_emit_shift(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
break;
|
||||
case IR_ROR:
|
||||
| ASM_REG_REG_REG_OP ror, type, def_reg, op1_reg, op2_reg
|
||||
if (ir_type_size[type] == 1) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
IR_ASSERT(tmp_reg != IR_REG_NONE);
|
||||
| and Rw(tmp_reg), Rw(op1_reg), #0xff
|
||||
| add Rw(tmp_reg), Rw(tmp_reg), Rw(tmp_reg), lsl #8
|
||||
| add Rw(tmp_reg), Rw(tmp_reg), Rw(tmp_reg), lsl #16
|
||||
| ror Rw(def_reg), Rw(tmp_reg), Rw(op2_reg)
|
||||
| and Rw(def_reg), Rw(def_reg), #0xff
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
IR_ASSERT(tmp_reg != IR_REG_NONE);
|
||||
| and Rw(tmp_reg), Rw(op1_reg), #0xffff
|
||||
| add Rw(tmp_reg), Rw(tmp_reg), Rw(tmp_reg), lsl #16
|
||||
| ror Rw(def_reg), Rw(tmp_reg), Rw(op2_reg)
|
||||
| and Rw(def_reg), Rw(def_reg), #0xffff
|
||||
} else {
|
||||
| ASM_REG_REG_REG_OP ror, type, def_reg, op1_reg, op2_reg
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (IR_REG_SPILLED(ctx->regs[def][0])) {
|
||||
@@ -1959,6 +2074,7 @@ static void ir_emit_shift_const(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
ir_ref op1 = insn->op1;
|
||||
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
|
||||
ir_reg op1_reg = ctx->regs[def][1];
|
||||
ir_reg tmp_reg;
|
||||
|
||||
IR_ASSERT(IR_IS_CONST_REF(insn->op2));
|
||||
IR_ASSERT(!IR_IS_SYM_CONST(ctx->ir_base[insn->op2].op));
|
||||
@@ -1972,16 +2088,42 @@ static void ir_emit_shift_const(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case IR_SHL:
|
||||
| ASM_REG_REG_IMM_OP lsl, type, def_reg, op1_reg, shift
|
||||
if (ir_type_size[type] == 1) {
|
||||
| ubfiz Rw(def_reg), Rw(op1_reg), #shift, #(8-shift)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| ubfiz Rw(def_reg), Rw(op1_reg), #shift, #(16-shift)
|
||||
} else {
|
||||
| ASM_REG_REG_IMM_OP lsl, type, def_reg, op1_reg, shift
|
||||
}
|
||||
break;
|
||||
case IR_SHR:
|
||||
| ASM_REG_REG_IMM_OP lsr, type, def_reg, op1_reg, shift
|
||||
if (ir_type_size[type] == 1) {
|
||||
| ubfx Rw(def_reg), Rw(op1_reg), #shift, #(8-shift)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| ubfx Rw(def_reg), Rw(op1_reg), #shift, #(16-shift)
|
||||
} else {
|
||||
| ASM_REG_REG_IMM_OP lsr, type, def_reg, op1_reg, shift
|
||||
}
|
||||
break;
|
||||
case IR_SAR:
|
||||
| ASM_REG_REG_IMM_OP asr, type, def_reg, op1_reg, shift
|
||||
if (ir_type_size[type] == 1) {
|
||||
| sbfx Rw(def_reg), Rw(op1_reg), #shift, #(8-shift)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
| sbfx Rw(def_reg), Rw(op1_reg), #shift, #(16-shift)
|
||||
} else {
|
||||
| ASM_REG_REG_IMM_OP asr, type, def_reg, op1_reg, shift
|
||||
}
|
||||
break;
|
||||
case IR_ROL:
|
||||
if (ir_type_size[type] == 8) {
|
||||
if (ir_type_size[type] == 1) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
| ubfx Rw(tmp_reg), Rw(op1_reg), #(8-shift), #shift
|
||||
| orr Rw(def_reg), Rw(tmp_reg), Rw(op1_reg), lsl #shift
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
| ubfx Rw(tmp_reg), Rw(op1_reg), #(16-shift), #shift
|
||||
| orr Rw(def_reg), Rw(tmp_reg), Rw(op1_reg), lsl #shift
|
||||
} else if (ir_type_size[type] == 8) {
|
||||
shift = (64 - shift) % 64;
|
||||
| ror Rx(def_reg), Rx(op1_reg), #shift
|
||||
} else {
|
||||
@@ -1990,7 +2132,17 @@ static void ir_emit_shift_const(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
}
|
||||
break;
|
||||
case IR_ROR:
|
||||
| ASM_REG_REG_IMM_OP ror, type, def_reg, op1_reg, shift
|
||||
if (ir_type_size[type] == 1) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
| ubfx Rw(tmp_reg), Rw(op1_reg), #shift, #(8-shift)
|
||||
| orr Rw(def_reg), Rw(tmp_reg), Rw(op1_reg), lsl #(8-shift)
|
||||
} else if (ir_type_size[type] == 2) {
|
||||
tmp_reg = ctx->regs[def][3];
|
||||
| ubfx Rw(tmp_reg), Rw(op1_reg), #shift, #(16-shift)
|
||||
| orr Rw(def_reg), Rw(tmp_reg), Rw(op1_reg), lsl #(16-shift)
|
||||
} else {
|
||||
| ASM_REG_REG_IMM_OP ror, type, def_reg, op1_reg, shift
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (IR_REG_SPILLED(ctx->regs[def][0])) {
|
||||
@@ -3653,7 +3805,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
|
||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||
IR_ASSERT(!IR_IS_SYM_CONST(val->op));
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 >= 0);
|
||||
|
||||
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||
/* Stack must be 16 byte aligned */
|
||||
@@ -4971,7 +5123,7 @@ static void ir_emit_load_params(ir_ctx *ctx)
|
||||
if (ctx->flags & IR_USE_FRAME_POINTER) {
|
||||
stack_offset = sizeof(void*) * 2; /* skip old frame pointer and return address */
|
||||
} else {
|
||||
stack_offset = sizeof(void*) + ctx->stack_frame_size + ctx->call_stack_size; /* skip return address */
|
||||
stack_offset = ctx->stack_frame_size + ctx->call_stack_size;
|
||||
}
|
||||
n = use_list->count;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
@@ -5079,8 +5231,7 @@ static void ir_fix_param_spills(ir_ctx *ctx)
|
||||
/* skip old frame pointer and return address */
|
||||
stack_offset = sizeof(void*) * 2 + (ctx->stack_frame_size - ctx->stack_frame_alignment);
|
||||
} else {
|
||||
/* skip return address */
|
||||
stack_offset = sizeof(void*) + ctx->stack_frame_size;
|
||||
stack_offset = ctx->stack_frame_size;
|
||||
}
|
||||
n = use_list->count;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
|
||||
@@ -586,26 +586,41 @@ IR_FOLD(NOT(C_BOOL))
|
||||
|
||||
IR_FOLD(NOT(C_U8))
|
||||
IR_FOLD(NOT(C_CHAR))
|
||||
IR_FOLD(NOT(C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(~op1_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(~op1_insn->val.i8);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_U16))
|
||||
IR_FOLD(NOT(C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(~op1_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(~op1_insn->val.i16);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_U32))
|
||||
IR_FOLD(NOT(C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(~op1_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(~op1_insn->val.i32);
|
||||
}
|
||||
|
||||
IR_FOLD(NOT(C_U64))
|
||||
IR_FOLD(NOT(C_I64))
|
||||
{
|
||||
@@ -619,70 +634,50 @@ IR_FOLD(OR(C_BOOL, C_BOOL))
|
||||
IR_FOLD_BOOL(op1_insn->val.b || op2_insn->val.b);
|
||||
}
|
||||
|
||||
IR_FOLD(OR(C_U8, C_U8))
|
||||
IR_FOLD(OR(C_CHAR, C_CHAR))
|
||||
IR_FOLD(OR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u8 | op2_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(OR(C_U8, C_U8))
|
||||
IR_FOLD(OR(C_U16, C_U16))
|
||||
IR_FOLD(OR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u16 | op2_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(OR(C_U32, C_U32))
|
||||
IR_FOLD(OR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u32 | op2_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(OR(C_U64, C_U64))
|
||||
IR_FOLD(OR(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u64 | op2_insn->val.u64);
|
||||
}
|
||||
|
||||
IR_FOLD(OR(C_I8, C_I8))
|
||||
IR_FOLD(OR(C_I16, C_I16))
|
||||
IR_FOLD(OR(C_I32, C_I32))
|
||||
IR_FOLD(OR(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i64 | op2_insn->val.i64);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_BOOL, C_BOOL))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_BOOL(op1_insn->val.b && op2_insn->val.b);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_U8, C_U8))
|
||||
IR_FOLD(AND(C_CHAR, C_CHAR))
|
||||
IR_FOLD(AND(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u8 & op2_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_U8, C_U8))
|
||||
IR_FOLD(AND(C_U16, C_U16))
|
||||
IR_FOLD(AND(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u16 & op2_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_U32, C_U32))
|
||||
IR_FOLD(AND(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u32 & op2_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_U64, C_U64))
|
||||
IR_FOLD(AND(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u64 & op2_insn->val.u64);
|
||||
}
|
||||
|
||||
IR_FOLD(AND(C_I8, C_I8))
|
||||
IR_FOLD(AND(C_I16, C_I16))
|
||||
IR_FOLD(AND(C_I32, C_I32))
|
||||
IR_FOLD(AND(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i64 & op2_insn->val.i64);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_BOOL, C_BOOL))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
@@ -691,55 +686,90 @@ IR_FOLD(XOR(C_BOOL, C_BOOL))
|
||||
|
||||
IR_FOLD(XOR(C_U8, C_U8))
|
||||
IR_FOLD(XOR(C_CHAR, C_CHAR))
|
||||
IR_FOLD(XOR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u8 ^ op2_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i8 ^ op2_insn->val.i8);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_U16, C_U16))
|
||||
IR_FOLD(XOR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u16 ^ op2_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i16 ^ op2_insn->val.i16);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_U32, C_U32))
|
||||
IR_FOLD(XOR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u32 ^ op2_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i32 ^ op2_insn->val.i32);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_U64, C_U64))
|
||||
IR_FOLD(XOR(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u64 ^ op2_insn->val.u64);
|
||||
}
|
||||
|
||||
IR_FOLD(XOR(C_I64, C_I64))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i64 ^ op2_insn->val.i64);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_U8, C_U8))
|
||||
IR_FOLD(SHL(C_CHAR, C_CHAR))
|
||||
IR_FOLD(SHL(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u8 << op2_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i8 << op2_insn->val.i8);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_U16, C_U16))
|
||||
IR_FOLD(SHL(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u16 << op2_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i16 << op2_insn->val.i16);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_U32, C_U32))
|
||||
IR_FOLD(SHL(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u32 << op2_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I(op1_insn->val.i32 << op2_insn->val.i32);
|
||||
}
|
||||
|
||||
IR_FOLD(SHL(C_U64, C_U64))
|
||||
IR_FOLD(SHL(C_I64, C_I64))
|
||||
{
|
||||
@@ -749,26 +779,41 @@ IR_FOLD(SHL(C_I64, C_I64))
|
||||
|
||||
IR_FOLD(SHR(C_U8, C_U8))
|
||||
IR_FOLD(SHR(C_CHAR, C_CHAR))
|
||||
IR_FOLD(SHR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u8 >> op2_insn->val.u8);
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int8_t)(op1_insn->val.u8 >> op2_insn->val.u8));
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_U16, C_U16))
|
||||
IR_FOLD(SHR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u16 >> op2_insn->val.u16);
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U((int16_t)(op1_insn->val.u16 >> op2_insn->val.u16));
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_U32, C_U32))
|
||||
IR_FOLD(SHR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(op1_insn->val.u32 >> op2_insn->val.u32);
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U((int32_t)(op1_insn->val.u32 >> op2_insn->val.u32));
|
||||
}
|
||||
|
||||
IR_FOLD(SHR(C_U64, C_U64))
|
||||
IR_FOLD(SHR(C_I64, C_I64))
|
||||
{
|
||||
@@ -778,6 +823,11 @@ IR_FOLD(SHR(C_I64, C_I64))
|
||||
|
||||
IR_FOLD(SAR(C_U8, C_U8))
|
||||
IR_FOLD(SAR(C_CHAR, C_CHAR))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U((uint8_t)(op1_insn->val.i8 >> op2_insn->val.i8));
|
||||
}
|
||||
|
||||
IR_FOLD(SAR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
@@ -785,6 +835,11 @@ IR_FOLD(SAR(C_I8, C_I8))
|
||||
}
|
||||
|
||||
IR_FOLD(SAR(C_U16, C_U16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U((uint16_t)(op1_insn->val.i16 >> op2_insn->val.i16));
|
||||
}
|
||||
|
||||
IR_FOLD(SAR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
@@ -792,6 +847,11 @@ IR_FOLD(SAR(C_I16, C_I16))
|
||||
}
|
||||
|
||||
IR_FOLD(SAR(C_U32, C_U32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U((uint32_t)(op1_insn->val.i32 >> op2_insn->val.i32));
|
||||
}
|
||||
|
||||
IR_FOLD(SAR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
@@ -807,26 +867,41 @@ IR_FOLD(SAR(C_I64, C_I64))
|
||||
|
||||
IR_FOLD(ROL(C_U8, C_U8))
|
||||
IR_FOLD(ROL(C_CHAR, C_CHAR))
|
||||
IR_FOLD(ROL(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_rol8(op1_insn->val.u8, op2_insn->val.u8));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int8_t)ir_rol8(op1_insn->val.u8, op2_insn->val.u8));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_U16, C_U16))
|
||||
IR_FOLD(ROL(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_rol16(op1_insn->val.u16, op2_insn->val.u16));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int16_t)ir_rol16(op1_insn->val.u16, op2_insn->val.u16));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_U32, C_U32))
|
||||
IR_FOLD(ROL(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_rol32(op1_insn->val.u32, op2_insn->val.u32));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int32_t)ir_rol32(op1_insn->val.u32, op2_insn->val.u32));
|
||||
}
|
||||
|
||||
IR_FOLD(ROL(C_U64, C_U64))
|
||||
IR_FOLD(ROL(C_I64, C_I64))
|
||||
{
|
||||
@@ -836,26 +911,41 @@ IR_FOLD(ROL(C_I64, C_I64))
|
||||
|
||||
IR_FOLD(ROR(C_U8, C_U8))
|
||||
IR_FOLD(ROR(C_CHAR, C_CHAR))
|
||||
IR_FOLD(ROR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_ror8(op1_insn->val.u8, op2_insn->val.u8));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_I8, C_I8))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int8_t)ir_ror8(op1_insn->val.u8, op2_insn->val.u8));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_U16, C_U16))
|
||||
IR_FOLD(ROR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_ror16(op1_insn->val.u16, op2_insn->val.u16));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_I16, C_I16))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int16_t)ir_ror16(op1_insn->val.u16, op2_insn->val.u16));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_U32, C_U32))
|
||||
IR_FOLD(ROR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_U(ir_ror32(op1_insn->val.u32, op2_insn->val.u32));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_I32, C_I32))
|
||||
{
|
||||
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
|
||||
IR_FOLD_CONST_I((int32_t)ir_ror32(op1_insn->val.u32, op2_insn->val.u32));
|
||||
}
|
||||
|
||||
IR_FOLD(ROR(C_U64, C_U64))
|
||||
IR_FOLD(ROR(C_I64, C_I64))
|
||||
{
|
||||
@@ -1020,6 +1110,8 @@ IR_FOLD(BITCAST(C_ADDR))
|
||||
switch (IR_OPT_TYPE(opt)) {
|
||||
default:
|
||||
IR_ASSERT(0);
|
||||
case IR_BOOL:
|
||||
IR_FOLD_BOOL(op1_insn->val.i8 != 0);
|
||||
case IR_I8:
|
||||
IR_FOLD_CONST_I(op1_insn->val.i8);
|
||||
case IR_I16:
|
||||
@@ -1871,6 +1963,34 @@ IR_FOLD(ROR(C_I64, _))
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(LT(ABS, C_I8))
|
||||
IR_FOLD(LT(ABS, C_I16))
|
||||
IR_FOLD(LT(ABS, C_I32))
|
||||
IR_FOLD(LT(ABS, C_I64))
|
||||
IR_FOLD(LT(ABS, C_FLOAT))
|
||||
IR_FOLD(LT(ABS, C_DOUBLE))
|
||||
{
|
||||
if (op2_insn->val.u64 == 0) {
|
||||
/* abs() < 0 => false */
|
||||
IR_FOLD_COPY(IR_FALSE);
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
IR_FOLD(GE(ABS, C_I8))
|
||||
IR_FOLD(GE(ABS, C_I16))
|
||||
IR_FOLD(GE(ABS, C_I32))
|
||||
IR_FOLD(GE(ABS, C_I64))
|
||||
IR_FOLD(GE(ABS, C_FLOAT))
|
||||
IR_FOLD(GE(ABS, C_DOUBLE))
|
||||
{
|
||||
if (op2_insn->val.u64 == 0) {
|
||||
/* abs() >= 0 => true */
|
||||
IR_FOLD_COPY(IR_TRUE);
|
||||
}
|
||||
IR_FOLD_NEXT;
|
||||
}
|
||||
|
||||
// TODO: conversions
|
||||
|
||||
// TODO: Reassociation
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
# include <sys/types.h>
|
||||
# include <sys/sysctl.h>
|
||||
# include <sys/user.h>
|
||||
# include <libutil.h>
|
||||
#endif
|
||||
|
||||
#include "ir.h"
|
||||
@@ -562,6 +561,22 @@ void ir_gdb_unregister_all(void)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
static bool ir_gdb_info_proc(pid_t pid, struct kinfo_proc *proc)
|
||||
{
|
||||
size_t len, plen;
|
||||
len = plen = sizeof(*proc);
|
||||
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
|
||||
|
||||
if (sysctl(mib, 4, proc, &len, NULL, 0) < 0 || len != plen ||
|
||||
proc->ki_structsize != (int)plen || proc->ki_pid != pid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ir_gdb_present(void)
|
||||
{
|
||||
bool ret = 0;
|
||||
@@ -598,13 +613,13 @@ bool ir_gdb_present(void)
|
||||
close(fd);
|
||||
}
|
||||
#elif defined(__FreeBSD__)
|
||||
struct kinfo_proc *proc = kinfo_getproc(getpid());
|
||||
struct kinfo_proc proc, dbg;
|
||||
|
||||
if (proc) {
|
||||
if ((proc->ki_flag & P_TRACED) != 0) {
|
||||
struct kinfo_proc *dbg = kinfo_getproc(proc->ki_tracer);
|
||||
|
||||
ret = (dbg && strstr(dbg->ki_comm, "gdb"));
|
||||
if (ir_gdb_info_proc(getpid(), &proc)) {
|
||||
if ((proc.ki_flag & P_TRACED) != 0) {
|
||||
if (ir_gdb_info_proc(proc.ki_tracer, &dbg)) {
|
||||
ret = strstr(dbg.ki_comm, "gdb");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3174,7 +3174,6 @@ try_next_available_register:
|
||||
|
||||
/* split any inactive interval for reg at the end of its lifetime hole */
|
||||
other = *inactive;
|
||||
prev = NULL;
|
||||
while (other) {
|
||||
/* freeUntilPos[it.reg] = next intersection of it with current */
|
||||
if (reg == other->reg) {
|
||||
@@ -3187,17 +3186,12 @@ try_next_available_register:
|
||||
IR_LOG_LSRA_CONFLICT(" ---- Conflict with inactive", other, overlap);
|
||||
// TODO: optimal split position (this case is not tested)
|
||||
child = ir_split_interval_at(ctx, other, overlap);
|
||||
if (prev) {
|
||||
prev->list_next = other = other->list_next;
|
||||
} else {
|
||||
*inactive = other = other->list_next;
|
||||
}
|
||||
/* reset range cache */
|
||||
other->current_range = &other->range;
|
||||
ir_add_to_unhandled(unhandled, child);
|
||||
IR_LOG_LSRA(" ---- Queue", child, "");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prev = other;
|
||||
other = other->list_next;
|
||||
}
|
||||
|
||||
@@ -3277,6 +3271,7 @@ static bool ir_ival_spill_for_fuse_load(ir_ctx *ctx, ir_live_interval *ival, ir_
|
||||
} else if (ival->flags & IR_LIVE_INTERVAL_MEM_LOAD) {
|
||||
insn = &ctx->ir_base[IR_LIVE_POS_TO_REF(use_pos->pos)];
|
||||
IR_ASSERT(insn->op == IR_VLOAD);
|
||||
IR_ASSERT(ctx->ir_base[insn->op2].op == IR_VAR);
|
||||
use_pos = use_pos->next;
|
||||
if (use_pos && (use_pos->next || (use_pos->flags & IR_USE_MUST_BE_IN_REG))) {
|
||||
return 0;
|
||||
@@ -3287,9 +3282,21 @@ static bool ir_ival_spill_for_fuse_load(ir_ctx *ctx, ir_live_interval *ival, ir_
|
||||
if (bb->loop_depth && bb != ir_block_from_live_pos(ctx, ival->use_pos->pos)) {
|
||||
return 0;
|
||||
}
|
||||
/* check if VAR may be clobbered between VLOAD and use */
|
||||
ir_use_list *use_list = &ctx->use_lists[insn->op2];
|
||||
ir_ref n = use_list->count;
|
||||
ir_ref *p = &ctx->use_edges[use_list->refs];
|
||||
for (; n > 0; p++, n--) {
|
||||
ir_ref use = *p;
|
||||
if (ctx->ir_base[use].op == IR_VSTORE) {
|
||||
if (use > IR_LIVE_POS_TO_REF(ival->use_pos->pos) && use < IR_LIVE_POS_TO_REF(use_pos->pos)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (ctx->ir_base[use].op == IR_VADDR) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IR_ASSERT(ctx->ir_base[insn->op2].op == IR_VAR);
|
||||
ival->stack_spill_pos = ctx->ir_base[insn->op2].op3;
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -594,30 +594,40 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
|
||||
if (input && IR_IS_FEASIBLE(input)) {
|
||||
ir_insn *input_insn = &ctx->ir_base[input];
|
||||
|
||||
IR_ASSERT(input_insn->op == IR_END || input_insn->op == IR_IJMP || input_insn->op == IR_UNREACHABLE);
|
||||
if (input_insn->op == IR_END) {
|
||||
ir_ref prev, next = IR_UNUSED;
|
||||
ir_insn *next_insn = NULL;
|
||||
IR_ASSERT(input_insn->op == IR_END || input_insn->op == IR_LOOP_END||
|
||||
input_insn->op == IR_IJMP || input_insn->op == IR_UNREACHABLE);
|
||||
if (input_insn->op == IR_END || input_insn->op == IR_LOOP_END) {
|
||||
if (input < ref) {
|
||||
ir_ref prev, next = IR_UNUSED;
|
||||
ir_insn *next_insn = NULL;
|
||||
|
||||
prev = input_insn->op1;
|
||||
use_list = &ctx->use_lists[ref];
|
||||
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
|
||||
use = *p;
|
||||
use_insn = &ctx->ir_base[use];
|
||||
IR_ASSERT((use_insn->op != IR_PHI) && "PHI must be already removed");
|
||||
if (ir_op_flags[use_insn->op] & IR_OP_FLAG_CONTROL) {
|
||||
next = use;
|
||||
next_insn = use_insn;
|
||||
break;
|
||||
prev = input_insn->op1;
|
||||
use_list = &ctx->use_lists[ref];
|
||||
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
|
||||
use = *p;
|
||||
use_insn = &ctx->ir_base[use];
|
||||
IR_ASSERT((use_insn->op != IR_PHI) && "PHI must be already removed");
|
||||
if (ir_op_flags[use_insn->op] & IR_OP_FLAG_CONTROL) {
|
||||
next = use;
|
||||
next_insn = use_insn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
IR_ASSERT(prev && next);
|
||||
/* remove MERGE and input END from double linked control list */
|
||||
next_insn->op1 = prev;
|
||||
ir_sccp_replace_use(ctx, prev, input, next);
|
||||
/* remove MERGE and input END instructions */
|
||||
ir_sccp_make_nop(ctx, ref);
|
||||
ir_sccp_make_nop(ctx, input);
|
||||
} else {
|
||||
for (i = 2; i <= n; i++) {
|
||||
ir_insn_set_op(insn, i, IR_UNUSED);
|
||||
}
|
||||
insn->op = IR_BEGIN;
|
||||
insn->op1 = input;
|
||||
input_insn->op = IR_END;
|
||||
}
|
||||
IR_ASSERT(prev && next);
|
||||
/* remove MERGE and input END from double linked control list */
|
||||
next_insn->op1 = prev;
|
||||
ir_sccp_replace_use(ctx, prev, input, next);
|
||||
/* remove MERGE and input END instructions */
|
||||
ir_sccp_make_nop(ctx, ref);
|
||||
ir_sccp_make_nop(ctx, input);
|
||||
break;
|
||||
} else {
|
||||
for (i = 2; i <= n; i++) {
|
||||
|
||||
@@ -23,6 +23,7 @@ static uint32_t ir_str_hash(const char *str, size_t len)
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
h = ((h << 5) + h) + *str;
|
||||
str++;
|
||||
}
|
||||
return h | 0x10000000;
|
||||
}
|
||||
|
||||
@@ -724,7 +724,15 @@ op2_const:
|
||||
break;
|
||||
case IR_LOAD_FP:
|
||||
case IR_LOAD_INT:
|
||||
case IR_MEM_OP_INT:
|
||||
case IR_MEM_INC:
|
||||
case IR_MEM_DEC:
|
||||
case IR_MEM_MUL_PWR2:
|
||||
case IR_MEM_DIV_PWR2:
|
||||
case IR_MEM_MOD_PWR2:
|
||||
case IR_MEM_BINOP_INT:
|
||||
case IR_MEM_SHIFT:
|
||||
case IR_MEM_SHIFT_CONST:
|
||||
flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG;
|
||||
insn = &ctx->ir_base[ref];
|
||||
if (IR_IS_CONST_REF(insn->op2)) {
|
||||
@@ -1072,30 +1080,30 @@ static uint32_t ir_match_insn(ir_ctx *ctx, ir_ref ref)
|
||||
&& insn->op1 == ref - 1) { /* previous instruction */
|
||||
ir_insn *op1_insn = &ctx->ir_base[insn->op1];
|
||||
|
||||
if (op1_insn->op == IR_ADD ||
|
||||
op1_insn->op == IR_SUB ||
|
||||
// op1_insn->op == IR_MUL ||
|
||||
op1_insn->op == IR_OR ||
|
||||
op1_insn->op == IR_AND ||
|
||||
op1_insn->op == IR_XOR) {
|
||||
|
||||
if (op1_insn->op == IR_AND && ctx->use_lists[insn->op1].count == 1) {
|
||||
/* v = AND(_, _); CMP(v, 0) => SKIP_TEST; TEST */
|
||||
if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
|
||||
ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
|
||||
} else {
|
||||
ir_match_fuse_load(ctx, op1_insn->op2, ref);
|
||||
}
|
||||
if (op1_insn->op == IR_AND && ctx->use_lists[insn->op1].count == 1) {
|
||||
/* v = AND(_, _); CMP(v, 0) => SKIP_TEST; TEST */
|
||||
if (IR_IS_CONST_REF(op1_insn->op2)) {
|
||||
ir_match_fuse_load(ctx, op1_insn->op1, ref);
|
||||
}
|
||||
ctx->rules[insn->op1] = IR_FUSED | IR_TEST_INT;
|
||||
return IR_TESTCC_INT;
|
||||
} else {
|
||||
/* v = BINOP(_, _); CMP(v, 0) => BINOP; SETCC */
|
||||
ctx->rules[insn->op1] = IR_BINOP_INT;
|
||||
return IR_SETCC_INT;
|
||||
if (IR_IS_CONST_REF(op1_insn->op2)) {
|
||||
ir_match_fuse_load(ctx, op1_insn->op1, ref);
|
||||
}
|
||||
ctx->rules[insn->op1] = IR_FUSED | IR_TEST_INT;
|
||||
return IR_TESTCC_INT;
|
||||
} else if ((op1_insn->op == IR_OR || op1_insn->op == IR_AND || op1_insn->op == IR_XOR) ||
|
||||
/* GT(ADD(_, _), 0) can't be optimized because ADD may overflow */
|
||||
((op1_insn->op == IR_ADD || op1_insn->op == IR_SUB) &&
|
||||
(insn->op == IR_EQ || insn->op == IR_NE))) {
|
||||
/* v = BINOP(_, _); CMP(v, 0) => BINOP; SETCC */
|
||||
if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
|
||||
ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
|
||||
} else {
|
||||
ir_match_fuse_load(ctx, op1_insn->op2, ref);
|
||||
}
|
||||
ctx->rules[insn->op1] = IR_BINOP_INT;
|
||||
return IR_SETCC_INT;
|
||||
}
|
||||
}
|
||||
ir_match_fuse_load_cmp_int(ctx, insn, ref);
|
||||
@@ -1703,32 +1711,32 @@ store_int:
|
||||
&& op2_insn->op1 == insn->op2 - 1) { /* previous instruction */
|
||||
ir_insn *op1_insn = &ctx->ir_base[op2_insn->op1];
|
||||
|
||||
if (op1_insn->op == IR_ADD ||
|
||||
op1_insn->op == IR_SUB ||
|
||||
// op1_insn->op == IR_MUL ||
|
||||
op1_insn->op == IR_OR ||
|
||||
op1_insn->op == IR_AND ||
|
||||
op1_insn->op == IR_XOR) {
|
||||
|
||||
if (op1_insn->op == IR_AND && ctx->use_lists[op2_insn->op1].count == 1) {
|
||||
/* v = AND(_, _); c = CMP(v, 0) ... IF(c) => SKIP_TEST; SKIP ... TEST_AND_BRANCH */
|
||||
if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
|
||||
ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
|
||||
} else {
|
||||
ir_match_fuse_load(ctx, op1_insn->op2, ref);
|
||||
}
|
||||
if (op1_insn->op == IR_AND && ctx->use_lists[op2_insn->op1].count == 1) {
|
||||
/* v = AND(_, _); c = CMP(v, 0) ... IF(c) => SKIP_TEST; SKIP ... TEST_AND_BRANCH */
|
||||
if (IR_IS_CONST_REF(op1_insn->op2)) {
|
||||
ir_match_fuse_load(ctx, op1_insn->op1, ref);
|
||||
}
|
||||
ctx->rules[op2_insn->op1] = IR_FUSED | IR_TEST_INT;
|
||||
ctx->rules[insn->op2] = IR_FUSED | IR_SIMPLE | IR_NOP;
|
||||
return IR_TEST_AND_BRANCH_INT;
|
||||
} else {
|
||||
/* v = BINOP(_, _); c = CMP(v, 0) ... IF(c) => BINOP; SKIP_CMP ... JCC */
|
||||
ctx->rules[op2_insn->op1] = IR_BINOP_INT;
|
||||
ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
|
||||
return IR_JCC_INT;
|
||||
if (IR_IS_CONST_REF(op1_insn->op2)) {
|
||||
ir_match_fuse_load(ctx, op1_insn->op1, ref);
|
||||
}
|
||||
ctx->rules[op2_insn->op1] = IR_FUSED | IR_TEST_INT;
|
||||
ctx->rules[insn->op2] = IR_FUSED | IR_SIMPLE | IR_NOP;
|
||||
return IR_TEST_AND_BRANCH_INT;
|
||||
} else if ((op1_insn->op == IR_OR || op1_insn->op == IR_AND || op1_insn->op == IR_XOR) ||
|
||||
/* GT(ADD(_, _), 0) can't be optimized because ADD may overflow */
|
||||
((op1_insn->op == IR_ADD || op1_insn->op == IR_SUB) &&
|
||||
(op2_insn->op == IR_EQ || op2_insn->op == IR_NE))) {
|
||||
/* v = BINOP(_, _); c = CMP(v, 0) ... IF(c) => BINOP; SKIP_CMP ... JCC */
|
||||
if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
|
||||
ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
|
||||
} else {
|
||||
ir_match_fuse_load(ctx, op1_insn->op2, ref);
|
||||
}
|
||||
ctx->rules[op2_insn->op1] = IR_BINOP_INT;
|
||||
ctx->rules[insn->op2] = IR_FUSED | IR_CMP_INT;
|
||||
return IR_JCC_INT;
|
||||
}
|
||||
}
|
||||
/* c = CMP(_, _) ... IF(c) => SKIP_CMP ... CMP_AND_BRANCH */
|
||||
@@ -1844,13 +1852,10 @@ store_int:
|
||||
if (op2_insn->op1 == insn->op2 - 1) { /* previous instruction */
|
||||
ir_insn *op1_insn = &ctx->ir_base[op2_insn->op1];
|
||||
|
||||
if (op1_insn->op == IR_ADD ||
|
||||
op1_insn->op == IR_SUB ||
|
||||
// op1_insn->op == IR_MUL ||
|
||||
op1_insn->op == IR_OR ||
|
||||
op1_insn->op == IR_AND ||
|
||||
op1_insn->op == IR_XOR) {
|
||||
|
||||
if ((op1_insn->op == IR_OR || op1_insn->op == IR_AND || op1_insn->op == IR_XOR) ||
|
||||
/* GT(ADD(_, _), 0) can't be optimized because ADD may overflow */
|
||||
((op1_insn->op == IR_ADD || op1_insn->op == IR_SUB) &&
|
||||
(op2_insn->op == IR_EQ || op2_insn->op == IR_NE))) {
|
||||
if (ir_op_flags[op1_insn->op] & IR_OP_FLAG_COMMUTATIVE) {
|
||||
ir_match_fuse_load_commutative_int(ctx, op1_insn, ref);
|
||||
} else {
|
||||
@@ -1870,12 +1875,10 @@ store_int:
|
||||
if (store_insn->op == IR_STORE && store_insn->op3 == op2_insn->op1) {
|
||||
ir_insn *op_insn = &ctx->ir_base[op2_insn->op1];
|
||||
|
||||
if (op_insn->op == IR_ADD ||
|
||||
op_insn->op == IR_SUB ||
|
||||
// op_insn->op == IR_MUL ||
|
||||
op_insn->op == IR_OR ||
|
||||
op_insn->op == IR_AND ||
|
||||
op_insn->op == IR_XOR) {
|
||||
if ((op_insn->op == IR_OR || op_insn->op == IR_AND || op_insn->op == IR_XOR) ||
|
||||
/* GT(ADD(_, _), 0) can't be optimized because ADD may overflow */
|
||||
((op_insn->op == IR_ADD || op_insn->op == IR_SUB) &&
|
||||
(op2_insn->op == IR_EQ || op2_insn->op == IR_NE))) {
|
||||
if (ctx->ir_base[op_insn->op1].op == IR_LOAD
|
||||
&& ctx->ir_base[op_insn->op1].op2 == store_insn->op2) {
|
||||
if (ir_in_same_block(ctx, op_insn->op1)
|
||||
@@ -6428,7 +6431,7 @@ static void ir_emit_alloca(ir_ctx *ctx, ir_ref def, ir_insn *insn)
|
||||
|
||||
IR_ASSERT(IR_IS_TYPE_INT(val->type));
|
||||
IR_ASSERT(!IR_IS_SYM_CONST(val->op));
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 > 0);
|
||||
IR_ASSERT(IR_IS_TYPE_UNSIGNED(val->type) || val->val.i64 >= 0);
|
||||
IR_ASSERT(IR_IS_SIGNED_32BIT(val->val.i64));
|
||||
|
||||
if (ctx->flags2 & IR_HAS_CALLS) {
|
||||
|
||||
Reference in New Issue
Block a user