mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-27 14:12:36 +00:00
factoring out temp-slot-assignment and using it for the declared locals too, makes -Olocal-temps more effective
This commit is contained in:
parent
b42328dbc6
commit
1cca992a8e
1 changed files with 59 additions and 39 deletions
98
ir.c
98
ir.c
|
@ -2133,11 +2133,13 @@ typedef struct {
|
||||||
bool *unique;
|
bool *unique;
|
||||||
} function_allocator;
|
} function_allocator;
|
||||||
|
|
||||||
static bool function_allocator_alloc(function_allocator *alloc, const ir_value *var)
|
static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
|
||||||
{
|
{
|
||||||
ir_value *slot;
|
ir_value *slot;
|
||||||
size_t vsize = ir_value_sizeof(var);
|
size_t vsize = ir_value_sizeof(var);
|
||||||
|
|
||||||
|
var->code.local = vec_size(alloc->locals);
|
||||||
|
|
||||||
slot = ir_value_var("reg", store_global, var->vtype);
|
slot = ir_value_var("reg", store_global, var->vtype);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2156,13 +2158,54 @@ localerror:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ir_function_allocator_assign(ir_function *self, function_allocator *alloc, ir_value *v)
|
||||||
|
{
|
||||||
|
size_t a;
|
||||||
|
ir_value *slot;
|
||||||
|
|
||||||
|
for (a = 0; a < vec_size(alloc->locals); ++a)
|
||||||
|
{
|
||||||
|
/* if it's reserved for a unique liferange: skip */
|
||||||
|
if (alloc->unique[a])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
slot = alloc->locals[a];
|
||||||
|
|
||||||
|
/* never resize parameters
|
||||||
|
* will be required later when overlapping temps + locals
|
||||||
|
*/
|
||||||
|
if (a < vec_size(self->params) &&
|
||||||
|
alloc->sizes[a] < ir_value_sizeof(v))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ir_values_overlap(v, slot))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!ir_value_life_merge_into(slot, v))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* adjust size for this slot */
|
||||||
|
if (alloc->sizes[a] < ir_value_sizeof(v))
|
||||||
|
alloc->sizes[a] = ir_value_sizeof(v);
|
||||||
|
|
||||||
|
v->code.local = a;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (a >= vec_size(alloc->locals)) {
|
||||||
|
if (!function_allocator_alloc(alloc, v))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ir_function_allocate_locals(ir_function *self)
|
bool ir_function_allocate_locals(ir_function *self)
|
||||||
{
|
{
|
||||||
size_t i, a;
|
size_t i;
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
ir_value *slot;
|
|
||||||
ir_value *v;
|
ir_value *v;
|
||||||
|
|
||||||
function_allocator alloc;
|
function_allocator alloc;
|
||||||
|
@ -2179,9 +2222,19 @@ bool ir_function_allocate_locals(ir_function *self)
|
||||||
{
|
{
|
||||||
if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS))
|
if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS))
|
||||||
self->locals[i]->unique_life = true;
|
self->locals[i]->unique_life = true;
|
||||||
|
else if (i >= vec_size(self->params))
|
||||||
|
break;
|
||||||
if (!function_allocator_alloc(&alloc, self->locals[i]))
|
if (!function_allocator_alloc(&alloc, self->locals[i]))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
for (; i < vec_size(self->locals); ++i)
|
||||||
|
{
|
||||||
|
v = self->locals[i];
|
||||||
|
if (!vec_size(v->life))
|
||||||
|
continue;
|
||||||
|
if (!ir_function_allocator_assign(self, &alloc, v))
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate a slot for any value that still exists */
|
/* Allocate a slot for any value that still exists */
|
||||||
for (i = 0; i < vec_size(self->values); ++i)
|
for (i = 0; i < vec_size(self->values); ++i)
|
||||||
|
@ -2233,41 +2286,8 @@ bool ir_function_allocate_locals(ir_function *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (a = 0; a < vec_size(alloc.locals); ++a)
|
if (!ir_function_allocator_assign(self, &alloc, v))
|
||||||
{
|
goto error;
|
||||||
/* if it's reserved for a unique liferange: skip */
|
|
||||||
if (alloc.unique[a])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
slot = alloc.locals[a];
|
|
||||||
|
|
||||||
/* never resize parameters
|
|
||||||
* will be required later when overlapping temps + locals
|
|
||||||
*/
|
|
||||||
if (a < vec_size(self->params) &&
|
|
||||||
alloc.sizes[a] < ir_value_sizeof(v))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ir_values_overlap(v, slot))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!ir_value_life_merge_into(slot, v))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
/* adjust size for this slot */
|
|
||||||
if (alloc.sizes[a] < ir_value_sizeof(v))
|
|
||||||
alloc.sizes[a] = ir_value_sizeof(v);
|
|
||||||
|
|
||||||
self->values[i]->code.local = a;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (a >= vec_size(alloc.locals)) {
|
|
||||||
self->values[i]->code.local = vec_size(alloc.locals);
|
|
||||||
if (!function_allocator_alloc(&alloc, v))
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!alloc.sizes) {
|
if (!alloc.sizes) {
|
||||||
|
@ -2291,7 +2311,7 @@ bool ir_function_allocate_locals(ir_function *self)
|
||||||
|
|
||||||
/* Locals need to know their new position */
|
/* Locals need to know their new position */
|
||||||
for (i = 0; i < vec_size(self->locals); ++i) {
|
for (i = 0; i < vec_size(self->locals); ++i) {
|
||||||
self->locals[i]->code.local = alloc.positions[i];
|
self->locals[i]->code.local = alloc.positions[self->locals[i]->code.local];
|
||||||
}
|
}
|
||||||
/* Take over the actual slot positions on values */
|
/* Take over the actual slot positions on values */
|
||||||
for (i = 0; i < vec_size(self->values); ++i) {
|
for (i = 0; i < vec_size(self->values); ++i) {
|
||||||
|
|
Loading…
Reference in a new issue