summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2012-10-24 13:58:55 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2012-10-30 10:26:25 +0100
commit8190361d1f60dc53334492c34b04b398ff644b57 (patch)
treeef692fc404d757414c1440c0854979f36449ab1e
parent287127a9ff31adbada4945a2e82cd4ab57786b85 (diff)
Use a reference counter to mature label blocks as early as possible.
-rw-r--r--ast2firm.c47
-rw-r--r--entity_t.h1
-rw-r--r--parser.c2
3 files changed, 34 insertions, 16 deletions
diff --git a/ast2firm.c b/ast2firm.c
index c1efc37..bc94473 100644
--- a/ast2firm.c
+++ b/ast2firm.c
@@ -76,9 +76,9 @@ static ir_node *continue_label;
static ir_node *break_label;
static ir_node *current_switch;
static bool saw_default_label;
-static label_t **all_labels;
static entity_t **inner_functions;
static ir_node *ijmp_list;
+static ir_node **ijmp_blocks;
static bool constant_folding;
#define PUSH_BREAK(val) \
@@ -3241,8 +3241,8 @@ static ir_node *get_label_block(label_t *label)
ir_node *block = new_immBlock();
label->block = block;
-
- ARR_APP1(label_t *, all_labels, label);
+ if (label->address_taken)
+ ARR_APP1(ir_node*, ijmp_blocks, block);
return block;
}
@@ -4762,17 +4762,34 @@ static ir_node *case_label_to_firm(const case_label_statement_t *statement)
return statement_to_firm(statement->statement);
}
+static void try_mature_label(label_t *const label)
+{
+ if (--label->n_users == 0 && !label->address_taken)
+ mature_immBlock(label->block);
+}
+
static ir_node *label_to_firm(const label_statement_t *statement)
{
- ir_node *block = get_label_block(statement->label);
+ label_t *const label = statement->label;
+ ir_node *const block = get_label_block(label);
jump_to(block);
keep_alive(block);
keep_all_memory(block);
+ try_mature_label(label);
+
return statement_to_firm(statement->statement);
}
+static ir_node *goto_statement_to_firm(goto_statement_t *const stmt)
+{
+ label_t *const label = stmt->label;
+ create_jump_statement((statement_t*)stmt, get_label_block(label));
+ try_mature_label(label);
+ return NULL;
+}
+
static ir_node *computed_goto_to_firm(computed_goto_statement_t const *const statement)
{
if (!currently_reachable())
@@ -5053,6 +5070,7 @@ static ir_node *statement_to_firm(statement_t *const stmt)
case STATEMENT_EMPTY: return NULL; /* nothing */
case STATEMENT_EXPRESSION: return expression_statement_to_firm( &stmt->expression);
case STATEMENT_FOR: return for_statement_to_firm( &stmt->fors);
+ case STATEMENT_GOTO: return goto_statement_to_firm( &stmt->gotos);
case STATEMENT_IF: return if_statement_to_firm( &stmt->ifs);
case STATEMENT_LABEL: return label_to_firm( &stmt->label);
case STATEMENT_LEAVE: return leave_statement_to_firm( &stmt->leave);
@@ -5062,7 +5080,6 @@ static ir_node *statement_to_firm(statement_t *const stmt)
case STATEMENT_BREAK: return create_jump_statement(stmt, get_break_label());
case STATEMENT_CONTINUE: return create_jump_statement(stmt, continue_label);
- case STATEMENT_GOTO: return create_jump_statement(stmt, get_label_block(stmt->gotos.label));
case STATEMENT_ERROR: panic("error statement found");
}
@@ -5243,9 +5260,9 @@ static void create_function(entity_t *entity)
current_function_name = NULL;
current_funcsig = NULL;
- assert(all_labels == NULL);
- all_labels = NEW_ARR_F(label_t *, 0);
- ijmp_list = NULL;
+ assert(ijmp_blocks == NULL);
+ ijmp_blocks = NEW_ARR_F(ir_node*, 0);
+ ijmp_list = NULL;
int n_local_vars = get_function_n_local_vars(entity);
ir_graph *irg = new_ir_graph(function_entity, n_local_vars);
@@ -5294,16 +5311,14 @@ static void create_function(entity_t *entity)
add_immBlock_pred(end_block, ret);
}
- for (int i = ARR_LEN(all_labels) - 1; i >= 0; --i) {
- label_t *label = all_labels[i];
- if (label->address_taken) {
- gen_ijmp_branches(label->block);
- }
- mature_immBlock(label->block);
+ for (size_t i = ARR_LEN(ijmp_blocks); i-- != 0;) {
+ ir_node *const block = ijmp_blocks[i];
+ gen_ijmp_branches(block);
+ mature_immBlock(block);
}
- DEL_ARR_F(all_labels);
- all_labels = NULL;
+ DEL_ARR_F(ijmp_blocks);
+ ijmp_blocks = NULL;
irg_finalize_cons(irg);
diff --git a/entity_t.h b/entity_t.h
index 877a357..b570f1a 100644
--- a/entity_t.h
+++ b/entity_t.h
@@ -172,6 +172,7 @@ struct label_t {
entity_base_t base;
bool used : 1;
bool address_taken : 1;
+ unsigned n_users; /* Reference counter to mature the label block as early as possible. */
statement_t *statement;
/* ast2firm info */
diff --git a/parser.c b/parser.c
index d16e7f2..4e9d2f0 100644
--- a/parser.c
+++ b/parser.c
@@ -8971,6 +8971,7 @@ static statement_t *parse_label_statement(void)
} else {
label->base.source_position = *pos;
label->statement = statement;
+ label->n_users += 1;
}
eat(':');
@@ -9307,6 +9308,7 @@ static statement_t *parse_goto(void)
label_t *const label = get_label("while parsing goto");
if (label) {
+ label->n_users += 1;
label->used = true;
statement->gotos.label = label;