diff options
author | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-30 19:16:42 +0200 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-30 19:26:30 +0200 |
commit | b1e8b4f24927efc6ed68420e4f579fb20ab831a9 (patch) | |
tree | 119496bacb2758cee773138f0bd3a452c8b6ec60 | |
parent | efe28f579b8720ea506a4e5d24ec0290223b8745 (diff) |
gas: Optimize variable reference on assembly
We were moving the stack data for variable reference to another stack
position ending up with two pointer to the same value.
// a: i32 = 1;
mov $1, -8(%rbp)
// b: i32 = a;
mov -8(%rbp), %rax
mov %rax, -24(%rbp)
mov -24(%rbp), %rax
mov %rax, -16(%rbp)
After this changes, we wont create a new temp space on stack if we don't
need it. See bellow the example after the optimization:
// a: i32 = 1;
mov $1, -8(%rbp)
// b: i32 = a;
mov -8(%rbp), %rax
mov %rax, -16(%rbp)
Signed-off-by: Johnny Richard <johnny@johnnyrichard.com>
Co-authored-by: Carlos Maniero <carlosmaniero@gmail.com>
-rw-r--r-- | examples/variables.pipa | 3 | ||||
-rw-r--r-- | src/gas_assembly_generator.c | 34 | ||||
-rw-r--r-- | src/gas_assembly_generator.h | 2 |
3 files changed, 32 insertions, 7 deletions
diff --git a/examples/variables.pipa b/examples/variables.pipa index 9c395ce..25cbd59 100644 --- a/examples/variables.pipa +++ b/examples/variables.pipa @@ -3,5 +3,6 @@ main(): i32 { b: i32 = 32; c: i32 = 2 * (b + a); d: i32 = (c - 33) + 1; - return d / 2; + e: i32 = d; + return e / 2; } diff --git a/src/gas_assembly_generator.c b/src/gas_assembly_generator.c index b9b8537..dd5d240 100644 --- a/src/gas_assembly_generator.c +++ b/src/gas_assembly_generator.c @@ -54,6 +54,13 @@ gas_assembly_generator_set_latest_evaluation_to_rax(gas_assembly_generator_t *ge gen->latest_evaluation = (evaluation_result_t){ .kind = EVALUATION_RESULT_ON_RAX }; } +static void +gas_assembly_generator_set_latest_evaluation_on_stack(gas_assembly_generator_t *gen, int stack_offset) +{ + gen->latest_evaluation = + (evaluation_result_t){ .kind = EVALUATION_RESULT_ON_STACK, .data = { .stack_offset = stack_offset } }; +} + typedef struct ref_entry_t { ast_identifier_t *id; @@ -167,11 +174,15 @@ gas_assembly_generator_compile_variable_declaration(gas_assembly_generator_t *ge switch (gen->latest_evaluation.kind) { case EVALUATION_RESULT_AS_LITERAL_INTEGER: - fprintf(gen->stream, " mov $%ld, %d(%%rbp)\n", gen->latest_evaluation.data.literal_int, entry->stack_offset); + fprintf(gen->stream, " movq $%ld, %d(%%rbp)\n", gen->latest_evaluation.data.literal_int, entry->stack_offset); break; case EVALUATION_RESULT_ON_RAX: fprintf(gen->stream, " mov %%rax, %d(%%rbp)\n", entry->stack_offset); break; + case EVALUATION_RESULT_ON_STACK: + fprintf(gen->stream, " movq %d(%%rbp), %%rax\n", gen->latest_evaluation.data.stack_offset); + fprintf(gen->stream, " movq %%rax, %d(%%rbp)\n", entry->stack_offset); + break; case EVALUATION_RESULT_VOID: assert(false && "Unexpected void result for variable declaration"); // FIXME: store the latest node at latest evaluation and print_ast @@ -190,8 +201,7 @@ gas_assembly_generator_compile_variable(gas_assembly_generator_t *gen, ast_varia } } assert(entry && "reference not found"); - fprintf(gen->stream, " mov %d(%%rbp), %%rax\n", entry->stack_offset); - gas_assembly_generator_set_latest_evaluation_to_rax(gen); + gas_assembly_generator_set_latest_evaluation_on_stack(gen, entry->stack_offset); } static void @@ -228,15 +238,27 @@ gas_assembly_generator_binary_operation(gas_assembly_generator_t *gen, ast_binar fprintf(gen->stream, " mov %d(%%rbp), %%rcx\n", gen->stack_offset); gen->stack_offset += 8; break; + case EVALUATION_RESULT_ON_STACK: + fprintf(gen->stream, " movq %d(%%rbp), %%rcx\n", right_evaluation.data.stack_offset); + break; case EVALUATION_RESULT_VOID: - assert(false && "Unexpected void result for variable declaration"); + assert(false && "Unexpected void result for binary operation"); // FIXME: store the latest node at latest evaluation and print_ast } gas_assembly_generator_set_latest_evaluation_to_rax(gen); - if (left_evaluation.kind == EVALUATION_RESULT_AS_LITERAL_INTEGER) { - fprintf(gen->stream, " mov $%ld, %%rax\n", left_evaluation.data.literal_int); + switch (left_evaluation.kind) { + case EVALUATION_RESULT_AS_LITERAL_INTEGER: + fprintf(gen->stream, " mov $%ld, %%rax\n", left_evaluation.data.literal_int); + break; + case EVALUATION_RESULT_ON_STACK: + fprintf(gen->stream, " movq %d(%%rbp), %%rax\n", left_evaluation.data.stack_offset); + break; + case EVALUATION_RESULT_ON_RAX: + break; + case EVALUATION_RESULT_VOID: + assert(false && "Unexpected void result for binary operation"); } if (binary_operation->kind == AST_BINOP_ADITION) { diff --git a/src/gas_assembly_generator.h b/src/gas_assembly_generator.h index 8501a67..92972f9 100644 --- a/src/gas_assembly_generator.h +++ b/src/gas_assembly_generator.h @@ -25,12 +25,14 @@ typedef enum evaluation_result_kind_t { EVALUATION_RESULT_VOID, EVALUATION_RESULT_ON_RAX, + EVALUATION_RESULT_ON_STACK, EVALUATION_RESULT_AS_LITERAL_INTEGER } evaluation_result_kind_t; typedef union evaluation_result_data_t { int64_t literal_int; + int stack_offset; } evaluation_result_data_t; typedef struct evaluation_result_t |