Commit f6cc87ea authored by Matthias Braun's avatar Matthias Braun
Browse files

alternative algo for computing extbbs

[r8173]
parent 04f0f6a1
/*
* Project: libFIRM
* File name: ir/ana/irextbb2.c
* Purpose: Alternate extended basic block computation
* Author: Matthias Braun
* Modified by:
* Created: 5.2005
* CVS-ID: $Id$
* Copyright: (c) 2002-2005 Universitt Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
*/
/**
* @file irextbb.c
*
* Alternative algorithm for computing extended basic blocks (using out edges
* and execution frequencies)
*
* @author Matthias Braun
*/
#include "irextbb_t.h"
#include "irgwalk.h"
#include "irnode_t.h"
#include "irgraph_t.h"
#include "iredges_t.h"
#include "irouts.h"
#include "xmalloc.h"
#include "irprintf.h"
#include "execfreq.h"
typedef struct _env {
struct obstack *obst; /**< the obstack where allocations took place */
ir_extblk *head; /**< head of the list of all extended blocks */
exec_freq_t *execfreqs;
} env_t;
/**
* allocate a new extended block header.
*/
static ir_extblk *allocate_extblk(ir_node *block, env_t *env)
{
ir_extblk *extblk = obstack_alloc(env->obst, sizeof(*extblk));
extblk->kind = k_ir_extblk;
extblk->visited = 1;
extblk->blks = (ir_node **)env->head;
extblk->link = block;
env->head = extblk;
set_Block_extbb(block, extblk);
set_irn_link(block, NULL);
return extblk;
}
/**
* add a block to an extended block
*/
static void addto_extblk(ir_extblk *extblk, ir_node *block)
{
/* link all blocks belonging to this extended block */
set_irn_link(block, extblk->link);
extblk->link = block;
extblk->visited++;
set_Block_extbb(block, extblk);
}
/**
* Returns the number of block successors.
* we are interested only in 1, 2 and >2.
*/
static int get_block_n_succs(ir_node *block) {
if (edges_activated(current_ir_graph)) {
const ir_edge_t *edge;
edge = get_block_succ_first(block);
if (! edge)
return 0;
edge = get_block_succ_next(block, edge);
if (! edge)
return 1;
edge = get_block_succ_next(block, edge);
return edge ? 3 : 2;
}
return get_Block_n_cfg_outs(block);
}
static void pick_successor(ir_node *block, ir_extblk *extblk, env_t *env);
static void create_extblk(ir_node *block, env_t *env)
{
if(irn_visited(block))
return;
ir_extblk *extblk = allocate_extblk(block, env);
mark_irn_visited(block);
pick_successor(block, extblk, env);
}
static void pick_successor(ir_node *block, ir_extblk *extblk, env_t *env)
{
const ir_edge_t *edge;
ir_node *best_succ = NULL;
double best_execfreq = -1;
/* More than two successors means we have a jump table.
* we cannot include a jump target into the current extended
* basic block, so create a new one here.
*/
if(get_block_n_succs(block) > 2) {
const ir_edge_t *edge;
foreach_block_succ(block, edge) {
ir_node *succ = get_edge_src_irn(edge);
create_extblk(succ, env);
}
return;
}
foreach_block_succ(block, edge) {
ir_node *succ = get_edge_src_irn(edge);
double execfreq;
if(get_Block_n_cfgpreds(succ) > 1) {
create_extblk(succ, env);
continue;
}
execfreq = get_block_execfreq(env->execfreqs, succ);
// remember best sucessor and make non best successor with only 1
// pred block to new extbb leaders
if(execfreq > best_execfreq) {
if(best_succ != NULL) {
create_extblk(best_succ, env);
}
best_execfreq = execfreq;
best_succ = succ;
} else {
create_extblk(succ, env);
}
}
// add best successor and recursively try to pick more
if(best_succ != NULL) {
addto_extblk(extblk, best_succ);
mark_irn_visited(best_succ);
pick_successor(best_succ, extblk, env);
}
}
/*
* Compute the extended basic blocks for a graph
*/
void compute_extbb_execfreqs(ir_graph *irg, exec_freq_t *execfreqs) {
env_t env;
ir_extblk *extbb, *next;
ir_node *endblock;
if (irg->extbb_obst) {
obstack_free(irg->extbb_obst, NULL);
} else {
irg->extbb_obst = xmalloc(sizeof(*irg->extbb_obst));
}
obstack_init(irg->extbb_obst);
env.obst = irg->extbb_obst;
env.head = NULL;
env.execfreqs = execfreqs;
assure_irg_outs(irg);
/* we must mark nodes, so increase the visited flag */
inc_irg_visited(irg);
create_extblk(get_irg_start_block(irg), &env);
// the end block needs a extbb assigned (even for endless loops)
endblock = get_irg_end_block(irg);
if(!irn_visited(endblock)) {
create_extblk(endblock, &env);
}
/*
* Ok, we have now the list of all extended blocks starting with env.head
* every extended block "knowns" the number of blocks in visited and
* the blocks are linked in link.
* Now we can create arrays that hold the blocks, some kind of "out" edges
* for the extended block
*/
for (extbb = env.head; extbb; extbb = next) {
int i, len = (int)extbb->visited;
ir_node *block;
next = (ir_extblk *)extbb->blks;
extbb->blks = NEW_ARR_D(ir_node *, env.obst, len);
for (block = extbb->link, i = 0; i < len; ++i) {
ir_node *nblock = get_irn_link(block);
/* ensure that the leader is the first one */
extbb->blks[len - 1 - i] = block;
set_irn_link(block, NULL);
block = nblock;
}
for(i = 0; i < len; ++i) {
if(i > 0)
printf(", ");
ir_printf("%+F", extbb->blks[i]);
}
printf("\n");
extbb->link = NULL;
extbb->visited = 0;
}
irg->extblk_state = extblk_valid;
}
Supports Markdown
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