mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-29 06:10:09 +08:00
optimize the generated code when save_reg is required
Before this patch, save_reg can't reuse the temporary local variable created before to save register. It may consume a lot of stack memory. this patch make save_reg reuse the temporary local variable.
This commit is contained in:
parent
0c313f491b
commit
b3b685d92a
66
tccgen.c
66
tccgen.c
@ -70,6 +70,14 @@ ST_DATA struct switch_t {
|
||||
int def_sym; /* default symbol */
|
||||
} *cur_switch; /* current switch */
|
||||
|
||||
#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 0x4
|
||||
/*list of temporary local variables on the stack in current function. */
|
||||
ST_DATA struct temp_local_variable {
|
||||
int location; //offset on stack. Svalue.c.i
|
||||
short size;
|
||||
short align;
|
||||
} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
|
||||
short nb_temp_local_vars;
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static void gen_cast(CType *type);
|
||||
@ -97,6 +105,8 @@ static int gvtst(int inv, int t);
|
||||
static void gen_inline_functions(TCCState *s);
|
||||
static void skip_or_save_block(TokenString **str);
|
||||
static void gv_dup(void);
|
||||
static int get_temp_local_var(int size,int align);
|
||||
static void clear_temp_local_var_list();
|
||||
|
||||
ST_INLN int is_float(int t)
|
||||
{
|
||||
@ -1033,10 +1043,10 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||
type = &int_type;
|
||||
#endif
|
||||
size = type_size(type, &align);
|
||||
loc = (loc - size) & -align;
|
||||
l=get_temp_local_var(size,align);
|
||||
sv.type.t = type->t;
|
||||
sv.r = VT_LOCAL | VT_LVAL;
|
||||
sv.c.i = loc;
|
||||
sv.c.i = l;
|
||||
store(r, &sv);
|
||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
||||
/* x86 specific: need to pop fp register ST0 if saved */
|
||||
@ -1051,7 +1061,6 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
||||
store(p->r2, &sv);
|
||||
}
|
||||
#endif
|
||||
l = loc;
|
||||
saved = 1;
|
||||
}
|
||||
/* mark that stack entry as being saved on the stack */
|
||||
@ -1134,6 +1143,56 @@ ST_FUNC int get_reg(int rc)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* find a free temporary local variable (return the offset on stack) match the size and align. If none, add new temporary stack variable*/
|
||||
static int get_temp_local_var(int size,int align){
|
||||
int i;
|
||||
struct temp_local_variable *temp_var;
|
||||
int found_var;
|
||||
SValue *p;
|
||||
int r;
|
||||
char free;
|
||||
char found;
|
||||
found=0;
|
||||
for(i=0;i<nb_temp_local_vars;i++){
|
||||
temp_var=&arr_temp_local_vars[i];
|
||||
if(temp_var->size<size||align!=temp_var->align){
|
||||
continue;
|
||||
}
|
||||
/*check if temp_var is free*/
|
||||
free=1;
|
||||
for(p=vstack;p<=vtop;p++) {
|
||||
r=p->r&VT_VALMASK;
|
||||
if(r==VT_LOCAL||r==VT_LLOCAL){
|
||||
if(p->c.i==temp_var->location){
|
||||
free=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(free){
|
||||
found_var=temp_var->location;
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
loc = (loc - size) & -align;
|
||||
if(nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER){
|
||||
temp_var=&arr_temp_local_vars[i];
|
||||
temp_var->location=loc;
|
||||
temp_var->size=size;
|
||||
temp_var->align=align;
|
||||
nb_temp_local_vars++;
|
||||
}
|
||||
found_var=loc;
|
||||
}
|
||||
return found_var;
|
||||
}
|
||||
|
||||
static void clear_temp_local_var_list(){
|
||||
nb_temp_local_vars=0;
|
||||
}
|
||||
|
||||
/* move register 's' (of type 't') to 'r', and flush previous value of r to memory
|
||||
if needed */
|
||||
static void move_reg(int r, int s, int t)
|
||||
@ -7169,6 +7228,7 @@ static void gen_function(Sym *sym)
|
||||
gfunc_prolog(&sym->type);
|
||||
local_scope = 0;
|
||||
rsym = 0;
|
||||
clear_temp_local_var_list();
|
||||
block(NULL, NULL, 0);
|
||||
if (!(nocode_wanted & 0x20000000)
|
||||
&& ((func_vt.t & VT_BTYPE) == VT_INT)
|
||||
|
Loading…
Reference in New Issue
Block a user