From f978b666620bf01c3403c970906d7ef77912e877 Mon Sep 17 00:00:00 2001 From: Mid <> Date: Wed, 15 Oct 2025 14:10:42 +0300 Subject: [PATCH] Conditionally save volatile regs --- src/ast/usedef.c | 2 ++ src/x86/cg.c | 49 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/ast/usedef.c b/src/ast/usedef.c index 76cae9b..13bb464 100644 --- a/src/ast/usedef.c +++ b/src/ast/usedef.c @@ -204,6 +204,8 @@ void ast_usedef_reset(AST *chu) { for(size_t sii = 0; sii < chu->chunk.varCount; sii++) { ScopeItem *si = chu->chunk.vars[sii]; + assert(si->data.var.declaration != NULL && "All local vars must have defined declaration location"); + if(ast_stmt_is_after(chu, si->data.var.liveRangeEnd, s) == 0 && ast_stmt_is_after(chu, target, si->data.var.liveRangeEnd) == 0 && ast_stmt_is_after(chu, si->data.var.declaration, target) == 0) { si->data.var.liveRangeEnd = s; diff --git a/src/x86/cg.c b/src/x86/cg.c index 2c260a0..96b6022 100644 --- a/src/x86/cg.c +++ b/src/x86/cg.c @@ -260,6 +260,27 @@ static int lr_empty(ScopeItem *a) { return !a->data.var.liveRangeStart; } +static bool is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(AST *tlc, AST *statement, size_t resource) { + for(size_t vi = 0; vi < tlc->chunk.varCount; vi++) { + ScopeItem *si = tlc->chunk.vars[vi]; + if((REG_CLASSES[si->data.var.registerClass].rs[si->data.var.color] & resource) == 0) { + continue; + } + if(ast_stmt_is_after(tlc, statement, si->data.var.liveRangeEnd) == 1 || statement == si->data.var.liveRangeEnd) { + continue; + } + if(si->data.var.usedefFirst == NULL) { + // Even if the resource is in use, the variable itself isn't so we don't care + continue; + } + if(!lr_empty(si) && (ast_stmt_is_after(tlc, statement, si->data.var.liveRangeStart) == 1 + && ast_stmt_is_after(tlc, si->data.var.liveRangeEnd, statement) == 1)) { + return true; + } + } + return false; +} + void cg_chunk(CGState *cg, AST *a) { AST *s = a->chunk.statementFirst; @@ -390,12 +411,14 @@ void cg_chunk(CGState *cg, AST *a) { AST *e = s->stmtAssign.to; - if(x86_ia16()) { - puts("push cx"); - puts("push dx"); - } else { - puts("push ecx"); - puts("push edx"); + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) { + puts(x86_ia16() ? "push cx" : "push ecx"); + } + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) { + puts(x86_ia16() ? "push dx" : "push edx"); + } + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) { + puts(x86_ia16() ? "push ax" : "push eax"); } int argCount = e->exprCall.what->expression.type->pointer.of->function.argCount; @@ -422,12 +445,14 @@ void cg_chunk(CGState *cg, AST *a) { } } - if(x86_ia16()) { - puts("pop dx"); - puts("pop cx"); - } else { - puts("pop edx"); - puts("pop ecx"); + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EAX)) { + puts(x86_ia16() ? "pop ax" : "pop eax"); + } + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_EDX)) { + puts(x86_ia16() ? "pop dx" : "pop edx"); + } + if(is_resource_in_use_right_now_at_this_current_point_in_time_and_also_not_created_right_now(a, s, HWR_ECX)) { + puts(x86_ia16() ? "pop cx" : "pop ecx"); } } else if(s->nodeKind == AST_STMT_ASSIGN) {