mirror of
https://github.com/danog/ir.git
synced 2025-01-21 13:11:16 +01:00
Simplify access to nodes with variable inputs count
This commit is contained in:
parent
683f8d2124
commit
e01c43a967
72
ir.c
72
ir.c
@ -150,7 +150,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f)
|
||||
#define ir_op_flag_d2 (ir_op_flag_d | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_d2C (ir_op_flag_d | IR_OP_FLAG_COMMUTATIVE | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_d3 (ir_op_flag_d | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_dP (ir_op_flag_d | 5 | (5 << IR_OP_FLAG_OPERANDS_SHIFT)) // PHI (number of operands encoded in op1->op1)
|
||||
#define ir_op_flag_dN (ir_op_flag_d | IR_OP_FLAG_VAR_INPUTS) // PHI (number of operands encoded in op1->op1)
|
||||
#define ir_op_flag_r IR_OP_FLAG_DATA // "d" and "r" are the same now
|
||||
#define ir_op_flag_r0 ir_op_flag_r
|
||||
#define ir_op_flag_r0X1 (ir_op_flag_r | 0 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
@ -168,7 +168,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f)
|
||||
#define ir_op_flag_S1X1 (ir_op_flag_S | 1 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_S2 (ir_op_flag_S | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_S2X1 (ir_op_flag_S | 2 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_SN (ir_op_flag_S | 4 | (4 << IR_OP_FLAG_OPERANDS_SHIFT)) // MERGE (number of operands encoded in op1)
|
||||
#define ir_op_flag_SN (ir_op_flag_S | IR_OP_FLAG_VAR_INPUTS) // MERGE (number of operands encoded in op1)
|
||||
#define ir_op_flag_E (IR_OP_FLAG_CONTROL|IR_OP_FLAG_BB_END)
|
||||
#define ir_op_flag_E1 (ir_op_flag_E | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_E2 (ir_op_flag_E | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
@ -190,7 +190,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f)
|
||||
#define ir_op_flag_s3 (ir_op_flag_s | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_x1 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_x2 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_xN (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 4 | (4 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
#define ir_op_flag_xN (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | IR_OP_FLAG_VAR_INPUTS)
|
||||
#define ir_op_flag_a2 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_ALLOC | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
|
||||
|
||||
#define ir_op_kind____ IR_OPND_UNUSED
|
||||
@ -878,6 +878,9 @@ ir_fold_const:
|
||||
ir_ref ir_fold(ir_ctx *ctx, uint32_t opt, ir_ref op1, ir_ref op2, ir_ref op3)
|
||||
{
|
||||
if (UNEXPECTED(!(ctx->flags & IR_OPT_FOLDING))) {
|
||||
if ((opt & IR_OPT_OP_MASK) == IR_PHI) {
|
||||
opt |= (3 << IR_OPT_INPUTS_SHIFT);
|
||||
}
|
||||
return ir_emit(ctx, opt, op1, op2, op3);
|
||||
}
|
||||
return ir_folding(ctx, opt, op1, op2, op3, ctx->ir_base + op1, ctx->ir_base + op2, ctx->ir_base + op3);
|
||||
@ -916,10 +919,7 @@ ir_ref ir_emit_N(ir_ctx *ctx, uint32_t opt, int32_t count)
|
||||
ctx->insns_count = ref + 1 + count/4;
|
||||
|
||||
insn = &ctx->ir_base[ref];
|
||||
insn->optx = opt;
|
||||
if ((opt & IR_OPT_OP_MASK) != IR_PHI) {
|
||||
insn->inputs_count = count;
|
||||
}
|
||||
insn->optx = opt | (count << IR_OPT_INPUTS_SHIFT);
|
||||
for (i = 1, p = insn->ops + i; i <= (count|3); i++, p++) {
|
||||
*p = IR_UNUSED;
|
||||
}
|
||||
@ -931,29 +931,15 @@ void ir_set_op(ir_ctx *ctx, ir_ref ref, int32_t n, ir_ref val)
|
||||
{
|
||||
ir_insn *insn = &ctx->ir_base[ref];
|
||||
|
||||
#ifdef IR_DEBUG
|
||||
if (n > 3) {
|
||||
int32_t count = 3;
|
||||
int32_t count;
|
||||
|
||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||
count = insn->inputs_count;
|
||||
if (count == 0) {
|
||||
count = 2;
|
||||
}
|
||||
} else if (insn->op == IR_CALL || insn->op == IR_TAILCALL || insn->op == IR_SNAPSHOT) {
|
||||
count = insn->inputs_count;
|
||||
if (count == 0) {
|
||||
count = 2;
|
||||
}
|
||||
} else if (insn->op == IR_PHI) {
|
||||
count = ctx->ir_base[insn->op1].inputs_count + 1;
|
||||
if (count == 1) {
|
||||
count = 3;
|
||||
}
|
||||
} else {
|
||||
IR_ASSERT(0);
|
||||
}
|
||||
IR_ASSERT(IR_OP_HAS_VAR_INPUTS(ir_op_flags[insn->op]));
|
||||
count = insn->inputs_count;
|
||||
IR_ASSERT(n <= count);
|
||||
}
|
||||
#endif
|
||||
ir_insn_set_op(insn, n, val);
|
||||
}
|
||||
|
||||
@ -1467,7 +1453,7 @@ ir_ref _ir_PHI_2(ir_ctx *ctx, ir_ref src1, ir_ref src2)
|
||||
|
||||
IR_ASSERT(ctx->control);
|
||||
IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
|
||||
return ir_emit3(ctx, IR_OPT(IR_PHI, type), ctx->control, src1, src2);
|
||||
return ir_emit3(ctx, IR_OPTX(IR_PHI, type, 3), ctx->control, src1, src2);
|
||||
}
|
||||
|
||||
ir_ref _ir_PHI_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
|
||||
@ -1506,9 +1492,8 @@ void _ir_PHI_SET_OP(ir_ctx *ctx, ir_ref phi, ir_ref pos, ir_ref src)
|
||||
ir_ref *ops = insn->ops;
|
||||
|
||||
IR_ASSERT(insn->op == IR_PHI);
|
||||
insn = &ctx->ir_base[insn->op1];
|
||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||
IR_ASSERT(pos > 0 && pos <= (insn->inputs_count ? insn->inputs_count : 2));
|
||||
IR_ASSERT(ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN);
|
||||
IR_ASSERT(pos > 0 && pos < insn->inputs_count);
|
||||
pos++; /* op1 is used for control */
|
||||
ops[pos] = src;
|
||||
}
|
||||
@ -1601,7 +1586,7 @@ ir_ref _ir_END(ir_ctx *ctx)
|
||||
void _ir_MERGE_2(ir_ctx *ctx, ir_ref src1, ir_ref src2)
|
||||
{
|
||||
IR_ASSERT(!ctx->control);
|
||||
ctx->control = ir_emit2(ctx, IR_MERGE, src1, src2);
|
||||
ctx->control = ir_emit2(ctx, IR_OPTX(IR_MERGE, IR_VOID, 2), src1, src2);
|
||||
}
|
||||
|
||||
void _ir_MERGE_N(ir_ctx *ctx, ir_ref n, ir_ref *inputs)
|
||||
@ -1628,7 +1613,7 @@ void _ir_MERGE_SET_OP(ir_ctx *ctx, ir_ref merge, ir_ref pos, ir_ref src)
|
||||
ir_ref *ops = insn->ops;
|
||||
|
||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||
IR_ASSERT(pos > 0 && pos <= (insn->inputs_count ? insn->inputs_count : 2));
|
||||
IR_ASSERT(pos > 0 && pos <= insn->inputs_count);
|
||||
ops[pos] = src;
|
||||
}
|
||||
|
||||
@ -1686,7 +1671,7 @@ void _ir_MERGE_LIST(ir_ctx *ctx, ir_ref list)
|
||||
ir_ref _ir_LOOP_BEGIN(ir_ctx *ctx, ir_ref src1)
|
||||
{
|
||||
IR_ASSERT(!ctx->control);
|
||||
ctx->control = ir_emit2(ctx, IR_LOOP_BEGIN, src1, IR_UNUSED);
|
||||
ctx->control = ir_emit2(ctx, IR_OPTX(IR_LOOP_BEGIN, IR_VOID, 2), src1, IR_UNUSED);
|
||||
return ctx->control;
|
||||
}
|
||||
|
||||
@ -1703,20 +1688,13 @@ ir_ref _ir_LOOP_END(ir_ctx *ctx)
|
||||
ir_ref _ir_CALL(ir_ctx *ctx, ir_type type, ir_ref func)
|
||||
{
|
||||
IR_ASSERT(ctx->control);
|
||||
return ctx->control = ir_emit2(ctx, IR_OPT(IR_CALL, type), ctx->control, func);
|
||||
return ctx->control = ir_emit2(ctx, IR_OPTX(IR_CALL, type, 2), ctx->control, func);
|
||||
}
|
||||
|
||||
ir_ref _ir_CALL_1(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1)
|
||||
{
|
||||
ir_ref call;
|
||||
|
||||
IR_ASSERT(ctx->control);
|
||||
call = ir_emit_N(ctx, IR_OPT(IR_CALL, type), 3);
|
||||
ir_set_op(ctx, call, 1, ctx->control);
|
||||
ir_set_op(ctx, call, 2, func);
|
||||
ir_set_op(ctx, call, 3, arg1);
|
||||
ctx->control = call;
|
||||
return call;
|
||||
return ctx->control = ir_emit3(ctx, IR_OPTX(IR_CALL, type, 3), ctx->control, func, arg1);
|
||||
}
|
||||
|
||||
ir_ref _ir_CALL_2(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2)
|
||||
@ -1792,20 +1770,14 @@ void _ir_UNREACHABLE(ir_ctx *ctx)
|
||||
void _ir_TAILCALL(ir_ctx *ctx, ir_ref func)
|
||||
{
|
||||
IR_ASSERT(ctx->control);
|
||||
ctx->control = ir_emit2(ctx, IR_TAILCALL, ctx->control, func);
|
||||
ctx->control = ir_emit2(ctx, IR_OPTX(IR_TAILCALL, IR_VOID, 2), ctx->control, func);
|
||||
_ir_UNREACHABLE(ctx);
|
||||
}
|
||||
|
||||
void _ir_TAILCALL_1(ir_ctx *ctx, ir_ref func, ir_ref arg1)
|
||||
{
|
||||
ir_ref call;
|
||||
|
||||
IR_ASSERT(ctx->control);
|
||||
call = ir_emit_N(ctx, IR_TAILCALL, 3);
|
||||
ir_set_op(ctx, call, 1, ctx->control);
|
||||
ir_set_op(ctx, call, 2, func);
|
||||
ir_set_op(ctx, call, 3, arg1);
|
||||
ctx->control = call;
|
||||
ctx->control = ir_emit3(ctx, IR_OPTX(IR_TAILCALL, IR_VOID, 3), ctx->control, func, arg1);
|
||||
_ir_UNREACHABLE(ctx);
|
||||
}
|
||||
|
||||
|
13
ir.g
13
ir.g
@ -221,12 +221,16 @@ ir_insn(ir_parser_ctx *p):
|
||||
")"
|
||||
)?
|
||||
|
|
||||
{n = 0;}
|
||||
( "("
|
||||
( val(p, op, 1, &op1)
|
||||
{n = 1;}
|
||||
( ","
|
||||
val(p, op, 2, &op2)
|
||||
{n = 2;}
|
||||
( ","
|
||||
val(p, op, 3, &op3)
|
||||
{n = 3;}
|
||||
)?
|
||||
)?
|
||||
)?
|
||||
@ -239,7 +243,14 @@ ir_insn(ir_parser_ctx *p):
|
||||
&& !IR_IS_UNRESOLVED(op3)) {
|
||||
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||
} else {
|
||||
ref = ir_emit(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||
uint32_t opt;
|
||||
|
||||
if (!IR_OP_HAS_VAR_INPUTS(ir_op_flags[op])) {
|
||||
opt = IR_OPT(op, t);
|
||||
} else {
|
||||
opt = IR_OPTX(op, t, n);
|
||||
}
|
||||
ref = ir_emit(p->ctx, opt, op1, op2, op3);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
9
ir.h
9
ir.h
@ -155,8 +155,7 @@ typedef enum _ir_type {
|
||||
* x - call IR_OP_FLAG_MEM + IR_OP_FLAG_CALL
|
||||
* a - alloc IR_OP_FLAG_MEM + IR_OP_FLAG_ALLOC
|
||||
* 0-3 - number of input edges
|
||||
* N - number of arguments is defined in the insn->inputs_count (MERGE)
|
||||
* P - number of arguments is defined in the op1->inputs_count (PHI)
|
||||
* N - number of arguments is defined in the insn->inputs_count (MERGE, PHI, CALL)
|
||||
* X1-X3 - number of extra data ops
|
||||
* C - commutative operation ("d2C" => IR_OP_FLAG_DATA + IR_OP_FLAG_COMMUTATIVE)
|
||||
*
|
||||
@ -259,7 +258,7 @@ typedef enum _ir_type {
|
||||
_(COND, d3, def, def, def) /* op1 ? op2 : op3 */ \
|
||||
\
|
||||
/* data-flow and miscellaneous ops */ \
|
||||
_(PHI, dP, reg, def, def) /* SSA Phi function */ \
|
||||
_(PHI, dN, reg, def, def) /* SSA Phi function */ \
|
||||
_(COPY, d1X1, def, opt, ___) /* COPY (last foldable op) */ \
|
||||
_(PI, d2, reg, def, ___) /* e-SSA Pi constraint ??? */ \
|
||||
/* (USE, RENAME) */ \
|
||||
@ -332,8 +331,10 @@ typedef enum _ir_op {
|
||||
#define IR_OPT_OP_MASK 0x00ff
|
||||
#define IR_OPT_TYPE_MASK 0xff00
|
||||
#define IR_OPT_TYPE_SHIFT 8
|
||||
#define IR_OPT_INPUTS_SHIFT 16
|
||||
|
||||
#define IR_OPT(op, type) ((uint16_t)(op) | ((uint16_t)(type) << IR_OPT_TYPE_SHIFT))
|
||||
#define IR_OPTX(op, type, n) ((uint32_t)(op) | ((uint32_t)(type) << IR_OPT_TYPE_SHIFT) | ((uint32_t)(n) << IR_OPT_INPUTS_SHIFT))
|
||||
#define IR_OPT_TYPE(opt) (((opt) & IR_OPT_TYPE_MASK) >> IR_OPT_TYPE_SHIFT)
|
||||
|
||||
/* IR References */
|
||||
@ -409,7 +410,7 @@ typedef struct _ir_insn {
|
||||
uint16_t opt;
|
||||
},
|
||||
union {
|
||||
uint16_t inputs_count; /* number of input control edges for MERGE, CALL, TAILCALL */
|
||||
uint16_t inputs_count; /* number of input control edges for MERGE, PHI, CALL, TAILCALL */
|
||||
uint16_t prev_insn_offset; /* 16-bit backward offset from current instruction for CSE */
|
||||
uint16_t const_flags; /* flag to emit constant in rodat section */
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ static bool ir_call_needs_tmp_int_reg(const ir_ctx *ctx, const ir_insn *insn)
|
||||
int int_param = 0;
|
||||
int int_reg_params_count = IR_REG_INT_ARGS;
|
||||
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
for (j = 3; j <= n; j++) {
|
||||
arg = ir_insn_op(insn, j);
|
||||
arg_insn = &ctx->ir_base[arg];
|
||||
|
20
ir_cfg.c
20
ir_cfg.c
@ -82,7 +82,7 @@ IR_ALWAYS_INLINE void _ir_add_predecessors(const ir_insn *insn, ir_worklist *wor
|
||||
const ir_ref *p;
|
||||
|
||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
for (p = insn->ops + 1; n > 0; p++, n--) {
|
||||
ref = *p;
|
||||
IR_ASSERT(ref);
|
||||
@ -256,7 +256,7 @@ next_successor:
|
||||
} else {
|
||||
bb->flags = IR_BB_UNREACHABLE; /* all blocks are marked as UNREACHABLE first */
|
||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
bb->predecessors_count = n;
|
||||
edges_count += n;
|
||||
count += n;
|
||||
@ -286,7 +286,7 @@ next_successor:
|
||||
insn = &ctx->ir_base[bb->start];
|
||||
if (bb->predecessors_count > 1) {
|
||||
uint32_t *q = edges + bb->predecessors;
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
for (p = insn->ops + 1; n > 0; p++, q++, n--) {
|
||||
ref = *p;
|
||||
IR_ASSERT(ref);
|
||||
@ -382,9 +382,6 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
|
||||
|
||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||
n = insn->inputs_count;
|
||||
if (n == 0) {
|
||||
n = 3;
|
||||
}
|
||||
i = 1;
|
||||
life_inputs = ir_bitset_malloc(n + 1);
|
||||
for (j = 1; j <= n; j++) {
|
||||
@ -425,9 +422,6 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (i == 2) {
|
||||
i = 0;
|
||||
}
|
||||
insn->inputs_count = i;
|
||||
|
||||
n++;
|
||||
@ -531,9 +525,11 @@ int ir_remove_unreachable_blocks(ir_ctx *ctx)
|
||||
ir_insn *insn = &ctx->ir_base[bb->start];
|
||||
ir_ref *p, ref;
|
||||
|
||||
if (bb->predecessors_count > 1) {
|
||||
n = bb->predecessors_count;
|
||||
if (n > 1) {
|
||||
uint32_t *q = edges + bb->predecessors;
|
||||
n = ir_variable_inputs_count(insn);
|
||||
|
||||
IR_ASSERT(n == insn->inputs_count);
|
||||
for (p = insn->ops + 1; n > 0; p++, q++, n--) {
|
||||
ref = *p;
|
||||
IR_ASSERT(ref);
|
||||
@ -542,7 +538,7 @@ int ir_remove_unreachable_blocks(ir_ctx *ctx)
|
||||
*q = pred_b;
|
||||
edges[pred_bb->successors + pred_bb->successors_count++] = b;
|
||||
}
|
||||
} else if (bb->predecessors_count == 1) {
|
||||
} else if (n == 1) {
|
||||
ref = insn->op1;
|
||||
IR_ASSERT(ref);
|
||||
IR_ASSERT(IR_OPND_KIND(ir_op_flags[insn->op], 1) == IR_OPND_CONTROL);
|
||||
|
@ -235,6 +235,13 @@ bool ir_check(const ir_ctx *ctx)
|
||||
}
|
||||
|
||||
switch (insn->op) {
|
||||
case IR_PHI:
|
||||
if (insn->inputs_count != ctx->ir_base[insn->op1].inputs_count + 1) {
|
||||
fprintf(stderr, "ir_base[%d] inconsistent PHI inputs_count (%d != %d)\n",
|
||||
i, insn->inputs_count, ctx->ir_base[insn->op1].inputs_count + 1);
|
||||
ok = 0;
|
||||
}
|
||||
break;
|
||||
case IR_LOAD:
|
||||
case IR_STORE:
|
||||
type = ctx->ir_base[insn->op2].type;
|
||||
|
@ -183,7 +183,7 @@ static int ir_get_args_regs(const ir_ctx *ctx, const ir_insn *insn, int8_t *regs
|
||||
}
|
||||
#endif
|
||||
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
n = IR_MIN(n, IR_MAX_REG_ARGS + 2);
|
||||
for (j = 3; j <= n; j++) {
|
||||
type = ctx->ir_base[ir_insn_op(insn, j)].type;
|
||||
|
@ -1165,6 +1165,7 @@ IR_FOLD(PHI(_, _)) // TODO: PHI(_, _, _)
|
||||
IR_FOLD_COPY(op2);
|
||||
}
|
||||
/* skip CSE */
|
||||
opt = opt | (3 << IR_OPT_INPUTS_SHIFT);
|
||||
IR_FOLD_EMIT;
|
||||
}
|
||||
|
||||
|
22
ir_gcm.c
22
ir_gcm.c
@ -215,17 +215,10 @@ int ir_gcm(ir_ctx *ctx)
|
||||
insn = &ctx->ir_base[ref];
|
||||
_blocks[ref] = 1; /* pin to block */
|
||||
flags = ir_op_flags[insn->op];
|
||||
#if 1
|
||||
n = IR_INPUT_EDGES_COUNT(flags);
|
||||
if (!IR_IS_FIXED_INPUTS_COUNT(n) || n > 1) {
|
||||
if (IR_OP_HAS_VAR_INPUTS(flags) || IR_INPUT_EDGES_COUNT(flags) > 1) {
|
||||
/* insn has input data edges */
|
||||
ir_list_push_unchecked(&queue_early, ref);
|
||||
}
|
||||
#else
|
||||
if (IR_OPND_KIND(flags, 2) == IR_OPND_DATA
|
||||
|| IR_OPND_KIND(flags, 3) == IR_OPND_DATA) {
|
||||
ir_list_push_unchecked(&queue_early, ref);
|
||||
}
|
||||
#endif
|
||||
ref = insn->op1; /* control predecessor */
|
||||
} while (ref != 1); /* IR_START */
|
||||
_blocks[1] = 1; /* pin to block */
|
||||
@ -272,17 +265,10 @@ int ir_gcm(ir_ctx *ctx)
|
||||
ir_bitset_incl(visited, ref);
|
||||
_blocks[ref] = b; /* pin to block */
|
||||
flags = ir_op_flags[insn->op];
|
||||
#if 1
|
||||
n = IR_INPUT_EDGES_COUNT(flags);
|
||||
if (!IR_IS_FIXED_INPUTS_COUNT(n) || n > 1) {
|
||||
if (IR_OP_HAS_VAR_INPUTS(flags) || IR_INPUT_EDGES_COUNT(flags) > 1) {
|
||||
/* insn has input data edges */
|
||||
ir_list_push_unchecked(&queue_early, ref);
|
||||
}
|
||||
#else
|
||||
if (IR_OPND_KIND(flags, 2) == IR_OPND_DATA
|
||||
|| IR_OPND_KIND(flags, 3) == IR_OPND_DATA) {
|
||||
ir_list_push_unchecked(&queue_early, ref);
|
||||
}
|
||||
#endif
|
||||
if (insn->type != IR_VOID) {
|
||||
IR_ASSERT(flags & IR_OP_FLAG_MEM);
|
||||
ir_list_push_unchecked(&queue_late, ref);
|
||||
|
13
ir_load.c
13
ir_load.c
@ -829,16 +829,20 @@ _yy_state_0:
|
||||
sym = get_sym();
|
||||
}
|
||||
} else if (sym == YY__LPAREN || sym == YY__SEMICOLON) {
|
||||
n = 0;
|
||||
if (sym == YY__LPAREN) {
|
||||
sym = get_sym();
|
||||
if (sym == YY_ID || sym == YY_STRING || sym == YY_DECNUMBER || sym == YY_NULL) {
|
||||
sym = parse_val(sym, p, op, 1, &op1);
|
||||
n = 1;
|
||||
if (sym == YY__COMMA) {
|
||||
sym = get_sym();
|
||||
sym = parse_val(sym, p, op, 2, &op2);
|
||||
n = 2;
|
||||
if (sym == YY__COMMA) {
|
||||
sym = get_sym();
|
||||
sym = parse_val(sym, p, op, 3, &op3);
|
||||
n = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -853,7 +857,14 @@ _yy_state_0:
|
||||
&& !IR_IS_UNRESOLVED(op3)) {
|
||||
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||
} else {
|
||||
ref = ir_emit(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||
uint32_t opt;
|
||||
|
||||
if (!IR_OP_HAS_VAR_INPUTS(ir_op_flags[op])) {
|
||||
opt = IR_OPT(op, t);
|
||||
} else {
|
||||
opt = IR_OPTX(op, t, n);
|
||||
}
|
||||
ref = ir_emit(p->ctx, opt, op1, op2, op3);
|
||||
}
|
||||
} else {
|
||||
yy_error_sym("unexpected", sym);
|
||||
|
48
ir_private.h
48
ir_private.h
@ -776,8 +776,9 @@ IR_ALWAYS_INLINE bool ir_const_is_true(const ir_insn *v)
|
||||
/* IR OP flags */
|
||||
#define IR_OP_FLAG_OPERANDS_SHIFT 3
|
||||
|
||||
#define IR_OP_FLAG_EDGES_MSK 0x07
|
||||
#define IR_OP_FLAG_OPERANDS_MSK 0x38
|
||||
#define IR_OP_FLAG_EDGES_MASK 0x03
|
||||
#define IR_OP_FLAG_VAR_INPUTS 0x04
|
||||
#define IR_OP_FLAG_OPERANDS_MASK 0x18
|
||||
#define IR_OP_FLAG_MEM_MASK ((1<<6)|(1<<7))
|
||||
|
||||
#define IR_OP_FLAG_DATA (1<<8)
|
||||
@ -807,13 +808,10 @@ IR_ALWAYS_INLINE bool ir_const_is_true(const ir_insn *v)
|
||||
#define IR_OP_FLAGS(op_flags, op1_flags, op2_flags, op3_flags) \
|
||||
((op_flags) | ((op1_flags) << 20) | ((op2_flags) << 24) | ((op3_flags) << 28))
|
||||
|
||||
#define IR_INPUT_EDGES_COUNT(flags) (flags & IR_OP_FLAG_EDGES_MSK)
|
||||
#define IR_OPERANDS_COUNT(flags) ((flags & IR_OP_FLAG_OPERANDS_MSK) >> IR_OP_FLAG_OPERANDS_SHIFT)
|
||||
#define IR_INPUT_EDGES_COUNT(flags) (flags & IR_OP_FLAG_EDGES_MASK)
|
||||
#define IR_OPERANDS_COUNT(flags) ((flags & IR_OP_FLAG_OPERANDS_MASK) >> IR_OP_FLAG_OPERANDS_SHIFT)
|
||||
|
||||
#define IR_VARIABLE_INPUTS_COUNT 4
|
||||
#define IR_PHI_INPUTS_COUNT 5
|
||||
|
||||
#define IR_IS_FIXED_INPUTS_COUNT(n) ((n) < IR_VARIABLE_INPUTS_COUNT)
|
||||
#define IR_OP_HAS_VAR_INPUTS(flags) ((flags) & IR_OP_FLAG_VAR_INPUTS)
|
||||
|
||||
#define IR_OPND_KIND(flags, i) \
|
||||
(((flags) >> (16 + (4 * (((i) > 3) ? 3 : (i))))) & 0xf)
|
||||
@ -821,28 +819,14 @@ IR_ALWAYS_INLINE bool ir_const_is_true(const ir_insn *v)
|
||||
#define IR_IS_REF_OPND_KIND(kind) \
|
||||
((kind) >= IR_OPND_DATA && (kind) <= IR_OPND_VAR)
|
||||
|
||||
IR_ALWAYS_INLINE ir_ref ir_variable_inputs_count(const ir_insn *insn)
|
||||
{
|
||||
uint32_t n = insn->inputs_count;
|
||||
if (n == 0) {
|
||||
n = 2;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
IR_ALWAYS_INLINE ir_ref ir_operands_count(const ir_ctx *ctx, const ir_insn *insn)
|
||||
{
|
||||
uint32_t flags = ir_op_flags[insn->op];
|
||||
uint32_t n = IR_OPERANDS_COUNT(flags);
|
||||
if (EXPECTED(IR_IS_FIXED_INPUTS_COUNT(n))) {
|
||||
/* pass */
|
||||
} else if (n == IR_VARIABLE_INPUTS_COUNT) {
|
||||
/* MERGE or CALL */
|
||||
n = ir_variable_inputs_count(insn);
|
||||
} else {
|
||||
IR_ASSERT(n == IR_PHI_INPUTS_COUNT);
|
||||
/* PHI */
|
||||
n = ir_variable_inputs_count(&ctx->ir_base[insn->op1]) + 1;
|
||||
|
||||
if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) {
|
||||
/* MERGE, PHI, CALL, etc */
|
||||
n = insn->inputs_count;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@ -851,15 +835,9 @@ IR_ALWAYS_INLINE ir_ref ir_input_edges_count(const ir_ctx *ctx, const ir_insn *i
|
||||
{
|
||||
uint32_t flags = ir_op_flags[insn->op];
|
||||
uint32_t n = IR_INPUT_EDGES_COUNT(flags);
|
||||
if (EXPECTED(IR_IS_FIXED_INPUTS_COUNT(n))) {
|
||||
/* pass */
|
||||
} else if (n == IR_VARIABLE_INPUTS_COUNT) {
|
||||
/* MERGE or CALL */
|
||||
n = ir_variable_inputs_count(insn);
|
||||
} else {
|
||||
IR_ASSERT(n == IR_PHI_INPUTS_COUNT);
|
||||
/* PHI */
|
||||
n = ir_variable_inputs_count(&ctx->ir_base[insn->op1]) + 1;
|
||||
if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) {
|
||||
/* MERGE, PHI, CALL, etc */
|
||||
n = insn->inputs_count;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
14
ir_ra.c
14
ir_ra.c
@ -502,8 +502,8 @@ static void ir_add_fusion_ranges(ir_ctx *ctx, ir_ref ref, ir_ref input, ir_block
|
||||
|
||||
insn = &ctx->ir_base[input];
|
||||
flags = ir_op_flags[insn->op];
|
||||
IR_ASSERT(!IR_OP_HAS_VAR_INPUTS(flags));
|
||||
n = IR_INPUT_EDGES_COUNT(flags);
|
||||
IR_ASSERT(IR_IS_FIXED_INPUTS_COUNT(n));
|
||||
j = 1;
|
||||
p = insn->ops + j;
|
||||
if (flags & IR_OP_FLAG_CONTROL) {
|
||||
@ -1244,13 +1244,15 @@ int ir_coalesce(ir_ctx *ctx)
|
||||
ir_worklist_init(&blocks, ctx->cfg_blocks_count + 1);
|
||||
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||
if (bb->predecessors_count > 1) {
|
||||
k = bb->predecessors_count;
|
||||
if (k > 1) {
|
||||
uint32_t i;
|
||||
|
||||
use_list = &ctx->use_lists[bb->start];
|
||||
n = use_list->count;
|
||||
if (n > 1) {
|
||||
k = ir_variable_inputs_count(&ctx->ir_base[bb->start]) + 1;
|
||||
IR_ASSERT(k == ctx->ir_base[bb->start].inputs_count);
|
||||
k++;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
use = *p;
|
||||
insn = &ctx->ir_base[use];
|
||||
@ -1379,11 +1381,13 @@ int ir_compute_dessa_moves(ir_ctx *ctx)
|
||||
|
||||
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||
if (bb->predecessors_count > 1) {
|
||||
k = bb->predecessors_count;
|
||||
if (k > 1) {
|
||||
use_list = &ctx->use_lists[bb->start];
|
||||
n = use_list->count;
|
||||
if (n > 1) {
|
||||
k = ir_variable_inputs_count(&ctx->ir_base[bb->start]) + 1;
|
||||
IR_ASSERT(k == ctx->ir_base[bb->start].inputs_count);
|
||||
k++;
|
||||
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||
use = *p;
|
||||
insn = &ctx->ir_base[use];
|
||||
|
19
ir_sccp.c
19
ir_sccp.c
@ -437,9 +437,6 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
|
||||
insn = &ctx->ir_base[ref];
|
||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||
n = insn->inputs_count;
|
||||
if (n == 0) {
|
||||
n = 2;
|
||||
}
|
||||
if (n - unfeasible_inputs == 1) {
|
||||
/* remove MERGE completely */
|
||||
for (j = 1; j <= n; j++) {
|
||||
@ -483,9 +480,6 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
|
||||
}
|
||||
} else {
|
||||
n = insn->inputs_count;
|
||||
if (n == 0) {
|
||||
n = 3;
|
||||
}
|
||||
i = 1;
|
||||
life_inputs = ir_bitset_malloc(n + 1);
|
||||
for (j = 1; j <= n; j++) {
|
||||
@ -505,9 +499,6 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
|
||||
j++;
|
||||
}
|
||||
i--;
|
||||
if (i == 2) {
|
||||
i = 0;
|
||||
}
|
||||
insn->inputs_count = i;
|
||||
|
||||
n++;
|
||||
@ -534,6 +525,7 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
|
||||
ir_insn_set_op(use_insn, i, IR_UNUSED);
|
||||
i++;
|
||||
}
|
||||
use_insn->inputs_count = insn->inputs_count + 1;
|
||||
}
|
||||
}
|
||||
ir_mem_free(life_inputs);
|
||||
@ -566,7 +558,7 @@ int ir_sccp(ir_ctx *ctx)
|
||||
if (!IR_IS_FEASIBLE(insn->op1)) {
|
||||
continue;
|
||||
}
|
||||
n = ir_variable_inputs_count(merge_insn) + 1;
|
||||
n = merge_insn->inputs_count + 1;
|
||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||
for (j = 0; j < (n>>2); j++) {
|
||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
||||
@ -597,8 +589,8 @@ int ir_sccp(ir_ctx *ctx)
|
||||
bool may_benefit = 0;
|
||||
bool has_top = 0;
|
||||
|
||||
IR_ASSERT(!IR_OP_HAS_VAR_INPUTS(flags));
|
||||
n = IR_INPUT_EDGES_COUNT(flags);
|
||||
IR_ASSERT(IR_IS_FIXED_INPUTS_COUNT(n));
|
||||
for (p = insn->ops + 1; n > 0; p++, n--) {
|
||||
ir_ref input = *p;
|
||||
if (input > 0) {
|
||||
@ -631,7 +623,7 @@ int ir_sccp(ir_ctx *ctx)
|
||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||
ir_ref unfeasible_inputs = 0;
|
||||
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||
for (j = 0; j < (n>>2); j++) {
|
||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
||||
@ -740,8 +732,7 @@ int ir_sccp(ir_ctx *ctx)
|
||||
|
||||
/* control, call, load and strore instructions may have unprocessed inputs */
|
||||
n = IR_INPUT_EDGES_COUNT(flags);
|
||||
if (!IR_IS_FIXED_INPUTS_COUNT(n)
|
||||
&& (n = ir_variable_inputs_count(insn)) > 3) {
|
||||
if (IR_OP_HAS_VAR_INPUTS(flags) && (n = insn->inputs_count) > 3) {
|
||||
for (j = 0; j < (n>>2); j++) {
|
||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
||||
}
|
||||
|
@ -530,7 +530,7 @@ static bool ir_call_needs_tmp_int_reg(const ir_ctx *ctx, const ir_insn *insn)
|
||||
}
|
||||
#endif
|
||||
|
||||
n = ir_variable_inputs_count(insn);
|
||||
n = insn->inputs_count;
|
||||
for (j = 3; j <= n; j++) {
|
||||
arg = ir_insn_op(insn, j);
|
||||
arg_insn = &ctx->ir_base[arg];
|
||||
|
Loading…
x
Reference in New Issue
Block a user