added new licence header
[libfirm] / ir / be / beschedmris.c
1 /*
2  * Copyright (C) 1995-2007 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  * Implements a list scheduler for the MRIS algorithm in:
22  * Govindarajan, Yang, Amaral, Zhang, Gao
23  * Minimum Register Instruction Sequencing to Reduce Register Spills
24  * in out-of-order issue superscalar architectures
25  * @author Sebastian Hack
26  * @date   04.04.2006
27  */
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <limits.h>
33
34 #include "obst.h"
35 #include "debug.h"
36
37 #include "irgraph_t.h"
38 #include "irnode_t.h"
39 #include "iredges_t.h"
40 #include "ircons_t.h"
41 #include "irphase_t.h"
42 #include "irdump_t.h"
43 #include "irgwalk.h"
44 #include "irtools.h"
45 #include "irbitset.h"
46
47 #include "height.h"
48
49 #include "benode_t.h"
50 #include "besched_t.h"
51 #include "beschedmris.h"
52 #include "benodesets.h"
53 #include "beirg.h"
54
55 struct _mris_env_t {
56         ir_phase            ph;
57         heights_t         *heights;
58         const arch_env_t  *aenv;
59         ir_graph          *irg;
60         ir_node           *bl;
61         int               visited;
62         struct list_head  lineage_head;
63         struct obstack    obst;
64         DEBUG_ONLY(firm_dbg_module_t *dbg;)
65 };
66
67 typedef struct _mris_irn_t {
68         int visited;
69         ir_node *lineage_start;
70         ir_node *lineage_next;
71         ir_node *lineage_end;
72         struct list_head lineage_list;
73 } mris_irn_t;
74
75 #define to_appear(env, irn) (to_appear_in_schedule(irn) && get_nodes_block(irn) == env->bl)
76
77 #define get_mris_irn(env, irn)   ((mris_irn_t *) phase_get_or_set_irn_data(&env->ph, irn))
78 #define foreach_lineage(env, pos, tmp) list_for_each_entry_safe(mris_irn_t, pos, tmp, &(env)->lineage_head, lineage_list)
79
80 static void *mris_irn_data_init(ir_phase *ph, ir_node *irn, void *data)
81 {
82         mris_irn_t *mi = data ? data : phase_alloc(ph, sizeof(mi[0]));
83         memset(mi, 0, sizeof(mi[0]));
84         INIT_LIST_HEAD(&mi->lineage_list);
85         return mi;
86 }
87
88 #if 0
89 static int compute_height(mris_env_t *env, ir_node *irn, unsigned long visited)
90 {
91         mris_irn_t *mi = get_mris_irn(env, irn);
92
93         if(get_irn_visited(irn) >= visited) {
94                 DBG((env->dbg, LEVEL_3, "\theight of %+F = %d\n", irn, mi->height));
95                 return mi->height;
96         }
97
98         else {
99                 const ir_edge_t *edge;
100
101                 set_irn_visited(irn, visited);
102                 mi->height  = 0;
103
104                 foreach_out_edge(irn, edge) {
105                         ir_node *dep = get_edge_src_irn(edge);
106
107                         if(!is_Block(dep) && get_nodes_block(dep) == env->bl) {
108                                 int dep_height = compute_height(env, dep, visited);
109                                 mi->height     = MAX(mi->height, dep_height);
110                         }
111                 }
112
113                 mi->height++;
114                 DBG((env->dbg, LEVEL_3, "\tsetting height of %+F = %d\n", irn, mi->height));
115         }
116
117         return mi->height;
118 }
119
120 static void compute_heights(mris_env_t *env)
121 {
122         const ir_edge_t *edge;
123         unsigned long visited;
124
125         visited = get_irg_visited(env->irg) + 1;
126         set_irg_visited(env->irg, visited);
127
128         foreach_out_edge(env->bl, edge) {
129                 ir_node *dep = get_edge_src_irn(edge);
130                 if(to_appear(env, dep))
131                         compute_height(env, dep, visited);
132         }
133 }
134 #endif
135
136 #define valid_node(env, dep) (to_appear(env, dep) && !be_is_Keep(dep))
137
138 static void grow_all_descendands(mris_env_t *env, ir_node *irn, bitset_t *visited)
139 {
140         const ir_edge_t *edge;
141
142         // assert(get_irn_mode(irn) != mode_T);
143
144         foreach_out_edge(irn, edge) {
145                 ir_node *desc = get_edge_src_irn(edge);
146                 if(valid_node(env, desc) && !bitset_contains_irn(visited, desc)) {
147                         obstack_ptr_grow(&env->obst, desc);
148                         bitset_add_irn(visited, desc);
149                 }
150         }
151
152         foreach_out_edge_kind(irn, edge, EDGE_KIND_DEP) {
153                 ir_node *desc = get_edge_src_irn(edge);
154                 if(valid_node(env, desc) && !bitset_contains_irn(visited, desc)) {
155                         obstack_ptr_grow(&env->obst, desc);
156                         bitset_add_irn(visited, desc);
157                 }
158         }
159 }
160
161 static ir_node **all_descendants(mris_env_t *env, ir_node *irn)
162 {
163         bitset_t *visited = bitset_irg_malloc(env->irg);
164
165         grow_all_descendands(env, irn, visited);
166
167 #if 0
168         if(get_irn_mode(irn) == mode_T) {
169                 const ir_edge_t *edge;
170                 foreach_out_edge(irn, edge) {
171                         ir_node *desc = get_edge_src_irn(edge);
172                         assert(is_Proj(desc) && get_irn_mode(desc) != mode_T);
173                         grow_all_descendands(env, desc, visited);
174                 }
175         }
176
177         else
178                 grow_all_descendands(env, irn, visited);
179 #endif
180         bitset_free(visited);
181         obstack_ptr_grow(&env->obst, NULL);
182         return obstack_finish(&env->obst);
183 }
184
185 static ir_node *put_lowest_in_front(mris_env_t *env, ir_node **in)
186 {
187         int lowest_index       = 0;
188         unsigned lowest_height = INT_MAX;
189         int i;
190
191         for(i = 0; in[i]; ++i) {
192                 unsigned height = get_irn_height(env->heights, in[i]);
193                 if(height < lowest_height) {
194                         lowest_height = height;
195                         lowest_index  = i;
196                 }
197         }
198
199         if(i > 0) {
200                 ir_node *tmp     = in[0];
201                 in[0]            = in[lowest_index];
202                 in[lowest_index] = tmp;
203         }
204
205         return in[0];
206 }
207
208 #if 0
209 static void reaches_walker(mris_env_t *env, ir_node *irn, ir_node *tgt, int *found, unsigned long visited)
210 {
211         if(get_irn_visited(irn) < visited && get_nodes_block(irn) == env->bl) {
212
213                 set_irn_visited(irn, visited);
214
215                 if(irn == tgt)
216                         *found = 1;
217                 else {
218                         int i, n;
219
220                         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
221                                 ir_node *op = get_irn_n(irn, i);
222                                 if(!*found)
223                                         reaches_walker(env, op, tgt, found, visited);
224                         }
225                 }
226         }
227 }
228
229 static int reaches(mris_env_t *env, ir_node *src, ir_node *tgt)
230 {
231         int found = 0;
232         unsigned long visited = get_irg_visited(env->irg) + 1;
233
234         set_irg_visited(env->irg, visited);
235         reaches_walker(env, src, tgt, &found, visited);
236         return found;
237 }
238 #endif
239
240 static INLINE ir_node *skip_Projs(ir_node *irn)
241 {
242         return is_Proj(irn) ? skip_Projs(get_Proj_pred(irn)) : irn;
243 }
244
245 #if 0
246 static void replace_tuple_by_repr_proj(mris_env_t *env, ir_node **in)
247 {
248         int i;
249
250         for(i = 0; in[i]; ++i) {
251                 if(get_irn_mode(in[i]) == mode_T) {
252                         const ir_edge_t *edge;
253                         ir_node *proj  = NULL;
254                         ir_node *first = NULL;
255
256                         foreach_out_edge(in[i], edge) {
257                                 ir_node *desc = get_edge_src_irn(edge);
258
259                                 first = first ? first : desc;
260                                 if(get_irn_mode(desc) == mode_M) {
261                                         proj = desc;
262                                         break;
263                                 }
264                         }
265
266                         proj = proj ? proj : first;
267                         assert(proj);
268                         in[i] = proj;
269                 }
270         }
271 }
272 #endif
273
274 static void lineage_formation(mris_env_t *env)
275 {
276         DEBUG_ONLY(firm_dbg_module_t *dbg = env->dbg);
277         nodeset *nodes         = new_nodeset(128);
278
279         const ir_edge_t *edge;
280
281         foreach_out_edge(env->bl, edge) {
282                 ir_node *irn = get_edge_src_irn(edge);
283                 if(to_appear(env, irn))
284                         nodeset_insert(nodes, irn);
285         }
286
287         while(nodeset_count(nodes) > 0) {
288                 mris_irn_t *mi;
289                 ir_node *irn;
290                 ir_node *highest_node = NULL;
291                 ir_node *lowest_desc  = NULL;
292                 ir_node *start;
293                 mris_irn_t *start_mi;
294
295                 ir_node **in;
296                 int recompute_height  = 0;
297                 unsigned  curr_height = 0;
298
299                 /* search the highest node which is not yet in a lineage. */
300                 for(irn = nodeset_first(nodes); irn; irn = nodeset_next(nodes)) {
301                         unsigned height = get_irn_height(env->heights, irn);
302                         if(height > curr_height) {
303                                 highest_node = irn;
304                                 curr_height  = height;
305                         }
306                 }
307
308                 assert(highest_node);
309                 DBG((dbg, LEVEL_2, "highest node is %+F height %d\n", highest_node, get_irn_height(env->heights, highest_node)));
310
311                 start = highest_node;
312                 mi = start_mi = get_mris_irn(env, highest_node);
313
314                 /* start a lineage beginning with highest_node. */
315                 mi->lineage_start = highest_node;
316                 mi->lineage_next  = NULL;
317                 mi->lineage_end   = NULL;
318                 list_add(&mi->lineage_list, &env->lineage_head);
319                 nodeset_remove(nodes, highest_node);
320
321                 /*
322                         put all descendants in an array.
323                         we also move the lowest descendant in front, so that the other nodes
324                         are easily accessible as an array, too.
325                 */
326                 in          = all_descendants(env, highest_node);
327                 lowest_desc = put_lowest_in_front(env, in);
328
329                 /* as long as the current highest node has still descendants */
330                 while(lowest_desc) {
331                         mris_irn_t *lowest_mi  = get_mris_irn(env, lowest_desc);
332                         mris_irn_t *highest_mi = get_mris_irn(env, highest_node);
333                         int highest_is_tuple   = get_irn_mode(highest_node) == mode_T;
334
335                         int n_desc;
336
337                         DBG((dbg, LEVEL_2, "\tlowest descendant %+F height %d\n", lowest_desc, get_irn_height(env->heights, lowest_desc)));
338
339                         /* count the number of all descendants which are not the lowest descendant */
340                         for(n_desc = 0; in[n_desc]; ++n_desc);
341
342                         /*
343                         we insert a CopyKeep node to express the artificial dependencies from the lowest
344                         descendant to all other descendants.
345                         */
346                         if(n_desc > 1 && !be_is_Keep(lowest_desc)) {
347                                 ir_node *op;
348                                 int i, n;
349
350                                 for(i = 0, n = get_irn_ins_or_deps(lowest_desc); i < n; ++i) {
351                                         ir_node *cmp;
352
353                                         op  = get_irn_in_or_dep(lowest_desc, i);
354                                         cmp = highest_is_tuple ? skip_Projs(op) : op;
355
356                                         // if(cmp == highest_node)
357                                         if(op == highest_node)
358                                                 break;
359                                 }
360
361                                 assert(i < n && "could not find operand");
362
363                                 //replace_tuple_by_repr_proj(env, &in[1]);
364                                 if(!is_Proj(lowest_desc))
365                                         add_irn_dep(lowest_desc, in[1]);
366                         }
367                         obstack_free(&env->obst, in);
368
369                         /* if the current lowest node is not yet in a lineage, add it to the current one. */
370                         if(!lowest_mi->lineage_start) {
371                                 /* mark the current lowest node as the last one in the lineage. */
372                                 highest_mi->lineage_next = lowest_desc;
373                                 start_mi->lineage_end    = lowest_desc;
374
375                                 lowest_mi->lineage_start = start;
376                                 nodeset_remove(nodes, lowest_desc);
377                         }
378
379                         /* else we cannot extend this lineage, so break. */
380                         else
381                                 break;
382
383                         highest_node = lowest_desc;
384                         highest_mi   = lowest_mi;
385
386                         /* recompute the descendants array and the new lowest descendant. */
387                         in          = all_descendants(env, highest_node);
388                         lowest_desc = put_lowest_in_front(env, in);
389                 }
390
391                 /* recompute the heights if desired. */
392                 if(recompute_height)
393                         heights_recompute(env->heights);
394         }
395 }
396
397 static int fuse_two_lineages(mris_env_t *env, mris_irn_t *u, mris_irn_t *v)
398 {
399         mris_irn_t *mi;
400         ir_node *irn, *last;
401         ir_node *u_end   = u->lineage_end;
402         ir_node *v_start = v->lineage_start;
403         ir_node *start   = skip_Projs(v_start);
404
405         if(be_is_Keep(start))
406                 return 0;
407
408         /* set lineage end of nodes in u to end of v. */
409         irn = last = u->lineage_start;
410         mi         = get_mris_irn(env, irn);
411         while(irn && irn != u_end) {
412                 mi = get_mris_irn(env, irn);
413                 mi->lineage_end = v->lineage_end;
414                 last = irn;
415                 irn = mi->lineage_next;
416         }
417
418         /* insert a CopyKeep to make lineage v dependent on u. */
419         if(get_irn_ins_or_deps(start) == 0)
420                 return 0;
421
422         if(get_irn_mode(last) == mode_T) {
423                 const ir_edge_t *edge;
424                 foreach_out_edge(last, edge) {
425                         last = get_edge_src_irn(edge);
426                         break;
427                 }
428         }
429
430         /* irn now points to the last node in lineage u; mi has the info for the node _before_ the terminator of the lineage. */
431         mi->lineage_next       = v_start;
432
433         /* add a dependency from the first node in v's lineage to the last in u's */
434         add_irn_dep(u_end, v_start);
435
436         /* set lineage start of nodes in v to start of u. */
437         irn = v->lineage_start;
438         while(irn && irn != v->lineage_end) {
439                 mris_irn_t *mi = get_mris_irn(env, irn);
440                 mi->lineage_start = u->lineage_start;
441                 irn = mi->lineage_next;
442         }
443
444         heights_recompute(env->heights);
445
446         mi = get_mris_irn(env, v_start);
447         list_del(&mi->lineage_list);
448
449         return 1;
450 }
451
452 static void fuse_lineages(mris_env_t *env)
453 {
454         mris_irn_t *u, *v, *tmp1, *tmp2;
455
456 again:
457         foreach_lineage(env, u, tmp1) {
458                 foreach_lineage(env, v, tmp2) {
459                         if(u != v && u->lineage_start && v->lineage_start && u->lineage_end && v->lineage_end
460                                 && get_nodes_block(u->lineage_start) == get_nodes_block(v->lineage_start)) {
461                                 int uv = heights_reachable_in_block(env->heights, u->lineage_start, v->lineage_end);
462                                 int vu = heights_reachable_in_block(env->heights, v->lineage_start, u->lineage_end);
463
464                                 if(uv && !vu) {
465                                         if(fuse_two_lineages(env, u, v))
466                                                 goto again;
467                                 }
468                         }
469                 }
470         }
471 }
472
473 static mris_env_t *dump_env = NULL;
474
475 static void block_walker(ir_node *bl, void *data)
476 {
477         mris_env_t *env = data;
478         env->bl = bl;
479         lineage_formation(env);
480         fuse_lineages(env);
481 }
482
483 static int mris_edge_hook(FILE *F, ir_node *irn)
484 {
485         mris_irn_t *mi = get_mris_irn(dump_env, irn);
486
487         if(mi->lineage_next) {
488                 fprintf(F, "edge:{sourcename:\"");
489                 PRINT_NODEID(mi->lineage_next);
490                 fprintf(F, "\" targetname:\"");
491                 PRINT_NODEID(irn);
492                 fprintf(F, "\" color:lilac}\n");
493         }
494         return 1;
495 }
496
497 void dump_ir_block_graph_mris(mris_env_t *env, const char *suffix) {
498         DUMP_NODE_EDGE_FUNC old = get_dump_node_edge_hook();
499
500         dump_consts_local(0);
501         set_dump_node_edge_hook(mris_edge_hook);
502         dump_env = env;
503         dump_ir_block_graph(env->irg, suffix);
504         set_dump_node_edge_hook(old);
505 }
506
507 mris_env_t *be_sched_mris_preprocess(const be_irg_t *birg)
508 {
509         mris_env_t *env = xmalloc(sizeof(env[0]));
510         ir_graph   *irg = be_get_birg_irg(birg);
511
512         phase_init(&env->ph, "mris", irg, 2 * PHASE_DEFAULT_GROWTH, mris_irn_data_init, NULL);
513         env->aenv     = be_get_birg_arch_env(birg);
514         env->irg      = irg;
515         env->visited  = 0;
516         env->heights  = heights_new(irg);
517         INIT_LIST_HEAD(&env->lineage_head);
518         FIRM_DBG_REGISTER(env->dbg, "firm.be.sched.mris");
519         obstack_init(&env->obst);
520         irg_walk_graph(irg, firm_clear_link, NULL, NULL);
521         irg_block_walk_graph(irg, block_walker, NULL, env);
522         obstack_free(&env->obst, NULL);
523         // dump_ir_block_graph_mris(env, "-mris");
524         return env;
525 }
526
527 void be_sched_mris_free(mris_env_t *env)
528 {
529         phase_free(&env->ph);
530         heights_free(env->heights);
531         free(env);
532 }