mirror of
https://github.com/danog/ir.git
synced 2025-01-21 21:21:19 +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_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_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_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_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_r0 ir_op_flag_r
|
||||||
#define ir_op_flag_r0X1 (ir_op_flag_r | 0 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
|
#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_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_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_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_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_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))
|
#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_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_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_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_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
|
#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)
|
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 (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_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);
|
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;
|
ctx->insns_count = ref + 1 + count/4;
|
||||||
|
|
||||||
insn = &ctx->ir_base[ref];
|
insn = &ctx->ir_base[ref];
|
||||||
insn->optx = opt;
|
insn->optx = opt | (count << IR_OPT_INPUTS_SHIFT);
|
||||||
if ((opt & IR_OPT_OP_MASK) != IR_PHI) {
|
|
||||||
insn->inputs_count = count;
|
|
||||||
}
|
|
||||||
for (i = 1, p = insn->ops + i; i <= (count|3); i++, p++) {
|
for (i = 1, p = insn->ops + i; i <= (count|3); i++, p++) {
|
||||||
*p = IR_UNUSED;
|
*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];
|
ir_insn *insn = &ctx->ir_base[ref];
|
||||||
|
|
||||||
|
#ifdef IR_DEBUG
|
||||||
if (n > 3) {
|
if (n > 3) {
|
||||||
int32_t count = 3;
|
int32_t count;
|
||||||
|
|
||||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
IR_ASSERT(IR_OP_HAS_VAR_INPUTS(ir_op_flags[insn->op]));
|
||||||
count = insn->inputs_count;
|
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(n <= count);
|
IR_ASSERT(n <= count);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ir_insn_set_op(insn, n, val);
|
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->control);
|
||||||
IR_ASSERT(ctx->ir_base[ctx->control].op == IR_MERGE || ctx->ir_base[ctx->control].op == IR_LOOP_BEGIN);
|
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)
|
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_ref *ops = insn->ops;
|
||||||
|
|
||||||
IR_ASSERT(insn->op == IR_PHI);
|
IR_ASSERT(insn->op == IR_PHI);
|
||||||
insn = &ctx->ir_base[insn->op1];
|
IR_ASSERT(ctx->ir_base[insn->op1].op == IR_MERGE || ctx->ir_base[insn->op1].op == IR_LOOP_BEGIN);
|
||||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
IR_ASSERT(pos > 0 && pos < insn->inputs_count);
|
||||||
IR_ASSERT(pos > 0 && pos <= (insn->inputs_count ? insn->inputs_count : 2));
|
|
||||||
pos++; /* op1 is used for control */
|
pos++; /* op1 is used for control */
|
||||||
ops[pos] = src;
|
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)
|
void _ir_MERGE_2(ir_ctx *ctx, ir_ref src1, ir_ref src2)
|
||||||
{
|
{
|
||||||
IR_ASSERT(!ctx->control);
|
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)
|
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_ref *ops = insn->ops;
|
||||||
|
|
||||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
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;
|
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_ref _ir_LOOP_BEGIN(ir_ctx *ctx, ir_ref src1)
|
||||||
{
|
{
|
||||||
IR_ASSERT(!ctx->control);
|
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;
|
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_ref _ir_CALL(ir_ctx *ctx, ir_type type, ir_ref func)
|
||||||
{
|
{
|
||||||
IR_ASSERT(ctx->control);
|
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 _ir_CALL_1(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1)
|
||||||
{
|
{
|
||||||
ir_ref call;
|
|
||||||
|
|
||||||
IR_ASSERT(ctx->control);
|
IR_ASSERT(ctx->control);
|
||||||
call = ir_emit_N(ctx, IR_OPT(IR_CALL, type), 3);
|
return ctx->control = ir_emit3(ctx, IR_OPTX(IR_CALL, type, 3), ctx->control, func, arg1);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_ref _ir_CALL_2(ir_ctx *ctx, ir_type type, ir_ref func, ir_ref arg1, ir_ref arg2)
|
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)
|
void _ir_TAILCALL(ir_ctx *ctx, ir_ref func)
|
||||||
{
|
{
|
||||||
IR_ASSERT(ctx->control);
|
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);
|
_ir_UNREACHABLE(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _ir_TAILCALL_1(ir_ctx *ctx, ir_ref func, ir_ref arg1)
|
void _ir_TAILCALL_1(ir_ctx *ctx, ir_ref func, ir_ref arg1)
|
||||||
{
|
{
|
||||||
ir_ref call;
|
|
||||||
|
|
||||||
IR_ASSERT(ctx->control);
|
IR_ASSERT(ctx->control);
|
||||||
call = ir_emit_N(ctx, IR_TAILCALL, 3);
|
ctx->control = ir_emit3(ctx, IR_OPTX(IR_TAILCALL, IR_VOID, 3), ctx->control, func, arg1);
|
||||||
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;
|
|
||||||
_ir_UNREACHABLE(ctx);
|
_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)
|
( val(p, op, 1, &op1)
|
||||||
|
{n = 1;}
|
||||||
( ","
|
( ","
|
||||||
val(p, op, 2, &op2)
|
val(p, op, 2, &op2)
|
||||||
|
{n = 2;}
|
||||||
( ","
|
( ","
|
||||||
val(p, op, 3, &op3)
|
val(p, op, 3, &op3)
|
||||||
|
{n = 3;}
|
||||||
)?
|
)?
|
||||||
)?
|
)?
|
||||||
)?
|
)?
|
||||||
@ -239,7 +243,14 @@ ir_insn(ir_parser_ctx *p):
|
|||||||
&& !IR_IS_UNRESOLVED(op3)) {
|
&& !IR_IS_UNRESOLVED(op3)) {
|
||||||
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||||
} else {
|
} 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
|
* x - call IR_OP_FLAG_MEM + IR_OP_FLAG_CALL
|
||||||
* a - alloc IR_OP_FLAG_MEM + IR_OP_FLAG_ALLOC
|
* a - alloc IR_OP_FLAG_MEM + IR_OP_FLAG_ALLOC
|
||||||
* 0-3 - number of input edges
|
* 0-3 - number of input edges
|
||||||
* N - number of arguments is defined in the insn->inputs_count (MERGE)
|
* N - number of arguments is defined in the insn->inputs_count (MERGE, PHI, CALL)
|
||||||
* P - number of arguments is defined in the op1->inputs_count (PHI)
|
|
||||||
* X1-X3 - number of extra data ops
|
* X1-X3 - number of extra data ops
|
||||||
* C - commutative operation ("d2C" => IR_OP_FLAG_DATA + IR_OP_FLAG_COMMUTATIVE)
|
* 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 */ \
|
_(COND, d3, def, def, def) /* op1 ? op2 : op3 */ \
|
||||||
\
|
\
|
||||||
/* data-flow and miscellaneous ops */ \
|
/* 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) */ \
|
_(COPY, d1X1, def, opt, ___) /* COPY (last foldable op) */ \
|
||||||
_(PI, d2, reg, def, ___) /* e-SSA Pi constraint ??? */ \
|
_(PI, d2, reg, def, ___) /* e-SSA Pi constraint ??? */ \
|
||||||
/* (USE, RENAME) */ \
|
/* (USE, RENAME) */ \
|
||||||
@ -332,8 +331,10 @@ typedef enum _ir_op {
|
|||||||
#define IR_OPT_OP_MASK 0x00ff
|
#define IR_OPT_OP_MASK 0x00ff
|
||||||
#define IR_OPT_TYPE_MASK 0xff00
|
#define IR_OPT_TYPE_MASK 0xff00
|
||||||
#define IR_OPT_TYPE_SHIFT 8
|
#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_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)
|
#define IR_OPT_TYPE(opt) (((opt) & IR_OPT_TYPE_MASK) >> IR_OPT_TYPE_SHIFT)
|
||||||
|
|
||||||
/* IR References */
|
/* IR References */
|
||||||
@ -409,7 +410,7 @@ typedef struct _ir_insn {
|
|||||||
uint16_t opt;
|
uint16_t opt;
|
||||||
},
|
},
|
||||||
union {
|
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 prev_insn_offset; /* 16-bit backward offset from current instruction for CSE */
|
||||||
uint16_t const_flags; /* flag to emit constant in rodat section */
|
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_param = 0;
|
||||||
int int_reg_params_count = IR_REG_INT_ARGS;
|
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++) {
|
for (j = 3; j <= n; j++) {
|
||||||
arg = ir_insn_op(insn, j);
|
arg = ir_insn_op(insn, j);
|
||||||
arg_insn = &ctx->ir_base[arg];
|
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;
|
const ir_ref *p;
|
||||||
|
|
||||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
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--) {
|
for (p = insn->ops + 1; n > 0; p++, n--) {
|
||||||
ref = *p;
|
ref = *p;
|
||||||
IR_ASSERT(ref);
|
IR_ASSERT(ref);
|
||||||
@ -256,7 +256,7 @@ next_successor:
|
|||||||
} else {
|
} else {
|
||||||
bb->flags = IR_BB_UNREACHABLE; /* all blocks are marked as UNREACHABLE first */
|
bb->flags = IR_BB_UNREACHABLE; /* all blocks are marked as UNREACHABLE first */
|
||||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||||
n = ir_variable_inputs_count(insn);
|
n = insn->inputs_count;
|
||||||
bb->predecessors_count = n;
|
bb->predecessors_count = n;
|
||||||
edges_count += n;
|
edges_count += n;
|
||||||
count += n;
|
count += n;
|
||||||
@ -286,7 +286,7 @@ next_successor:
|
|||||||
insn = &ctx->ir_base[bb->start];
|
insn = &ctx->ir_base[bb->start];
|
||||||
if (bb->predecessors_count > 1) {
|
if (bb->predecessors_count > 1) {
|
||||||
uint32_t *q = edges + bb->predecessors;
|
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--) {
|
for (p = insn->ops + 1; n > 0; p++, q++, n--) {
|
||||||
ref = *p;
|
ref = *p;
|
||||||
IR_ASSERT(ref);
|
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);
|
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||||
n = insn->inputs_count;
|
n = insn->inputs_count;
|
||||||
if (n == 0) {
|
|
||||||
n = 3;
|
|
||||||
}
|
|
||||||
i = 1;
|
i = 1;
|
||||||
life_inputs = ir_bitset_malloc(n + 1);
|
life_inputs = ir_bitset_malloc(n + 1);
|
||||||
for (j = 1; j <= n; j++) {
|
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 {
|
} else {
|
||||||
if (i == 2) {
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
insn->inputs_count = i;
|
insn->inputs_count = i;
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
@ -531,9 +525,11 @@ int ir_remove_unreachable_blocks(ir_ctx *ctx)
|
|||||||
ir_insn *insn = &ctx->ir_base[bb->start];
|
ir_insn *insn = &ctx->ir_base[bb->start];
|
||||||
ir_ref *p, ref;
|
ir_ref *p, ref;
|
||||||
|
|
||||||
if (bb->predecessors_count > 1) {
|
n = bb->predecessors_count;
|
||||||
|
if (n > 1) {
|
||||||
uint32_t *q = edges + bb->predecessors;
|
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--) {
|
for (p = insn->ops + 1; n > 0; p++, q++, n--) {
|
||||||
ref = *p;
|
ref = *p;
|
||||||
IR_ASSERT(ref);
|
IR_ASSERT(ref);
|
||||||
@ -542,7 +538,7 @@ int ir_remove_unreachable_blocks(ir_ctx *ctx)
|
|||||||
*q = pred_b;
|
*q = pred_b;
|
||||||
edges[pred_bb->successors + pred_bb->successors_count++] = b;
|
edges[pred_bb->successors + pred_bb->successors_count++] = b;
|
||||||
}
|
}
|
||||||
} else if (bb->predecessors_count == 1) {
|
} else if (n == 1) {
|
||||||
ref = insn->op1;
|
ref = insn->op1;
|
||||||
IR_ASSERT(ref);
|
IR_ASSERT(ref);
|
||||||
IR_ASSERT(IR_OPND_KIND(ir_op_flags[insn->op], 1) == IR_OPND_CONTROL);
|
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) {
|
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_LOAD:
|
||||||
case IR_STORE:
|
case IR_STORE:
|
||||||
type = ctx->ir_base[insn->op2].type;
|
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
|
#endif
|
||||||
|
|
||||||
n = ir_variable_inputs_count(insn);
|
n = insn->inputs_count;
|
||||||
n = IR_MIN(n, IR_MAX_REG_ARGS + 2);
|
n = IR_MIN(n, IR_MAX_REG_ARGS + 2);
|
||||||
for (j = 3; j <= n; j++) {
|
for (j = 3; j <= n; j++) {
|
||||||
type = ctx->ir_base[ir_insn_op(insn, j)].type;
|
type = ctx->ir_base[ir_insn_op(insn, j)].type;
|
||||||
|
@ -1165,6 +1165,7 @@ IR_FOLD(PHI(_, _)) // TODO: PHI(_, _, _)
|
|||||||
IR_FOLD_COPY(op2);
|
IR_FOLD_COPY(op2);
|
||||||
}
|
}
|
||||||
/* skip CSE */
|
/* skip CSE */
|
||||||
|
opt = opt | (3 << IR_OPT_INPUTS_SHIFT);
|
||||||
IR_FOLD_EMIT;
|
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];
|
insn = &ctx->ir_base[ref];
|
||||||
_blocks[ref] = 1; /* pin to block */
|
_blocks[ref] = 1; /* pin to block */
|
||||||
flags = ir_op_flags[insn->op];
|
flags = ir_op_flags[insn->op];
|
||||||
#if 1
|
if (IR_OP_HAS_VAR_INPUTS(flags) || IR_INPUT_EDGES_COUNT(flags) > 1) {
|
||||||
n = IR_INPUT_EDGES_COUNT(flags);
|
/* insn has input data edges */
|
||||||
if (!IR_IS_FIXED_INPUTS_COUNT(n) || n > 1) {
|
|
||||||
ir_list_push_unchecked(&queue_early, ref);
|
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 */
|
ref = insn->op1; /* control predecessor */
|
||||||
} while (ref != 1); /* IR_START */
|
} while (ref != 1); /* IR_START */
|
||||||
_blocks[1] = 1; /* pin to block */
|
_blocks[1] = 1; /* pin to block */
|
||||||
@ -272,17 +265,10 @@ int ir_gcm(ir_ctx *ctx)
|
|||||||
ir_bitset_incl(visited, ref);
|
ir_bitset_incl(visited, ref);
|
||||||
_blocks[ref] = b; /* pin to block */
|
_blocks[ref] = b; /* pin to block */
|
||||||
flags = ir_op_flags[insn->op];
|
flags = ir_op_flags[insn->op];
|
||||||
#if 1
|
if (IR_OP_HAS_VAR_INPUTS(flags) || IR_INPUT_EDGES_COUNT(flags) > 1) {
|
||||||
n = IR_INPUT_EDGES_COUNT(flags);
|
/* insn has input data edges */
|
||||||
if (!IR_IS_FIXED_INPUTS_COUNT(n) || n > 1) {
|
|
||||||
ir_list_push_unchecked(&queue_early, ref);
|
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) {
|
if (insn->type != IR_VOID) {
|
||||||
IR_ASSERT(flags & IR_OP_FLAG_MEM);
|
IR_ASSERT(flags & IR_OP_FLAG_MEM);
|
||||||
ir_list_push_unchecked(&queue_late, ref);
|
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();
|
sym = get_sym();
|
||||||
}
|
}
|
||||||
} else if (sym == YY__LPAREN || sym == YY__SEMICOLON) {
|
} else if (sym == YY__LPAREN || sym == YY__SEMICOLON) {
|
||||||
|
n = 0;
|
||||||
if (sym == YY__LPAREN) {
|
if (sym == YY__LPAREN) {
|
||||||
sym = get_sym();
|
sym = get_sym();
|
||||||
if (sym == YY_ID || sym == YY_STRING || sym == YY_DECNUMBER || sym == YY_NULL) {
|
if (sym == YY_ID || sym == YY_STRING || sym == YY_DECNUMBER || sym == YY_NULL) {
|
||||||
sym = parse_val(sym, p, op, 1, &op1);
|
sym = parse_val(sym, p, op, 1, &op1);
|
||||||
|
n = 1;
|
||||||
if (sym == YY__COMMA) {
|
if (sym == YY__COMMA) {
|
||||||
sym = get_sym();
|
sym = get_sym();
|
||||||
sym = parse_val(sym, p, op, 2, &op2);
|
sym = parse_val(sym, p, op, 2, &op2);
|
||||||
|
n = 2;
|
||||||
if (sym == YY__COMMA) {
|
if (sym == YY__COMMA) {
|
||||||
sym = get_sym();
|
sym = get_sym();
|
||||||
sym = parse_val(sym, p, op, 3, &op3);
|
sym = parse_val(sym, p, op, 3, &op3);
|
||||||
|
n = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -853,7 +857,14 @@ _yy_state_0:
|
|||||||
&& !IR_IS_UNRESOLVED(op3)) {
|
&& !IR_IS_UNRESOLVED(op3)) {
|
||||||
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
ref = ir_fold(p->ctx, IR_OPT(op, t), op1, op2, op3);
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
yy_error_sym("unexpected", sym);
|
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 */
|
/* IR OP flags */
|
||||||
#define IR_OP_FLAG_OPERANDS_SHIFT 3
|
#define IR_OP_FLAG_OPERANDS_SHIFT 3
|
||||||
|
|
||||||
#define IR_OP_FLAG_EDGES_MSK 0x07
|
#define IR_OP_FLAG_EDGES_MASK 0x03
|
||||||
#define IR_OP_FLAG_OPERANDS_MSK 0x38
|
#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_MEM_MASK ((1<<6)|(1<<7))
|
||||||
|
|
||||||
#define IR_OP_FLAG_DATA (1<<8)
|
#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) \
|
#define IR_OP_FLAGS(op_flags, op1_flags, op2_flags, op3_flags) \
|
||||||
((op_flags) | ((op1_flags) << 20) | ((op2_flags) << 24) | ((op3_flags) << 28))
|
((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_INPUT_EDGES_COUNT(flags) (flags & IR_OP_FLAG_EDGES_MASK)
|
||||||
#define IR_OPERANDS_COUNT(flags) ((flags & IR_OP_FLAG_OPERANDS_MSK) >> IR_OP_FLAG_OPERANDS_SHIFT)
|
#define IR_OPERANDS_COUNT(flags) ((flags & IR_OP_FLAG_OPERANDS_MASK) >> IR_OP_FLAG_OPERANDS_SHIFT)
|
||||||
|
|
||||||
#define IR_VARIABLE_INPUTS_COUNT 4
|
#define IR_OP_HAS_VAR_INPUTS(flags) ((flags) & IR_OP_FLAG_VAR_INPUTS)
|
||||||
#define IR_PHI_INPUTS_COUNT 5
|
|
||||||
|
|
||||||
#define IR_IS_FIXED_INPUTS_COUNT(n) ((n) < IR_VARIABLE_INPUTS_COUNT)
|
|
||||||
|
|
||||||
#define IR_OPND_KIND(flags, i) \
|
#define IR_OPND_KIND(flags, i) \
|
||||||
(((flags) >> (16 + (4 * (((i) > 3) ? 3 : (i))))) & 0xf)
|
(((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) \
|
#define IR_IS_REF_OPND_KIND(kind) \
|
||||||
((kind) >= IR_OPND_DATA && (kind) <= IR_OPND_VAR)
|
((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)
|
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 flags = ir_op_flags[insn->op];
|
||||||
uint32_t n = IR_OPERANDS_COUNT(flags);
|
uint32_t n = IR_OPERANDS_COUNT(flags);
|
||||||
if (EXPECTED(IR_IS_FIXED_INPUTS_COUNT(n))) {
|
|
||||||
/* pass */
|
if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) {
|
||||||
} else if (n == IR_VARIABLE_INPUTS_COUNT) {
|
/* MERGE, PHI, CALL, etc */
|
||||||
/* MERGE or CALL */
|
n = insn->inputs_count;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return n;
|
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 flags = ir_op_flags[insn->op];
|
||||||
uint32_t n = IR_INPUT_EDGES_COUNT(flags);
|
uint32_t n = IR_INPUT_EDGES_COUNT(flags);
|
||||||
if (EXPECTED(IR_IS_FIXED_INPUTS_COUNT(n))) {
|
if (UNEXPECTED(IR_OP_HAS_VAR_INPUTS(flags))) {
|
||||||
/* pass */
|
/* MERGE, PHI, CALL, etc */
|
||||||
} else if (n == IR_VARIABLE_INPUTS_COUNT) {
|
n = insn->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;
|
|
||||||
}
|
}
|
||||||
return n;
|
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];
|
insn = &ctx->ir_base[input];
|
||||||
flags = ir_op_flags[insn->op];
|
flags = ir_op_flags[insn->op];
|
||||||
|
IR_ASSERT(!IR_OP_HAS_VAR_INPUTS(flags));
|
||||||
n = IR_INPUT_EDGES_COUNT(flags);
|
n = IR_INPUT_EDGES_COUNT(flags);
|
||||||
IR_ASSERT(IR_IS_FIXED_INPUTS_COUNT(n));
|
|
||||||
j = 1;
|
j = 1;
|
||||||
p = insn->ops + j;
|
p = insn->ops + j;
|
||||||
if (flags & IR_OP_FLAG_CONTROL) {
|
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);
|
ir_worklist_init(&blocks, ctx->cfg_blocks_count + 1);
|
||||||
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
||||||
if (bb->predecessors_count > 1) {
|
k = bb->predecessors_count;
|
||||||
|
if (k > 1) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
use_list = &ctx->use_lists[bb->start];
|
use_list = &ctx->use_lists[bb->start];
|
||||||
n = use_list->count;
|
n = use_list->count;
|
||||||
if (n > 1) {
|
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++) {
|
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||||
use = *p;
|
use = *p;
|
||||||
insn = &ctx->ir_base[use];
|
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++) {
|
for (b = 1, bb = &ctx->cfg_blocks[1]; b <= ctx->cfg_blocks_count; b++, bb++) {
|
||||||
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
|
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];
|
use_list = &ctx->use_lists[bb->start];
|
||||||
n = use_list->count;
|
n = use_list->count;
|
||||||
if (n > 1) {
|
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++) {
|
for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) {
|
||||||
use = *p;
|
use = *p;
|
||||||
insn = &ctx->ir_base[use];
|
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];
|
insn = &ctx->ir_base[ref];
|
||||||
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
|
||||||
n = insn->inputs_count;
|
n = insn->inputs_count;
|
||||||
if (n == 0) {
|
|
||||||
n = 2;
|
|
||||||
}
|
|
||||||
if (n - unfeasible_inputs == 1) {
|
if (n - unfeasible_inputs == 1) {
|
||||||
/* remove MERGE completely */
|
/* remove MERGE completely */
|
||||||
for (j = 1; j <= n; j++) {
|
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 {
|
} else {
|
||||||
n = insn->inputs_count;
|
n = insn->inputs_count;
|
||||||
if (n == 0) {
|
|
||||||
n = 3;
|
|
||||||
}
|
|
||||||
i = 1;
|
i = 1;
|
||||||
life_inputs = ir_bitset_malloc(n + 1);
|
life_inputs = ir_bitset_malloc(n + 1);
|
||||||
for (j = 1; j <= n; j++) {
|
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++;
|
j++;
|
||||||
}
|
}
|
||||||
i--;
|
i--;
|
||||||
if (i == 2) {
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
insn->inputs_count = i;
|
insn->inputs_count = i;
|
||||||
|
|
||||||
n++;
|
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);
|
ir_insn_set_op(use_insn, i, IR_UNUSED);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
use_insn->inputs_count = insn->inputs_count + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir_mem_free(life_inputs);
|
ir_mem_free(life_inputs);
|
||||||
@ -566,7 +558,7 @@ int ir_sccp(ir_ctx *ctx)
|
|||||||
if (!IR_IS_FEASIBLE(insn->op1)) {
|
if (!IR_IS_FEASIBLE(insn->op1)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
n = ir_variable_inputs_count(merge_insn) + 1;
|
n = merge_insn->inputs_count + 1;
|
||||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||||
for (j = 0; j < (n>>2); j++) {
|
for (j = 0; j < (n>>2); j++) {
|
||||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
_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 may_benefit = 0;
|
||||||
bool has_top = 0;
|
bool has_top = 0;
|
||||||
|
|
||||||
|
IR_ASSERT(!IR_OP_HAS_VAR_INPUTS(flags));
|
||||||
n = IR_INPUT_EDGES_COUNT(flags);
|
n = IR_INPUT_EDGES_COUNT(flags);
|
||||||
IR_ASSERT(IR_IS_FIXED_INPUTS_COUNT(n));
|
|
||||||
for (p = insn->ops + 1; n > 0; p++, n--) {
|
for (p = insn->ops + 1; n > 0; p++, n--) {
|
||||||
ir_ref input = *p;
|
ir_ref input = *p;
|
||||||
if (input > 0) {
|
if (input > 0) {
|
||||||
@ -631,7 +623,7 @@ int ir_sccp(ir_ctx *ctx)
|
|||||||
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
|
||||||
ir_ref unfeasible_inputs = 0;
|
ir_ref unfeasible_inputs = 0;
|
||||||
|
|
||||||
n = ir_variable_inputs_count(insn);
|
n = insn->inputs_count;
|
||||||
if (n > 3 && _values[i].optx == IR_TOP) {
|
if (n > 3 && _values[i].optx == IR_TOP) {
|
||||||
for (j = 0; j < (n>>2); j++) {
|
for (j = 0; j < (n>>2); j++) {
|
||||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
_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 */
|
/* control, call, load and strore instructions may have unprocessed inputs */
|
||||||
n = IR_INPUT_EDGES_COUNT(flags);
|
n = IR_INPUT_EDGES_COUNT(flags);
|
||||||
if (!IR_IS_FIXED_INPUTS_COUNT(n)
|
if (IR_OP_HAS_VAR_INPUTS(flags) && (n = insn->inputs_count) > 3) {
|
||||||
&& (n = ir_variable_inputs_count(insn)) > 3) {
|
|
||||||
for (j = 0; j < (n>>2); j++) {
|
for (j = 0; j < (n>>2); j++) {
|
||||||
_values[i+j+1].optx = IR_BOTTOM; /* keep the tail of a long multislot instruction */
|
_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
|
#endif
|
||||||
|
|
||||||
n = ir_variable_inputs_count(insn);
|
n = insn->inputs_count;
|
||||||
for (j = 3; j <= n; j++) {
|
for (j = 3; j <= n; j++) {
|
||||||
arg = ir_insn_op(insn, j);
|
arg = ir_insn_op(insn, j);
|
||||||
arg_insn = &ctx->ir_base[arg];
|
arg_insn = &ctx->ir_base[arg];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user