make unique types/entities part of irprog
[libfirm] / ir / be / beschedtrace.c
1 /*
2  * Copyright (C) 1995-2011 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief       Implements a trace scheduler as presented in Muchnik[TM].
23  * @author      Michael Beck
24  * @date        28.08.2006
25  */
26 #include "config.h"
27
28 #include <stdlib.h>
29
30 #include "iredges_t.h"
31
32 #include "besched.h"
33 #include "belistsched.h"
34 #include "benode.h"
35 #include "belive.h"
36 #include "bemodule.h"
37
38 /* we need a special mark */
39 static char _mark;
40 #define MARK &_mark
41
42 typedef struct trace_irn {
43         sched_timestep_t delay;      /**< The delay for this node if already calculated, else 0. */
44         sched_timestep_t etime;      /**< The earliest time of this node. */
45         unsigned num_user;           /**< The number real users (mode datab) of this node */
46         int      reg_diff;           /**< The difference of num(out registers) - num(in registers) */
47         int      preorder;           /**< The pre-order position */
48         unsigned critical_path_len;  /**< The weighted length of the longest critical path */
49         unsigned is_root       : 1;  /**< is a root node of a block */
50 } trace_irn_t;
51
52 typedef struct trace_env {
53         trace_irn_t      *sched_info;               /**< trace scheduling information about the nodes */
54         sched_timestep_t curr_time;                 /**< current time of the scheduler */
55         be_lv_t          *liveness;                 /**< The liveness for the irg */
56         DEBUG_ONLY(firm_dbg_module_t *dbg;)
57 } trace_env_t;
58
59 /**
60  * Returns a random node from a nodeset
61  */
62 static ir_node *get_nodeset_node(const ir_nodeset_t *nodeset)
63 {
64         ir_nodeset_iterator_t iter;
65
66         ir_nodeset_iterator_init(&iter, nodeset);
67         return ir_nodeset_iterator_next(&iter);
68 }
69
70 /**
71  * Returns non-zero if the node is a root node
72  */
73 static inline unsigned is_root_node(trace_env_t *env, ir_node *n)
74 {
75         unsigned const idx = get_irn_idx(n);
76
77         assert(idx < ARR_LEN(env->sched_info));
78         return env->sched_info[idx].is_root;
79 }
80
81 /**
82  * Mark a node as root node
83  */
84 static inline void mark_root_node(trace_env_t *env, ir_node *n)
85 {
86         unsigned const idx = get_irn_idx(n);
87
88         assert(idx < ARR_LEN(env->sched_info));
89         env->sched_info[idx].is_root = 1;
90 }
91
92 /**
93  * Get the current delay.
94  */
95 static inline sched_timestep_t get_irn_delay(trace_env_t *env, ir_node *n)
96 {
97         unsigned const idx = get_irn_idx(n);
98
99         assert(idx < ARR_LEN(env->sched_info));
100         return env->sched_info[idx].delay;
101 }
102
103 /**
104  * Set the current delay.
105  */
106 static inline void set_irn_delay(trace_env_t *env, ir_node *n, sched_timestep_t delay)
107 {
108         unsigned const idx = get_irn_idx(n);
109
110         assert(idx < ARR_LEN(env->sched_info));
111         env->sched_info[idx].delay = delay;
112 }
113
114 /**
115  * Get the current etime.
116  */
117 static inline sched_timestep_t get_irn_etime(trace_env_t *env, ir_node *n)
118 {
119         unsigned const idx = get_irn_idx(n);
120
121         assert(idx < ARR_LEN(env->sched_info));
122         return env->sched_info[idx].etime;
123 }
124
125 /**
126  * Set the current etime.
127  */
128 static inline void set_irn_etime(trace_env_t *env, ir_node *n, sched_timestep_t etime)
129 {
130         unsigned const idx = get_irn_idx(n);
131
132         assert(idx < ARR_LEN(env->sched_info));
133         env->sched_info[idx].etime = etime;
134 }
135
136 /**
137  * Get the number of users.
138  */
139 static inline unsigned get_irn_num_user(trace_env_t *env, ir_node *n)
140 {
141         unsigned const idx = get_irn_idx(n);
142
143         assert(idx < ARR_LEN(env->sched_info));
144         return env->sched_info[idx].num_user;
145 }
146
147 /**
148  * Set the number of users.
149  */
150 static inline void set_irn_num_user(trace_env_t *env, ir_node *n, unsigned num_user)
151 {
152         unsigned const idx = get_irn_idx(n);
153
154         assert(idx < ARR_LEN(env->sched_info));
155         env->sched_info[idx].num_user = num_user;
156 }
157
158 /**
159  * Get the register difference.
160  */
161 static inline int get_irn_reg_diff(trace_env_t *env, ir_node *n)
162 {
163         unsigned const idx = get_irn_idx(n);
164
165         assert(idx < ARR_LEN(env->sched_info));
166         return env->sched_info[idx].reg_diff;
167 }
168
169 /**
170  * Set the register difference.
171  */
172 static inline void set_irn_reg_diff(trace_env_t *env, ir_node *n, int reg_diff)
173 {
174         unsigned const idx = get_irn_idx(n);
175
176         assert(idx < ARR_LEN(env->sched_info));
177         env->sched_info[idx].reg_diff = reg_diff;
178 }
179
180 /**
181  * Get the pre-order position.
182  */
183 static inline int get_irn_preorder(trace_env_t *env, ir_node *n)
184 {
185         unsigned const idx = get_irn_idx(n);
186
187         assert(idx < ARR_LEN(env->sched_info));
188         return env->sched_info[idx].preorder;
189 }
190
191 /**
192  * Set the pre-order position.
193  */
194 static inline void set_irn_preorder(trace_env_t *env, ir_node *n, int pos)
195 {
196         unsigned const idx = get_irn_idx(n);
197
198         assert(idx < ARR_LEN(env->sched_info));
199         env->sched_info[idx].preorder = pos;
200 }
201
202 /**
203  * Get the pre-order position.
204  */
205 static inline unsigned get_irn_critical_path_len(trace_env_t *env, ir_node *n)
206 {
207         unsigned const idx = get_irn_idx(n);
208
209         assert(idx < ARR_LEN(env->sched_info));
210         return env->sched_info[idx].critical_path_len;
211 }
212
213 /**
214  * Set the pre-order position.
215  */
216 static inline void set_irn_critical_path_len(trace_env_t *env, ir_node *n, unsigned len)
217 {
218         unsigned const idx = get_irn_idx(n);
219
220         assert(idx < ARR_LEN(env->sched_info));
221         env->sched_info[idx].critical_path_len = len;
222 }
223
224 /**
225  * returns the exec-time for node n.
226  */
227 static sched_timestep_t exectime(trace_env_t *env, ir_node *n)
228 {
229         (void) env;
230         if (be_is_Keep(n) || is_Proj(n))
231                 return 0;
232 #if 0
233         if (env->selector->exectime)
234                 return env->selector->exectime(env->selector_env, n);
235 #endif
236         return 1;
237 }
238
239 /**
240  * Calculates the latency for between two ops
241  */
242 static sched_timestep_t latency(trace_env_t *env, ir_node *pred, int pred_cycle, ir_node *curr, int curr_cycle)
243 {
244         (void) pred_cycle;
245         (void) curr_cycle;
246         /* a Keep hides a root */
247         if (be_is_Keep(curr))
248                 return exectime(env, pred);
249
250         /* Proj's are executed immediately */
251         if (is_Proj(curr))
252                 return 0;
253
254         /* predecessors Proj's must be skipped */
255         if (is_Proj(pred))
256                 pred = get_Proj_pred(pred);
257
258 #if 0
259         if (env->selector->latency)
260                 return env->selector->latency(env->selector_env, pred, pred_cycle, curr, curr_cycle);
261 #endif
262
263         return 1;
264 }
265
266 /**
267  * Returns the number of users of a node having mode datab.
268  */
269 static int get_num_successors(ir_node *irn)
270 {
271         int sum = 0;
272         const ir_edge_t *edge;
273
274         if (get_irn_mode(irn) == mode_T) {
275                 /* for mode_T nodes: count the users of all Projs */
276                 foreach_out_edge(irn, edge) {
277                         ir_node *proj = get_edge_src_irn(edge);
278                         ir_mode *mode = get_irn_mode(proj);
279
280                         if (mode == mode_T)
281                                 sum += get_num_successors(proj);
282                         else if (mode_is_datab(mode))
283                                 sum += get_irn_n_edges(proj);
284                 }
285         }
286         else {
287                 /* do not count keep-alive edges */
288                 foreach_out_edge(irn, edge) {
289                         if (get_irn_opcode(get_edge_src_irn(edge)) != iro_End)
290                                 sum++;
291                 }
292         }
293
294         return sum;
295 }
296
297 /**
298  * Returns the difference of regs_output - regs_input;
299  */
300 static int get_reg_difference(trace_env_t *env, ir_node *irn)
301 {
302         int num_out = 0;
303         int num_in  = 0;
304         int i;
305         ir_node *block = get_nodes_block(irn);
306
307         if (be_is_Call(irn)) {
308                 /* we want calls preferred */
309                 return -5;
310         }
311
312         if (get_irn_mode(irn) == mode_T) {
313                 /* mode_T nodes: num out regs == num Projs with mode datab */
314                 const ir_edge_t *edge;
315                 foreach_out_edge(irn, edge) {
316                         ir_node *proj = get_edge_src_irn(edge);
317                         if (mode_is_datab(get_irn_mode(proj)))
318                                 num_out++;
319                 }
320         }
321         else
322                 num_out = 1;
323
324         /* num in regs: number of ins with mode datab and not ignore */
325         for (i = get_irn_arity(irn) - 1; i >= 0; i--) {
326                 ir_node *in = get_irn_n(irn, i);
327
328                 if (!mode_is_datab(get_irn_mode(in)))
329                         continue;
330
331                 if (arch_irn_is_ignore(in))
332                         continue;
333
334                 if (be_is_live_end(env->liveness, block, in))
335                         continue;
336
337                 num_in++;
338         }
339
340         return num_out - num_in;
341 }
342
343 /**
344  * descent into a dag and create a pre-order list.
345  */
346 static void descent(ir_node *root, ir_node *block, ir_node **list, trace_env_t *env, unsigned path_len)
347 {
348         int i;
349
350         if (! is_Phi(root)) {
351                 path_len += exectime(env, root);
352                 if (get_irn_critical_path_len(env, root) < path_len) {
353                         set_irn_critical_path_len(env, root, path_len);
354                 }
355                 /* calculate number of users (needed for heuristic) */
356                 set_irn_num_user(env, root, get_num_successors(root));
357
358                 /* calculate register difference (needed for heuristic) */
359                 set_irn_reg_diff(env, root, get_reg_difference(env, root));
360
361                 /* Phi nodes always leave the block */
362                 for (i = get_irn_arity(root) - 1; i >= 0; --i) {
363                         ir_node *pred = get_irn_n(root, i);
364
365                         DBG((env->dbg, LEVEL_3, "   node %+F\n", pred));
366
367                         /* Blocks may happen as predecessors of End nodes */
368                         if (is_Block(pred))
369                                 continue;
370
371                         /* already seen nodes are not marked */
372                         if (get_irn_link(pred) != MARK)
373                                 continue;
374
375                         /* don't leave our block */
376                         if (get_nodes_block(pred) != block)
377                                 continue;
378
379                         set_irn_link(pred, NULL);
380
381                         descent(pred, block, list, env, path_len);
382                 }
383         }
384         set_irn_link(root, *list);
385         *list = root;
386 }
387
388 /**
389  * Returns non-zero if root is a root in the block block.
390  */
391 static int is_root(ir_node *root, ir_node *block)
392 {
393         const ir_edge_t *edge;
394
395         foreach_out_edge(root, edge) {
396                 ir_node *succ = get_edge_src_irn(edge);
397
398                 if (is_Block(succ))
399                         continue;
400                 /* Phi nodes are always in "another block */
401                 if (is_Phi(succ))
402                         continue;
403                 if (get_nodes_block(succ) == block)
404                         return 0;
405         }
406         return 1;
407 }
408
409 /**
410  * Performs initial block calculations for trace scheduling.
411  */
412 static void trace_preprocess_block(trace_env_t *env, ir_node *block)
413 {
414         ir_node *root = NULL, *preord = NULL;
415         ir_node *curr, *irn;
416         int cur_pos;
417         const ir_edge_t *edge;
418
419         /* First step: Find the root set. */
420         foreach_out_edge(block, edge) {
421                 ir_node *succ = get_edge_src_irn(edge);
422
423                 if (is_Anchor(succ)) {
424                         /* ignore a keep alive edge */
425                         continue;
426                 }
427                 if (is_root(succ, block)) {
428                         mark_root_node(env, succ);
429                         set_irn_link(succ, root);
430                         root = succ;
431                 }
432                 else
433                         set_irn_link(succ, MARK);
434         }
435
436         /* Second step: calculate the pre-order list. */
437         preord = NULL;
438         for (curr = root; curr; curr = irn) {
439                 irn = (ir_node*)get_irn_link(curr);
440                 DBG((env->dbg, LEVEL_2, "   DAG root %+F\n", curr));
441                 descent(curr, block, &preord, env, 0);
442         }
443         root = preord;
444
445         /* Third step: calculate the Delay. Note that our
446         * list is now in pre-order, starting at root
447         */
448         for (cur_pos = 0, curr = root; curr; curr = (ir_node*)get_irn_link(curr), cur_pos++) {
449                 sched_timestep_t d;
450
451                 if (is_cfop(curr)) {
452                         /* assure, that branches can be executed last */
453                         d = 0;
454                 }
455                 else {
456                         if (is_root_node(env, curr))
457                                 d = exectime(env, curr);
458                         else {
459                                 d = 0;
460                                 foreach_out_edge(curr, edge) {
461                                         ir_node *n = get_edge_src_irn(edge);
462
463                                         if (get_nodes_block(n) == block) {
464                                                 sched_timestep_t ld;
465
466                                                 ld = latency(env, curr, 1, n, 0) + get_irn_delay(env, n);
467                                                 d = ld > d ? ld : d;
468                                         }
469                                 }
470                         }
471                 }
472                 set_irn_delay(env, curr, d);
473                 DB((env->dbg, LEVEL_2, "\t%+F delay %u\n", curr, d));
474
475                 /* set the etime of all nodes to 0 */
476                 set_irn_etime(env, curr, 0);
477
478                 set_irn_preorder(env, curr, cur_pos);
479         }
480 }
481
482 /**
483  * This functions gets called after a node finally has been made ready.
484  */
485 static void trace_node_ready(void *data, ir_node *irn, ir_node *pred)
486 {
487         trace_env_t *env = (trace_env_t*)data;
488         sched_timestep_t etime_p, etime;
489
490         etime = env->curr_time;
491         if (pred) {
492                 etime_p = get_irn_etime(env, pred);
493                 etime  += latency(env, pred, 1, irn, 0);
494                 etime   = etime_p > etime ? etime_p : etime;
495         }
496
497         set_irn_etime(env, irn, etime);
498         DB((env->dbg, LEVEL_2, "\tset etime of %+F to %u\n", irn, etime));
499 }
500
501 /**
502  * Update the current time after irn has been selected.
503  */
504 static void trace_update_time(void *data, ir_node *irn)
505 {
506         trace_env_t *env = (trace_env_t*)data;
507         if (is_Phi(irn) || get_irn_opcode(irn) == beo_Start) {
508                 env->curr_time += get_irn_etime(env, irn);
509         }
510         else {
511                 env->curr_time += exectime(env, irn);
512         }
513 }
514
515 /**
516  * Allocates memory and initializes trace scheduling environment.
517  * @param irg   The backend irg object
518  * @return The environment
519  */
520 static trace_env_t *trace_init(ir_graph *irg)
521 {
522         trace_env_t *env = XMALLOCZ(trace_env_t);
523         int         nn   = get_irg_last_idx(irg);
524
525         env->curr_time  = 0;
526         env->sched_info = NEW_ARR_F(trace_irn_t, nn);
527         env->liveness   = be_liveness(irg);
528         FIRM_DBG_REGISTER(env->dbg, "firm.be.sched.trace");
529
530         be_liveness_assure_chk(env->liveness);
531         memset(env->sched_info, 0, nn * sizeof(*(env->sched_info)));
532
533         return env;
534 }
535
536 /**
537  * Frees all memory allocated for trace scheduling environment.
538  * @param env  The environment
539  */
540 static void trace_free(void *data)
541 {
542         trace_env_t *env = (trace_env_t*)data;
543         be_liveness_free(env->liveness);
544         DEL_ARR_F(env->sched_info);
545         free(env);
546 }
547
548 /**
549  * Simple selector. Just assure that jumps are scheduled last.
550  */
551 static ir_node *basic_selection(ir_nodeset_t *ready_set)
552 {
553         ir_node *irn = NULL;
554         ir_nodeset_iterator_t iter;
555
556         /* assure that branches and constants are executed last */
557         foreach_ir_nodeset(ready_set, irn, iter) {
558                 if (!is_cfop(irn)) {
559                         return irn;
560                 }
561         }
562
563         /* at last: schedule branches */
564         irn = get_nodeset_node(ready_set);
565
566         return irn;
567 }
568
569 /**
570 * The muchnik selector.
571 */
572 static ir_node *muchnik_select(void *block_env, ir_nodeset_t *ready_set)
573 {
574         trace_env_t *env = (trace_env_t*)block_env;
575         ir_nodeset_t mcands, ecands;
576         ir_nodeset_iterator_t iter;
577         sched_timestep_t max_delay = 0;
578         ir_node *irn;
579
580         /* calculate the max delay of all candidates */
581         foreach_ir_nodeset(ready_set, irn, iter) {
582                 sched_timestep_t d = get_irn_delay(env, irn);
583
584                 max_delay = d > max_delay ? d : max_delay;
585         }
586
587         ir_nodeset_init_size(&mcands, 8);
588         ir_nodeset_init_size(&ecands, 8);
589
590         /* build mcands and ecands */
591         foreach_ir_nodeset(ready_set, irn, iter) {
592                 if (get_irn_delay(env, irn) == max_delay) {
593                         ir_nodeset_insert(&mcands, irn);
594                         if (get_irn_etime(env, irn) <= env->curr_time)
595                                 ir_nodeset_insert(&ecands, irn);
596                 }
597         }
598
599         /* select a node */
600         if (ir_nodeset_size(&mcands) == 1) {
601                 irn = get_nodeset_node(&mcands);
602                 DB((env->dbg, LEVEL_3, "\tirn = %+F, mcand = 1, max_delay = %u\n", irn, max_delay));
603         }
604         else {
605                 size_t cnt = ir_nodeset_size(&ecands);
606                 if (cnt == 1) {
607                         irn = get_nodeset_node(&ecands);
608
609                         if (is_cfop(irn)) {
610                                 /* BEWARE: don't select a JUMP if others are still possible */
611                                 goto force_mcands;
612                         }
613                         DB((env->dbg, LEVEL_3, "\tirn = %+F, ecand = 1, max_delay = %u\n", irn, max_delay));
614                 }
615                 else if (cnt > 1) {
616                         DB((env->dbg, LEVEL_3, "\tecand = %zu, max_delay = %u\n", cnt, max_delay));
617                         irn = basic_selection(&ecands);
618                 }
619                 else {
620 force_mcands:
621                         DB((env->dbg, LEVEL_3, "\tmcand = %zu\n", ir_nodeset_size(&mcands)));
622                         irn = basic_selection(&mcands);
623                 }
624         }
625
626         return irn;
627 }
628
629 static void *muchnik_init_graph(ir_graph *irg)
630 {
631         trace_env_t *env  = trace_init(irg);
632         return (void *)env;
633 }
634
635 static void *muchnik_init_block(void *graph_env, ir_node *bl)
636 {
637         trace_env_t *env = (trace_env_t*) graph_env;
638         trace_preprocess_block(env, bl);
639         return graph_env;
640 }
641
642 static void sched_muchnik(ir_graph *irg)
643 {
644         static const list_sched_selector_t muchnik_selector = {
645                 muchnik_init_graph,
646                 muchnik_init_block,
647                 muchnik_select,
648                 trace_node_ready,    /* node_ready */
649                 trace_update_time,   /* node_selected */
650                 NULL,                /* finish_block */
651                 trace_free           /* finish_graph */
652         };
653         be_list_sched_graph(irg, &muchnik_selector);
654 }
655
656 /**
657  * Execute the heuristic function.
658  */
659 static ir_node *heuristic_select(void *block_env, ir_nodeset_t *ns)
660 {
661         trace_env_t *trace_env   = (trace_env_t*)block_env;
662         ir_node     *irn, *cand  = NULL;
663         int         max_prio     = INT_MIN;
664         int         cur_prio     = INT_MIN;
665         int         reg_fact;
666         ir_nodeset_iterator_t iter;
667         /* Note: register pressure calculation needs an overhaul, you need correct
668          * tracking for each register class indidually and weight by each class
669         int         cur_pressure = ir_nodeset_size(lv); */
670         int         cur_pressure = 1;
671
672         /* prefer instructions which can be scheduled early */
673 #define PRIO_TIME        3
674         /* prefer instructions with lots of successors */
675 #define PRIO_NUMSUCCS    8
676         /* prefer instructions with long critical path */
677 #define PRIO_LEVEL      12
678         /* prefer instructions coming early in preorder */
679 #define PRIO_PREORD      8
680         /* weight of current register pressure */
681 #define PRIO_CUR_PRESS  20
682         /* weight of register pressure difference */
683 #define PRIO_CHG_PRESS   8
684
685         /* priority based selection, heuristic inspired by mueller diss */
686         foreach_ir_nodeset(ns, irn, iter) {
687                 /* make sure that branches are scheduled last */
688                 if (!is_cfop(irn)) {
689                         int rdiff = get_irn_reg_diff(trace_env, irn);
690                         int sign  = rdiff < 0;
691                         int chg   = (rdiff < 0 ? -rdiff : rdiff) << PRIO_CHG_PRESS;
692
693                         reg_fact = chg * cur_pressure;
694                         if (reg_fact < chg)
695                                 reg_fact = INT_MAX - 2;
696                         reg_fact = sign ? -reg_fact : reg_fact;
697
698                         cur_prio = (get_irn_critical_path_len(trace_env, irn) << PRIO_LEVEL)
699                                 //- (get_irn_delay(trace_env, irn) << PRIO_LEVEL)
700                                 + (get_irn_num_user(trace_env, irn) << PRIO_NUMSUCCS)
701                                 - (get_irn_etime(trace_env, irn) << PRIO_TIME)
702                                 //- ((get_irn_reg_diff(trace_env, irn) >> PRIO_CHG_PRESS) << ((cur_pressure >> PRIO_CUR_PRESS) - 3))
703                                 - reg_fact
704                                 + (get_irn_preorder(trace_env, irn) << PRIO_PREORD); /* high preorder means early schedule */
705                         if (cur_prio > max_prio) {
706                                 cand          = irn;
707                                 max_prio      = cur_prio;
708                         }
709
710                         DBG((trace_env->dbg, LEVEL_4, "checked NODE %+F\n", irn));
711                         DBG((trace_env->dbg, LEVEL_4, "\tpriority: %d\n", cur_prio));
712                         DBG((trace_env->dbg, LEVEL_4, "\tpath len: %d (%d)\n", get_irn_critical_path_len(trace_env, irn), get_irn_critical_path_len(trace_env, irn) << PRIO_LEVEL));
713                         DBG((trace_env->dbg, LEVEL_4, "\tdelay:    %d (%d)\n", get_irn_delay(trace_env, irn), get_irn_delay(trace_env, irn) << PRIO_LEVEL));
714                         DBG((trace_env->dbg, LEVEL_4, "\t#user:    %d (%d)\n", get_irn_num_user(trace_env, irn), get_irn_num_user(trace_env, irn) << PRIO_NUMSUCCS));
715                         DBG((trace_env->dbg, LEVEL_4, "\tetime:    %d (%d)\n", get_irn_etime(trace_env, irn), 0 - (get_irn_etime(trace_env, irn) << PRIO_TIME)));
716                         DBG((trace_env->dbg, LEVEL_4, "\tpreorder: %d (%d)\n", get_irn_preorder(trace_env, irn), get_irn_preorder(trace_env, irn) << PRIO_PREORD));
717                         DBG((trace_env->dbg, LEVEL_4, "\treg diff: %d (%d)\n", get_irn_reg_diff(trace_env, irn), 0 - reg_fact));
718                         DBG((trace_env->dbg, LEVEL_4, "\tpressure: %d\n", cur_pressure));
719                 }
720         }
721
722         if (cand) {
723                 DBG((trace_env->dbg, LEVEL_4, "heuristic selected %+F:\n", cand));
724         }
725         else {
726                 cand = basic_selection(ns);
727         }
728
729         return cand;
730 }
731
732 static void sched_heuristic(ir_graph *irg)
733 {
734         static const list_sched_selector_t heuristic_selector = {
735                 muchnik_init_graph,
736                 muchnik_init_block,
737                 heuristic_select,
738                 trace_node_ready,    /* node_ready */
739                 trace_update_time,   /* node_selected */
740                 NULL,                /* finish_block */
741                 trace_free           /* finish_graph */
742         };
743         be_list_sched_graph(irg, &heuristic_selector);
744 }
745
746 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_sched_trace)
747 void be_init_sched_trace(void)
748 {
749         be_register_scheduler("heur", sched_heuristic);
750         be_register_scheduler("muchnik", sched_muchnik);
751 }