From e44934551432adc17b0355df7b86bf5d7a61208f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 19 Apr 2022 16:45:03 +0300 Subject: [PATCH] Fix few CSSP bugs --- ir_sccp.c | 48 +++++++++++++++++++++++++++++++---- tests/025.irt | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 tests/025.irt diff --git a/ir_sccp.c b/ir_sccp.c index 5761c32..8817e31 100644 --- a/ir_sccp.c +++ b/ir_sccp.c @@ -244,6 +244,19 @@ static void ir_sccp_replace_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_r insn->optx = IR_NOP; } +static void ir_sccp_replace_use(ir_ctx *ctx, ir_ref ref, ir_ref use, ir_ref new_use) +{ + ir_use_list *use_list = &ctx->use_lists[ref]; + ir_ref i, n, *p; + + n = use_list->count; + for (i = 0, p = &ctx->use_edges[use_list->refs]; i < n; i++, p++) { + if (*p == use) { + *p = new_use; + } + } +} + static void ir_sccp_remove_if(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref dst) { ir_ref j, n, *p, use, next; @@ -259,7 +272,7 @@ static void ir_sccp_remove_if(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref next_insn = &ctx->ir_base[next]; /* remove IF and IF_TRUE/FALSE from double linked control list */ next_insn->op1 = insn->op1; - ctx->use_edges[ctx->use_lists[insn->op1].refs] = next; + ir_sccp_replace_use(ctx, insn->op1, ref, next); /* remove IF and IF_TRUE/FALSE instructions */ ir_sccp_replace_insn(ctx, _values, ref, IR_UNUSED); ir_sccp_replace_insn(ctx, _values, use, IR_UNUSED); @@ -303,7 +316,7 @@ static void ir_sccp_remove_unreachable_merge_inputs(ir_ctx *ctx, ir_insn *_value IR_ASSERT(prev && next); /* remove MERGE and input END from double linked control list */ next_insn->op1 = prev; - ctx->use_edges[ctx->use_lists[prev].refs] = next; + ir_sccp_replace_use(ctx, prev, input, next); /* remove MERGE and input END instructions */ ir_sccp_replace_insn(ctx, _values, ref, IR_UNUSED); ir_sccp_replace_insn(ctx, _values, input, IR_UNUSED); @@ -560,7 +573,13 @@ int ir_sccp(ir_ctx *ctx) for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) { use = *p; insn = &ctx->ir_base[use]; - if (insn->op != IR_PHI || IR_IS_REACHABLE(insn->op1)) { + if ((ir_op_flags[insn->op] & IR_OP_FLAG_DATA)) { + if (insn->op != IR_PHI || IR_IS_REACHABLE(insn->op1)) { + if (!IR_IS_BOTTOM(use)) { + ir_bitset_incl(worklist, use); + } + } + } else if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN || IR_IS_REACHABLE(insn->op1)) { if (!IR_IS_BOTTOM(use)) { ir_bitset_incl(worklist, use); } @@ -600,8 +619,27 @@ int ir_sccp(ir_ctx *ctx) ir_sccp_replace_insn(ctx, _values, i, _values[i].op1); #endif } else if (IR_IS_TOP(i)) { - if (ctx->ir_base[i].op != IR_PARAM && ctx->ir_base[i].op != IR_VAR) { - /* remove unreachable instruction */ + /* remove unreachable instruction */ + insn = &ctx->ir_base[i]; + if (ir_op_flags[insn->op] & IR_OP_FLAG_DATA) { + if (insn->op != IR_PARAM && insn->op != IR_VAR) { + ir_sccp_replace_insn(ctx, _values, i, IR_UNUSED); + } + } else { + if (insn->op == IR_RETURN || insn->op == IR_UNREACHABLE) { + ir_ref ref = ctx->ir_base[1].op1; + if (ref == i) { + ctx->ir_base[1].op1 = insn->op3; + } else { + do { + if (ctx->ir_base[ref].op3 == i) { + ctx->ir_base[ref].op3 = insn->op3; + break; + } + ref = ctx->ir_base[ref].op3; + } while (ref); + } + } ir_sccp_replace_insn(ctx, _values, i, IR_UNUSED); } } else if (_values[i].op == IR_IF) { diff --git a/tests/025.irt b/tests/025.irt new file mode 100644 index 0000000..7ff578a --- /dev/null +++ b/tests/025.irt @@ -0,0 +1,69 @@ +--TEST-- +025: SCCP+DCE (Removing RETURN nodes) +--ARGS-- +--save +--CODE-- +{ + uintptr_t c_1 = 0; + bool c_2 = 0; + bool c_3 = 1; + double c_4 = 0.5; + double c_5 = 0; + int32_t c_6 = 1000; + int32_t c_7 = 1; + double c_8 = 16; + int32_t c_9 = 1000; + l_1 = START(l_35); + double d_2 = PARAM(l_1, "x", 0); + double d_3 = PARAM(l_1, "y", 1); + double d_4 = VAR(l_1, "cr"); + double d_5 = SUB(d_3, c_4); + double d_6 = VAR(l_1, "ci"); + double d_7 = VAR(l_1, "zi"); + double d_8 = VAR(l_1, "zr"); + int32_t d_9 = VAR(l_1, "i"); + l_10 = END(l_1); + l_11 = LOOP_BEGIN(l_10, l_37); + double d_12 = PHI(l_11, c_5, d_25); + double d_13 = PHI(l_11, c_5, d_23); + int32_t d_14 = PHI(l_11, c_6, d_15); + int32_t d_15 = ADD(d_14, c_7); + double d_16 = VAR(l_11, "temp"); + double d_17 = MUL(d_13, d_12); + double d_18 = VAR(l_11, "zr2"); + double d_19 = MUL(d_13, d_13); + double d_20 = VAR(l_11, "zi2"); + double d_21 = MUL(d_12, d_12); + double d_22 = SUB(d_19, d_21); + double d_23 = ADD(d_22, d_5); + double d_24 = ADD(d_17, d_17); + double d_25 = ADD(d_24, d_2); + double d_26 = ADD(d_21, d_19); + bool d_27 = GT(d_26, c_8); + l_28 = IF(l_11, d_27); + l_29 = IF_TRUE(l_28); + l_30 = RETURN(l_29, d_15); + l_31 = IF_FALSE(l_28); + bool d_32 = GT(d_15, c_9); + l_33 = IF(l_31, d_32); + l_34 = IF_TRUE(l_33); + l_35 = RETURN(l_34, c_6, l_30); + l_36 = IF_FALSE(l_33); + l_37 = LOOP_END(l_36, l_11); +} +--EXPECT-- +{ + uintptr_t c_1 = 0; + bool c_2 = 0; + bool c_3 = 1; + int32_t c_4 = 1000; + l_1 = START(l_9); + double d_2 = PARAM(l_1, "x", 0); + double d_3 = PARAM(l_1, "y", 1); + double d_4 = VAR(l_1, "cr"); + double d_5 = VAR(l_1, "ci"); + double d_6 = VAR(l_1, "zi"); + double d_7 = VAR(l_1, "zr"); + int32_t d_8 = VAR(l_1, "i"); + l_9 = RETURN(l_1, c_4); +}