[qfcc] Use auxiliary operands for move instructions

Since Ruamoko progs must use lea to get the address of a local variable,
add use/def/kill references to the move instruction in order to inform
flow analysis of the variable since it is otherwise lost via the
resulting pointer (not an issue when direct var reference move can be
used).

The test and digging for the def can probably do with being more
aggressive, but this did nicely as a proof of concept.
This commit is contained in:
Bill Currie 2022-01-29 18:24:16 +09:00
parent f853a449b8
commit fbaf1456fe
3 changed files with 39 additions and 0 deletions

View file

@ -629,6 +629,14 @@ int expr_integral (expr_t *e) __attribute__((pure));
*/
int is_constant (expr_t *e) __attribute__((pure));
/** Check if the expression refers to a variable.
\param e The expression to check.
\return True if the expression refers to a variable (def
expression, var symbol expression, or temp expression).
*/
int is_variable (expr_t *e) __attribute__((pure));
/** Check if the expression refers to a selector
\param e The expression to check.

View file

@ -956,6 +956,20 @@ is_constant (expr_t *e)
return 0;
}
int
is_variable (expr_t *e)
{
while (e->type == ex_alias) {
e = e->e.alias.expr;
}
if (e->type == ex_def
|| (e->type == ex_symbol && e->e.symbol->sy_type == sy_var)
|| e->type == ex_temp) {
return 1;
}
return 0;
}
int
is_selector (expr_t *e)
{

View file

@ -827,6 +827,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
const char *opcode;
int need_ptr = 0;
st_type_t type = st_move;
operand_t *use = 0;
operand_t *def = 0;
operand_t *kill = 0;
if ((src && src->op_type == op_nil) || src_expr->type == ex_nil) {
// switch to memset because nil is type agnostic 0 and structures
@ -859,6 +862,11 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
*op = src;
}
if (is_indirect (dst_expr)) {
if (is_variable (src_expr)) {
// FIXME this probably needs to be more agressive
// shouldn't emit code...
sblock = statement_subexpr (sblock, src_expr, &use);
}
src = operand_address (src, src_expr);
need_ptr = 1;
}
@ -867,6 +875,12 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
// dst_expr and/or src_expr are dereferenced pointers, so need to
// un-dereference dst_expr to get the pointer and switch to movep
// or memsetp instructions.
if (is_variable (dst_expr)) {
// FIXME this probably needs to be more agressive
// shouldn't emit code...
sblock = statement_subexpr (sblock, dst_expr, &def);
sblock = statement_subexpr (sblock, dst_expr, &kill);
}
dst_expr = expr_file_line (address_expr (dst_expr, 0), e);
need_ptr = 1;
}
@ -895,6 +909,9 @@ expr_assign_copy (sblock_t *sblock, expr_t *e, operand_t **op, operand_t *src)
s->opa = src;
s->opb = size;
s->opc = dst;
s->use = use;
s->def = def;
s->kill = kill;
sblock_add_statement (sblock, s);
return sblock;
}