From: Wolfgang (Blub) Bumiller Date: Wed, 25 Apr 2012 13:08:03 +0000 (+0200) Subject: _naive_ phi solver X-Git-Tag: 0.1-rc1~601 X-Git-Url: http://de.git.xonotic.org/?a=commitdiff_plain;h=08f6e65b1c7583199e43e47057f9125def1f82cb;p=xonotic%2Fgmqcc.git _naive_ phi solver --- diff --git a/ir.c b/ir.c index bb0008f..8c53fd4 100644 --- a/ir.c +++ b/ir.c @@ -851,3 +851,102 @@ ir_value* ir_block_create_div(ir_block *self, } return ir_block_create_binop(self, label, op, left, right); } + +/* PHI resolving breaks the SSA, and must thus be the last + * step before life-range calculation. + */ + +static void ir_block_naive_phi(ir_block *self); +void ir_function_naive_phi(ir_function *self) +{ + size_t i; + + for (i = 0; i < self->blocks_count; ++i) + ir_block_naive_phi(self->blocks[i]); +} + +static void ir_naive_phi_emit_store(ir_block *block, size_t iid, ir_value *old, ir_value *what) +{ + ir_instr *instr; + size_t i; + + /* create a store */ + ir_block_create_store(block, old, what); + + /* we now move it up */ + instr = block->instr[block->instr_count-1]; + for (i = block->instr_count; i > iid; --i) + block->instr[i] = block->instr[i-1]; + block->instr[i] = instr; +} + +static void ir_block_naive_phi(ir_block *self) +{ + size_t i, p, w; + /* FIXME: optionally, create_phi can add the phis + * to a list so we don't need to loop through blocks + * - anyway: "don't optimize YET" + */ + for (i = 0; i < self->instr_count; ++i) + { + ir_instr *instr = self->instr[i]; + if (instr->opcode != VINSTR_PHI) + continue; + + ir_block_instr_remove(self, i); + --i; /* NOTE: i+1 below */ + + for (p = 0; p < instr->phi_count; ++p) + { + ir_value *v = instr->phi[p].value; + for (w = 0; w < v->writes_count; ++w) { + ir_value *old; + + if (!v->writes[w]->_ops[0]) + continue; + + /* When the write was to a global, we have to emit a mov */ + old = v->writes[w]->_ops[0]; + + /* The original instruction now writes to the PHI target local */ + if (v->writes[w]->_ops[0] == v) + v->writes[w]->_ops[0] = instr->_ops[0]; + + if (old->store != qc_localval) + { + /* If it originally wrote to a global we need to store the value + * there as welli + */ + ir_naive_phi_emit_store(self, i+1, old, v); + if (i+1 < self->instr_count) + instr = self->instr[i+1]; + else + instr = NULL; + /* In case I forget and access instr later, it'll be NULL + * when it's a problem, to make sure we crash, rather than accessing + * invalid data. + */ + } + else + { + /* If it didn't, we can replace all reads by the phi target now. */ + size_t r; + for (r = 0; r < old->reads_count; ++r) + { + size_t op; + ir_instr *ri = old->reads[r]; + for (op = 0; op < ri->phi_count; ++op) { + if (ri->phi[op].value == old) + ri->phi[op].value = v; + } + for (op = 0; op < 3; ++op) { + if (ri->_ops[op] == old) + ri->_ops[op] = v; + } + } + } + } + } + ir_instr_delete(instr); + } +}