From: Wolfgang Bumiller Date: Wed, 26 Dec 2012 22:18:45 +0000 (+0100) Subject: -Oglobal-temps X-Git-Tag: before-library~479 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=d4483bfda63dac509144741c1f0e11d68d989b66 -Oglobal-temps --- diff --git a/ast.c b/ast.c index 1a686de..b6a8a78 100644 --- a/ast.c +++ b/ast.c @@ -1169,6 +1169,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) } v->context = ast_ctx(self); v->unique_life = true; + v->locked = true; array->ir_v = self->ir_v = v; namelen = strlen(self->name); @@ -1187,6 +1188,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) } array->ir_values[ai]->context = ast_ctx(self); array->ir_values[ai]->unique_life = true; + array->ir_values[ai]->locked = true; } mem_d(name); } @@ -1220,6 +1222,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) } v->context = ast_ctx(self); v->unique_life = true; + v->locked = true; namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); @@ -1237,6 +1240,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield) } self->ir_values[ai]->context = ast_ctx(self); self->ir_values[ai]->unique_life = true; + self->ir_values[ai]->locked = true; } mem_d(name); } @@ -1350,6 +1354,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param) } v->context = ast_ctx(self); v->unique_life = true; + v->locked = true; namelen = strlen(self->name); name = (char*)mem_a(namelen + 16); @@ -1365,6 +1370,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func, bool param) } self->ir_values[ai]->context = ast_ctx(self); self->ir_values[ai]->unique_life = true; + self->ir_values[ai]->locked = true; } } else diff --git a/ir.c b/ir.c index 6145c07..e9a7352 100644 --- a/ir.c +++ b/ir.c @@ -288,7 +288,10 @@ ir_builder* ir_builder_new(const char *modulename) self->extparams = NULL; self->extparam_protos = NULL; - self->max_locals = 0; + self->first_common_globaltemp = 0; + self->max_globaltemps = 0; + self->first_common_local = 0; + self->max_locals = 0; self->str_immediate = 0; self->name = NULL; @@ -454,6 +457,7 @@ ir_function* ir_function_new(ir_builder* owner, int outtype) self->code_function_def = -1; self->allocated_locals = 0; + self->globaltemps = 0; self->run_id = 0; return self; @@ -800,6 +804,8 @@ ir_value* ir_function_create_local(ir_function *self, const char *name, int vtyp } ve = ir_value_var(name, (param ? store_param : store_local), vtype); + if (param) + ve->locked = true; vec_push(self->locals, ve); return ve; } @@ -2205,26 +2211,36 @@ bool ir_function_allocate_locals(ir_function *self) size_t i; bool retval = true; size_t pos; + bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS); ir_value *v; - function_allocator alloc; + function_allocator lockalloc, globalloc; if (!vec_size(self->locals) && !vec_size(self->values)) return true; - alloc.locals = NULL; - alloc.sizes = NULL; - alloc.positions = NULL; - alloc.unique = NULL; + globalloc.locals = NULL; + globalloc.sizes = NULL; + globalloc.positions = NULL; + globalloc.unique = NULL; + lockalloc.locals = NULL; + lockalloc.sizes = NULL; + lockalloc.positions = NULL; + lockalloc.unique = NULL; for (i = 0; i < vec_size(self->locals); ++i) { - if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) - self->locals[i]->unique_life = true; + v = self->locals[i]; + if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) { + v->locked = true; + v->unique_life = true; + } else if (i >= vec_size(self->params)) break; - if (!function_allocator_alloc(&alloc, self->locals[i])) + else + v->locked = true; /* lock parameters locals */ + if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), self->locals[i])) goto error; } for (; i < vec_size(self->locals); ++i) @@ -2232,7 +2248,7 @@ bool ir_function_allocate_locals(ir_function *self) v = self->locals[i]; if (!vec_size(v->life)) continue; - if (!ir_function_allocator_assign(self, &alloc, v)) + if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } @@ -2248,7 +2264,7 @@ bool ir_function_allocate_locals(ir_function *self) * If the value is a parameter-temp: 1 write, 1 read from a CALL * and it's not "locked", write it to the OFS_PARM directly. */ - if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked) { + if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked && !v->unique_life) { if (vec_size(v->reads) == 1 && vec_size(v->writes) == 1 && (v->reads[0]->opcode == VINSTR_NRCALL || (v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8) @@ -2286,36 +2302,55 @@ bool ir_function_allocate_locals(ir_function *self) } } - if (!ir_function_allocator_assign(self, &alloc, v)) + if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } - if (!alloc.sizes) { + if (!lockalloc.sizes && !globalloc.sizes) { goto cleanup; } + vec_push(lockalloc.positions, 0); + vec_push(globalloc.positions, 0); /* Adjust slot positions based on sizes */ - vec_push(alloc.positions, 0); - - if (vec_size(alloc.sizes)) - pos = alloc.positions[0] + alloc.sizes[0]; - else - pos = 0; - for (i = 1; i < vec_size(alloc.sizes); ++i) - { - pos = alloc.positions[i-1] + alloc.sizes[i-1]; - vec_push(alloc.positions, pos); + if (lockalloc.sizes) { + pos = (vec_size(lockalloc.sizes) ? (lockalloc.positions[0] + lockalloc.sizes[0]) : 0); + for (i = 1; i < vec_size(lockalloc.sizes); ++i) + { + pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1]; + vec_push(lockalloc.positions, pos); + } + self->allocated_locals = pos + vec_last(lockalloc.sizes); + } + if (globalloc.sizes) { + pos = (vec_size(globalloc.sizes) ? (globalloc.positions[0] + globalloc.sizes[0]) : 0); + for (i = 1; i < vec_size(globalloc.sizes); ++i) + { + pos = globalloc.positions[i-1] + globalloc.sizes[i-1]; + vec_push(globalloc.positions, pos); + } + self->globaltemps = pos + vec_last(globalloc.sizes); } - - self->allocated_locals = pos + vec_last(alloc.sizes); /* Locals need to know their new position */ for (i = 0; i < vec_size(self->locals); ++i) { - self->locals[i]->code.local = alloc.positions[self->locals[i]->code.local]; + v = self->locals[i]; + if (i >= vec_size(self->params) && !vec_size(v->life)) + continue; + if (v->locked || !opt_gt) + v->code.local = lockalloc.positions[v->code.local]; + else + v->code.local = globalloc.positions[v->code.local]; } /* Take over the actual slot positions on values */ for (i = 0; i < vec_size(self->values); ++i) { - self->values[i]->code.local = alloc.positions[self->values[i]->code.local]; + v = self->values[i]; + if (!vec_size(v->life)) + continue; + if (v->locked || !opt_gt) + v->code.local = lockalloc.positions[v->code.local]; + else + v->code.local = globalloc.positions[v->code.local]; } goto cleanup; @@ -2323,12 +2358,18 @@ bool ir_function_allocate_locals(ir_function *self) error: retval = false; cleanup: - for (i = 0; i < vec_size(alloc.locals); ++i) - ir_value_delete(alloc.locals[i]); - vec_free(alloc.unique); - vec_free(alloc.locals); - vec_free(alloc.sizes); - vec_free(alloc.positions); + for (i = 0; i < vec_size(lockalloc.locals); ++i) + ir_value_delete(lockalloc.locals[i]); + for (i = 0; i < vec_size(globalloc.locals); ++i) + ir_value_delete(globalloc.locals[i]); + vec_free(globalloc.unique); + vec_free(globalloc.locals); + vec_free(globalloc.sizes); + vec_free(globalloc.positions); + vec_free(lockalloc.unique); + vec_free(lockalloc.locals); + vec_free(lockalloc.sizes); + vec_free(lockalloc.positions); return retval; } @@ -3158,7 +3199,7 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global) prog_section_function *def; ir_function *irfun; size_t i; - uint32_t firstlocal; + uint32_t firstlocal, firstglobal; irfun = global->constval.vfunc; def = code_functions + irfun->code_function_def; @@ -3170,21 +3211,31 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global) ++opts_optimizationcount[OPTIM_OVERLAP_LOCALS]; } + firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->first_common_globaltemp : firstlocal); + for (i = vec_size(code_globals); i < firstlocal + irfun->allocated_locals; ++i) vec_push(code_globals, 0); for (i = 0; i < vec_size(irfun->locals); ++i) { - ir_value_code_setaddr(irfun->locals[i], firstlocal + irfun->locals[i]->code.local); - if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { - irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name); - return false; + ir_value *v = irfun->locals[i]; + if (v->locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) { + ir_value_code_setaddr(v, firstlocal + v->code.local); + if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { + irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name); + return false; + } } + else + ir_value_code_setaddr(v, firstglobal + v->code.local); } for (i = 0; i < vec_size(irfun->values); ++i) { ir_value *v = irfun->values[i]; if (v->callparam) continue; - ir_value_code_setaddr(v, firstlocal + v->code.local); + if (v->locked) + ir_value_code_setaddr(v, firstlocal + v->code.local); + else + ir_value_code_setaddr(v, firstglobal + v->code.local); } return true; } @@ -3556,6 +3607,8 @@ bool ir_builder_generate(ir_builder *self, const char *filename) { self->max_locals = func->allocated_locals; } + if (func && self->max_globaltemps < func->globaltemps) + self->max_globaltemps = func->globaltemps; } } @@ -3566,6 +3619,11 @@ bool ir_builder_generate(ir_builder *self, const char *filename) } } + /* generate global temps */ + self->first_common_globaltemp = vec_size(code_globals); + for (i = 0; i < self->max_globaltemps; ++i) { + vec_push(code_globals, 0); + } /* generate common locals */ self->first_common_local = vec_size(code_globals); for (i = 0; i < self->max_locals; ++i) { @@ -3697,9 +3755,16 @@ void ir_function_dump(ir_function *f, char *ind, } oprintf("%sliferanges:\n", ind); for (i = 0; i < vec_size(f->locals); ++i) { + const char *attr = ""; size_t l, m; ir_value *v = f->locals[i]; - oprintf("%s\t%s: %s@%i ", ind, v->name, (v->unique_life ? "unique " : ""), (int)v->code.local); + if (v->unique_life && v->locked) + attr = "unique,locked "; + else if (v->unique_life) + attr = "unique "; + else if (v->locked) + attr = "locked "; + oprintf("%s\t%s: %s@%i ", ind, v->name, attr, (int)v->code.local); for (l = 0; l < vec_size(v->life); ++l) { oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); } @@ -3708,7 +3773,13 @@ void ir_function_dump(ir_function *f, char *ind, ir_value *vm = v->members[m]; if (!vm) continue; - oprintf("%s\t%s: %s@%i ", ind, vm->name, (vm->unique_life ? "unique " : ""), (int)vm->code.local); + if (vm->unique_life && vm->locked) + attr = "unique,locked "; + else if (vm->unique_life) + attr = "unique "; + else if (vm->locked) + attr = "locked "; + oprintf("%s\t%s: %s@%i ", ind, vm->name, attr, (int)vm->code.local); for (l = 0; l < vec_size(vm->life); ++l) { oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end); } diff --git a/ir.h b/ir.h index 6eaba3c..05b7447 100644 --- a/ir.h +++ b/ir.h @@ -252,6 +252,7 @@ typedef struct ir_function_s ir_value **locals; size_t allocated_locals; + size_t globaltemps; ir_block* first; ir_block* last; @@ -314,7 +315,9 @@ typedef struct ir_builder_s /* the highest func->allocated_locals */ size_t max_locals; + size_t max_globaltemps; uint32_t first_common_local; + uint32_t first_common_globaltemp; const char **filenames; qcint *filestrings; diff --git a/opts.def b/opts.def index 5d76039..f6582ef 100644 --- a/opts.def +++ b/opts.def @@ -81,6 +81,7 @@ #ifdef GMQCC_TYPE_OPTIMIZATIONS GMQCC_DEFINE_FLAG(PEEPHOLE, 1) GMQCC_DEFINE_FLAG(LOCAL_TEMPS, 3) + GMQCC_DEFINE_FLAG(GLOBAL_TEMPS, 3) GMQCC_DEFINE_FLAG(TAIL_RECURSION, 1) GMQCC_DEFINE_FLAG(TAIL_CALLS, 2) GMQCC_DEFINE_FLAG(OVERLAP_LOCALS, 3)