From 9f67080d8fbe0b137dbf6b293f0c93ff6d4278e2 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 10 Jun 2004 03:06:07 +0000 Subject: [PATCH] Don't over-allocate x86 stack frames if EBX, ESI, and EDI don't need to be saved; don't perform global register allocation on stacked parameters because it confuses the register spill logic. --- ChangeLog | 7 +++++ include/jit/jit-plus.h | 1 + include/jit/jit-value.h | 1 + jit/jit-insn.c | 4 +++ jit/jit-internal.h | 2 ++ jit/jit-reg-alloc.c | 3 ++- jit/jit-rules-x86.c | 60 +++++++++++++---------------------------- jit/jit-value.c | 12 +++++++++ 8 files changed, 48 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3fade0d..002bf3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -21,6 +21,13 @@ the overhead of function calls that involve stacked arguments on non-x86 platforms; use parameter areas in the ARM back end. + * include/jit/jit-plus.h, include/jit/jit-value.h, jit/jit-insn.c, + jit/jit-internal.h, jit/jit-reg-alloc.c, jit/jit-rules-x86.c, + jit/jit-value.c: don't over-allocate x86 stack frames if + EBX, ESI, and EDI don't need to be saved; don't perform global + register allocation on stacked parameters because it confuses + the register spill logic. + 2004-06-09 Rhys Weatherley * jit/jit-rules-arm.c (flush_constants): update the instruction diff --git a/include/jit/jit-plus.h b/include/jit/jit-plus.h index e6ad1a7..d8cb174 100644 --- a/include/jit/jit-plus.h +++ b/include/jit/jit-plus.h @@ -42,6 +42,7 @@ public: int is_temporary() const { return jit_value_is_temporary(value); } int is_local() const { return jit_value_is_local(value); } int is_constant() const { return jit_value_is_constant(value); } + int is_parameter() const { return jit_value_is_parameter(value); } void set_volatile() { jit_value_set_volatile(value); } int is_volatile() const { return jit_value_is_volatile(value); } diff --git a/include/jit/jit-value.h b/include/jit/jit-value.h index 81e7c56..9568a15 100644 --- a/include/jit/jit-value.h +++ b/include/jit/jit-value.h @@ -75,6 +75,7 @@ jit_value_t jit_value_get_struct_pointer(jit_function_t func) JIT_NOTHROW; int jit_value_is_temporary(jit_value_t value) JIT_NOTHROW; int jit_value_is_local(jit_value_t value) JIT_NOTHROW; int jit_value_is_constant(jit_value_t value) JIT_NOTHROW; +int jit_value_is_parameter(jit_value_t value) JIT_NOTHROW; void jit_value_ref(jit_function_t func, jit_value_t value) JIT_NOTHROW; void jit_value_set_volatile(jit_value_t value) JIT_NOTHROW; int jit_value_is_volatile(jit_value_t value) JIT_NOTHROW; diff --git a/jit/jit-insn.c b/jit/jit-insn.c index 46235ec..19f56ba 100644 --- a/jit/jit-insn.c +++ b/jit/jit-insn.c @@ -5685,6 +5685,10 @@ jit_value_t jit_insn_call_intrinsic @*/ int jit_insn_incoming_reg(jit_function_t func, jit_value_t value, int reg) { + if(value && value->is_parameter) + { + value->is_reg_parameter = 1; + } return create_note(func, JIT_OP_INCOMING_REG, value, jit_value_create_nint_constant (func, jit_type_int, (jit_nint)reg)); diff --git a/jit/jit-internal.h b/jit/jit-internal.h index db56d07..8ec50ca 100644 --- a/jit/jit-internal.h +++ b/jit/jit-internal.h @@ -201,6 +201,8 @@ struct _jit_value int is_addressable : 1; int is_constant : 1; int is_nint_constant : 1; + int is_parameter : 1; + int is_reg_parameter : 1; int has_address : 1; int free_address : 1; int in_register : 1; diff --git a/jit/jit-reg-alloc.c b/jit/jit-reg-alloc.c index 465cf55..7501190 100644 --- a/jit/jit-reg-alloc.c +++ b/jit/jit-reg-alloc.c @@ -1460,7 +1460,8 @@ void _jit_regs_alloc_global(jit_gencode_t gen, jit_function_t func) value = (jit_value_t)(block->data + posn * sizeof(struct _jit_value)); if(value->global_candidate && value->usage_count >= JIT_MIN_USED && - !(value->is_addressable) && !(value->is_volatile)) + !(value->is_addressable) && !(value->is_volatile) && + (!(value->is_parameter) || value->is_reg_parameter)) { /* Insert this candidate into the list, ordered on count */ index = 0; diff --git a/jit/jit-rules-x86.c b/jit/jit-rules-x86.c index 435723a..3a09e83 100644 --- a/jit/jit-rules-x86.c +++ b/jit/jit-rules-x86.c @@ -163,9 +163,8 @@ int _jit_create_entry_insns(jit_function_t func) unsigned int size; unsigned int num_stack_words; - /* Reset the frame size for this function. We start by assuming - that ESI, EDI, and EBX need to be saved in the local frame */ - func->builder->frame_size = 3 * sizeof(void *); + /* Reset the local variable frame size for this function */ + func->builder->frame_size = 0; /* Determine the number of registers to allocate to parameters */ #if JIT_APPLY_X86_FASTCALL == 1 @@ -690,7 +689,6 @@ void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) unsigned char prolog[JIT_PROLOG_SIZE]; unsigned char *inst = prolog; int reg; - unsigned int saved; /* Push ebp onto the stack */ x86_push_reg(inst, X86_EBP); @@ -698,26 +696,23 @@ void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) /* Initialize EBP for the current frame */ x86_mov_reg_reg(inst, X86_EBP, X86_ESP, sizeof(void *)); + /* Allocate space for the local variable frame */ + if(func->builder->frame_size > 0) + { + x86_alu_reg_imm(inst, X86_SUB, X86_ESP, + (int)(func->builder->frame_size)); + } + /* Save registers that we need to preserve */ - saved = 0; for(reg = 0; reg <= 7; ++reg) { if(jit_reg_is_used(gen->touched, reg) && (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) { x86_push_reg(inst, _jit_reg_info[reg].cpu_reg); - saved += sizeof(void *); } } - /* Allocate space for the local variable frame. Subtract off - the space for the registers that we just saved */ - if((func->builder->frame_size - saved) > 0) - { - x86_alu_reg_imm(inst, X86_SUB, X86_ESP, - (int)(func->builder->frame_size - saved)); - } - /* Copy the prolog into place and return the adjusted entry position */ reg = (int)(inst - prolog); jit_memcpy(((unsigned char *)buf) + JIT_PROLOG_SIZE - reg, prolog, reg); @@ -727,14 +722,14 @@ void *_jit_gen_prolog(jit_gencode_t gen, jit_function_t func, void *buf) void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) { jit_nint pop_bytes = 0; - int num_regs, reg; + int reg, offset; unsigned char *inst; int struct_return_offset = 0; void **fixup; void **next; /* Bail out if there is insufficient space for the epilog */ - if(!jit_cache_check_for_n(&(gen->posn), 32)) + if(!jit_cache_check_for_n(&(gen->posn), 48)) { jit_cache_mark_full(&(gen->posn)); return; @@ -823,38 +818,21 @@ void _jit_gen_epilog(jit_gencode_t gen, jit_function_t func) x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4); } - /* Determine the number of callee save registers on the stack */ - num_regs = 0; - for(reg = 7; reg >= 0; --reg) - { - if(jit_reg_is_used(gen->touched, reg) && - (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) - { - ++num_regs; - } - } - - /* Pop the local stack frame, and get back to the callee save regs */ - if(num_regs == 0) - { - x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *)); - } - else - { - x86_lea_membase(inst, X86_ESP, X86_EBP, -(sizeof(void *) * num_regs)); - } - - /* Pop the callee save registers that we used */ - for(reg = 7; reg >= 0; --reg) + /* Restore the callee save registers that we used */ + offset = -(func->builder->frame_size); + for(reg = 0; reg <= 7; ++reg) { if(jit_reg_is_used(gen->touched, reg) && (_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0) { - x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg); + offset -= sizeof(void *); + x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg, + X86_EBP, offset, sizeof(void *)); } } - /* Pop the saved copy of ebp */ + /* Pop the stack frame and restore the saved copy of ebp */ + x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *)); x86_pop_reg(inst, X86_EBP); /* Return from the current function */ diff --git a/jit/jit-value.c b/jit/jit-value.c index 1e4852b..f5c1d86 100644 --- a/jit/jit-value.c +++ b/jit/jit-value.c @@ -505,6 +505,7 @@ jit_value_t jit_value_get_param(jit_function_t func, unsigned int param) /* The value belongs to the entry block, no matter where it happens to be created */ values[current]->block = func->builder->entry; + values[current]->is_parameter = 1; } } @@ -546,6 +547,7 @@ jit_value_t jit_value_get_struct_pointer(jit_function_t func) /* The value belongs to the entry block, no matter where it happens to be created */ value->block = func->builder->entry; + value->is_parameter = 1; } jit_type_free(type); } @@ -587,6 +589,16 @@ int jit_value_is_constant(jit_value_t value) return value->is_constant; } +/*@ + * @deftypefun int jit_value_is_parameter (jit_value_t value) + * Determine if a value is a function parameter. + * @end deftypefun +@*/ +int jit_value_is_parameter(jit_value_t value) +{ + return value->is_parameter; +} + /*@ * @deftypefun void jit_value_ref (jit_function_t func, jit_value_t value) * Create a reference to the specified @code{value} from the current -- 2.47.3