2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * Implementation of a register saturating list scheduler
22 * as described in: Sid-Ahmed-Ali Touati
23 * Register Saturation in Superscalar and VLIW Codes
25 * @license This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
26 * @author Christian Wuerdig
39 #include "irgraph_t.h"
41 #include "iredges_t.h"
43 #include "irphase_t.h"
49 #include "bipartite.h"
50 #include "hungarian.h"
58 #include "besched_t.h"
61 #include <libcore/lc_opts.h>
62 #include <libcore/lc_opts_enum.h>
65 #define ARR_LEN_SAFE(arr) ((arr) != NULL ? ARR_LEN((arr)) : 0)
67 #define HASH_RSS_EDGE(edge) ((get_irn_node_nr((edge)->src) << 16) | (get_irn_node_nr((edge)->tgt) & 0xFFFF))
68 #define BSEARCH_IRN_ARR(val, arr) \
69 bsearch(&(val), (arr), ARR_LEN_SAFE((arr)), sizeof((arr)[0]), cmp_irn_idx)
71 #define BLOCK_IDX_MAP(rss, irn) bsearch_for_index(get_irn_idx((irn)), (rss)->idx_map, ARR_LEN_SAFE((rss)->idx_map), 1)
74 typedef struct _rss_opts_t {
78 /* Represents a child with associated costs */
79 typedef struct _child {
84 /* We need edges for several purposes. */
85 typedef struct _rss_edge {
91 /* Represents a connected bipartite component. */
93 ir_nodeset_t parents; /**< = S a set of value producers */
94 ir_nodeset_t children; /**< = T a set of value consumers */
95 pset *kill_edges; /**< = E a set of edges (t in T, s in S) such as each s in S gets killed by at least one t in T */
96 int nr; /**< a deterministic index for set insertion (used as hash) */
99 /* Represents a disjoint value DAG. */
100 typedef struct _dvg {
105 /* Represents a chain of nodes. */
106 typedef struct _chain {
107 plist_t *elements; /**< List of chain elements */
108 int nr; /**< a deterministic index for set insertion (used as hash) */
111 typedef struct _rss_irn {
112 plist_t *consumer_list; /**< List of consumers */
113 ir_node **consumer; /**< Sorted consumer array (needed for faster access) */
115 plist_t *parent_list; /**< List of parents */
116 plist_t *pkiller_list; /**< List of potential killers */
118 plist_t *descendant_list; /**< List of descendants */
119 ir_node **descendants; /**< Sorted descendant array (needed for faster access) */
121 ir_node *killer; /**< The selected unique killer */
122 ir_node *irn; /**< The corresponding firm node to this rss_irn */
124 chain_t *chain; /**< The chain, this node is associated to */
126 unsigned desc_walk; /**< visited flag for collecting descendants */
127 unsigned kill_count; /**< number of nodes killed by this one */
129 unsigned live_out : 1; /**< irn has consumers outside of it's block */
130 unsigned visited : 1; /**< visited flag for bipartite decomposition */
131 unsigned havecons : 1; /**< visited flag collect consumer */
132 unsigned handled : 1; /**< flag indicating whether or not the list structures have been build */
133 unsigned dumped : 1; /**< flag indication whether or not this node was dumped */
136 /* Represents a serialization edge with associated costs. */
137 typedef struct _serialization {
138 rss_irn_t *u; /* the top node */
139 rss_irn_t *v; /* the node about to be serialized after u */
140 rss_edge_t *edge; /* the edge selected for the serialization */
141 int omega1; /* estimated: available regs - RS reduction */
142 int omega2; /* increase in critical path length */
146 typedef struct _rss {
147 ir_phase ph; /**< Phase to hold some data */
148 heights_t *h; /**< The current height object */
149 ir_graph *irg; /**< The irg to preprocess */
150 plist_t *nodes; /**< The list of interesting nodes */
151 const arch_env_t *arch_env; /**< The architecture environment */
152 be_abi_irg_t *abi; /**< The abi for this irg */
153 pset *cbc_set; /**< A set of connected bipartite components */
154 ir_node *block; /**< The current block in progress. */
155 int *idx_map; /**< Mapping irn indices to per block indices */
156 unsigned max_height; /**< maximum height in the current block */
157 rss_opts_t *opts; /**< The options */
158 be_lv_t *liveness; /**< The liveness information for this irg */
159 pset *live_block; /**< Values alive at end of block */
160 const arch_register_class_t *cls; /**< The current register class */
161 DEBUG_ONLY(firm_dbg_module_t *dbg);
164 #define get_rss_irn(rss, irn) (phase_get_or_set_irn_data(&rss->ph, irn))
167 * We need some special nodes:
168 * a source and a sink for all live-in and live-out values of a block
176 /** The opcode of the rss_Source node once allocated. */
177 static ir_op *op_rss_Source;
178 /** The opcode of the rss_Sink node once allocated. */
179 static ir_op *op_rss_Sink;
181 /** The rss_Source node of the current graph. */
182 static ir_node *_source = NULL;
183 /** The rss_Sink node of the current graph. */
184 static ir_node *_sink = NULL;
186 #define is_Source(irn) ((irn) == _source)
187 #define is_Sink(irn) ((irn) == _sink)
191 RSS_DUMP_CBC = 1 << 0,
192 RSS_DUMP_PKG = 1 << 1,
193 RSS_DUMP_KILL = 1 << 2,
194 RSS_DUMP_DVG = 1 << 3,
195 RSS_DUMP_MAXAC = 1 << 4,
196 RSS_DUMP_ALL = (RSS_DUMP_MAXAC << 1) - 1,
199 static rss_opts_t rss_options = {
203 static const lc_opt_enum_int_items_t dump_items[] = {
204 { "none", RSS_DUMP_NONE },
205 { "cbc", RSS_DUMP_CBC },
206 { "pkg", RSS_DUMP_PKG },
207 { "kill", RSS_DUMP_KILL },
208 { "dvg", RSS_DUMP_DVG },
209 { "maxac", RSS_DUMP_MAXAC },
210 { "all", RSS_DUMP_ALL },
214 static lc_opt_enum_int_var_t dump_var = {
215 &rss_options.dump_flags, dump_items
218 static const lc_opt_table_entry_t rss_option_table[] = {
219 LC_OPT_ENT_ENUM_MASK("dump", "dump phases", &dump_var),
223 /******************************************************************************
225 * | | | | / _| | | (_)
226 * | |__ ___| |_ __ ___ _ __ | |_ _ _ _ __ ___| |_ _ ___ _ __ ___
227 * | '_ \ / _ \ | '_ \ / _ \ '__| | _| | | | '_ \ / __| __| |/ _ \| '_ \/ __|
228 * | | | | __/ | |_) | __/ | | | | |_| | | | | (__| |_| | (_) | | | \__ \
229 * |_| |_|\___|_| .__/ \___|_| |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/
232 ******************************************************************************/
235 * Acquire opcodes if needed and create source and sink nodes.
237 static void init_rss_special_nodes(ir_graph *irg) {
240 if (op_rss_Source == NULL) {
241 int iro_rss_base = get_next_ir_opcodes(iro_rss_last);
242 op_rss_Source = new_ir_op(iro_rss_base + iro_rss_Source, "rss_Source", op_pin_state_pinned, irop_flag_none, oparity_zero, 0, 0, NULL);
243 op_rss_Sink = new_ir_op(iro_rss_base + iro_rss_Sink, "rss_Sink", op_pin_state_pinned, irop_flag_none, oparity_zero, 0, 0, NULL);
245 block = get_irg_start_block(irg);
246 _source = new_ir_node(NULL, irg, block, op_rss_Source, mode_ANY, 0, NULL);
247 _sink = new_ir_node(NULL, irg, block, op_rss_Sink, mode_ANY, 0, NULL);
250 static int cmp_int(const void *a, const void *b) {
254 return QSORT_CMP(*i1, *i2);
257 static int cmp_child_costs(const void *a, const void *b) {
258 const child_t *c1 = a;
259 const child_t *c2 = b;
261 return QSORT_CMP(c1->cost, c2->cost);
264 static int cmp_irn_idx(const void *a, const void *b) {
265 const ir_node *n1 = *(ir_node **)a;
266 const ir_node *n2 = *(ir_node **)b;
268 return QSORT_CMP(get_irn_idx(n1), get_irn_idx(n2));
271 static int cmp_rss_edges(const void *a, const void *b) {
272 const rss_edge_t *e1 = a;
273 const rss_edge_t *e2 = b;
275 return (e1->src != e2->src) || (e1->tgt != e2->tgt);
278 static int bsearch_for_index(int key, int *arr, size_t len, int force) {
282 while (right >= left) {
283 int idx = (left + right) / 2;
287 else if (key > arr[idx])
294 assert(0 && "Something is wrong, key not found.");
298 static ir_node **build_sorted_array_from_list(plist_t *irn_list, struct obstack *obst) {
301 int len = plist_count(irn_list);
302 ir_node **arr = NEW_ARR_D(ir_node *, obst, len);
304 /* copy the list into the array */
305 foreach_plist(irn_list, el) {
306 arr[i++] = plist_element_get_value(el);
309 /* sort the array by node index */
310 qsort(arr, len, sizeof(arr[0]), cmp_irn_idx);
315 /*****************************************************
318 * __| | ___| |__ _ _ __ _ __ _ _ _ __ __ _
319 * / _` |/ _ \ '_ \| | | |/ _` |/ _` | | '_ \ / _` |
320 * | (_| | __/ |_) | |_| | (_| | (_| | | | | | (_| |
321 * \__,_|\___|_.__/ \__,_|\__, |\__, |_|_| |_|\__, |
325 *****************************************************/
328 static void dump_nodeset(ir_nodeset_t *ns, const char *prefix) {
329 ir_nodeset_iterator_t iter;
332 ir_nodeset_iterator_init(&iter, ns);
333 while( (irn = ir_nodeset_iterator_next(&iter)) != NULL ) {
334 ir_fprintf(stderr, "%s%+F\n", prefix, irn);
339 static void build_file_name(rss_t *rss, const char *suffix, size_t suf_len, char *buf, size_t len) {
340 const char *irg_name;
343 irg_name = get_entity_name(get_irg_entity(rss->irg));
344 snprintf(buf, len - suf_len, "%s-%s-block-%ld",
345 irg_name, arch_register_class_name(rss->cls), get_irn_node_nr(rss->block));
349 /* Dumps all collected bipartite components of current irg as vcg. */
350 static void debug_vcg_dump_bipartite(rss_t *rss) {
354 static const char suffix[] = "-RSS-CBC.vcg";
356 build_file_name(rss, suffix, sizeof(suffix), file_name, sizeof(file_name));
357 f = fopen(file_name, "w");
359 ir_fprintf(f, "graph: { title: \"connected bipartite component graph of %+F\"\n", rss->irg);
360 fprintf(f, "display_edge_labels: no\n");
361 fprintf(f, "layoutalgorithm: mindepth\n");
362 fprintf(f, "manhattan_edges: yes\n\n");
364 foreach_pset(rss->cbc_set, cbc) {
365 ir_nodeset_iterator_t iter;
369 fprintf(f, "graph: { titel: \"cbc %d\" label: \"cbc %d\" status:clustered color:yellow\n", cbc->nr, cbc->nr);
370 foreach_ir_nodeset(&cbc->parents, n, iter) {
371 ir_fprintf(f, "node: { title: \"n%d_%d\" label: \"%+F\" }\n", get_irn_node_nr(n), cbc->nr, n);
373 foreach_ir_nodeset(&cbc->children, n, iter) {
374 ir_fprintf(f, "node: { title: \"n%d_%d\" label: \"%+F\" }\n", get_irn_node_nr(n), cbc->nr, n);
376 foreach_pset(cbc->kill_edges, ke) {
377 ir_fprintf(f, "edge: { sourcename: \"n%d_%d\" targetname: \"n%d_%d\" }\n",
378 get_irn_node_nr(ke->src), cbc->nr, get_irn_node_nr(ke->tgt), cbc->nr);
386 /* Dump the computed killing function as vcg. */
387 static void debug_vcg_dump_kill(rss_t *rss) {
391 static const char suffix[] = "-RSS-KILL.vcg";
393 build_file_name(rss, suffix, sizeof(suffix), file_name, sizeof(file_name));
394 f = fopen(file_name, "w");
396 ir_fprintf(f, "graph: { title: \"computed kill graph of %+F, block %d\"\n", rss->irg, get_irn_node_nr(rss->block));
397 fprintf(f, "display_edge_labels: no\n");
398 fprintf(f, "layoutalgorithm: mindepth\n");
399 fprintf(f, "manhattan_edges: yes\n\n");
402 /* reset dump_flag */
404 foreach_phase_irn(&rss->ph, irn) {
405 rss_irn_t *node = get_rss_irn(rss, irn);
410 /* dump all nodes and their killers */
411 foreach_plist(rss->nodes, el) {
412 ir_node *irn = plist_element_get_value(el);
413 rss_irn_t *rirn = get_rss_irn(rss, irn);
414 rss_irn_t *pk_rirn = get_rss_irn(rss, rirn->killer);
416 if (! rirn->dumped) {
417 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" }\n", get_irn_node_nr(irn), irn);
421 if (! pk_rirn->dumped) {
422 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" }\n", get_irn_node_nr(rirn->killer), rirn->killer);
426 ir_fprintf(f, "edge: { sourcename: \"n%d\" targetname: \"n%d\" }\n",
427 get_irn_node_nr(rirn->killer), get_irn_node_nr(irn));
434 /* Dumps the potential killing DAG (PKG) as vcg. */
435 static void debug_vcg_dump_pkg(rss_t *rss, ir_nodeset_t *max_ac, int iteration) {
438 char *suffix = alloca(32);
439 static const char suffix1[] = "-RSS-PKG.vcg";
440 static const char suffix2[] = "-RSS-PKG-MAXAC.vcg";
444 snprintf(suffix, 32, "%s", suffix1);
447 snprintf(suffix, 32, "-%02d%s", iteration, suffix2);
450 build_file_name(rss, suffix, strlen(suffix) + 1, file_name, sizeof(file_name));
451 f = fopen(file_name, "w");
453 ir_fprintf(f, "graph: { title: \"potential killing DAG of %+F, block %d\"\n", rss->irg, get_irn_node_nr(rss->block));
454 fprintf(f, "display_edge_labels: no\n");
455 fprintf(f, "layoutalgorithm: mindepth\n");
456 fprintf(f, "manhattan_edges: yes\n\n");
459 /* reset dump_flag */
461 foreach_phase_irn(&rss->ph, irn) {
462 rss_irn_t *node = get_rss_irn(rss, irn);
467 foreach_plist(rss->nodes, el) {
468 ir_node *irn = plist_element_get_value(el);
469 rss_irn_t *rirn = get_rss_irn(rss, irn);
471 plist_element_t *k_el;
473 /* dump selected saturating values in yellow */
474 if (max_ac && ir_nodeset_contains(max_ac, irn))
477 if (! rirn->dumped) {
479 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F c%d\" %s }\n", get_irn_node_nr(irn), irn, rirn->chain->nr, c1);
481 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" %s }\n", get_irn_node_nr(irn), irn, c1);
485 foreach_plist(rirn->pkiller_list, k_el) {
486 ir_node *pkiller = plist_element_get_value(k_el);
487 rss_irn_t *pk_rirn = get_rss_irn(rss, pkiller);
490 if (max_ac && ir_nodeset_contains(max_ac, pkiller))
493 if (! pk_rirn->dumped) {
495 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F c%d\" %s }\n", get_irn_node_nr(pkiller), pkiller, pk_rirn->chain->nr, c2);
497 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" %s }\n", get_irn_node_nr(pkiller), pkiller, c2);
500 ir_fprintf(f, "edge: { sourcename: \"n%d\" targetname: \"n%d\" }\n",
501 get_irn_node_nr(pkiller), get_irn_node_nr(irn));
508 /* Dumps the disjoint value DAG (DVG) as vcg. */
509 static void debug_vcg_dump_dvg(rss_t *rss, dvg_t *dvg) {
510 static const char suffix[] = "-RSS-DVG.vcg";
513 ir_nodeset_iterator_t iter;
517 build_file_name(rss, suffix, sizeof(suffix), file_name, sizeof(file_name));
518 f = fopen(file_name, "w");
520 ir_fprintf(f, "graph: { title: \"disjoint value DAG of %+F, block %d\"\n", rss->irg, get_irn_node_nr(rss->block));
521 fprintf(f, "display_edge_labels: no\n");
522 fprintf(f, "layoutalgorithm: mindepth\n");
523 fprintf(f, "manhattan_edges: yes\n\n");
526 foreach_ir_nodeset(&dvg->nodes, irn, iter) {
527 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" }\n", get_irn_node_nr(irn), irn);
531 foreach_pset(dvg->edges, edge) {
532 ir_fprintf(f, "edge: { sourcename: \"n%d\" targetname: \"n%d\" }\n",
533 get_irn_node_nr(edge->src), get_irn_node_nr(edge->tgt));
541 /* Dumps the PKG(DVG). */
542 static void debug_vcg_dump_dvg_pkiller(rss_t *rss, dvg_t *dvg) {
543 static const char suffix[] = "-RSS-DVG-PKG.vcg";
546 ir_nodeset_iterator_t iter;
549 build_file_name(rss, suffix, sizeof(suffix), file_name, sizeof(file_name));
550 f = fopen(file_name, "w");
552 ir_fprintf(f, "graph: { title: \"PKG of disjoint value DAG of %+F, block %d\"\n", rss->irg, get_irn_node_nr(rss->block));
553 fprintf(f, "display_edge_labels: no\n");
554 fprintf(f, "layoutalgorithm: mindepth\n");
555 fprintf(f, "manhattan_edges: yes\n\n");
558 foreach_ir_nodeset(&dvg->nodes, irn, iter) {
559 ir_fprintf(f, "node: { title: \"n%d\" label: \"%+F\" }\n", get_irn_node_nr(irn), irn);
563 foreach_ir_nodeset(&dvg->nodes, irn, iter) {
564 rss_irn_t *node = get_rss_irn(rss, irn);
567 foreach_plist(node->dvg_pkiller_list, el) {
568 ir_fprintf(f, "edge: { sourcename: \"n%d\" targetname: \"n%d\" }\n",
569 get_irn_node_nr(plist_element_get_value(el)), get_irn_node_nr(irn));
579 * In case there is no rss information for irn, initialize it.
581 static void *init_rss_irn(ir_phase *ph, ir_node *irn, void *old) {
582 rss_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
584 res->descendant_list = plist_obstack_new(phase_obst(ph));
585 res->descendants = NULL;
587 res->consumer_list = plist_obstack_new(phase_obst(ph));
588 res->consumer = NULL;
590 res->pkiller_list = plist_obstack_new(phase_obst(ph));
592 res->parent_list = plist_obstack_new(phase_obst(ph));
610 * Collect all nodes data dependent on current node.
612 static void collect_descendants(rss_t *rss, rss_irn_t *rirn, ir_node *irn, int *got_sink, unsigned cur_desc_walk) {
613 const ir_edge_t *edge;
614 rss_irn_t *cur_node = get_rss_irn(rss, irn);
615 ir_node *block = rss->block;
616 ir_edge_kind_t ekind[2] = { EDGE_KIND_NORMAL, EDGE_KIND_DEP };
619 if (cur_node->desc_walk >= cur_desc_walk)
621 cur_node->desc_walk = cur_desc_walk;
623 /* Stop at Barriers */
624 if (be_is_Barrier(irn))
627 /* loop over normal and dependency edges */
628 for (i = 0; i < 2; ++i) {
629 foreach_out_edge_kind(irn, edge, ekind[i]) {
630 ir_node *user = get_edge_src_irn(edge);
632 /* skip ignore nodes as they do not really contribute to register pressure */
633 if (arch_irn_is(rss->arch_env, user, ignore))
637 (a) mode_X means Jump -> out_edge
638 (b) Phi as user of a normal node -> out-edge
640 if (get_irn_mode(user) == mode_X || is_Phi(user)) {
649 //if (arch_get_irn_reg_class(rss->arch_env, user, -1) == rss->cls)
650 collect_descendants(rss, rirn, user, got_sink, cur_desc_walk);
653 /* check if user lives in block and is not a control flow node */
654 if (get_nodes_block(user) == block) {
655 if (! plist_has_value(rirn->descendant_list, user)) {
656 plist_insert_back(rirn->descendant_list, user);
657 DBG((rss->dbg, LEVEL_2, "\t\tdescendant %+F\n", user));
659 collect_descendants(rss, rirn, user, got_sink, cur_desc_walk);
661 else if (! *got_sink) {
663 /* user lives out of block: add sink as descendant if not already done */
664 plist_insert_back(rirn->descendant_list, _sink);
666 DBG((rss->dbg, LEVEL_2, "\t\tdescendant %+F\n", _sink));
674 * Handles a single consumer.
676 static void collect_single_consumer(rss_t *rss, rss_irn_t *rss_irn, ir_node *consumer, int *got_sink) {
677 ir_node *block = rss->block;
679 assert(! is_Proj(consumer) && "Cannot handle Projs");
681 if (! is_Phi(consumer) && ! is_Block(consumer) && get_nodes_block(consumer) == block) {
682 if (! arch_irn_is(rss->arch_env, consumer, ignore) && ! plist_has_value(rss_irn->consumer_list, consumer)) {
683 plist_insert_back(rss_irn->consumer_list, consumer);
684 DBG((rss->dbg, LEVEL_2, "\t\tconsumer %+F\n", consumer));
688 rss_irn->live_out = 1;
689 DBG((rss->dbg, LEVEL_2, "\t\tlive out %+F", consumer));
691 plist_insert_back(rss_irn->consumer_list, _sink);
693 DB((rss->dbg, LEVEL_2, ", %+F added instead", _sink));
695 DB((rss->dbg, LEVEL_2, "\n"));
700 * Collect all nodes consuming the value(s) produced by current node.
702 static void collect_consumer(rss_t *rss, rss_irn_t *rss_irn, ir_node *irn, int *got_sink) {
703 const ir_edge_t *edge;
705 ir_edge_kind_t ekind[2] = { EDGE_KIND_NORMAL, EDGE_KIND_DEP };
706 rss_irn_t *cur_node = get_rss_irn(rss, irn);
708 if (cur_node->havecons)
710 cur_node->havecons = 1;
712 for (i = 0; i < 2; ++i) {
713 foreach_out_edge_kind(irn, edge, ekind[i]) {
714 ir_node *consumer = get_edge_src_irn(edge);
716 if (is_Proj(consumer)) {
717 //if (arch_get_irn_reg_class(rss->arch_env, consumer, -1) == rss->cls)
718 collect_consumer(rss, rss_irn, consumer, got_sink);
721 collect_single_consumer(rss, rss_irn, consumer, got_sink);
727 * Collects all consumer and descendant of a irn.
729 static void collect_node_info(rss_t *rss, ir_node *irn) {
730 static unsigned cur_desc_walk = 0;
731 rss_irn_t *rss_irn = get_rss_irn(rss, irn);
734 assert(! is_Proj(irn) && "Cannot handle Projs.");
736 /* check if node info is already available */
737 if (rss_irn->handled)
739 //phase_reinit_single_irn_data(&rss->ph, irn);
741 DBG((rss->dbg, LEVEL_1, "\tcomputing consumers of %+F:\n", irn));
743 /* collect all consumer */
745 collect_consumer(rss, rss_irn, irn, &got_sink);
747 /* build sorted consumer array */
748 rss_irn->consumer = build_sorted_array_from_list(rss_irn->consumer_list, phase_obst(&rss->ph));
750 DBG((rss->dbg, LEVEL_1, "\tcompute descendants of %+F:\n", irn));
752 /* collect descendants */
754 collect_descendants(rss, rss_irn, irn, &got_sink, ++cur_desc_walk);
756 /* build sorted descendant array */
757 rss_irn->descendants = build_sorted_array_from_list(rss_irn->descendant_list, phase_obst(&rss->ph));
759 rss_irn->handled = 1;
763 * Checks if v is a potential killer of u.
764 * v is in pkill(u) iff descendants(v) cut consumer(u) is v
766 * @param rss The rss object
767 * @param v The node to check for killer
768 * @param u The potentially killed value
769 * @return 1 if v is in pkill(u), 0 otherwise
771 static int is_potential_killer(rss_t *rss, rss_irn_t *v, rss_irn_t *u) {
776 assert(is_Sink(v->irn) || ((plist_count(v->descendant_list) > 0 && v->descendants) || 1));
777 assert(is_Sink(u->irn) || ((plist_count(u->consumer_list) > 0 && u->consumer) || 1));
779 /* as we loop over the list: loop over the shorter one */
780 if (plist_count(v->descendant_list) > plist_count(u->consumer_list)) {
781 list = u->consumer_list;
782 arr = v->descendants;
785 list = v->descendant_list;
789 /* for each list element: try to find element in array */
790 foreach_plist(list, el) {
791 ir_node *irn = plist_element_get_value(el);
792 ir_node *match = BSEARCH_IRN_ARR(irn, arr);
794 if (match && match != irn)
802 * Update descendants, consumer and pkiller list for the given irn.
804 static void update_node_info(rss_t *rss, ir_node *irn, ir_node *pk_irn) {
805 rss_irn_t *node = get_rss_irn(rss, irn);
806 rss_irn_t *pkiller = get_rss_irn(rss, pk_irn);
808 /* add consumer and rebuild the consumer array */
809 if (! plist_has_value(node->consumer_list, pk_irn)) {
810 plist_insert_back(node->consumer_list, pk_irn);
811 node->consumer = build_sorted_array_from_list(node->consumer_list, phase_obst(&rss->ph));
814 /* add pk_irn as descendant, add it's descendants to irn's and rebuild array */
815 if (! plist_has_value(node->descendant_list, pk_irn)) {
818 plist_insert_back(node->descendant_list, pk_irn);
820 foreach_plist(pkiller->descendant_list, el) {
821 ir_node *desc = plist_element_get_value(el);
823 if (! plist_has_value(node->descendant_list, desc))
824 plist_insert_back(node->descendant_list, desc);
827 node->descendants = build_sorted_array_from_list(node->descendant_list, phase_obst(&rss->ph));
833 * Compute the potential killing set PK.
835 static void compute_pkill_set(rss_t *rss) {
836 plist_element_t *u_el, *v_el;
838 foreach_plist(rss->nodes, u_el) {
839 ir_node *u_irn = plist_element_get_value(u_el);
840 rss_irn_t *u = get_rss_irn(rss, u_irn);
842 DBG((rss->dbg, LEVEL_1, "\tcomputing potential killers of %+F:\n", u_irn));
844 /* check each consumer if it is a potential killer */
845 foreach_plist(u->consumer_list, v_el) {
846 ir_node *v_irn = plist_element_get_value(v_el);
847 rss_irn_t *v = get_rss_irn(rss, v_irn);
849 /* check, if v is a potential killer of u */
850 if (is_potential_killer(rss, v, u)) {
851 if (! plist_has_value(u->pkiller_list, v_irn))
852 plist_insert_back(u->pkiller_list, v_irn);
854 DBG((rss->dbg, LEVEL_2, "\t\tpotential killer %+F\n", v_irn));
861 if (rss->opts->dump_flags & RSS_DUMP_PKG)
862 debug_vcg_dump_pkg(rss, NULL, 0);
866 * Build set of killing edges (from values to their potential killers)
868 static void build_kill_edges(rss_t *rss, pset *epk) {
869 plist_element_t *el, *k_el;
871 foreach_plist(rss->nodes, el) {
872 ir_node *irn = plist_element_get_value(el);
873 rss_irn_t *rirn = get_rss_irn(rss, irn);
875 DBG((rss->dbg, LEVEL_3, "\t\tbuilding kill edges for %+F:\n", irn));
877 foreach_plist(rirn->pkiller_list, k_el) {
878 ir_node *pkiller = plist_element_get_value(k_el);
879 rss_edge_t *ke = obstack_alloc(phase_obst(&rss->ph), sizeof(*ke));
885 DBG((rss->dbg, LEVEL_3, "\t\t\ttarget %+F\n", pkiller));
887 pset_insert(epk, ke, HASH_RSS_EDGE(ke));
893 /* print the given cbc for debugging purpose */
894 static void debug_print_cbc(firm_dbg_module_t *mod, cbc_t *cbc) {
895 ir_nodeset_iterator_t iter;
899 DBG((mod, LEVEL_3, "\t\tS = set of parents:\n"));
900 foreach_ir_nodeset(&cbc->parents, n, iter) {
901 DBG((mod, LEVEL_3, "\t\t\t%+F\n", n));
903 DBG((mod, LEVEL_3, "\t\tT = set of children:\n"));
904 foreach_ir_nodeset(&cbc->children, n, iter) {
905 DBG((mod, LEVEL_3, "\t\t\t%+F\n", n));
907 DBG((mod, LEVEL_3, "\t\tE = Edges from producers to consumers\n"));
908 foreach_pset(cbc->kill_edges, ke) {
909 DBG((mod, LEVEL_3, "\t\t\t%+F -> %+F\n", ke->src, ke->tgt));
915 * Construct the bipartite decomposition.
916 * Sid-Ahmed-Ali Touati, Phd Thesis
917 * Register Pressure in Instruction Level Parallelism, p. 71
919 static void compute_bipartite_decomposition(rss_t *rss) {
920 pset *epk = new_pset(cmp_rss_edges, 10);
925 DBG((rss->dbg, LEVEL_1, "\tcomputing bipartite decomposition:\n"));
927 build_kill_edges(rss, epk);
929 foreach_plist(rss->nodes, el) {
930 ir_node *u_irn = plist_element_get_value(el);
931 rss_irn_t *u = get_rss_irn(rss, u_irn);
937 plist_element_t *el2;
939 rss_edge_t *kedge_root = NULL;
940 ir_node *t_irn, *s_irn;
941 ir_nodeset_iterator_t iter;
943 if (u->visited || u_irn == _sink)
946 DBG((rss->dbg, LEVEL_2, "\t\t%+F choosen:\n", u_irn));
948 cbc = obstack_alloc(phase_obst(&rss->ph), sizeof(*cbc));
951 /* initialize S_cb */
952 ir_nodeset_init_size(&cbc->parents, 5);
953 ir_nodeset_insert(&cbc->parents, u_irn);
954 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F added to parents (init)\n", u_irn));
957 cbc->kill_edges = new_pset(cmp_rss_edges, 5);
959 /* each parent gets killed by at least one value from children */
961 /* T_cb = PK_successors(u) */
962 ir_nodeset_init_size(&cbc->children, 5);
963 foreach_plist(u->pkiller_list, el2) {
964 ir_nodeset_insert(&cbc->children, plist_element_get_value(el2));
965 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F added to children (init)\n", plist_element_get_value(el2)));
969 Now: insert the parents of all children into the parent set
970 and insert the children of all parents into the children set
971 until the sets don't change any more
973 while (p_change || c_change) {
974 ir_nodeset_iterator_t iter;
975 p_change = c_change = 0;
977 /* accumulate parents */
978 foreach_ir_nodeset(&cbc->children, t_irn, iter) {
979 foreach_pset(epk, k_edge) {
980 ir_node *val = k_edge->src;
982 if (k_edge->tgt == t_irn && ! ir_nodeset_contains(&cbc->parents, val)) {
983 ir_nodeset_insert(&cbc->parents, val);
985 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F added to parents (killed by %+F)\n", val, t_irn));
990 /* accumulate children */
991 foreach_ir_nodeset(&cbc->parents, s_irn, iter) {
992 foreach_pset(epk, k_edge) {
993 ir_node *val = k_edge->tgt;
995 if (k_edge->src == s_irn && ! ir_nodeset_contains(&cbc->children, val)) {
996 ir_nodeset_insert(&cbc->children, val);
998 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F added to children (kills %+F)\n", val, s_irn));
1004 /* mark all parent values as visited */
1005 foreach_ir_nodeset(&cbc->parents, s_irn, iter) {
1006 rss_irn_t *s = get_rss_irn(rss, s_irn);
1008 /* assure bipartite property */
1010 if (ir_nodeset_contains(&cbc->children, s_irn)) {
1011 ir_nodeset_remove(&cbc->children, s_irn);
1012 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F removed from to children\n", s_irn));
1018 foreach_pset(epk, k_edge) {
1019 if (ir_nodeset_contains(&cbc->parents, k_edge->src) &&
1020 ir_nodeset_contains(&cbc->children, k_edge->tgt)) {
1021 pset_insert(cbc->kill_edges, k_edge, HASH_RSS_EDGE(k_edge));
1023 Link all k_edges which are about to be removed together.
1024 Beware: pset_remove kills the iterator.
1026 k_edge->next = kedge_root;
1027 kedge_root = k_edge;
1031 /* remove all linked k_edges */
1032 for (; kedge_root; kedge_root = kedge_root->next) {
1033 pset_remove(epk, kedge_root, HASH_RSS_EDGE(kedge_root));
1036 /* verify the cbc */
1037 foreach_ir_nodeset(&cbc->parents, s_irn, iter) {
1040 foreach_pset(cbc->kill_edges, k_edge) {
1041 if (k_edge->src == s_irn) {
1043 pset_break(cbc->kill_edges);
1050 ir_fprintf(stderr, "Warning: parent %+F is not killed in current cbc\n", s_irn);
1053 assert(vrfy_ok && "Verification of CBC failed");
1055 /* add the connected bipartite component */
1056 if (ir_nodeset_size(&cbc->parents) > 0 &&
1057 ir_nodeset_size(&cbc->children) > 0 &&
1058 pset_count(cbc->kill_edges) > 0)
1059 pset_insert(rss->cbc_set, cbc, (unsigned)cbc->nr);
1060 DBG((rss->dbg, LEVEL_2, "\tbipartite component %d inserted:\n", cbc->nr));
1062 if (firm_dbg_get_mask(rss->dbg) & LEVEL_2)
1063 debug_print_cbc(rss->dbg, cbc);
1067 if (rss->opts->dump_flags & RSS_DUMP_CBC)
1068 debug_vcg_dump_bipartite(rss);
1074 * Select the child with the maximum cost.
1076 static child_t *select_child_max_cost(rss_t *rss, ir_nodeset_t *x, ir_nodeset_t *y, child_t *t, cbc_t *cbc) {
1078 ir_nodeset_iterator_t iter;
1079 float max_cost = -1.0f;
1081 DBG((rss->dbg, LEVEL_2, "\t\tcomputing children costs:\n"));
1083 foreach_ir_nodeset(&cbc->children, child, iter) {
1084 rss_irn_t *r_child = get_rss_irn(rss, child);
1085 int num_unkilled_parents = 0;
1086 int num_descendants;
1090 /* get the number of unkilled parents */
1091 foreach_pset(cbc->kill_edges, k_edge) {
1092 if (k_edge->tgt == child && ir_nodeset_contains(x, k_edge->src))
1093 ++num_unkilled_parents;
1096 cost = (float)num_unkilled_parents;
1098 num_descendants = plist_count(r_child->descendant_list) + ir_nodeset_size(y);
1100 if (num_descendants > 0)
1101 cost /= (float)num_descendants;
1103 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F, #desc %d, cost %.3f\n", child, num_descendants, cost));
1105 if (cost > max_cost) {
1116 * Remove all parents from x which are killed by t_irn.
1118 static void remove_covered_parents(rss_t *rss, ir_nodeset_t *x, ir_node *t_irn, cbc_t *cbc) {
1119 rss_irn_t *t = get_rss_irn(rss, t_irn);
1122 DBG((rss->dbg, LEVEL_2, "\t\tremoving parents covered by %+F:\n", t_irn));
1124 foreach_pset(cbc->kill_edges, k_edge) {
1125 if (k_edge->tgt == t_irn && ir_nodeset_contains(x, k_edge->src)) {
1126 ir_nodeset_remove(x, k_edge->src);
1127 plist_insert_back(t->parent_list, k_edge->src);
1128 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F\n", k_edge->src));
1133 static void update_cumulated_descendent_values(rss_t *rss, ir_nodeset_t *y, ir_node *t_irn) {
1134 rss_irn_t *t = get_rss_irn(rss, t_irn);
1135 plist_element_t *el;
1137 DBG((rss->dbg, LEVEL_2, "\t\tupdating cumulated descendant value of %+F:\n", t_irn));
1139 foreach_plist(t->descendant_list, el) {
1140 ir_nodeset_insert(y, plist_element_get_value(el));
1141 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F\n", plist_element_get_value(el)));
1146 * Greedy-k: a heuristics for the MMA problem
1148 static void compute_killing_function(rss_t *rss) {
1150 struct obstack obst;
1152 obstack_init(&obst);
1154 rss->cbc_set = pset_new_ptr(5);
1155 compute_bipartite_decomposition(rss);
1157 /* for all bipartite components do: */
1158 foreach_pset(rss->cbc_set, cbc) {
1162 ir_nodeset_iterator_t iter;
1163 child_t **sks = NEW_ARR_F(child_t *, 20);
1168 ir_nodeset_init_size(&x, 10);
1169 ir_nodeset_init_size(&y, 10);
1171 DBG((rss->dbg, LEVEL_1, "\tcomputing SKS for cbc %d:\n", cbc->nr));
1172 DBG((rss->dbg, LEVEL_2, "\t\tinitializing parents X:\n"));
1174 /* X = S_cb (all parents are initially uncovered) */
1175 foreach_ir_nodeset(&cbc->parents, p, iter) {
1176 ir_nodeset_insert(&x, p);
1177 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F\n", p));
1180 /* while X not empty */
1181 while (ir_nodeset_size(&x) > 0) {
1182 child_t *t = obstack_alloc(&obst, sizeof(*t));
1183 memset(t, 0, sizeof(*t));
1185 t = select_child_max_cost(rss, &x, &y, t, cbc);
1187 if (cur_len >= cur_size) {
1188 ARR_EXTO(child_t *, sks, cur_size * 2);
1192 DBG((rss->dbg, LEVEL_2, "\t\tinsert child %+F (%.3f) into SKS at pos %d\n", t->irn, t->cost, cur_len));
1195 remove_covered_parents(rss, &x, t->irn, cbc);
1196 update_cumulated_descendent_values(rss, &y, t->irn);
1199 ARR_SHRINKLEN(sks, cur_len);
1201 /* sort SKS in increasing cost order */
1202 qsort(sks, cur_len, sizeof(sks[0]), cmp_child_costs);
1204 DBG((rss->dbg, LEVEL_2, "\tprocessing SKS for cbc %d:\n", cbc->nr));
1206 /* build killing function */
1207 for (i = cur_len - 1; i >= 0; --i) { /* loop over sks in decreasing cost order */
1208 child_t *t = sks[i];
1209 rss_irn_t *rt = get_rss_irn(rss, t->irn);
1210 plist_element_t *p_el;
1212 DBG((rss->dbg, LEVEL_3, "\t\t\tkiller %+F (%.3f):\n", t->irn, t->cost));
1214 /* kill all unkilled parents of t */
1215 foreach_plist(rt->parent_list, p_el) {
1216 ir_node *par = plist_element_get_value(p_el);
1217 rss_irn_t *rpar = get_rss_irn(rss, par);
1219 if (is_Sink(rpar->killer)) {
1220 rpar->killer = t->irn;
1221 DBG((rss->dbg, LEVEL_2, "\t\tkill %+F\n", rpar->irn));
1224 DBG((rss->dbg, LEVEL_3, "\t\t\tkeeping %+F as killer for %+F\n", rpar->killer, rpar->irn));
1229 ir_nodeset_destroy(&x);
1230 ir_nodeset_destroy(&y);
1234 if (rss->opts->dump_flags & RSS_DUMP_KILL)
1235 debug_vcg_dump_kill(rss);
1237 del_pset(rss->cbc_set);
1238 obstack_free(&obst, NULL);
1242 * Adds the edge src -> tgt to the dvg. Checks if reverse edge is already there (asserts).
1244 static INLINE void add_dvg_edge(rss_t *rss, dvg_t *dvg, ir_node *src, ir_node *tgt, int have_source) {
1245 rss_edge_t *dvg_edge;
1249 ir_nodeset_insert(&dvg->nodes, src);
1251 assert(ir_nodeset_contains(&dvg->nodes, src) && "Wrong assumption");
1253 ir_nodeset_insert(&dvg->nodes, tgt);
1257 assert(pset_find(dvg->edges, &key, HASH_RSS_EDGE(&key)) == NULL && "DVG must be acyclic!");
1261 if (NULL != pset_find(dvg->edges, &key, HASH_RSS_EDGE(&key))) {
1262 /* add the edge to the DVG */
1263 dvg_edge = obstack_alloc(phase_obst(&rss->ph), sizeof(*dvg_edge));
1265 dvg_edge->src = src;
1266 dvg_edge->tgt = tgt;
1267 dvg_edge->next = NULL;
1269 DBG((rss->dbg, LEVEL_3, "\t\tadd edge %+F -> %+F\n", src, tgt));
1270 pset_insert(dvg->edges, dvg_edge, HASH_RSS_EDGE(dvg_edge));
1275 * Computes the disjoint value DAG (DVG).
1276 * BEWARE: It is not made explicitly clear in the Touati paper,
1277 * but the DVG is meant to be build from the KILLING DAG
1279 static void compute_dvg(rss_t *rss, dvg_t *dvg) {
1280 plist_element_t *el;
1282 DBG((rss->dbg, LEVEL_1, "\tcomputing DVG:\n"));
1284 foreach_plist(rss->nodes, el) {
1285 ir_node *u_irn = plist_element_get_value(el);
1286 rss_irn_t *u = get_rss_irn(rss, u_irn);
1287 rss_irn_t *u_killer = get_rss_irn(rss, u->killer);
1290 /* TODO: omit nodes only having sink as pkiller and killing no one */
1292 /* add an edge to killer */
1293 add_dvg_edge(rss, dvg, u_irn, u->killer, 0);
1295 if (is_Sink(u->killer))
1298 /* We add an edge to every killer, from where we could be reached. */
1299 for (i = ARR_LEN_SAFE(u_killer->descendants) - 1; i >= 0; --i) {
1300 add_dvg_edge(rss, dvg, u_irn, u_killer->descendants[i], 1);
1305 foreach_plist(rss->nodes, el2) {
1306 ir_node *v_irn = plist_element_get_value(el2);
1309 There is an edge (u, v) in the DVG iff v is a descendant of the killer(u).
1311 if (BSEARCH_IRN_ARR(v_irn, u_kill->descendants)) {
1312 rss_edge_t *dvg_edge = obstack_alloc(phase_obst(&rss->ph), sizeof(*dvg_edge));
1315 /* insert the user into the DVG and append it to the user list of u */
1316 ir_nodeset_insert(&dvg->nodes, v_irn);
1317 if (! plist_has_value(u->dvg_user_list, v_irn))
1318 plist_insert_back(u->dvg_user_list, v_irn);
1320 dvg_edge->src = u_irn;
1321 dvg_edge->tgt = v_irn;
1322 dvg_edge->next = NULL;
1327 assert(pset_find(dvg->edges, &key, HASH_RSS_EDGE(&key)) == NULL && "DVG must be acyclic!");
1329 /* add the edge to the DVG */
1330 DBG((rss->dbg, LEVEL_3, "\t\tadd edge %+F -> %+F\n", u_irn, v_irn));
1331 pset_insert(dvg->edges, dvg_edge, HASH_RSS_EDGE(dvg_edge));
1337 if (rss->opts->dump_flags & RSS_DUMP_DVG)
1338 debug_vcg_dump_dvg(rss, dvg);
1342 * Updates the dvg structure when a serialization edge from src -> tgt is added.
1344 static void update_dvg(rss_t *rss, dvg_t *dvg, rss_irn_t *src, rss_irn_t *tgt) {
1347 rss_edge_t **arr = alloca(pset_count(dvg->edges) * sizeof(arr[0]));
1350 Add an edge from serialization target to serialization src:
1351 src cannot be alive with target
1353 add_dvg_edge(rss, dvg, tgt->irn, src->irn, 0);
1355 /* Add edges to src's descendants as well, they also getting serialized. */
1356 for (i = ARR_LEN_SAFE(src->descendants) - 1; i >= 0; --i) {
1357 add_dvg_edge(rss, dvg, tgt->irn, src->descendants[i], 1);
1360 /* We also have to add edges from targets predecessors in dvg */
1362 /* We cannot insert elements into set over which we iterate ... */
1363 foreach_pset(dvg->edges, edge) {
1364 if (edge->tgt == tgt->irn) {
1369 for (i = 0; i < idx; ++i) {
1371 add_dvg_edge(rss, dvg, edge->src, src->irn, 1);
1372 for (j = ARR_LEN_SAFE(src->descendants) - 1; j >= 0; --j) {
1373 add_dvg_edge(rss, dvg, edge->src, src->descendants[j], 1);
1380 * Accumulate all descendants for root into list.
1382 static void accumulate_dvg_descendant_values(rss_t *rss, rss_irn_t *root, plist_t *list) {
1383 if (plist_count(root->dvg_user_list) > 0) {
1384 plist_element_t *el;
1386 foreach_plist(root->dvg_user_list, el) {
1387 ir_node *v_irn = plist_element_get_value(el);
1388 rss_irn_t *v = get_rss_irn(rss, v_irn);
1390 /* add v as descendant */
1391 if (! plist_has_value(list, v_irn)) {
1392 plist_insert_back(list, v_irn);
1393 DBG((rss->dbg, DEBUG_DVG, "\t\t\tadd DVG descendant %+F\n", v_irn));
1396 /* accumulate v's descendants */
1397 accumulate_dvg_descendant_values(rss, v, list);
1403 * Builds the list of potential killers for each node
1405 * Needs the descendant list for all user as sorted array.
1407 static void build_dvg_pkiller_list(rss_t *rss, dvg_t *dvg) {
1408 ir_nodeset_iterator_t iter;
1411 foreach_nodeset(&dvg->nodes, irn, iter) {
1412 rss_irn_t *node = get_rss_irn(rss, irn);
1413 plist_element_t *el, *el2;
1415 DBG((rss->dbg, DEBUG_DVG, "\t\tbuilding pkiller list for %+F\n", irn));
1417 /* check each user */
1418 foreach_plist(node->dvg_user_list, el) {
1419 ir_node *u_irn = plist_element_get_value(el);
1421 /* is the current user u_irn not a descendant of any other user -> pkiller */
1422 foreach_plist(node->dvg_user_list, el2) {
1423 ir_node *v_irn = plist_element_get_value(el2);
1424 rss_irn_t *v = get_rss_irn(rss, v_irn);
1427 ! BSEARCH_IRN_ARR(u_irn, v->dvg_desc) &&
1428 ! plist_has_value(node->dvg_pkiller_list, u_irn))
1430 plist_insert_back(node->dvg_pkiller_list, u_irn);
1431 DBG((rss->dbg, DEBUG_DVG, "\t\t\tadd DVG pkiller %+F\n", u_irn));
1436 node->dvg_pkiller = build_sorted_array_from_list(node->dvg_pkiller_list, phase_obst(&rss->ph));
1440 if (firm_dbg_get_mask(rss->dbg) & DEBUG_DVG)
1441 debug_vcg_dump_dvg_pkiller(rss, dvg);
1448 * Compute the maximal antichain of the current DVG.
1449 * This is a reimplementation of the MAXIMAL_ANTI_CHAIN function
1450 * from the DDG library 1.1 (DAG.cpp).
1452 static ir_nodeset_t *compute_maximal_antichain(rss_t *rss, dvg_t *dvg, int iteration) {
1453 int n = ir_nodeset_size(&dvg->nodes);
1454 int *assignment = alloca(n * sizeof(assignment[0]));
1455 int *assignment_rev = alloca(n * sizeof(assignment_rev[0]));
1456 int *idx_map = alloca(n * sizeof(idx_map[0]));
1457 hungarian_problem_t *bp;
1458 ir_nodeset_t *values, *temp;
1459 ir_nodeset_iterator_t iter;
1461 int i, j, cost, cur_chain, res;
1462 rss_edge_t *dvg_edge;
1464 #define MAP_IDX(irn) bsearch_for_index(get_irn_idx(irn), idx_map, n, 1)
1466 if (pset_count(dvg->edges) == 0)
1469 bp = hungarian_new(n, n, 1, HUNGARIAN_MATCH_NORMAL);
1472 At first, we build an index map for the nodes in the DVG,
1473 because we cannot use the irn idx therefore as the resulting
1474 bipartite data structure would have around 1.2GB.
1475 So we limit the size to the number of nodes we have in the DVG
1476 and build a sorted index map for their irn indices.
1479 foreach_ir_nodeset(&dvg->nodes, u_irn, iter) {
1480 idx_map[i++] = get_irn_idx(u_irn);
1482 qsort(idx_map, n, sizeof(idx_map[0]), cmp_int);
1484 foreach_pset(dvg->edges, dvg_edge) {
1485 int idx_u = MAP_IDX(dvg_edge->src);
1486 int idx_v = MAP_IDX(dvg_edge->tgt);
1488 /* add the entry to the bipartite data structure */
1489 hungarian_add(bp, idx_u, idx_v, 1);
1490 DBG((rss->dbg, LEVEL_3, "\t\t\tadd %d (%+F) -> %d (%+F)\n",
1491 idx_u, dvg_edge->src, idx_v, dvg_edge->tgt));
1495 Add a bipartite entry for each pair of nodes (u, v), where exists a
1496 path in the DVG from u to v, ie. connect all descendants(v) to v.
1497 desc_dvg(v) = accumulated descendants of all z in dvg_user_list(v)
1499 foreach_ir_nodeset(&dvg->nodes, u_irn, iter) {
1500 rss_irn_t *u = get_rss_irn(rss, u_irn);
1501 int idx_u_irn = MAP_IDX(u_irn);
1503 DBG((rss->dbg, DEBUG_DVG, "\t\tcomputing DVG descendants of %+F:\n", u_irn));
1505 //plist_clear(u->dvg_desc_list);
1506 //accumulate_dvg_descendant_values(rss, u, u->dvg_desc_list);
1509 FIXME: The array is build on the phase obstack and we cannot free the data.
1510 So the array get as many times allocated as this function is called.
1513 /* build the sorted array for faster searches */
1514 //u->dvg_desc = build_sorted_array_from_list(u->dvg_desc_list, phase_obst(&rss->ph));
1516 DBG((rss->dbg, DEBUG_MAX_AC, "\t\tadding bipartite entries of %+F:\n", u_irn));
1518 /* add the bipartite entries for all descendants */
1519 for (i = ARR_LEN_SAFE(u->dvg_desc) - 1; i >= 0; --i) {
1520 rss_irn_t *desc = get_rss_irn(rss, u->dvg_desc[i]);
1521 int idx_desc = MAP_IDX(u->dvg_desc[i]);
1523 /* add the entry to the bipartite data structure */
1524 hungarian_add(bp, idx_u_irn, idx_desc, 1);
1525 DBG((rss->dbg, DEBUG_MAX_AC, "\t\t\tadd %d (%+F) -> %d (%+F)\n",
1526 idx_u_irn, u_irn, idx_desc, u->dvg_desc[i]));
1533 /* We want maximum cardinality matching */
1534 hungarian_prepare_cost_matrix(bp, HUNGARIAN_MODE_MAXIMIZE_UTIL);
1537 DBG((rss->dbg, DEBUG_DVG, "\t\tcomputing DVG pkiller:\n"));
1538 /* beware: the following function needs the dvg_desc array */
1539 build_dvg_pkiller_list(rss, dvg);
1542 DBG((rss->dbg, LEVEL_2, "\t\tcomputing bipartite matching\n"));
1544 The maximum cardinality bipartite matching gives us the minimal
1545 chain partition, which corresponds to the maximum anti chains.
1547 res = hungarian_solve(bp, assignment, &cost, 1);
1548 assert(res == 0 && "Bipartite matching failed!");
1551 memset(assignment_rev, -1, n * sizeof(assignment_rev[0]));
1553 /* build the reverse assignment, ie. foreach i -> j, add j -> i */
1554 for (i = 0; i < n; ++i) {
1555 if (assignment[i] >= 0) {
1556 int j = assignment[i];
1557 assignment_rev[j] = i;
1561 DBG((rss->dbg, LEVEL_2, "\t\tgot assignment with cost %d\n", cost));
1562 DBG((rss->dbg, LEVEL_3, "\t\t\tassignment --- reverse assignment\n", cost));
1563 for (i = 0; i < n; ++i) {
1564 DBG((rss->dbg, LEVEL_3, "\t\t\t%3d -> %3d %3d -> %3d\n", i, assignment[i], i, assignment_rev[i]));
1567 values = xmalloc(sizeof(values[0]));
1568 ir_nodeset_init_size(values, 10);
1570 /* Construction of the minimal chain partition */
1571 for (j = 0; j < n; ++j) {
1572 /* check nodes, which did not occur as target */
1573 if (assignment_rev[j] == -1) {
1574 int xj = idx_map[j];
1575 ir_node *xj_irn = get_idx_irn(rss->irg, xj);
1576 rss_irn_t *xj_rss = get_rss_irn(rss, xj_irn);
1577 chain_t *c = obstack_alloc(phase_obst(&rss->ph), sizeof(*c));
1580 /* there was no source for j -> we have a source of a new chain */
1581 ir_nodeset_insert(values, xj_irn);
1583 c->elements = plist_obstack_new(phase_obst(&rss->ph));
1584 c->nr = cur_chain++;
1585 plist_insert_back(c->elements, xj_irn);
1589 DBG((rss->dbg, LEVEL_2, "\t\tstarting chain %d:\n", c->nr));
1590 DBG((rss->dbg, LEVEL_2, "\t\t\t%+F (%d)", xj_irn, j));
1592 /* follow chain, having j as source */
1594 while (assignment[source] >= 0) {
1595 int target = assignment[source];
1596 int irn_idx = idx_map[target];
1597 ir_node *irn = get_idx_irn(rss->irg, irn_idx);
1598 rss_irn_t *node = get_rss_irn(rss, irn);
1600 plist_insert_back(c->elements, irn);
1603 DB((rss->dbg, LEVEL_2, " -> %+F (%d)", irn, target));
1605 /* new source = last target */
1609 DB((rss->dbg, LEVEL_2, "\n"));
1614 Computing the maximal antichain: Select an element from each
1615 chain such, such it is parallel with the others.
1617 DBG((rss->dbg, LEVEL_1, "\t\tcomputing set of saturation values (MAX AC)\n"));
1618 DBG((rss->dbg, LEVEL_3, "\t\tstarting with:\n"));
1621 if (firm_dbg_get_mask(rss->dbg) & LEVEL_3)
1622 dump_nodeset(values, "\t\t\t");
1628 We need an explicit array for the values as
1629 we cannot iterate multiple times over the same
1630 set at the same time. :-(((((
1631 TODO Matze: now we can, so rewrite this...
1633 int n = ir_nodeset_size(values);
1635 ir_node **val_arr = NEW_ARR_F(ir_node *, n);
1637 foreach_ir_nodeset(values, u_irn, iter)
1638 val_arr[i++] = u_irn;
1641 ir_nodeset_destroy(temp);
1645 temp = xmalloc(sizeof(temp[0]));
1646 ir_nodeset_init_size(temp, 10);
1648 /* Select all nodes from current value set, having another node in the set as descendant. */
1649 for (i = 0; i < n; ++i) {
1650 rss_irn_t *u = get_rss_irn(rss, val_arr[i]);
1652 for (j = 0; j < n; ++j) {
1656 key.src = val_arr[i];
1657 key.tgt = val_arr[j];
1659 if (pset_find(dvg->edges, &key, HASH_RSS_EDGE(&key))) {
1660 /* v[j] is descendant of u -> remove u and break */
1661 ir_nodeset_insert(temp, u->irn);
1662 ir_nodeset_remove(values, u->irn);
1664 DBG((rss->dbg, LEVEL_3, "\t\t\tremoving %+F from values, adding it to temp\n", u->irn));
1672 /* Try to insert the chain predecessor of all selected u's */
1673 foreach_ir_nodeset(temp, u_irn, iter) {
1674 rss_irn_t *u = get_rss_irn(rss, u_irn);
1675 chain_t *c = u->chain;
1676 plist_element_t *el = plist_find_value(c->elements, u_irn);
1678 assert(el && "Missing element in chain!");
1680 /* If u has predecessor in chain: insert the predecessor */
1681 if (el == plist_element_get_prev(el)) {
1682 ir_nodeset_insert(values, plist_element_get_value(el));
1683 DBG((rss->dbg, LEVEL_3, "\t\t\tadding %+F to values\n", plist_element_get_value(el)));
1689 } while (ir_nodeset_size(temp) > 0);
1691 DBG((rss->dbg, LEVEL_2, "\t\tfinal set:\n"));
1693 if (firm_dbg_get_mask(rss->dbg) & LEVEL_2) {
1694 dump_nodeset(values, "\t\t\t");
1698 if (rss->opts->dump_flags & RSS_DUMP_MAXAC)
1699 debug_vcg_dump_pkg(rss, values, iteration);
1702 ir_nodeset_destroy(temp);
1712 * Computes the best serialization between two nodes of sat_vals.
1714 static serialization_t *compute_best_admissible_serialization(rss_t *rss, ir_nodeset_t *sat_vals, serialization_t *ser, int num_regs) {
1715 int n = ir_nodeset_size(sat_vals);
1716 int n_idx = ARR_LEN_SAFE(rss->idx_map);
1718 ir_node **val_arr = alloca(n * sizeof(val_arr[0]));
1719 bitset_t *bs_sv = bitset_alloca(n_idx);
1720 bitset_t *bs_vdesc = bitset_alloca(n_idx);
1721 bitset_t *bs_tmp = bitset_alloca(n_idx);
1722 bitset_t *bs_ukilldesc = bitset_alloca(n_idx);
1723 int best_benefit = INT_MAX;
1724 int best_omega2 = INT_MAX;
1725 int best_benefit_omega20 = INT_MAX;
1729 ir_nodeset_iterator_t iter;
1730 rss_edge_t min_benefit_edge;
1731 rss_edge_t min_omega20_edge;
1732 rss_irn_t *ser_u_omega1 = NULL, *ser_v_omega1 = NULL;
1733 rss_irn_t *ser_u_omega20 = NULL, *ser_v_omega20 = NULL;
1735 DBG((rss->dbg, LEVEL_1, "\tcomputing admissible serializations:\n"));
1738 We need an explicit array for the values as
1739 we cannot iterate multiple times over the same
1740 set at the same time. :-(((((
1743 foreach_ir_nodeset(sat_vals, irn, iter) {
1745 bitset_set(bs_sv, BLOCK_IDX_MAP(rss, irn));
1749 We build all admissible serializations and remember the best found so far.
1752 if v in pkiller(u): add edge from v to all other pkiller(u)
1753 else: for all vv in pkiller(u): add edge from v to vv if there exists no path from vv to v
1757 A node is unserializable if:
1758 - it has only one killer and this one is Sink
1759 - it kills no other values
1760 In this case there is no serialization which could
1761 reduce the registerpressure
1763 #define IS_UNSERIALIZABLE_NODE(rss_node) \
1766 (plist_count(rss_node->pkiller_list) == 1) && \
1767 is_Sink(rss_node->killer) && \
1768 (rss_node->kill_count == 0) \
1770 be_is_Barrier(rss_node->irn) || \
1771 be_is_Keep(rss_node->irn) \
1774 /* for all u in sat_vals */
1775 for (i = 0; i < n; ++i) {
1776 rss_irn_t *u = get_rss_irn(rss, val_arr[i]);
1777 plist_element_t *el;
1779 /* ignore nodes where serialization does not help */
1780 if (IS_UNSERIALIZABLE_NODE(u)) {
1781 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F considered unserializable\n", u->irn));
1785 /* accumulate all descendants of all pkiller(u) */
1786 bitset_clear_all(bs_ukilldesc);
1787 foreach_plist(u->pkiller_list, el) {
1788 ir_node *irn = plist_element_get_value(el);
1789 rss_irn_t *node = get_rss_irn(rss, irn);
1792 bitset_set(bs_ukilldesc, BLOCK_IDX_MAP(rss, irn));
1796 for (k = ARR_LEN_SAFE(node->descendants) - 1; k >= 0; --k) {
1797 if (! is_Sink(node->descendants[k]))
1798 bitset_set(bs_ukilldesc, BLOCK_IDX_MAP(rss, node->descendants[k]));
1802 /* for all v in sat_vals */
1803 for (j = 0; j < n; ++j) {
1804 ir_node *v_irn = val_arr[j];
1805 rss_irn_t *v = get_rss_irn(rss, v_irn);
1806 unsigned v_height = get_irn_height(rss->h, v_irn);
1807 int omega1, omega2, is_pkiller;
1809 /* v cannot be serialized with itself
1810 * ignore nodes where serialization does not help */
1811 if (i == j || IS_UNSERIALIZABLE_NODE(v)) {
1813 DBG((rss->dbg, LEVEL_3, "\t\t\t%+F considered unserializable\n", v->irn));
1817 /* get descendants of v */
1818 bitset_clear_all(bs_vdesc);
1819 bitset_set(bs_vdesc, BLOCK_IDX_MAP(rss, v_irn));
1820 for (k = ARR_LEN_SAFE(v->descendants) - 1; k >= 0; --k) {
1821 if (! is_Sink(v->descendants[k]))
1822 bitset_set(bs_vdesc, BLOCK_IDX_MAP(rss, v->descendants[k]));
1825 /* if v is in pkiller(u) */
1826 is_pkiller = plist_has_value(u->pkiller_list, v_irn);
1828 /* for all vv in pkiller(u) */
1829 foreach_plist(u->pkiller_list, el) {
1830 ir_node *vv_irn = plist_element_get_value(el);
1833 if (is_Sink(vv_irn) || is_cfop(vv_irn))
1837 add_edge = vv_irn != v_irn && skip_Proj(vv_irn) != skip_Proj(v_irn);
1839 add_edge = ! heights_reachable_in_block(rss->h, skip_Proj(vv_irn), skip_Proj(v_irn));
1842 As we add an edge from vv -> v, we have to make sure,
1843 that there exists no path from v to vv.
1847 unsigned vv_height = get_irn_height(rss->h, vv_irn);
1848 unsigned critical_path_cost;
1852 mu1 = | descendants(v) cut sat_vals |
1853 the number of saturating values which cannot
1854 be simultaneously alive with u
1856 bitset_copy(bs_tmp, bs_vdesc);
1857 mu1 = bitset_popcnt(bitset_and(bs_tmp, bs_sv));
1860 mu2 = | accum_desc_all_pkiller(u) without descendants(v) |
1863 bitset_copy(bs_tmp, bs_ukilldesc);
1864 mu2 = bitset_popcnt(bitset_andnot(bs_tmp, bs_vdesc));
1870 /* omega1 = mu1 - mu2 */
1876 /* omega2 = increase of critical path */
1877 critical_path_cost =
1878 v_height /* longest path from v to sink */
1879 + rss->max_height - vv_height /* longest path from source to vv */
1883 If critical_path_cost > max_height -> the new edge
1884 would increase the longest critical path by the difference.
1886 omega2 = critical_path_cost > rss->max_height ? critical_path_cost - rss->max_height : 0;
1888 /* this keeps track of the edge with the best benefit */
1889 if (omega1 >= num_regs - n && omega1 < best_benefit) {
1890 min_benefit_edge.src = v_irn;
1891 min_benefit_edge.tgt = vv_irn;
1896 best_benefit = omega1;
1897 ser->new_killer = is_pkiller;
1900 /* this keeps track of the edge with the best omega1 costs where omega2 == 0 */
1901 if (omega2 == 0 && omega1 >= num_regs - n && omega1 < best_benefit_omega20) {
1902 min_omega20_edge.src = v_irn;
1903 min_omega20_edge.tgt = vv_irn;
1908 best_benefit_omega20 = omega1;
1909 ser->new_killer = is_pkiller;
1912 best_omega2 = MIN(best_omega2, omega2);
1914 DBG((rss->dbg, LEVEL_2, "\t\tfound %+F -> %+F (w1 %d, w2 %d)\n",
1915 v_irn, vv_irn, omega1, omega2));
1917 } /* for all vv in pkiller(u) */
1918 } /* for all v in sat_vals */
1919 } /* for all u in sat_vals */
1924 if (best_omega2 == 0) {
1925 ser->u = ser_u_omega20;
1926 ser->v = ser_v_omega20;
1927 ser->edge->src = min_omega20_edge.src;
1928 ser->edge->tgt = min_omega20_edge.tgt;
1929 ser->omega1 = best_benefit_omega20;
1930 ser->omega2 = best_omega2;
1933 ser->u = ser_u_omega1;
1934 ser->v = ser_v_omega1;
1935 ser->edge->src = min_benefit_edge.src;
1936 ser->edge->tgt = min_benefit_edge.tgt;
1937 ser->omega1 = best_benefit;
1938 ser->omega2 = best_omega2;
1943 #undef IS_UNSERIALIZABLE_NODE
1947 * Perform the value serialization heuristic and add all
1948 * computed serialization edges as dependencies to the irg.
1950 static void perform_value_serialization_heuristic(rss_t *rss) {
1951 bitset_t *arch_nonign_bs = bitset_alloca(arch_register_class_n_regs(rss->cls));
1952 bitset_t *abi_ign_bs = bitset_alloca(arch_register_class_n_regs(rss->cls));
1953 unsigned available_regs, iteration;
1955 ir_nodeset_t *sat_vals;
1956 pset *ser_set = new_pset(cmp_rss_edges, 20);
1958 /* available_regs = R = |arch_non_ignore_regs cut ~abi_ignore_regs| */
1959 arch_put_non_ignore_regs(rss->arch_env, rss->cls, arch_nonign_bs);
1960 be_abi_put_ignore_regs(rss->abi, rss->cls, abi_ign_bs);
1961 bitset_andnot(arch_nonign_bs, abi_ign_bs);
1962 available_regs = bitset_popcnt(arch_nonign_bs);
1963 //num_live = pset_count(rss->live_block);
1964 //available_regs -= num_live < available_regs ? num_live : 0;
1966 DBG((rss->dbg, LEVEL_1, "\n\t#available regs: %d\n\n", available_regs));
1969 At first we need to compute the disjoint value DAG (DVG = {V, E_dv}).
1970 V = set of all nodes we are currently interested in
1971 E_dv = there is an edge from u to v iff v is a descendant of killer(u), forall u, v in V
1973 ir_nodeset_init_size(&dvg.nodes, plist_count(rss->nodes));
1974 dvg.edges = new_pset(cmp_rss_edges, plist_count(rss->nodes) * 5);
1975 compute_dvg(rss, &dvg);
1978 Then we perform the heuristic serialization algorithm
1979 on the DVG which gives us all necessary serialization
1982 DBG((rss->dbg, LEVEL_1, "\tcomputing maximal antichain:\n"));
1984 sat_vals = compute_maximal_antichain(rss, &dvg, iteration++);
1985 while (sat_vals && (ir_nodeset_size(sat_vals) > available_regs)) {
1986 serialization_t *ser, best_ser;
1987 rss_edge_t *edge = obstack_alloc(phase_obst(&rss->ph), sizeof(*edge));
1988 ir_node *dep_src, *dep_tgt;
1990 best_ser.edge = edge;
1991 ser = compute_best_admissible_serialization(rss, sat_vals, &best_ser, available_regs);
1993 DBG((rss->dbg, LEVEL_1, "\tcurrent register saturation %d, target %d\n", ir_nodeset_size(sat_vals), available_regs));
1996 DBG((rss->dbg, LEVEL_1, "\tno RS improving serialization found, breaking at iteration %d\n", iteration));
2000 /* Insert the serialization as dependency edge into the irg. */
2001 DBG((rss->dbg, LEVEL_1, "\tserializing %+F -> %+F with edge %+F -> %+F and cost %d, %d\n",
2002 ser->u->irn, ser->v->irn, ser->edge->src, ser->edge->tgt, ser->omega1, ser->omega2));
2004 if (pset_find(ser_set, ser->edge, HASH_RSS_EDGE(ser->edge)))
2005 ir_printf("WARNING: serialization %+F -> %+F computed twice!\n", ser->edge->src, ser->edge->tgt);
2008 pset_insert(ser_set, ser->edge, HASH_RSS_EDGE(ser->edge));
2010 /* update the dvg */
2011 update_dvg(rss, &dvg, ser->v, ser->u);
2012 update_dvg(rss, &dvg, get_rss_irn(rss, ser->edge->src), get_rss_irn(rss, ser->edge->tgt));
2013 if(sat_vals != NULL) {
2014 ir_nodeset_destroy(sat_vals);
2018 dep_src = skip_Proj(ser->edge->src);
2019 dep_tgt = ser->edge->tgt;
2020 add_irn_dep(dep_src, dep_tgt);
2022 /* Update descendants, consumer and pkillers of the target */
2023 update_node_info(rss, ser->edge->tgt, ser->edge->src);
2025 /* TODO: try to find a cheaper way for updating height information */
2026 rss->max_height = heights_recompute_block(rss->h, rss->block);
2028 /* Recompute the antichain for next serialization */
2029 DBG((rss->dbg, LEVEL_1, "\tre-computing maximal antichain:\n"));
2030 sat_vals = compute_maximal_antichain(rss, &dvg, iteration++);
2033 ir_nodeset_destroy(&dvg.nodes);
2034 del_pset(dvg.edges);
2038 * Do initial calculations for a block.
2040 static void process_block(ir_node *block, void *env) {
2043 const ir_edge_t *edge;
2045 phase_init(&rss->ph, "rss block preprocessor", rss->irg, PHASE_DEFAULT_GROWTH, init_rss_irn, NULL);
2047 DBG((rss->dbg, LEVEL_1, "preprocessing block %+F\n", block));
2050 /* build an index map for all nodes in the current block */
2052 n = get_irn_n_edges(block);
2053 NEW_ARR_A(int *, rss->idx_map, n);
2054 foreach_out_edge(block, edge) {
2055 ir_node *irn = get_edge_src_irn(edge);
2056 rss->idx_map[i++] = get_irn_idx(irn);
2058 qsort(rss->idx_map, n, sizeof(rss->idx_map[0]), cmp_int);
2059 rss->max_height = heights_recompute_block(rss->h, block);
2061 /* loop over all register classes */
2062 for (i = arch_isa_get_n_reg_class(rss->arch_env->isa) - 1; i >= 0; --i) {
2063 const arch_register_class_t *cls = arch_isa_get_reg_class(rss->arch_env->isa, i);
2066 DBG((rss->dbg, LEVEL_1, "register class %s\n", arch_register_class_name(cls)));
2068 /* Get all live value at end of Block having current register class */
2069 rss->live_block = pset_new_ptr(10);
2070 be_liveness_end_of_block(rss->liveness, rss->arch_env, rss->cls, rss->block, rss->live_block);
2072 /* reset the list of interesting nodes */
2073 plist_clear(rss->nodes);
2074 plist_insert_back(rss->nodes, _sink);
2076 /* collect all nodes having a certain register class */
2077 foreach_out_edge(block, edge) {
2078 ir_node *irn = get_edge_src_irn(edge);
2079 ir_mode *mode = get_irn_mode(irn);
2083 - mode_T nodes (the projs are asked)
2084 - mode_X nodes (control flow nodes are always scheduled last)
2085 - Keeps (they are always immediately scheduled)
2086 - Phi (same as Keep)
2088 if (mode == mode_T || mode == mode_X || is_Phi(irn))
2092 In case of a proj, we skip
2093 - Barrier (they are a Barrier :)
2095 - the Proj itself, as it's scheduled always with it's super node
2098 ir_node *pred = get_Proj_pred(irn);
2099 if (be_is_Barrier(pred) || is_Start(pred))
2103 /* calculate the descendants and consumer for each node in the block */
2104 collect_node_info(rss, skip_Proj(irn));
2106 if (be_is_Keep(irn))
2109 if (! arch_irn_is(rss->arch_env, irn, ignore) && arch_get_irn_reg_class(rss->arch_env, irn, -1) == cls) {
2110 plist_insert_back(rss->nodes, skip_Proj(irn));
2115 /* compute the potential killing set PK(G) */
2116 compute_pkill_set(rss);
2118 /* compute the killing function k* */
2119 compute_killing_function(rss);
2122 Compute the heuristic value serialization and
2123 add the necessary dependencies to the irg.
2125 perform_value_serialization_heuristic(rss);
2127 del_pset(rss->live_block);
2130 phase_free(&rss->ph);
2134 * Register the options.
2136 void be_init_schedrss(void) {
2137 lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
2138 lc_opt_entry_t *sched_grp = lc_opt_get_grp(be_grp, "sched");
2139 lc_opt_entry_t *rss_grp = lc_opt_get_grp(sched_grp, "rss");
2141 lc_opt_add_table(rss_grp, rss_option_table);
2144 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_schedrss);
2147 * Preprocess the irg for scheduling.
2149 void rss_schedule_preparation(const be_irg_t *birg) {
2150 ir_graph *irg = be_get_birg_irg(birg);
2153 FIRM_DBG_REGISTER(rss.dbg, "firm.be.sched.rss");
2155 //firm_dbg_set_mask(rss.dbg, LEVEL_1 | LEVEL_2 | LEVEL_3);
2157 init_rss_special_nodes(irg);
2160 rss.arch_env = be_get_birg_arch_env(birg);
2161 rss.abi = birg->abi;
2162 rss.h = heights_new(irg);
2163 rss.nodes = plist_new();
2164 rss.opts = &rss_options;
2165 rss.liveness = be_liveness(irg);
2166 irg_block_walk_graph(irg, NULL, process_block, &rss);
2167 heights_free(rss.h);
2168 plist_free(rss.nodes);
2169 be_liveness_free(rss.liveness);
2171 if (birg->main_env->options->dump_flags & DUMP_SCHED)
2172 be_dump(rss.irg, "-rss", dump_ir_block_graph);