Skip to content

Commit

Permalink
Extend types of induction varibles
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Apr 16, 2024
1 parent 04b682d commit c407241
Showing 1 changed file with 159 additions and 4 deletions.
163 changes: 159 additions & 4 deletions ir_sccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,6 +967,145 @@ static ir_ref ir_promote_i2i(ir_ctx *ctx, ir_type type, ir_ref ref, ir_ref use)
return ref;
}

static ir_ref ir_ext_const(ir_ctx *ctx, ir_insn *val_insn, ir_op op, ir_type type)
{
ir_val new_val;

switch (val_insn->type) {
default:
IR_ASSERT(0);
case IR_I8:
case IR_U8:
case IR_BOOL:
if (op == IR_SEXT) {
new_val.i64 = (int64_t)val_insn->val.i8;
} else {
new_val.u64 = (uint64_t)val_insn->val.u8;
}
break;
case IR_I16:
case IR_U16:
if (op == IR_SEXT) {
new_val.i64 = (int64_t)val_insn->val.i16;
} else {
new_val.u64 = (uint64_t)val_insn->val.u16;
}
break;
case IR_I32:
case IR_U32:
if (op == IR_SEXT) {
new_val.i64 = (int64_t)val_insn->val.i32;
} else {
new_val.u64 = (uint64_t)val_insn->val.u32;
}
break;
}
return ir_const(ctx, new_val, type);
}

static ir_ref ir_ext_ref(ir_ctx *ctx, ir_ref var_ref, ir_ref src_ref, ir_op op, ir_type type)
{
ir_ref new_ext_ref = ir_emit1(ctx, IR_OPTX(op, type, 1), src_ref);

ctx->use_lists = ir_mem_realloc(ctx->use_lists, ctx->insns_count * sizeof(ir_use_list));
ctx->use_lists[new_ext_ref].count = 0;
ctx->use_lists[new_ext_ref].refs = IR_UNUSED;
ir_use_list_add(ctx, new_ext_ref, var_ref);
if (!IR_IS_CONST_REF(src_ref)) {
ir_use_list_replace_one(ctx, src_ref, var_ref, new_ext_ref);
}
return new_ext_ref;
}

static bool ir_try_promote_ext(ir_ctx *ctx, ir_ref ext_ref, ir_insn *insn, ir_bitqueue *worklist)
{
ir_type type = insn->type;
ir_op op = insn->op;
ir_ref ref = insn->op1;
ir_insn *phi_insn = &ctx->ir_base[ref];
ir_insn *op_insn;
ir_use_list *use_list;
ir_ref n, *p, use, op_ref;

/* Check for simple induction variable in the form: x2 = PHI(loop, x1, x3); x3 = ADD(x2, _); */
if (phi_insn->op != IR_PHI
|| phi_insn->inputs_count != 3 /* (2 values) */
|| ctx->ir_base[phi_insn->op1].op != IR_LOOP_BEGIN) {
return 0;
}

op_ref = phi_insn->op3;
op_insn = &ctx->ir_base[op_ref];
if ((op_insn->op != IR_ADD && op_insn->op != IR_SUB && op_insn->op != IR_MUL)
|| op_insn->op1 != ref
|| op_insn->op2 == ref
|| ctx->use_lists[op_ref].count != 1) {
return 0;
}

/* Check if we may change the type of the induction variable */
use_list = &ctx->use_lists[ref];
n = use_list->count;
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
use = *p;
if (use == op_ref || use == ext_ref) {
continue;
} else {
ir_insn *use_insn = &ctx->ir_base[use];

if ((use_insn->op >= IR_EQ && use_insn->op <= IR_UGT)
&& use_insn->op1 == ref
&& use_insn->op2 != ref) {
continue;
} else if (use_insn->op == IR_IF) {
continue;
} else {
return 0;
}
}
}

phi_insn->type = insn->type;
op_insn->type = insn->type;

