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:
Bill Currie 2019-06-12 00:37:02 +09:00
parent b18a744288
commit fa69aeef0f
8 changed files with 62 additions and 23 deletions

View File

@ -46,6 +46,7 @@ typedef struct flowvar_s {
struct set_s *define; ///< set of statements that define this var
struct operand_s *op; ///< an operand using this var
int number; ///< number of variable in func's ref list
int flowaddr; ///< psuedo address for local and temp vars
} flowvar_t;
typedef struct flowloop_s {

View File

@ -94,6 +94,7 @@ typedef struct function_s {
struct set_s *global_vars;///< set indicating which vars are global
struct statement_s **statements;
int num_statements;
int tmpaddr; ///< tmp var "address" for flow analysis
} function_t;
extern function_t *current_func;

View File

@ -49,6 +49,7 @@ typedef struct {
struct operand_s *alias;
struct operand_s *alias_ops;
int users;
int flowaddr; ///< "address" of temp in flow analysis, != 0
} tempop_t;
typedef struct operand_s {

View File

@ -1478,7 +1478,7 @@ fold_constants (expr_t *e)
}
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;
}

View File

@ -158,8 +158,8 @@ operand_label (dag_t *dag, operand_t *op)
return 0;
if (op->op_type == op_temp) {
while (op->o.tempop.alias)
op = op->o.tempop.alias;
//while (op->o.tempop.alias)
// op = op->o.tempop.alias;
if (op->o.tempop.daglabel)
return op->o.tempop.daglabel;
label = new_label (dag);

View File

@ -91,10 +91,18 @@ get_operand_def (expr_t *expr, operand_t *op)
zero_def.type = &type_short;
return &zero_def; //FIXME
case op_temp:
while (op->o.tempop.alias)
op = op->o.tempop.alias;
if (!op->o.tempop.def)
if (op->o.tempop.def) {
return 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);
}
return op->o.tempop.def;
case op_alias:
return get_operand_def (expr, op->o.alias);

View File

@ -204,6 +204,12 @@ flowvar_is_param (flowvar_t *var)
return 0;
return 1;
}
static int
flowvar_is_local (flowvar_t *var)
{
return !(flowvar_is_global (var) || flowvar_is_param (var));
}
#if 0
static int
flowvar_is_initialized (flowvar_t *var)
@ -263,6 +269,24 @@ count_operand (operand_t *op)
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
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->op = op;
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 ();
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
// first, add .return and .param_[0-7] as they are always needed
for (i = 0; i < num_flow_params; i++)
@ -382,27 +414,18 @@ flow_build_vars (function_t *func)
// ([num_statements ... num_statements+localsize])
// 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
// before adding the number of statements in the function:
// ([num_statements+localsize ... num_vars])
// 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
// temporary vars are pseudo allocated and their addresses are added as for
// locals
// add_operand takes care of setting flowaddr for both locals and temps
for (i = 0; i < func->num_vars; i++) {
int offset, size;
int j;
var = func->vars[i];
if (flowvar_is_global (var) || flowvar_is_param (var))
if (flowvar_is_global (var) || flowvar_is_param (var)) {
continue;
if (var->op->op_type == op_temp) {
j = func->symtab->space->size + var->number;
set_add (var->define, func->num_statements + 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);
}
for (j = 0; j < var->op->size; j++) {
set_add (var->define, var->flowaddr + j);
}
}

View File

@ -126,10 +126,11 @@ operand_string (operand_t *op)
return op->o.label->name;
case op_temp:
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],
op, op->o.tempop.users,
op->o.tempop.alias,
op->o.tempop.offset,
op->o.tempop.alias->o.tempop.users);
return va ("<tmp %s %p:%d>", pr_type_name[op->o.tempop.type->type],
op, op->o.tempop.users);
@ -307,6 +308,7 @@ def_operand (def_t *def, type_t *type)
type = def->type;
op = new_operand (op_def);
op->type = low_level_type (type);
op->size = type_size (type);
op->o.def = def;
return op;
}
@ -830,6 +832,8 @@ expr_alias (sblock_t *sblock, expr_t *e, operand_t **op)
aop = aop->o.tempop.alias;
if (aop->op_type != op_temp)
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) {
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) {
top = new_operand (op_temp);
top->type = type;
top->size = pr_type_size[type];
top->o.tempop.alias = aop;
top->o.tempop.offset = offset;
top->next = aop->o.tempop.alias_ops;