X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ir.c;h=8aef17ff6258743b328c0f1f92e615cbcf4489ca;hb=debfe136a59968b250e7d57ac5d6f397c404bfb6;hp=9f76892f67af0cd3be1c0015c3e4957127a1dd86;hpb=2b1eaa6df3e29b19d79b66db7333dfe635580a60;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index 9f76892..8aef17f 100644 --- a/ir.c +++ b/ir.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 + * Copyright (C) 2012, 2013 * Wolfgang Bumiller * * Permission is hereby granted, free of charge, to any person obtaining a copy of @@ -44,7 +44,8 @@ const char *type_name[TYPE_COUNT] = { "union", "array", - "nil" + "nil", + "" }; size_t type_sizeof_[TYPE_COUNT] = { @@ -62,6 +63,7 @@ size_t type_sizeof_[TYPE_COUNT] = { 0, /* TYPE_UNION */ 0, /* TYPE_ARRAY */ 0, /* TYPE_NIL */ + 0, /* TYPE_NOESPR */ }; uint16_t type_store_instr[TYPE_COUNT] = { @@ -85,6 +87,7 @@ uint16_t type_store_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; uint16_t field_store_instr[TYPE_COUNT] = { @@ -108,6 +111,7 @@ uint16_t field_store_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; uint16_t type_storep_instr[TYPE_COUNT] = { @@ -131,6 +135,7 @@ uint16_t type_storep_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; uint16_t type_eq_instr[TYPE_COUNT] = { @@ -154,6 +159,7 @@ uint16_t type_eq_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; uint16_t type_ne_instr[TYPE_COUNT] = { @@ -177,6 +183,7 @@ uint16_t type_ne_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; uint16_t type_not_instr[TYPE_COUNT] = { @@ -200,6 +207,7 @@ uint16_t type_not_instr[TYPE_COUNT] = { AINSTR_END, /* union */ AINSTR_END, /* array */ AINSTR_END, /* nil */ + AINSTR_END, /* noexpr */ }; /* protos */ @@ -1905,26 +1913,6 @@ bool ir_function_naive_phi(ir_function *self) return true; } -#if 0 -static bool 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 */ - if (!ir_block_create_store(block, old, what)) - return false; - - /* we now move it up */ - instr = vec_last(block->instr); - for (i = vec_size(block->instr)-1; i > iid; --i) - block->instr[i] = block->instr[i-1]; - block->instr[i] = instr; - - return true; -} -#endif - static bool ir_block_naive_phi(ir_block *self) { size_t i, p; /*, w;*/ @@ -1967,58 +1955,6 @@ static bool ir_block_naive_phi(ir_block *self) vec_push(b->instr, prevjump); b->final = true; } - -#if 0 - ir_value *v = instr->phi[p].value; - for (w = 0; w < vec_size(v->writes); ++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 != store_value && old->store != store_local && old->store != store_param) - { - /* If it originally wrote to a global we need to store the value - * there as welli - */ - if (!ir_naive_phi_emit_store(self, i+1, old, v)) - return false; - if (i+1 < vec_size(self->instr)) - 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 < vec_size(old->reads); ++r) - { - size_t op; - ir_instr *ri = old->reads[r]; - for (op = 0; op < vec_size(ri->phi); ++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; - } - } - } - } -#endif } ir_instr_delete(instr); } @@ -2184,6 +2120,9 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * size_t a; ir_value *slot; + if (v->unique_life) + return function_allocator_alloc(alloc, v); + for (a = 0; a < vec_size(alloc->locals); ++a) { /* if it's reserved for a unique liferange: skip */ @@ -2221,6 +2160,16 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * return true; } +static bool ir_value_has_point_life(const ir_value *v) +{ + size_t i, vs = vec_size(v->life); + for (i = 0; i < vs; ++i) { + if (v->life[i].start == v->life[i].end) + return true; + } + return false; +} + bool ir_function_allocate_locals(ir_function *self) { size_t i; @@ -2247,6 +2196,8 @@ bool ir_function_allocate_locals(ir_function *self) for (i = 0; i < vec_size(self->locals); ++i) { v = self->locals[i]; + if (ir_value_has_point_life(v)) + v->unique_life = true; if (!OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) { v->locked = true; v->unique_life = true; @@ -2255,7 +2206,7 @@ bool ir_function_allocate_locals(ir_function *self) break; else v->locked = true; /* lock parameters locals */ - if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), self->locals[i])) + if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } for (; i < vec_size(self->locals); ++i) @@ -2263,6 +2214,8 @@ bool ir_function_allocate_locals(ir_function *self) v = self->locals[i]; if (!vec_size(v->life)) continue; + if (ir_value_has_point_life(v)) + v->unique_life = true; if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } @@ -2274,6 +2227,15 @@ bool ir_function_allocate_locals(ir_function *self) if (!vec_size(v->life)) continue; + if (ir_value_has_point_life(v)) { + /* happens on free ternarys like: + if (x) { + cond ? a : b; + } + irerror(v->context, "internal error: point life SSA value leaked: %s", v->name); + */ + v->unique_life = true; + } /* CALL optimization: * If the value is a parameter-temp: 1 write, 1 read from a CALL @@ -2449,9 +2411,10 @@ static bool ir_block_living_lock(ir_block *self) bool changed = false; for (i = 0; i != vec_size(self->living); ++i) { - if (!self->living[i]->locked) + if (!self->living[i]->locked) { + self->living[i]->locked = true; changed = true; - self->living[i]->locked = true; + } } return changed; } @@ -2876,7 +2839,7 @@ tailcall: if (onfalse->generated) { /* fixup the jump address */ code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx); - if (code_statements[stidx].o2.s1 == 1) { + if (stidx+2 == vec_size(code_statements) && code_statements[stidx].o2.s1 == 1) { code_statements[stidx] = code_statements[stidx+1]; if (code_statements[stidx].o1.s1 < 0) code_statements[stidx].o1.s1++; @@ -2901,7 +2864,7 @@ tailcall: code_push_statement(&stmt, instr->context.line); return true; } - else if (code_statements[stidx].o2.s1 == 1) { + else if (stidx+2 == vec_size(code_statements) && code_statements[stidx].o2.s1 == 1) { code_statements[stidx] = code_statements[stidx+1]; if (code_statements[stidx].o1.s1 < 0) code_statements[stidx].o1.s1++; @@ -3794,7 +3757,9 @@ void ir_function_dump(ir_function *f, char *ind, attr = "unique "; else if (v->locked) attr = "locked "; - oprintf("%s\t%s: %s %s@%i ", ind, v->name, type_name[v->vtype], attr, (int)v->code.local); + oprintf("%s\t%s: %s %s%s@%i ", ind, v->name, type_name[v->vtype], + attr, (v->callparam ? "callparam " : ""), + (int)v->code.local); for (l = 0; l < vec_size(v->life); ++l) { oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); } @@ -3826,7 +3791,9 @@ void ir_function_dump(ir_function *f, char *ind, attr = "unique "; else if (v->locked) attr = "locked "; - oprintf("%s\t%s: %s %s@%i ", ind, v->name, type_name[v->vtype], attr, (int)v->code.local); + oprintf("%s\t%s: %s %s%s@%i ", ind, v->name, type_name[v->vtype], + attr, (v->callparam ? "callparam " : ""), + (int)v->code.local); for (l = 0; l < vec_size(v->life); ++l) { oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); }