From 0c3aeb30aad5b7f00044fcfb6f38ca6547c73449 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 18 Nov 2012 19:08:16 +0900 Subject: [PATCH] Reuse tempary variables. Now that I've got nice code, it was worth doing. Unfortunatly, bsearch style switch statements have problems. switch.r:14: BUG: temp users went negative: switch.r:14: BUG: temp users went negative: switch.r:14: BUG: temp users went negative: switch.r:14: BUG: temp users went negative: --- tools/qfcc/include/def.h | 1 + tools/qfcc/include/function.h | 1 + tools/qfcc/include/statements.h | 1 + tools/qfcc/source/dags.c | 5 +++++ tools/qfcc/source/def.c | 13 +++++++++++++ tools/qfcc/source/dot_dag.c | 3 ++- tools/qfcc/source/emit.c | 25 +++++++++++++++++++++---- tools/qfcc/source/flow.c | 2 +- tools/qfcc/source/statements.c | 2 +- 9 files changed, 46 insertions(+), 7 deletions(-) diff --git a/tools/qfcc/include/def.h b/tools/qfcc/include/def.h index cc53d5502..34aad90d7 100644 --- a/tools/qfcc/include/def.h +++ b/tools/qfcc/include/def.h @@ -77,6 +77,7 @@ def_t *new_def (const char *name, struct type_s *type, struct defspace_s *space, storage_class_t storage); def_t *alias_def (def_t *def, struct type_s *type); def_t *temp_def (etype_t type, int size); +void free_temp_def (def_t *temp); void free_def (def_t *def); void def_to_ddef (def_t *def, ddef_t *ddef, int aux); diff --git a/tools/qfcc/include/function.h b/tools/qfcc/include/function.h index f7f26878b..c682d0db4 100644 --- a/tools/qfcc/include/function.h +++ b/tools/qfcc/include/function.h @@ -67,6 +67,7 @@ typedef struct function_s { string_t s_file; ///< source file with definition string_t s_name; ///< name of function in output int temp_num; ///< number for next temp var + struct def_s *temp_defs[4]; ///< freed temp vars (by size) struct def_s *def; ///< output def holding function number struct symbol_s *sym; ///< internal symbol for this function /** Root scope symbol table of the function. diff --git a/tools/qfcc/include/statements.h b/tools/qfcc/include/statements.h index cdd6e9604..8c96f0823 100644 --- a/tools/qfcc/include/statements.h +++ b/tools/qfcc/include/statements.h @@ -45,6 +45,7 @@ typedef struct { struct def_s *def; struct flowvar_s *flowvar; struct daglabel_s *daglabel; + int users; } tempop_t; typedef struct operand_s { diff --git a/tools/qfcc/source/dags.c b/tools/qfcc/source/dags.c index 0402bc3ea..fc45b3746 100644 --- a/tools/qfcc/source/dags.c +++ b/tools/qfcc/source/dags.c @@ -498,6 +498,10 @@ make_operand (dag_t *dag, sblock_t *block, const dagnode_t *dagnode, int index) operand_t *op; op = dagnode->children[index]->value; + while (op->op_type == op_alias) + op = op->o.alias; + if (op->op_type == op_temp) + op->o.tempop.users++; op = fix_op_type (op, dagnode->types[index]); return op; } @@ -525,6 +529,7 @@ dag_gencode (dag_t *dag, sblock_t *block, dagnode_t *dagnode) operands[1] = make_operand (dag, block, dagnode, 1); if (!(var_iter = set_first (dagnode->identifiers))) { operands[2] = temp_operand (get_type (dagnode->label->expr)); + operands[2]->o.tempop.users++; } else { daglabel_t *var = dag->labels[var_iter->member]; etype_t type = extract_type (dagnode->label->expr); diff --git a/tools/qfcc/source/def.c b/tools/qfcc/source/def.c index d9e6f1c75..1f17cbb06 100644 --- a/tools/qfcc/source/def.c +++ b/tools/qfcc/source/def.c @@ -162,6 +162,11 @@ temp_def (etype_t type, int size) def_t *temp; defspace_t *space = current_func->symtab->space; + if ((temp = current_func->temp_defs[size - 1])) { + current_func->temp_defs[size - 1] = temp->next; + temp->next = 0; + return temp; + } ALLOC (16384, def_t, defs, temp); temp->return_addr = __builtin_return_address (0); temp->name = save_string (va (".tmp%d", current_func->temp_num++)); @@ -176,6 +181,14 @@ temp_def (etype_t type, int size) return temp; } +void +free_temp_def (def_t *temp) +{ + int size = type_size (temp->type) - 1; + temp->next = current_func->temp_defs[size]; + current_func->temp_defs[size] = temp; +} + void free_def (def_t *def) { diff --git a/tools/qfcc/source/dot_dag.c b/tools/qfcc/source/dot_dag.c index 0a96ab05d..224e82a84 100644 --- a/tools/qfcc/source/dot_dag.c +++ b/tools/qfcc/source/dot_dag.c @@ -46,6 +46,7 @@ #include "dags.h" #include "set.h" #include "statements.h" +#include "strpool.h" #include "symtab.h" #include "type.h" @@ -123,7 +124,7 @@ print_node (dstring_t *dstr, dag_t *dag, dagnode_t *node) for (id_iter = set_first (node->identifiers); id_iter; id_iter = set_next (id_iter)) { id = dag->labels[id_iter->member]; - dasprintf (dstr, " %s", daglabel_string(id)); + dasprintf (dstr, " %s", html_string (daglabel_string(id))); } dasprintf (dstr, " "); dasprintf (dstr, " \n"); diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 8a7540df4..f475f4fd6 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -171,16 +171,33 @@ add_statement_op_ref (operand_t *op, dstatement_t *st, int field) } } +static void +use_tempop (operand_t *op) +{ + if (!op || op->op_type != op_temp) + return; + if (--op->o.tempop.users == 0) + free_temp_def (op->o.tempop.def); + if (op->o.tempop.users <= -1) + bug (0, "temp users went negative: %s", operand_string (op)); +} + static void emit_statement (statement_t *statement) { const char *opcode = statement->opcode; - def_t *def_a = get_operand_def (statement->expr, statement->opa); - def_t *def_b = get_operand_def (statement->expr, statement->opb); - def_t *def_c = get_operand_def (statement->expr, statement->opc); - opcode_t *op = opcode_find (opcode, def_a, def_b, def_c); + def_t *def_a, *def_b, *def_c; + opcode_t *op; dstatement_t *s; + def_a = get_operand_def (statement->expr, statement->opa); + use_tempop (statement->opa); + def_b = get_operand_def (statement->expr, statement->opb); + use_tempop (statement->opb); + def_c = get_operand_def (statement->expr, statement->opc); + use_tempop (statement->opc); + op = opcode_find (opcode, def_a, def_b, def_c); + if (!op) { print_expr (statement->expr); print_statement (statement); diff --git a/tools/qfcc/source/flow.c b/tools/qfcc/source/flow.c index e7647aeb8..37e7b6c6d 100644 --- a/tools/qfcc/source/flow.c +++ b/tools/qfcc/source/flow.c @@ -435,7 +435,7 @@ flow_generate (flowgraph_t *graph) // generate new statements from the dag; dag_generate (node->dag, block); } - //dump_dot ("post", code, dump_dot_sblock); + dump_dot ("post", code, dump_dot_sblock); return code; } diff --git a/tools/qfcc/source/statements.c b/tools/qfcc/source/statements.c index 52843e8c2..623b37bed 100644 --- a/tools/qfcc/source/statements.c +++ b/tools/qfcc/source/statements.c @@ -108,7 +108,7 @@ operand_string (operand_t *op) case op_label: return op->o.label->name; case op_temp: - return va ("tmp %p", op); + return va ("", op, op->o.tempop.users); case op_pointer: type = op->o.value->v.pointer.type; if (op->o.value->v.pointer.def)