10 #include "irphase_t.h"
11 #include "iredges_t.h"
13 typedef struct _heights_t heights_t;
19 struct list_head sink_head;
26 struct list_head sink_list;
29 static void irn_height_init(const phase_t *ph, const ir_node *irn, void *data)
31 irn_height_t *h = data;
32 memset(h, 0, sizeof(h[0]));
33 INIT_LIST_HEAD(&h->sink_list);
36 static void height_dump_cb(void *data, FILE *f, const ir_node *irn)
38 heights_t *heights = data;
39 irn_height_t *h = phase_get_irn_data(&heights->ph, irn);
42 fprintf(f, "height: %u\n", h->height);
46 * Check, if we can reach a target node from a given node inside one basic block.
47 * @param h The heights object.
48 * @param curr The current node from which we tried to reach the other one.
49 * @param tgt The node we try to reach.
50 * @return 1, one of tgt can be reached from curr, 0 else.
52 static int search(heights_t *h, const ir_node *curr, const ir_node *tgt)
58 /* if the current node is the one we were looking for, we're done. */
62 /* If we are in another block we won't find our target. */
63 if(get_nodes_block(curr) != get_nodes_block(tgt))
66 /* Check, if we have already been here. Coming more often won't help :-) */
67 h_curr = phase_get_irn_data(&h->ph, curr);
68 if(h_curr->visited >= h->visited)
71 /* If we are too deep into the DAG we won't find the target either. */
72 h_tgt = phase_get_irn_data(&h->ph, tgt);
73 if(h_curr->height > h_tgt->height)
76 /* Mark this place as visited. */
77 h_curr->visited = h->visited;
79 /* Start a search from this node. */
80 for(i = 0, n = get_irn_arity(curr); i < n; ++i) {
81 ir_node *op = get_irn_n(curr, i);
82 if(search(h, op, tgt))
90 * Check, if one node can be reached from another one, according to data dependence.
92 int heights_reachable_in_block(heights_t *h, const ir_node *n, const ir_node *m)
95 irn_height_t *hn = phase_get_irn_data(&h->ph, n);
96 irn_height_t *hm = phase_get_irn_data(&h->ph, m);
98 assert(get_nodes_block(n) == get_nodes_block(m));
99 assert(hn != NULL && hm != NULL);
101 if(hn->height <= hm->height) {
103 res = search(h, n, m);
110 * Compute the height of a node in a block.
111 * @param h The heights object.
112 * @param irn The node.
113 * @param bl The block.
115 static unsigned compute_height(heights_t *h, const ir_node *irn, const ir_node *bl)
117 irn_height_t *ih = phase_get_or_set_irn_data(&h->ph, irn);
120 const ir_edge_t *edge;
122 /* bail out if we already visited that node. */
123 if(ih->visited >= h->visited)
126 ih->visited = h->visited;
131 foreach_out_edge(irn, edge) {
132 ir_node *dep = get_edge_src_irn(edge);
134 if(!is_Block(dep) && get_nodes_block(dep) == bl) {
135 unsigned dep_height = compute_height(h, dep, bl);
136 ih->height = MAX(ih->height, dep_height);
143 ih->is_sink = is_sink;
145 list_add(&ih->sink_list, &h->sink_head);
150 static void compute_heights_in_block(ir_node *bl, void *data)
153 const ir_edge_t *edge;
157 foreach_out_edge(bl, edge) {
158 ir_node *dep = get_edge_src_irn(edge);
159 compute_height(h, dep, bl);
163 unsigned get_irn_height(heights_t *heights, const ir_node *irn)
165 irn_height_t *h = phase_get_irn_data(&heights->ph, irn);
166 assert(h && "No height information for node");
170 void heights_recompute(heights_t *h)
172 edges_assure(phase_get_irg(&h->ph));
173 phase_reinit_irn_data(&h->ph);
175 INIT_LIST_HEAD(&h->sink_head);
176 irg_block_walk_graph(phase_get_irg(&h->ph), compute_heights_in_block, NULL, h);
179 heights_t *heights_new(ir_graph *irg)
181 heights_t *res = xmalloc(sizeof(res[0]));
182 phase_init(&res->ph, "heights", irg, sizeof(irn_height_t), PHASE_DEFAULT_GROWTH, irn_height_init);
183 res->dump_handle = dump_add_node_info_callback(height_dump_cb, res);
184 heights_recompute(res);
189 void heights_free(heights_t *h)
192 dump_remv_node_info_callback(h->dump_handle);