bool ir_function_finalize(ir_function *self)
{
+ size_t i;
+
if (self->builtin)
return true;
if (!ir_function_naive_phi(self))
return false;
+ for (i = 0; i < vec_size(self->locals); ++i) {
+ ir_value *v = self->locals[i];
+ if (v->vtype == TYPE_VECTOR ||
+ (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
+ {
+ ir_value_vector_member(v, 0);
+ ir_value_vector_member(v, 1);
+ ir_value_vector_member(v, 2);
+ }
+ }
+ for (i = 0; i < vec_size(self->values); ++i) {
+ ir_value *v = self->values[i];
+ if (v->vtype == TYPE_VECTOR ||
+ (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR))
+ {
+ ir_value_vector_member(v, 0);
+ ir_value_vector_member(v, 1);
+ ir_value_vector_member(v, 2);
+ }
+ }
+
ir_function_enumerate(self);
if (!ir_function_calculate_liferanges(self))
* If the value is a parameter-temp: 1 write, 1 read from a CALL
* and it's not "locked", write it to the OFS_PARM directly.
*/
- if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES)) {
- if (!v->locked && vec_size(v->reads) == 1 && vec_size(v->writes) == 1 &&
+ if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked) {
+ if (vec_size(v->reads) == 1 && vec_size(v->writes) == 1 &&
(v->reads[0]->opcode == VINSTR_NRCALL ||
(v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8)
)
goto error;
}
+ ++opts_optimizationcount[OPTIM_CALL_STORES];
v->callparam = true;
if (param < 8)
ir_value_code_setaddr(v, OFS_PARM0 + 3*param);
}
continue;
}
+ if (vec_size(v->writes) == 1 && v->writes[0]->opcode == INSTR_CALL0)
+ {
+ v->store = store_return;
+ ++opts_optimizationcount[OPTIM_CALL_STORES];
+ continue;
+ }
}
for (a = 0; a < vec_size(alloc.locals); ++a)
*
* Breaking conventions is annoying...
*/
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal, bool defs_only);
+static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal);
static bool gen_global_field(ir_value *global)
{
static bool gen_function_code(ir_function *self)
{
ir_block *block;
- prog_section_statement stmt;
+ prog_section_statement stmt, *retst;
/* Starting from entry point, we generate blocks "as they come"
* for now. Dead blocks will not be translated obviously.
}
/* code_write and qcvm -disasm need to know that the function ends here */
- stmt.opcode = INSTR_DONE;
- stmt.o1.u1 = 0;
- stmt.o2.u1 = 0;
- stmt.o3.u1 = 0;
- code_push_statement(&stmt, vec_last(code_linenums));
+ retst = &vec_last(code_statements);
+ if (OPTS_OPTIMIZATION(OPTIM_VOID_RETURN) &&
+ self->outtype == TYPE_VOID &&
+ retst->opcode == INSTR_RETURN &&
+ !retst->o1.u1 && !retst->o2.u1 && !retst->o3.u1)
+ {
+ retst->opcode = INSTR_DONE;
+ ++opts_optimizationcount[OPTIM_VOID_RETURN];
+ } else {
+ stmt.opcode = INSTR_DONE;
+ stmt.o1.u1 = 0;
+ stmt.o2.u1 = 0;
+ stmt.o3.u1 = 0;
+ code_push_statement(&stmt, vec_last(code_linenums));
+ }
return true;
}
vec_push(code_globals, 0);
for (i = 0; i < vec_size(irfun->locals); ++i) {
ir_value_code_setaddr(irfun->locals[i], firstlocal + irfun->locals[i]->code.local);
- if (!ir_builder_gen_global(ir, irfun->locals[i], true, true)) {
+ if (!ir_builder_gen_global(ir, irfun->locals[i], true)) {
irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name);
return false;
}
}
}
-static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal, bool defs_only)
+static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal)
{
size_t i;
int32_t *iptr;
prog_section_def def;
bool pushdef = false;
+ def.type = global->vtype;
+ def.offset = vec_size(code_globals);
+ def.name = 0;
if (opts.g || !islocal)
{
pushdef = true;
- def.type = global->vtype;
- def.offset = vec_size(code_globals);
if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
(global->name[0] == '#' || global->cvq == CV_CONST))
}
else
def.name = 0;
- if (defs_only) {
+ if (islocal) {
def.offset = ir_value_code_addr(global);
vec_push(code_defs, def);
if (global->vtype == TYPE_VECTOR)
return true;
}
}
- if (defs_only)
+ if (islocal)
return true;
switch (global->vtype)
case TYPE_FIELD:
if (pushdef) {
vec_push(code_defs, def);
- if (global->fieldtype == TYPE_VECTOR) {
+ if (global->fieldtype == TYPE_VECTOR)
gen_vector_defs(def, global->name);
- ir_value_vector_member(global, 0);
- ir_value_vector_member(global, 1);
- ir_value_vector_member(global, 2);
- }
}
return gen_global_field(global);
case TYPE_ENTITY:
case TYPE_VECTOR:
{
size_t d;
- ir_value_vector_member(global, 0);
- ir_value_vector_member(global, 1);
- ir_value_vector_member(global, 2);
ir_value_code_setaddr(global, vec_size(code_globals));
if (global->hasvalue) {
iptr = (int32_t*)&global->constval.ivec[0];
for (i = 0; i < vec_size(self->globals); ++i)
{
- if (!ir_builder_gen_global(self, self->globals[i], false, false)) {
+ if (!ir_builder_gen_global(self, self->globals[i], false)) {
return false;
}
if (self->globals[i]->vtype == TYPE_FUNCTION) {