[qfcc] Set a flowvar's minimum size based on usage

But really only for memset and memmove because they need to use an int
alias of the variable and it may be only that alias that sets a much
larger variable.
This commit is contained in:
Bill Currie 2023-09-11 22:56:37 +09:00
parent 73d1044bec
commit 8ec66f118a
2 changed files with 23 additions and 1 deletions

View file

@ -49,6 +49,7 @@ typedef struct flowvar_s {
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 int flowaddr; ///< psuedo address for local and temp vars
int minsize; ///< minimum size (via memset/move)
} flowvar_t; } flowvar_t;
typedef struct udchain_s { typedef struct udchain_s {

View file

@ -572,7 +572,11 @@ clear_operand_chain (operand_t *op)
static void static void
add_var_addrs (set_t *set, flowvar_t *var) add_var_addrs (set_t *set, flowvar_t *var)
{ {
for (int i = 0; i < var->op->size; i++) { int size = var->op->size;
if (size < var->minsize) {
size = var->minsize;
}
for (int i = 0; i < size; i++) {
set_add (set, var->flowaddr + i); set_add (set, var->flowaddr + i);
} }
} }
@ -835,6 +839,17 @@ flow_add_op_var (set_t *set, operand_t *op, int ol)
} }
} }
static void
flow_set_minsize (operand_t *op, int size)
{
flowvar_t *var;
if (!(var = flow_get_var (op)))
return;
if (var->minsize < size) {
var->minsize = size;
}
}
static void static void
flow_add_op_var_size (set_t *set, operand_t *op, int size, int ol) flow_add_op_var_size (set_t *set, operand_t *op, int size, int ol)
{ {
@ -1605,6 +1620,12 @@ flow_analyze_statement (statement_t *s, set_t *use, set_t *def, set_t *kill,
print_type (s->opb->type); print_type (s->opb->type);
internal_error (s->expr, "unexpected type for memset/move"); internal_error (s->expr, "unexpected type for memset/move");
} }
if (s->type == st_move) {
flow_set_minsize (s->opa, size);
}
if (s->type == st_move || s->type == st_memset) {
flow_set_minsize (s->opc, size);
}
} else { } else {
size = -1; size = -1;
} }