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

remove extended basic block support

First it is unclear what is a good way to deconstruct a program into extended
basic blocks, also none of our optimizations works on extended basic
blocks.
parent 8294af81
......@@ -24,7 +24,6 @@ libfirminclude_HEADERS = \
irdump.h \
iredgekinds.h \
iredges.h \
irextbb.h \
irflag.h \
irgmod.h \
irgopt.h \
......
......@@ -91,7 +91,6 @@
#include "irdump.h"
#include "iredgekinds.h"
#include "iredges.h"
#include "irextbb.h"
#include "irflag.h"
#include "irgmod.h"
#include "irgopt.h"
......
......@@ -65,7 +65,6 @@ typedef enum {
k_tarval, /**< A tarval. */
k_ir_loop, /**< A loop. */
k_ir_compound_graph_path, /**< A compound graph path, see entity.h. */
k_ir_extblk, /**< An extended basic block. */
k_ir_prog, /**< A program representation (irp). */
k_ir_graph_pass, /**< An ir_graph pass. */
k_ir_prog_pass, /**< An ir_prog pass. */
......
......@@ -94,8 +94,6 @@ typedef struct ir_loop ir_loop;
/** @ingroup ir_entity
* Entity */
typedef struct ir_entity ir_entity;
/** Extended Basic Block */
typedef struct ir_extblk ir_extblk;
/** @ingroup execfreq
* Execution Frequency Analysis Results */
typedef struct ir_exec_freq ir_exec_freq;
......
......@@ -39,7 +39,6 @@ enum firmstat_options_t {
FIRMSTAT_COUNT_DELETED = 0x00000010, /**< if set, count deleted graphs */
FIRMSTAT_COUNT_SELS = 0x00000020, /**< if set, count Sel(Sel(..)) differently */
FIRMSTAT_COUNT_CONSTS = 0x00000040, /**< if set, count Const statistics */
FIRMSTAT_COUNT_EXTBB = 0x00000080, /**< if set, count extended Basic Block statistics */
FIRMSTAT_CSV_OUTPUT = 0x10000000 /**< CSV output of some mini-statistic */
};
......
......@@ -292,8 +292,6 @@ FIRM_API ir_dump_verbosity_t ir_get_dump_verbosity(void);
typedef enum {
/** dump basic blocks as subgraphs which contain the nodes in the block */
ir_dump_flag_blocks_as_subgraphs = 1U << 0,
/** display blocks in extended basic grouped inside a subgraph */
ir_dump_flag_group_extbb = 1U << 1,
/** dump (parts of) typegraph along with nodes */
ir_dump_flag_with_typegraph = 1U << 2,
/** Sets the vcg flag "display_edge_labels" to no.
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Extended basis block support.
* @author Michael Beck
* @date 5.2005
*/
#ifndef FIRM_ANA_IREXTBB_H
#define FIRM_ANA_IREXTBB_H
#include "firm_types.h"
#include "execfreq.h"
#include "begin.h"
/* type of callback function for ir_graph walk */
#ifndef _EXTBB_WALK_FUNC_TYPEDEF_
#define _EXTBB_WALK_FUNC_TYPEDEF_
/**
* The type of a walk function. Does not use the link field.
*
* @param blk - the extended basic block that is just visited
* @param env - an environment pointer passed by the walk functions
*/
typedef void extbb_walk_func(ir_extblk *blk, void *env);
#endif
/**
* Checks whether a pointer points to a extended basic block.
* Intern version for libFirm.
*/
FIRM_API int is_ir_extbb(const void *thing);
/**
* Compute the extended basic blocks for a graph.
*/
FIRM_API void compute_extbb(ir_graph *irg);
/**
* Compute the extended basic blocks for a graph based on execution frequencies.
*/
FIRM_API void compute_extbb_execfreqs(ir_graph *irg, ir_exec_freq *execfreqs);
/**
* free all extended block info.
*/
FIRM_API void free_extbb(ir_graph *irg);
/**
* Returns the extended block of a node.
*
* @param node the node
*/
FIRM_API ir_extblk *get_nodes_extbb(const ir_node *node);
/**
* Returns the visited counter of an extended block.
*
* @param blk the extended basic block
*/
FIRM_API ir_visited_t get_extbb_visited(const ir_extblk *blk);
/**
* Sets the visited counter of an extended block.
*
* @param blk the extended basic block
* @param visited new value for the visited counter
*/
FIRM_API void set_extbb_visited(ir_extblk *blk, ir_visited_t visited);
/**
* Mark an extended block as visited in a graph.
* Uses the block visit flag.
*
* @param blk the extended basic block
*/
FIRM_API void mark_extbb_visited(ir_extblk *blk);
/**
* Returns non-zero if an extended was visited.
* Uses the block visit flag.
*
* @param blk the extended basic block
*/
FIRM_API int extbb_visited(const ir_extblk *blk);
/**
* Returns non-zero if an extended block was NOT visited.
* Uses the block visit flag.
*
* @param blk the extended basic block
*/
FIRM_API int extbb_not_visited(const ir_extblk *blk);
/**
* Returns the link field of an extended block.
*
* @param blk the extended basic block
*/
FIRM_API void *get_extbb_link(const ir_extblk *blk);
/**
* Sets the link field of an extended block.
*
* @param blk the extended basic block
* @param link the new link value
*/
FIRM_API void set_extbb_link(ir_extblk *blk, void *link);
/**
* Returns the number of basic blocks of an extended block.
*
* @param blk the extended basic block
*/
FIRM_API int get_extbb_n_blocks(const ir_extblk *blk);
/**
* Returns the i'th basic block of an extended block.
*
* @param blk the extended basic block
* @param pos the position
*/
FIRM_API ir_node *get_extbb_block(const ir_extblk *blk, int pos);
/**
* Returns the leader basic block of an extended block.
*
* @param blk the extended basic block
*/
FIRM_API ir_node *get_extbb_leader(const ir_extblk *blk);
/**
* Returns the node number of an extended block.
* Its the block number of the leader block
*
* @param blk the extended basic block
*/
FIRM_API long get_extbb_node_nr(const ir_extblk *blk);
/**
* Walks only over Extended Basic Block nodes in the graph.
*
* @param blk - the start extended block node
* @param pre - walker function, executed before the predecessor of a node are
* visited
* @param post - walker function, executed after the predecessor of a node are
* visited
* @param env - environment, passed to pre and post
*
* This function Walks only over Block nodes in the graph. Has its own visited
* flag, so that it can be interleaved with the other walker.
* If a none block is passed, starts at the block this node belongs to.
* If end is passed also visits kept alive blocks. Does not use the link field.
*/
FIRM_API void irg_extblock_walk(ir_extblk *blk, extbb_walk_func *pre,
extbb_walk_func *post, void *env);
/**
* Walks only over reachable Extended Basic Block nodes in the graph.
* Ensures, that the extended block containing the End node is visited last
* and the block containing Start visited first (in post order).
*
* @param irg - the irg graph
* @param pre - walker function, executed before the predecessor of a block
* are visited
* @param post - walker function, executed after the predecessor of a block
* are visited
* @param env - environment, passed to pre and post
*/
FIRM_API void irg_extblock_walk_graph(ir_graph *irg, extbb_walk_func *pre,
extbb_walk_func *post, void *env);
#include "end.h"
#endif
......@@ -474,10 +474,8 @@ typedef enum {
IR_GRAPH_STATE_CONSISTENT_LOOPINFO = 1U << 13,
/** entity usage information is computed and up to date */
IR_GRAPH_STATE_CONSISTENT_ENTITY_USAGE = 1U << 14,
/** extended basic blocks have been formed and are up to date */
IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS = 1U << 15,
/** graph contains as many returns as possible */
IR_GRAPH_STATE_MANY_RETURNS = 1U << 16,
IR_GRAPH_STATE_MANY_RETURNS = 1U << 15,
} ir_graph_state_t;
ENUM_BITSET(ir_graph_state_t)
......
......@@ -259,10 +259,6 @@ FIRM_API void set_Block_cfgpred(ir_node *block, int pos, ir_node *pred);
* @param pred a predecessor block of block
*
* @return the position of pred in block or -1
*
* @note When using the old extended basic block form for blocks
* with exception exists, a predecessor block might have more
* than one position. In that case it is not specified, with is returned.
*/
FIRM_API int get_Block_cfgpred_pos(const ir_node *block, const ir_node *pred);
......@@ -295,10 +291,6 @@ FIRM_API void mark_Block_block_visited(ir_node *node);
/** Returns 1 if a block is marked as visited */
FIRM_API int Block_block_visited(const ir_node *node);
/** Returns the extended basic block a block belongs to. */
FIRM_API ir_extblk *get_Block_extbb(const ir_node *block);
/** Sets the extended basic block a block belongs to. */
FIRM_API void set_Block_extbb(ir_node *block, ir_extblk *extblk);
/** Returns the ir_graph this Block belongs to. */
FIRM_API ir_graph *get_Block_irg(const ir_node *block);
/** Returns the entity for a Block (creating it if necessary) */
......
......@@ -54,8 +54,6 @@ libfirm_la_SOURCES = \
ana/ircfscc.c \
ana/irconsconfirm.c \
ana/irdom.c \
ana/irextbb2.c \
ana/irextbb.c \
ana/irlivechk.c \
ana/irloop.c \
ana/irmemory.c \
......@@ -273,7 +271,6 @@ EXTRA_DIST = \
ana/dfs_t.h \
ana/irbackedge_t.h \
ana/irdom_t.h \
ana/irextbb_t.h \
ana/irlivechk.h \
ana/irloop_t.h \
ana/irmemory_t.h \
......
/*
* Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief Extended basis block support.
* @author Michael Beck
* @date 5.2005
*/
#include "config.h"
#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"
/**
* Environment for extbb construction.
*/
typedef struct env {
struct obstack *obst; /**< the obstack where allocations took place */
ir_extblk *head; /**< head of the list of all extended blocks */
ir_node *start_block; /**< the start block of the current graph */
} env_t;
int (is_ir_extbb)(const void *thing)
{
return _is_ir_extbb(thing);
}
/**
* allocate a new extended block header.
*/
static void allocate_extblk(ir_node *block, env_t *env)
{
ir_extblk *extblk = OALLOC(env->obst, ir_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);
}
/**
* 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);
}
/**
* Pre block-walker. Calculates the extended block info.
*/
static void pre_walk_calc_extbb(ir_node *block, void *ctx)
{
int n = get_Block_n_cfgpreds(block);
env_t *env = (env_t*) ctx;
if (n <= 0 || n > 1 || block == env->start_block) {
/*
* block is a JOIN-node ie the control flow from
* many other blocks joins here. block is a leader.
* Note that we handle unreachable blocks (n <= 0) here too.
*/
allocate_extblk(block, env);
}
else { /* we have only one control flow predecessor */
ir_node *add_to = get_Block_cfgpred_block(block, 0);
/* blocks with only one BAD predecessors are leaders too */
if (is_Bad(add_to)) {
allocate_extblk(block, env);
} else {
/*
* Only one control flow predecessor. This block belongs
* to the same extended basic block as its predecessor.
*/
ir_node *cf_op = skip_Proj(get_Block_cfgpred(block, 0));
if (!irn_visited_else_mark(cf_op)) {
ir_node *pred_bl = get_nodes_block(cf_op);
if (get_block_n_succs(pred_bl) > 2) {
/* 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.
*/
allocate_extblk(block, env);
} else {
/* either the previous block has only one successor or
* this is the first successor after an if, include it.
*/
set_Block_extbb(block, NULL);
}
} else {
/* already marked, so begin a new extended block here */
allocate_extblk(block, env);
}
}
}
}
/** A special extended block used as sentinel */
static ir_extblk _sentinel = { k_ir_extblk, 0xFEA1DEAD, NULL, NULL };
/**
* Post block-walker. Calculates the extended block info.
* During construction, we use the (free) block input of all basic blocks
* to point to their previous block.
*/
static void post_walk_calc_extbb(ir_node *block, void *ctx)
{
ir_extblk *extbb = get_Block_extbb(block);
env_t *env = (env_t*) ctx;
ir_extblk *sentinel = &_sentinel;
if (! extbb) {
ir_node *curr, *prev, *list;
/*
* Search the leader. It can happen, that we fall into an endless
* loop, because we enter an unreachable loop that is not yet detected.
* We break the loop using a sentinel.
*/
for (curr = block; !extbb; curr = prev) {
prev = get_Block_cfgpred_block(curr, 0);
extbb = get_Block_extbb(prev);
set_Block_extbb(curr, sentinel);
}
if (extbb == sentinel) {
/* We detect a dead loop. We fix this by allocating a
* special Extended block
*/
ir_printf("Dead loop detected starting with %+F::%+F\n", get_irg_entity(current_ir_graph), block);
allocate_extblk(block, env);
extbb = get_Block_extbb(block);
set_Block_extbb(block, sentinel);
}
/* replace all sentinels by the extbb info */
prev = block;
list = NULL;
for (;;) {
if (get_Block_extbb(prev) != sentinel)
break;
set_irn_link(prev, list);
list = prev;
prev = get_Block_cfgpred_block(prev, 0);
}
/* arg, the list is in wrong order, turn around and add to the extbb list */
for (curr = list; curr; curr = prev) {
prev = (ir_node*) get_irn_link(curr);
set_irn_link(curr, extbb->link);
extbb->link = curr;
set_Block_extbb(curr, extbb);
++extbb->visited;
}
}
}
void compute_extbb(ir_graph *irg)
{
env_t env;
ir_extblk *extbb, *next;
if (irg->extbb_obst)
obstack_free(irg->extbb_obst, NULL);
else
irg->extbb_obst = XMALLOC(struct obstack);
obstack_init(irg->extbb_obst);
env.obst = irg->extbb_obst;
env.head = NULL;
env.start_block = get_irg_start_block(irg);
if (! edges_activated(irg)) {
/* we don't have edges */
assure_irg_outs(irg);
}
/* we must mark nodes, so increase the visited flag */
inc_irg_visited(irg);
irg_block_walk_graph(irg, pre_walk_calc_extbb, post_walk_calc_extbb, &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 = (ir_node*) extbb->link, i = 0; i < len; ++i) {
ir_node *nblock = (ir_node*) 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;
}
#ifndef NDEBUG
/* check it */
for (i = len - 1; i > 0; --i) {
ir_node *blk = extbb->blks[i];
if (get_Block_n_cfgpreds(blk) != 1) {
assert(!"Block for more than one predecessors is no leader");
} else if (get_Block_cfgpred_block(blk, 0) != extbb->blks[i - 1]) {
assert(!"extbb block order wrong");
}
}
#endif
extbb->link = NULL;
extbb->visited = 0;
}
set_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS);
}
void free_extbb(ir_graph *irg)
{
if (irg->extbb_obst) {
obstack_free(irg->extbb_obst, NULL);
xfree(irg->extbb_obst);
irg->extbb_obst = NULL;
}
clear_irg_state(irg, IR_GRAPH_STATE_VALID_EXTENDED_BLOCKS);
}
ir_extblk *get_nodes_extbb(const ir_node *node)
{
const ir_node *block = is_Block(node) ? node : get_nodes_block(node);
return get_Block_extbb(block);
}
ir_visited_t (get_extbb_visited)(const ir_extblk *blk)
{
return _get_extbb_visited(blk);
}
void (set_extbb_visited)(ir_extblk *blk, ir_visited_t visited)
{
_set_extbb_visited(blk, visited);
}
void (mark_extbb_visited)(ir_extblk *blk)
{
_mark_extbb_visited(blk);
}
int (extbb_visited)(const ir_extblk *blk)
{
return _extbb_visited(blk);
}
int (extbb_not_visited)(const ir_extblk *blk)
{
return _extbb_not_visited(blk);
}
void *(get_extbb_link)(const ir_extblk *blk)
{
return _get_extbb_link(blk);
}
void (set_extbb_link)(ir_extblk *blk, void *link)
{
_set_extbb_link(blk, link);
}
int (get_extbb_n_blocks)(const ir_extblk *blk)
{
return _get_extbb_n_blocks(blk);
}
ir_node *(get_extbb_block)(const ir_extblk *blk, int pos)
{
return _get_extbb_block(blk, pos);
}
ir_node *(get_extbb_leader)(const ir_extblk *blk)
{
return _get_extbb_leader(blk);
}