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 */
|
int def_sym; /* default symbol */
|
||||||
} *cur_switch; /* current switch */
|
} *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);
|
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 gen_inline_functions(TCCState *s);
|
||||||
static void skip_or_save_block(TokenString **str);
|
static void skip_or_save_block(TokenString **str);
|
||||||
static void gv_dup(void);
|
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)
|
ST_INLN int is_float(int t)
|
||||||
{
|
{
|
||||||
@ -1033,10 +1043,10 @@ ST_FUNC void save_reg_upstack(int r, int n)
|
|||||||
type = &int_type;
|
type = &int_type;
|
||||||
#endif
|
#endif
|
||||||
size = type_size(type, &align);
|
size = type_size(type, &align);
|
||||||
loc = (loc - size) & -align;
|
l=get_temp_local_var(size,align);
|
||||||
sv.type.t = type->t;
|
sv.type.t = type->t;
|
||||||
sv.r = VT_LOCAL | VT_LVAL;
|
sv.r = VT_LOCAL | VT_LVAL;
|
||||||
sv.c.i = loc;
|
sv.c.i = l;
|
||||||
store(r, &sv);
|
store(r, &sv);
|
||||||
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
|
||||||
/* x86 specific: need to pop fp register ST0 if saved */
|
/* 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);
|
store(p->r2, &sv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
l = loc;
|
|
||||||
saved = 1;
|
saved = 1;
|
||||||
}
|
}
|
||||||
/* mark that stack entry as being saved on the stack */
|
/* mark that stack entry as being saved on the stack */
|
||||||
@ -1134,6 +1143,56 @@ ST_FUNC int get_reg(int rc)
|
|||||||
return -1;
|
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
|
/* move register 's' (of type 't') to 'r', and flush previous value of r to memory
|
||||||
if needed */
|
if needed */
|
||||||
static void move_reg(int r, int s, int t)
|
static void move_reg(int r, int s, int t)
|
||||||
@ -7169,6 +7228,7 @@ static void gen_function(Sym *sym)
|
|||||||
gfunc_prolog(&sym->type);
|
gfunc_prolog(&sym->type);
|
||||||
local_scope = 0;
|
local_scope = 0;
|
||||||
rsym = 0;
|
rsym = 0;
|
||||||
|
clear_temp_local_var_list();
|
||||||
block(NULL, NULL, 0);
|
block(NULL, NULL, 0);
|
||||||
if (!(nocode_wanted & 0x20000000)
|
if (!(nocode_wanted & 0x20000000)
|
||||||
&& ((func_vt.t & VT_BTYPE) == VT_INT)
|
&& ((func_vt.t & VT_BTYPE) == VT_INT)
|
||||||
|
Loading…
Reference in New Issue
Block a user