3 * File name: ir/ir/irgwalk_blk.c
9 * Copyright: (c) 1999-2004 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
17 #include "irgraph_t.h" /* visited flag */
24 * Metadata for block walker
26 typedef struct _blk_collect_data_t {
27 struct obstack obst; /**< obstack to allocate objects on */
28 pset *blk_map; /**< Hash map: Block -> List */
29 pdeq *blk_list; /**< the Block list */
33 * An entry for a block in the blk_map
35 typedef struct _block_entry_t {
36 ir_node *block; /**< the block */
37 pdeq *list; /**< the instruction list */
41 * compare two block_entries
43 static int addr_cmp(const void *elt, const void *key) {
44 const block_entry_t *e1 = elt;
45 const block_entry_t *e2 = key;
47 return e1->block != e2->block;
51 * calculates a hash value for an block address
52 * Addresses are typically aligned at 32bit, so we ignore the lowest bits
54 static INLINE unsigned block_hash(const ir_node *node) {
55 return (unsigned)node >> 3;
59 * Returns the associates block_entry_t for an block
61 static block_entry_t *block_find_entry(ir_node *block, blk_collect_data_t *ctx)
67 elem = pset_find(ctx->blk_map, &key, block_hash(block));
71 elem = obstack_alloc(&ctx->obst, sizeof(*elem));
74 elem->list = new_pdeq();
76 return pset_insert(ctx->blk_map, elem, block_hash(block));
80 * Post-walker: collect nodes and put them on the right list
82 static void collect_nodes(ir_node *node, void *env)
84 blk_collect_data_t *ctx = env;
89 /* it's a block, put it into the block list */
90 pdeq_putl(ctx->blk_list, node);
94 block = get_nodes_block(node);
95 entry = block_find_entry(block, ctx);
97 if (get_irn_mode(node) == mode_X) {
99 * put all mode_X nodes to the start, later we can
100 * move them to the end.
102 pdeq_putr(entry->list, node);
105 pdeq_putl(entry->list, node);
109 * move mode_X nodes to the end of the schedule
111 static void move_X_nodes_to_end(pdeq *list)
115 /* move mode_X nodes to the end */
116 for (j = pdeq_len(list); j > 0; --j) {
117 ir_node *node = pdeq_getr(list);
119 if (get_irn_mode(node) == mode_X) {
120 pdeq_putl(list, node);
123 pdeq_putr(list, node);
130 * traverse the pre order only, from End to Start
132 static void traverse_pre(blk_collect_data_t* blks, irg_walk_func *pre, void *env)
136 for (i = pdeq_len(blks->blk_list); i > 0; --i) {
137 ir_node *block = pdeq_getl(blks->blk_list);
138 block_entry_t *entry = block_find_entry(block, blks);
140 /* move mode_X nodes to the end */
141 move_X_nodes_to_end(entry->list);
143 for (j = pdeq_len(entry->list); j > 0; --j) {
144 ir_node *node = pdeq_getl(entry->list);
152 * traverse the post order only, from Start to End
154 static void traverse_post(blk_collect_data_t* blks, irg_walk_func *post, void *env)
158 for (i = pdeq_len(blks->blk_list); i > 0; --i) {
159 ir_node *block = pdeq_getr(blks->blk_list);
160 block_entry_t *entry = block_find_entry(block, blks);
164 /* move mode_X nodes to the end */
165 move_X_nodes_to_end(entry->list);
167 for (j = pdeq_len(entry->list); j > 0; --j) {
168 ir_node *node = pdeq_getr(entry->list);
177 static void traverse_both(blk_collect_data_t* blks, irg_walk_func *pre, irg_walk_func *post, void *env)
181 /* pre walk, rotate all lists */
182 for (i = pdeq_len(blks->blk_list); i > 0; --i) {
183 ir_node *block = pdeq_getl(blks->blk_list);
184 block_entry_t *entry = block_find_entry(block, blks);
186 pdeq_putr(blks->blk_list, block);
188 /* move mode_X nodes to the end */
189 move_X_nodes_to_end(entry->list);
191 for (j = pdeq_len(entry->list); j > 0; --j) {
192 ir_node *node = pdeq_getl(entry->list);
194 pdeq_putr(entry->list, node);
201 for (i = pdeq_len(blks->blk_list); i > 0; --i) {
202 ir_node *block = pdeq_getr(blks->blk_list);
203 block_entry_t *entry = block_find_entry(block, blks);
207 for (j = pdeq_len(entry->list); j > 0; --j) {
208 ir_node *node = pdeq_getr(entry->list);
218 static void traverse(blk_collect_data_t* blks, irg_walk_func *pre, irg_walk_func *post, void *env)
220 if (!post) traverse_pre (blks, pre, env);
221 else if (!pre) traverse_post(blks, post, env);
222 else traverse_both(blks, pre, post, env);
226 * Intraprozedural graph walker over blocks.
229 do_irg_walk_blk(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
231 blk_collect_data_t blks;
232 int old_view = get_interprocedural_view();
234 /* switch off interprocedural view */
235 set_interprocedural_view(false);
237 obstack_init(&blks.obst);
238 blks.blk_map = new_pset(addr_cmp, 1);
239 blks.blk_list = new_pdeq();
241 if (node->visited < current_ir_graph->visited) {
242 /* first step: traverse the graph and fill the lists */
243 irg_walk(node, NULL, collect_nodes, &blks);
245 /* second step: traverse the list */
246 traverse(&blks, pre, post, env);
249 del_pdeq(blks.blk_list);
250 del_pset(blks.blk_map);
251 obstack_free(&blks.obst, NULL);
253 set_interprocedural_view(old_view);
256 void irg_walk_blkwise(ir_node *node, irg_walk_func *pre, irg_walk_func *post, void *env)
258 inc_irg_visited(current_ir_graph);
259 do_irg_walk_blk(node, pre, post, env);
262 void irg_walk_blkwise_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env)
264 ir_graph * rem = current_ir_graph;
266 hook_irg_walk_blkwise(irg, (void *)pre, (void *)post);
267 current_ir_graph = irg;
268 irg_walk_blkwise(get_irg_end(irg), pre, post, env);
269 current_ir_graph = rem;