static bool ir_block_life_propagate(ir_block *b, ir_block *prev, bool *changed);
bool ir_function_calculate_liferanges(ir_function *self)
{
- size_t i;
+ size_t i, s;
bool changed;
/* parameters live at 0 */
ir_value *v = block->living[i];
if (v->store != store_local)
continue;
- if ((v->members[0] && v->members[1] && v->members[2])) {
- /* all vector members have been accessed - only treat this as uninitialized
- * if any of them is also uninitialized.
- */
- if (!vec_ir_value_find(block->living, v->members[0], NULL) &&
- !vec_ir_value_find(block->living, v->members[1], NULL) &&
- !vec_ir_value_find(block->living, v->members[2], NULL))
+ if (v->vtype == TYPE_VECTOR)
+ continue;
+ self->flags |= IR_FLAG_HAS_UNINITIALIZED;
+ /* find the instruction reading from it */
+ for (s = 0; s < vec_size(v->reads); ++s) {
+ if (v->reads[s]->eid == v->life[0].end)
+ break;
+ }
+ if (s < vec_size(v->reads)) {
+ if (irwarning(v->context, WARN_USED_UNINITIALIZED,
+ "variable `%s` may be used uninitialized in this function\n"
+ " -> %s:%i",
+ v->name,
+ v->reads[s]->context.file, v->reads[s]->context.line)
+ )
{
- continue;
+ return false;
}
+ continue;
}
if (v->memberof) {
- /* A member is only uninitialized if the whole vector is also uninitialized */
- if (!vec_ir_value_find(block->living, v->memberof, NULL))
+ ir_value *vec = v->memberof;
+ for (s = 0; s < vec_size(vec->reads); ++s) {
+ if (vec->reads[s]->eid == v->life[0].end)
+ break;
+ }
+ if (s < vec_size(vec->reads)) {
+ if (irwarning(v->context, WARN_USED_UNINITIALIZED,
+ "variable `%s` may be used uninitialized in this function\n"
+ " -> %s:%i",
+ v->name,
+ vec->reads[s]->context.file, vec->reads[s]->context.line)
+ )
+ {
+ return false;
+ }
continue;
+ }
}
- self->flags |= IR_FLAG_HAS_UNINITIALIZED;
if (irwarning(v->context, WARN_USED_UNINITIALIZED,
"variable `%s` may be used uninitialized in this function", v->name))
{
ir_instr *instr;
ir_value *value;
bool tempbool;
- size_t i, o, p;
+ size_t i, o, p, mem;
/* bitmasks which operands are read from or written to */
size_t read, write;
char dbg_ind[16] = { '#', '0' };
* and make sure it's only printed once
* since this function is run multiple times.
*/
- /* For now: debug info: */
/* con_err( "Value only written %s\n", value->name); */
tempbool = ir_value_life_merge(value, instr->eid);
*changed = *changed || tempbool;
- /*
- ir_instr_dump(instr, dbg_ind, printf);
- abort();
- */
} else {
/* since 'living' won't contain it
* anymore, merge the value, since
/* Then remove */
vec_remove(self->living, idx, 1);
}
+ /* Removing a vector removes all members */
+ for (mem = 0; mem < 3; ++mem) {
+ if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], &idx)) {
+ tempbool = ir_value_life_merge(value->members[mem], instr->eid);
+ *changed = *changed || tempbool;
+ vec_remove(self->living, idx, 1);
+ }
+ }
+ /* Removing the last member removes the vector */
+ if (value->memberof) {
+ value = value->memberof;
+ for (mem = 0; mem < 3; ++mem) {
+ if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], NULL))
+ break;
+ }
+ if (mem == 3 && vec_ir_value_find(self->living, value, &idx)) {
+ tempbool = ir_value_life_merge(value, instr->eid);
+ *changed = *changed || tempbool;
+ vec_remove(self->living, idx, 1);
+ }
+ }
}
}
{
if (!vec_ir_value_find(self->living, value, NULL))
vec_push(self->living, value);
+ /* reading adds the full vector */
+ if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+ vec_push(self->living, value->memberof);
+ for (mem = 0; mem < 3; ++mem) {
+ if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+ vec_push(self->living, value->members[mem]);
+ }
}
}
/* PHI operands are always read operands */
value = instr->phi[p].value;
if (!vec_ir_value_find(self->living, value, NULL))
vec_push(self->living, value);
+ /* reading adds the full vector */
+ if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+ vec_push(self->living, value->memberof);
+ for (mem = 0; mem < 3; ++mem) {
+ if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+ vec_push(self->living, value->members[mem]);
+ }
}
/* call params are read operands too */
value = instr->params[p];
if (!vec_ir_value_find(self->living, value, NULL))
vec_push(self->living, value);
+ /* reading adds the full vector */
+ if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL))
+ vec_push(self->living, value->memberof);
+ for (mem = 0; mem < 3; ++mem) {
+ if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL))
+ vec_push(self->living, value->members[mem]);
+ }
}
/* (A) */
}
oprintf("%sliferanges:\n", ind);
for (i = 0; i < vec_size(f->locals); ++i) {
- size_t l;
+ size_t l, m;
ir_value *v = f->locals[i];
oprintf("%s\t%s: %s@%i ", ind, v->name, (v->unique_life ? "unique " : ""), (int)v->code.local);
for (l = 0; l < vec_size(v->life); ++l) {
oprintf("[%i,%i] ", v->life[l].start, v->life[l].end);
}
oprintf("\n");
+ for (m = 0; m < 3; ++m) {
+ ir_value *vm = v->members[m];
+ if (!vm)
+ continue;
+ oprintf("%s\t%s: %s@%i ", ind, vm->name, (vm->unique_life ? "unique " : ""), (int)vm->code.local);
+ for (l = 0; l < vec_size(vm->life); ++l) {
+ oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end);
+ }
+ oprintf("\n");
+ }
}
for (i = 0; i < vec_size(f->values); ++i) {
size_t l;