Commit 4524bf07 authored by Matthias Braun's avatar Matthias Braun
Browse files

cfopt: use a hashmap for sparse block->data mapping

parent 9476fdab
......@@ -57,7 +57,8 @@
#include "irflag_t.h"
#include "firmstat.h"
#include "irpass.h"
#include "irphase_t.h"
#include "irnodehashmap.h"
#include "irtools.h"
#include "iropt_dbg.h"
......@@ -625,52 +626,53 @@ typedef enum block_flags_t {
BF_IS_UNKNOWN_JUMP_TARGET = 1 << 2,
} block_flags_t;
static bool get_phase_flag(ir_phase *block_info, ir_node *block, int flag)
static bool get_block_flag(const ir_nodehashmap_t *infos, const ir_node *block,
int flag)
{
return PTR_TO_INT(phase_get_irn_data(block_info, block)) & flag;
return PTR_TO_INT(ir_nodehashmap_get(infos, block)) & flag;
}
static void set_phase_flag(ir_phase *block_info, ir_node *block,
static void set_block_flag(ir_nodehashmap_t *infos, ir_node *block,
block_flags_t flag)
{
int data = PTR_TO_INT(phase_get_irn_data(block_info, block));
int data = PTR_TO_INT(ir_nodehashmap_get(infos, block));
data |= flag;
phase_set_irn_data(block_info, block, INT_TO_PTR(data));
ir_nodehashmap_insert(infos, block, INT_TO_PTR(data));
}
static void clear_phase_flag(ir_phase *block_info, ir_node *block)
static void clear_block_flag(ir_nodehashmap_t *infos, const ir_node *block)
{
phase_set_irn_data(block_info, block, NULL);
ir_nodehashmap_remove(infos, block);
}
static bool has_operations(ir_phase *block_info, ir_node *block)
static bool has_operations(ir_nodehashmap_t *infos, const ir_node *block)
{
return get_phase_flag(block_info, block, BF_HAS_OPERATIONS);
return get_block_flag(infos, block, BF_HAS_OPERATIONS);
}
static void set_has_operations(ir_phase *block_info, ir_node *block)
static void set_has_operations(ir_nodehashmap_t *infos, ir_node *block)
{
set_phase_flag(block_info, block, BF_HAS_OPERATIONS);
set_block_flag(infos, block, BF_HAS_OPERATIONS);
}
static bool has_phis(ir_phase *block_info, ir_node *block)
static bool has_phis(ir_nodehashmap_t *infos, const ir_node *block)
{
return get_phase_flag(block_info, block, BF_HAS_PHIS);
return get_block_flag(infos, block, BF_HAS_PHIS);
}
static void set_has_phis(ir_phase *block_info, ir_node *block)
static void set_has_phis(ir_nodehashmap_t *infos, ir_node *block)
{
set_phase_flag(block_info, block, BF_HAS_PHIS);
set_block_flag(infos, block, BF_HAS_PHIS);
}
static bool is_unknown_jump_target(ir_phase *block_info, ir_node *block)
static bool is_unknown_jump_target(ir_nodehashmap_t *infos, const ir_node *block)
{
return get_phase_flag(block_info, block, BF_IS_UNKNOWN_JUMP_TARGET);
return get_block_flag(infos, block, BF_IS_UNKNOWN_JUMP_TARGET);
}
static void set_is_unknown_jump_target(ir_phase *block_info, ir_node *block)
static void set_is_unknown_jump_target(ir_nodehashmap_t *infos, ir_node *block)
{
set_phase_flag(block_info, block, BF_IS_UNKNOWN_JUMP_TARGET);
set_block_flag(infos, block, BF_IS_UNKNOWN_JUMP_TARGET);
}
/**
......@@ -678,36 +680,36 @@ static void set_is_unknown_jump_target(ir_phase *block_info, ir_node *block)
*/
static void compute_block_info(ir_node *n, void *x)
{
ir_phase *block_info = (ir_phase *)x;
ir_nodehashmap_t *infos = (ir_nodehashmap_t*)x;
if (is_Block(n)) {
int i, max = get_Block_n_cfgpreds(n);
for (i=0; i<max; i++) {
ir_node *pred = get_Block_cfgpred(n,i);
if (is_unknown_jump(pred)) {
set_is_unknown_jump_target(block_info, n);
set_is_unknown_jump_target(infos, n);
}
}
} else if (is_Phi(n)) {
ir_node *block = get_nodes_block(n);
set_has_phis(block_info, block);
set_has_phis(infos, block);
} else if (is_Jmp(n) || is_Cond(n) || is_Proj(n)) {
/* ignore */
} else {
ir_node *block = get_nodes_block(n);
set_has_operations(block_info, block);
set_has_operations(infos, block);
}
}
static void clear_block_info(ir_node *block, void *x)
{
ir_phase *block_info = (ir_phase *)x;
clear_phase_flag(block_info, block);
ir_nodehashmap_t *infos = (ir_nodehashmap_t*)x;
clear_block_flag(infos, block);
}
typedef struct skip_env {
bool changed;
ir_phase *phase;
bool changed;
ir_nodehashmap_t block_infos;
} skip_env;
/**
......@@ -720,7 +722,7 @@ static void optimize_ifs(ir_node *block, void *x)
int i, j;
int n_preds = get_Block_n_cfgpreds(block);
if (has_phis(env->phase, block))
if (has_phis(&env->block_infos, block))
return;
/* optimize Cond predecessors (might produce Bad predecessors) */
......@@ -751,11 +753,11 @@ static void remove_empty_blocks(ir_node *block, void *x)
jmp_block = get_nodes_block(jmp);
if (jmp_block == block)
continue; /* this infinite loop cannot be optimized any further */
if (is_unknown_jump_target(env->phase, jmp_block))
if (is_unknown_jump_target(&env->block_infos, jmp_block))
continue; /* unknown jump target must not be optimized */
if (has_operations(env->phase,jmp_block))
if (has_operations(&env->block_infos,jmp_block))
continue; /* this block contains operations and cannot be skipped */
if (has_phis(env->phase,jmp_block))
if (has_phis(&env->block_infos,jmp_block))
continue; /* this block contains Phis and is not skipped */
if (Block_block_visited(jmp_block)) {
continue;
......@@ -796,7 +798,7 @@ static void remove_empty_blocks(ir_node *block, void *x)
pred_block = get_nodes_block(pred);
exchange(jmp_block, pred_block);
env->changed = true;
} else if (! has_phis(env->phase, block)) {
} else if (! has_phis(&env->block_infos, block)) {
/* all predecessors can skip the jmp block, so block gets some new
* predecessors
*
......@@ -840,11 +842,13 @@ static void remove_empty_blocks(ir_node *block, void *x)
*/
static void cfgopt_ignoring_phis(ir_graph *irg)
{
ir_phase *block_info = new_phase(irg, NULL);
skip_env env = { true, block_info };
skip_env env;
env.changed = true;
ir_nodehashmap_init(&env.block_infos);
while (env.changed) {
irg_walk_graph(irg, compute_block_info, NULL, block_info);
irg_walk_graph(irg, compute_block_info, NULL, &env.block_infos);
env.changed = false;
/* Remove blocks, which only consist of a Jmp */
......@@ -856,7 +860,7 @@ static void cfgopt_ignoring_phis(ir_graph *irg)
if (env.changed) {
clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE);
/* clear block info, because it must be recomputed */
irg_block_walk_graph(irg, clear_block_info, NULL, block_info);
irg_block_walk_graph(irg, clear_block_info, NULL, &env.block_infos);
/* Removing blocks and Conds might enable more optimizations */
continue;
} else {
......@@ -864,7 +868,7 @@ static void cfgopt_ignoring_phis(ir_graph *irg)
}
}
phase_free(block_info);
ir_nodehashmap_destroy(&env.block_infos);
}
/* Optimizations of the control flow that also require changes of Phi nodes. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment