summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChristoph Mallon <christoph.mallon@gmx.de>2012-10-26 11:00:37 +0200
committerChristoph Mallon <christoph.mallon@gmx.de>2012-10-30 10:39:49 +0100
commit8af3e71f6683905a7085f83eec99faf6cf742b29 (patch)
treedefde76a4054edb4435e7ec3b65ae297b856194b
parent108fbfe7bdab64ab7a2b1d058a1384c8450d9987 (diff)
Use jump_target for goto labels.
This saves an unnecessary block, if only a single forward jump reaches a label.
-rw-r--r--ast2firm.c68
-rw-r--r--entity_t.h3
2 files changed, 20 insertions, 51 deletions
diff --git a/ast2firm.c b/ast2firm.c
index b38585c..b759dde 100644
--- a/ast2firm.c
+++ b/ast2firm.c
@@ -3247,20 +3247,14 @@ static ir_node *builtin_types_compatible_to_firm(
return create_Const_from_bool(mode, value);
}
-static ir_node *get_label_block(label_t *label)
+static void prepare_label_target(label_t *const label)
{
- if (label->block != NULL)
- return label->block;
-
- ir_node *block = new_immBlock();
- label->block = block;
- if (label->address_taken) {
+ if (label->address_taken && !label->indirect_block) {
ir_node *const iblock = new_immBlock();
label->indirect_block = iblock;
- add_immBlock_pred(block, new_r_Jmp(iblock));
ARR_APP1(ir_node*, ijmp_blocks, iblock);
+ jump_from_block_to_target(&label->target, iblock);
}
- return block;
}
/**
@@ -3272,7 +3266,7 @@ static ir_node *label_address_to_firm(const label_address_expression_t *label)
/* Beware: Might be called from create initializer with current_ir_graph
* set to const_code_irg. */
PUSH_IRG(current_function);
- get_label_block(label->label);
+ prepare_label_target(label->label);
POP_IRG();
symconst_symbol value;
@@ -4497,18 +4491,6 @@ static ir_node *if_statement_to_firm(if_statement_t *statement)
return NULL;
}
-/**
- * Add an unconditional jump to the target block. If the source block is not
- * reachable, then a Bad predecessor is created to prevent Phi-less unreachable
- * loops. This is necessary if the jump potentially enters a loop.
- */
-static void jump_to(ir_node *const target_block)
-{
- ir_node *const pred = currently_reachable() ? new_Jmp() : new_Bad(mode_X);
- add_immBlock_pred(target_block, pred);
- set_cur_block(target_block);
-}
-
static ir_node *do_while_statement_to_firm(do_while_statement_t *statement)
{
create_local_declarations(statement->scope.entities);
@@ -4601,19 +4583,6 @@ static ir_node *for_statement_to_firm(for_statement_t *statement)
return NULL;
}
-static ir_node *create_jump_statement(const statement_t *statement, ir_node *target_block)
-{
- if (!currently_reachable())
- return NULL;
-
- dbg_info *dbgi = get_dbg_info(&statement->base.source_position);
- ir_node *jump = new_d_Jmp(dbgi);
- add_immBlock_pred(target_block, jump);
-
- set_unreachable_now();
- return NULL;
-}
-
static ir_switch_table *create_switch_table(const switch_statement_t *statement)
{
/* determine number of cases */
@@ -4705,22 +4674,18 @@ 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)
- mature_immBlock(label->block);
-}
-
static ir_node *label_to_firm(const label_statement_t *statement)
{
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);
+ prepare_label_target(label);
+ jump_to_target(&label->target);
+ if (--label->n_users == 0) {
+ enter_jump_target(&label->target);
+ } else {
+ enter_immature_jump_target(&label->target);
+ keep_alive(label->target.block);
+ keep_all_memory(label->target.block);
+ }
return statement_to_firm(statement->statement);
}
@@ -4728,8 +4693,11 @@ static ir_node *label_to_firm(const label_statement_t *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);
+ prepare_label_target(label);
+ jump_to_target(&label->target);
+ if (--label->n_users == 0)
+ enter_jump_target(&label->target);
+ set_unreachable_now();
return NULL;
}
diff --git a/entity_t.h b/entity_t.h
index c23d950..e1a26ed 100644
--- a/entity_t.h
+++ b/entity_t.h
@@ -25,6 +25,7 @@
#include "attribute.h"
#include <libfirm/firm_types.h>
#include "builtins.h"
+#include "jump_target.h"
#include "token_t.h"
typedef enum {
@@ -176,7 +177,7 @@ struct label_t {
statement_t *statement;
/* ast2firm info */
- ir_node *block;
+ jump_target target;
ir_node *indirect_block;
};