use_list = &ctx->use_lists[ref];
n = use_list->count;
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
use = *p;
if (use == ext_ref) {
continue;
} else {
ir_insn *use_insn = &ctx->ir_base[use];

if (use_insn->op == IR_IF) {
continue;
}
IR_ASSERT(((use_insn->op >= IR_EQ && use_insn->op <= IR_UGT)
|| use_insn->op == IR_ADD || use_insn->op == IR_SUB || use_insn->op == IR_MUL)
&& use_insn->op1 == ref
&& use_insn->op2 != ref);
if (IR_IS_CONST_REF(use_insn->op2)
&& !IR_IS_SYM_CONST(ctx->ir_base[use_insn->op2].op)) {
ctx->ir_base[use].op2 = ir_ext_const(ctx, &ctx->ir_base[use_insn->op2], op, type);
} else {
ctx->ir_base[use].op2 = ir_ext_ref(ctx, use, use_insn->op2, op, type);
}
}
}

ir_sccp_replace_insn2(ctx, ext_ref, ref, worklist);

phi_insn = &ctx->ir_base[ref];
if (IR_IS_CONST_REF(phi_insn->op2)
&& !IR_IS_SYM_CONST(ctx->ir_base[phi_insn->op2].op)) {
ctx->ir_base[ref].op2 = ir_ext_const(ctx, &ctx->ir_base[phi_insn->op2], op, type);
} else {
ctx->ir_base[ref].op2 = ir_ext_ref(ctx, ref, phi_insn->op2, op, type);
}

return 1;
}

int ir_sccp(ir_ctx *ctx)
{
ir_ref i, j, n, *p, use;
Expand Down Expand Up @@ -1025,12 +1164,18 @@ int ir_sccp(ir_ctx *ctx)
}
if (!may_benefit) {
IR_MAKE_BOTTOM(i);
if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC) {
if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC
|| insn->op == IR_ZEXT || insn->op == IR_SEXT) {
ir_bitqueue_add(&worklist2, i);
}
} else if (!ir_sccp_fold(ctx, _values, i, insn->opt, insn->op1, insn->op2, insn->op3)) {
/* not changed */
continue;
} else if (_values[i].optx == IR_BOTTOM) {
if (insn->op == IR_FP2FP || insn->op == IR_FP2INT || insn->op == IR_TRUNC
|| insn->op == IR_ZEXT || insn->op == IR_SEXT) {
ir_bitqueue_add(&worklist2, i);
}
}
} else {
IR_MAKE_BOTTOM(i);
Expand Down Expand Up @@ -1298,15 +1443,17 @@ int ir_sccp(ir_ctx *ctx)
ir_ref ref = ir_promote_d2f(ctx, insn->op1, i);
insn->op1 = ref;
ir_sccp_replace_insn2(ctx, i, ref, &worklist2);
break;
}
} else {
if (ir_may_promote_f2d(ctx, insn->op1)) {
ir_ref ref = ir_promote_f2d(ctx, insn->op1, i);
insn->op1 = ref;
ir_sccp_replace_insn2(ctx, i, ref, &worklist2);
break;
}
}
break;
goto folding;
case IR_FP2INT:
if (ctx->ir_base[insn->op1].type == IR_DOUBLE) {
if (ir_may_promote_d2f(ctx, insn->op1)) {
Expand All @@ -1317,17 +1464,25 @@ int ir_sccp(ir_ctx *ctx)
insn->op1 = ir_promote_f2d(ctx, insn->op1, i);
}
}
break;
goto folding;
case IR_TRUNC:
if (ir_may_promote_i2i(ctx, insn->type, insn->op1)) {
ir_ref ref = ir_promote_i2i(ctx, insn->type, insn->op1, i);
insn->op1 = ref;
ir_sccp_replace_insn2(ctx, i, ref, &worklist2);
break;
}
break;
goto folding;
case IR_SEXT:
case IR_ZEXT:
if (ir_try_promote_ext(ctx, i, insn, &worklist2)) {
break;
}
goto folding;
case IR_PHI:
break;
default:
folding:
ir_sccp_fold2(ctx, i, &worklist2);
break;
}
Expand Down

0 comments on commit c407241

Please sign in to comment.