mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-19 07:20:50 +00:00
Improve handling of temp aliases
This makes all tests pass when not optimizing. More work needs to be done in dags.
This commit is contained in:
parent
b18a744288
commit
fa69aeef0f
8 changed files with 62 additions and 23 deletions
|
@ -46,6 +46,7 @@ typedef struct flowvar_s {
|
||||||
struct set_s *define; ///< set of statements that define this var
|
struct set_s *define; ///< set of statements that define this var
|
||||||
struct operand_s *op; ///< an operand using this var
|
struct operand_s *op; ///< an operand using this var
|
||||||
int number; ///< number of variable in func's ref list
|
int number; ///< number of variable in func's ref list
|
||||||
|
int flowaddr; ///< psuedo address for local and temp vars
|
||||||
} flowvar_t;
|
} flowvar_t;
|
||||||
|
|
||||||
typedef struct flowloop_s {
|
typedef struct flowloop_s {
|
||||||
|
|
|
@ -94,6 +94,7 @@ typedef struct function_s {
|
||||||
struct set_s *global_vars;///< set indicating which vars are global
|
struct set_s *global_vars;///< set indicating which vars are global
|
||||||
struct statement_s **statements;
|
struct statement_s **statements;
|
||||||
int num_statements;
|
int num_statements;
|
||||||
|
int tmpaddr; ///< tmp var "address" for flow analysis
|
||||||
} function_t;
|
} function_t;
|
||||||
|
|
||||||
extern function_t *current_func;
|
extern function_t *current_func;
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct {
|
||||||
struct operand_s *alias;
|
struct operand_s *alias;
|
||||||
struct operand_s *alias_ops;
|
struct operand_s *alias_ops;
|
||||||
int users;
|
int users;
|
||||||
|
int flowaddr; ///< "address" of temp in flow analysis, != 0
|
||||||
} tempop_t;
|
} tempop_t;
|
||||||
|
|
||||||
typedef struct operand_s {
|
typedef struct operand_s {
|
||||||
|
|
|
@ -1478,7 +1478,7 @@ fold_constants (expr_t *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
op = e->e.expr.op;
|
op = e->e.expr.op;
|
||||||
if (op == 'i' || op == 'n' || op == 'c' || op == 's') {
|
if (op == 'A' || op == 'i' || op == 'n' || op == 'c' || op == 's') {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,8 +158,8 @@ operand_label (dag_t *dag, operand_t *op)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (op->op_type == op_temp) {
|
if (op->op_type == op_temp) {
|
||||||
while (op->o.tempop.alias)
|
//while (op->o.tempop.alias)
|
||||||
op = op->o.tempop.alias;
|
// op = op->o.tempop.alias;
|
||||||
if (op->o.tempop.daglabel)
|
if (op->o.tempop.daglabel)
|
||||||
return op->o.tempop.daglabel;
|
return op->o.tempop.daglabel;
|
||||||
label = new_label (dag);
|
label = new_label (dag);
|
||||||
|
|
|
@ -91,10 +91,18 @@ get_operand_def (expr_t *expr, operand_t *op)
|
||||||
zero_def.type = &type_short;
|
zero_def.type = &type_short;
|
||||||
return &zero_def; //FIXME
|
return &zero_def; //FIXME
|
||||||
case op_temp:
|
case op_temp:
|
||||||
while (op->o.tempop.alias)
|
if (op->o.tempop.def) {
|
||||||
op = op->o.tempop.alias;
|
return op->o.tempop.def;
|
||||||
if (!op->o.tempop.def)
|
}
|
||||||
|
if (op->o.tempop.alias) {
|
||||||
|
def_t *tdef = get_operand_def (expr, op->o.tempop.alias);
|
||||||
|
int offset = op->o.tempop.offset;
|
||||||
|
type_t *type = ev_types[op->type];
|
||||||
|
op->o.tempop.def = alias_def (tdef, type, offset);
|
||||||
|
}
|
||||||
|
if (!op->o.tempop.def) {
|
||||||
op->o.tempop.def = temp_def (op->type, op->size);
|
op->o.tempop.def = temp_def (op->type, op->size);
|
||||||
|
}
|
||||||
return op->o.tempop.def;
|
return op->o.tempop.def;
|
||||||
case op_alias:
|
case op_alias:
|
||||||
return get_operand_def (expr, op->o.alias);
|
return get_operand_def (expr, op->o.alias);
|
||||||
|
|
|
@ -204,6 +204,12 @@ flowvar_is_param (flowvar_t *var)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
flowvar_is_local (flowvar_t *var)
|
||||||
|
{
|
||||||
|
return !(flowvar_is_global (var) || flowvar_is_param (var));
|
||||||
|
}
|
||||||
#if 0
|
#if 0
|
||||||
static int
|
static int
|
||||||
flowvar_is_initialized (flowvar_t *var)
|
flowvar_is_initialized (flowvar_t *var)
|
||||||
|
@ -263,6 +269,24 @@ count_operand (operand_t *op)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_temp_address (function_t *func, operand_t *op)
|
||||||
|
{
|
||||||
|
operand_t *top = op;
|
||||||
|
if (op->o.tempop.flowaddr) {
|
||||||
|
return op->o.tempop.flowaddr;
|
||||||
|
}
|
||||||
|
while (top->o.tempop.alias) {
|
||||||
|
top = top->o.tempop.alias;
|
||||||
|
}
|
||||||
|
if (!top->o.tempop.flowaddr) {
|
||||||
|
top->o.tempop.flowaddr = func->tmpaddr;
|
||||||
|
func->tmpaddr += top->size;
|
||||||
|
}
|
||||||
|
op->o.tempop.flowaddr = top->o.tempop.flowaddr + op->o.tempop.offset;
|
||||||
|
return op->o.tempop.flowaddr;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_operand (function_t *func, operand_t *op)
|
add_operand (function_t *func, operand_t *op)
|
||||||
{
|
{
|
||||||
|
@ -280,6 +304,11 @@ add_operand (function_t *func, operand_t *op)
|
||||||
var->number = func->num_vars++;
|
var->number = func->num_vars++;
|
||||||
var->op = op;
|
var->op = op;
|
||||||
func->vars[var->number] = var;
|
func->vars[var->number] = var;
|
||||||
|
if (op->op_type == op_temp) {
|
||||||
|
var->flowaddr = get_temp_address (func, op);
|
||||||
|
} else if (flowvar_is_local (var)) {
|
||||||
|
var->flowaddr = func->num_statements + def_offset (var->op->o.def);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +377,9 @@ flow_build_vars (function_t *func)
|
||||||
stuse = set_new ();
|
stuse = set_new ();
|
||||||
stdef = set_new ();
|
stdef = set_new ();
|
||||||
|
|
||||||
|
// set up pseudo address space for temp vars so accessing tmp vars
|
||||||
|
// though aliases analyses correctly
|
||||||
|
func->tmpaddr = func->num_statements + func->symtab->space->size;
|
||||||
func->num_vars = 0; // incremented by add_operand
|
func->num_vars = 0; // incremented by add_operand
|
||||||
// first, add .return and .param_[0-7] as they are always needed
|
// first, add .return and .param_[0-7] as they are always needed
|
||||||
for (i = 0; i < num_flow_params; i++)
|
for (i = 0; i < num_flow_params; i++)
|
||||||
|
@ -382,27 +414,18 @@ flow_build_vars (function_t *func)
|
||||||
// ([num_statements ... num_statements+localsize])
|
// ([num_statements ... num_statements+localsize])
|
||||||
// with a set element for each def used in the local space
|
// with a set element for each def used in the local space
|
||||||
//
|
//
|
||||||
// temporary vars add their var number to the size of the local space
|
// temporary vars are pseudo allocated and their addresses are added as for
|
||||||
// before adding the number of statements in the function:
|
// locals
|
||||||
// ([num_statements+localsize ... num_vars])
|
// add_operand takes care of setting flowaddr for both locals and temps
|
||||||
// temporary vars are always accessed as a full var, so only one set
|
|
||||||
// element per temporary var is needed. This can lead to holes in the
|
|
||||||
// temporary var set element space, but it does keep things simple
|
|
||||||
for (i = 0; i < func->num_vars; i++) {
|
for (i = 0; i < func->num_vars; i++) {
|
||||||
int offset, size;
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
var = func->vars[i];
|
var = func->vars[i];
|
||||||
if (flowvar_is_global (var) || flowvar_is_param (var))
|
if (flowvar_is_global (var) || flowvar_is_param (var)) {
|
||||||
continue;
|
continue;
|
||||||
if (var->op->op_type == op_temp) {
|
}
|
||||||
j = func->symtab->space->size + var->number;
|
for (j = 0; j < var->op->size; j++) {
|
||||||
set_add (var->define, func->num_statements + j);
|
set_add (var->define, var->flowaddr + j);
|
||||||
} else {
|
|
||||||
offset = def_offset (var->op->o.def);
|
|
||||||
size = def_size (var->op->o.def);
|
|
||||||
for (j = offset; j < offset + size; j++)
|
|
||||||
set_add (var->define, func->num_statements + j);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,10 +126,11 @@ operand_string (operand_t *op)
|
||||||
return op->o.label->name;
|
return op->o.label->name;
|
||||||
case op_temp:
|
case op_temp:
|
||||||
if (op->o.tempop.alias)
|
if (op->o.tempop.alias)
|
||||||
return va ("<tmp %s %p:%d:%p:%d>",
|
return va ("<tmp %s %p:%d:%p:%d:%d>",
|
||||||
pr_type_name[op->type],
|
pr_type_name[op->type],
|
||||||
op, op->o.tempop.users,
|
op, op->o.tempop.users,
|
||||||
op->o.tempop.alias,
|
op->o.tempop.alias,
|
||||||
|
op->o.tempop.offset,
|
||||||
op->o.tempop.alias->o.tempop.users);
|
op->o.tempop.alias->o.tempop.users);
|
||||||
return va ("<tmp %s %p:%d>", pr_type_name[op->o.tempop.type->type],
|
return va ("<tmp %s %p:%d>", pr_type_name[op->o.tempop.type->type],
|
||||||
op, op->o.tempop.users);
|
op, op->o.tempop.users);
|
||||||
|
@ -307,6 +308,7 @@ def_operand (def_t *def, type_t *type)
|
||||||
type = def->type;
|
type = def->type;
|
||||||
op = new_operand (op_def);
|
op = new_operand (op_def);
|
||||||
op->type = low_level_type (type);
|
op->type = low_level_type (type);
|
||||||
|
op->size = type_size (type);
|
||||||
op->o.def = def;
|
op->o.def = def;
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
@ -830,6 +832,8 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
aop = aop->o.tempop.alias;
|
aop = aop->o.tempop.alias;
|
||||||
if (aop->op_type != op_temp)
|
if (aop->op_type != op_temp)
|
||||||
internal_error (e, "temp alias of non-temp var");
|
internal_error (e, "temp alias of non-temp var");
|
||||||
|
if (aop->o.tempop.alias)
|
||||||
|
bug (e, "aliased temp alias");
|
||||||
}
|
}
|
||||||
for (top = aop->o.tempop.alias_ops; top; top = top->next) {
|
for (top = aop->o.tempop.alias_ops; top; top = top->next) {
|
||||||
if (top->type == type && top->o.tempop.offset == offset) {
|
if (top->type == type && top->o.tempop.offset == offset) {
|
||||||
|
@ -839,6 +843,7 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
|
||||||
if (!top) {
|
if (!top) {
|
||||||
top = new_operand (op_temp);
|
top = new_operand (op_temp);
|
||||||
top->type = type;
|
top->type = type;
|
||||||
|
top->size = pr_type_size[type];
|
||||||
top->o.tempop.alias = aop;
|
top->o.tempop.alias = aop;
|
||||||
top->o.tempop.offset = offset;
|
top->o.tempop.offset = offset;
|
||||||
top->next = aop->o.tempop.alias_ops;
|
top->next = aop->o.tempop.alias_ops;
|
||||||
|
|
Loading…
Reference in a new issue