diff --git a/ir.c b/ir.c index 3c102ce..48e4a1e 100644 --- a/ir.c +++ b/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); } diff --git a/ir.g b/ir.g index 13a63a3..0ff4fd1 100644 --- a/ir.g +++ b/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); } } ) diff --git a/ir.h b/ir.h index 1b1243d..e863851 100644 --- a/ir.h +++ b/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 */ } diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 2638a23..be56619 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -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]; diff --git a/ir_cfg.c b/ir_cfg.c index c7d4730..01cda93 100644 --- a/ir_cfg.c +++ b/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); diff --git a/ir_check.c b/ir_check.c index f902994..35b3355 100644 --- a/ir_check.c +++ b/ir_check.c @@ -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; diff --git a/ir_emit.c b/ir_emit.c index 3e29bca..da663b1 100644 --- a/ir_emit.c +++ b/ir_emit.c @@ -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; diff --git a/ir_fold.h b/ir_fold.h index 247b022..a2d49f4 100644 --- a/ir_fold.h +++ b/ir_fold.h @@ -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; } diff --git a/ir_gcm.c b/ir_gcm.c index 880bff3..865e445 100644 --- a/ir_gcm.c +++ b/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); diff --git a/ir_load.c b/ir_load.c index 7c0cdf5..81b2f91 100644 --- a/ir_load.c +++ b/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); diff --git a/ir_private.h b/ir_private.h index f0a4cc2..2a5263d 100644 --- a/ir_private.h +++ b/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; } diff --git a/ir_ra.c b/ir_ra.c index 1fba294..c7c2142 100644 --- a/ir_ra.c +++ b/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]; diff --git a/ir_sccp.c b/ir_sccp.c index 7f8d9f7..d57ee45 100644 --- a/ir_sccp.c +++ b/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 */ } diff --git a/ir_x86.dasc b/ir_x86.dasc index 9f1cbd5..bc0de86 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -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];