From c404bb04f0d11511b6fa8c2c7e3e68a3fb5a3ad3 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 28 Jan 2024 11:32:08 +0000 Subject: [PATCH] Optimise vcode load op in more cases --- src/vcode.c | 43 ++++++++++++++++++++++++++++++------------- test/test_lower.c | 2 -- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/vcode.c b/src/vcode.c index 03d7fa17..1f456d2c 100644 --- a/src/vcode.c +++ b/src/vcode.c @@ -3631,29 +3631,46 @@ vcode_reg_t emit_load(vcode_var_t var) { // Try scanning backwards through the block for another load or store to // this variable + enum { EAGER, CONSERVATIVE, UNSAFE } state = EAGER; vcode_reg_t fold = VCODE_INVALID_REG; - bool aliased = false; VCODE_FOR_EACH_OP(other) { - if (fold == VCODE_INVALID_REG) { + switch (state) { + case EAGER: if (other->kind == VCODE_OP_LOAD && other->address == var) - fold = other->result; + return other->result; else if (other->kind == VCODE_OP_STORE && other->address == var) + return other->args.items[0]; + else if (other->kind == VCODE_OP_FCALL + || other->kind == VCODE_OP_PCALL + || other->kind == VCODE_OP_FILE_READ + || other->kind == VCODE_OP_STORE_INDIRECT + || other->kind == VCODE_OP_DEALLOCATE) + state = CONSERVATIVE; // May write to variable + break; + + case CONSERVATIVE: + if (other->kind == VCODE_OP_LOAD && other->address == var + && fold == VCODE_INVALID_REG) + fold = other->result; + else if (other->kind == VCODE_OP_STORE && other->address == var + && fold == VCODE_INVALID_REG) fold = other->args.items[0]; - } + else if (other->kind == VCODE_OP_INDEX && other->address == var) + state = UNSAFE; + else if (other->kind == VCODE_OP_CONTEXT_UPREF && other->hops == 0) + state = UNSAFE; // Nested call captures variables + break; - if (other->kind == VCODE_OP_INDEX && other->address == var) - aliased = true; - else if (other->kind == VCODE_OP_FCALL || other->kind == VCODE_OP_PCALL) - break; // Nested call captures variables - else if (other->kind == VCODE_OP_FILE_READ) - break; // May write to variable + case UNSAFE: + break; + } } - var_t *v = vcode_var_data(var); - - if (fold != VCODE_INVALID_REG && !aliased) + if (fold != VCODE_INVALID_REG && state != UNSAFE) return fold; + var_t *v = vcode_var_data(var); + op_t *op = vcode_add_op(VCODE_OP_LOAD); op->address = var; op->result = vcode_add_reg(v->type); diff --git a/test/test_lower.c b/test/test_lower.c index ab2a5e40..133d4d42 100644 --- a/test/test_lower.c +++ b/test/test_lower.c @@ -2974,7 +2974,6 @@ START_TEST(test_hintbug) { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_WRAP }, - { VCODE_OP_LOAD, .name = "X" }, { VCODE_OP_CONST, .value = 0 }, { VCODE_OP_CONST, .value = 1 }, { VCODE_OP_ALLOC }, @@ -3015,7 +3014,6 @@ START_TEST(test_issue351) { VCODE_OP_FCALL, .func = "*WORK.ISSUE351.DUMP_WORDS" }, { VCODE_OP_LOAD, .name = "*right" }, { VCODE_OP_LOAD, .name = "*step" }, - { VCODE_OP_LOAD, .name = "I.LOOP1" }, { VCODE_OP_ADD }, { VCODE_OP_STORE, .name = "I.LOOP1" }, { VCODE_OP_CMP, .cmp = VCODE_CMP_EQ }, -- 2.39.2