Add pass creating for loop inversion, unrolling, peeling and mux lowering.
[libfirm] / ir / opt / loop.c
1 /*
2  * Copyright (C) 1995-2008 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  * @author   Christian Helmer
23  * @brief    loop inversion and loop unrolling, loop peeling
24  *
25  * @version  $Id$
26  */
27 #include "config.h"
28
29 #include "irnode.h"
30 #include "debug.h"
31
32 #include "ircons.h"
33 #include "irgopt.h"
34 #include "irgmod.h"
35 #include "irgwalk.h"
36 #include "irouts.h"
37 #include "iredges.h"
38 #include "irtools.h"
39 #include "array_t.h"    /* automatic array */
40 #include "beutil.h"             /* get_block */
41 #include "irloop_t.h"   /* set_irn_loop*/
42 #include "irpass.h"
43
44 #if 0
45         #include "irdump_t.h"
46 #endif
47
48
49 DEBUG_ONLY(static firm_dbg_module_t *dbg);
50
51 /**
52  * Convenience macro for iterating over every phi node of the given block.
53  * Requires phi list per block.
54  */
55 #define for_each_phi(block, phi) \
56         for ( (phi) = get_Block_phis( (block) ); (phi) ; (phi) = get_Phi_next( (phi) ) )
57
58 /* current loop */
59 static ir_loop *cur_loop;
60
61 /* abortable walker function */
62 typedef unsigned irg_walk_func_abortable(ir_node *, void *);
63
64 /* condition for walking a node during a copy_walk */
65 typedef unsigned walker_condition(ir_node *);
66
67 /* node and position of a predecessor */
68 typedef struct out_edges {
69         ir_node *node;
70         int pred_irn_n;
71 } out_edge;
72
73 /* access complex values through the nodes links */
74 typedef struct node_info {
75         unsigned invariant:1;
76         ir_node *copy;
77         ir_node *link;                                  /* temporary links for ssa creation */
78         ir_node **ins;                                  /* ins for phi nodes, during rewiring of blocks */
79         unsigned done;
80         struct node_info *freelistnext; /* linked list to free all node_infos */
81 } node_info;
82
83 static node_info *link_node_state_list;         /* head of the linked list to free all node_infos */
84
85 static out_edge *cur_loop_outs;                         /* A walker may start visiting the current loop with these nodes. */
86 static out_edge *cur_head_outs;                         /* A walker may start visiting the cur head with these nodes. */
87
88 static ir_node *loop_cf_head = NULL;                            /* Loop head node */
89 static unsigned loop_cf_head_valid = 1;                         /* A loop may have one head, otherwise we do not touch it. */
90
91 ir_node **loops;
92
93 /* Inverted head */
94 static ir_node *loop_inv_head = NULL;
95 /* Peeled head */
96 static ir_node *loop_peeled_head = NULL;
97
98 /* Loop analysis informations */
99 typedef struct loop_info_t {
100         unsigned blocks;                        /* number of blocks in the loop */
101         unsigned calls;                         /* number of calls */
102         unsigned loads;                         /* number of load nodes */
103         unsigned outs;                          /* outs without keepalives */
104 #if 0
105         unsigned invariant_loads;
106         unsigned stores;                        /* number of store nodes */
107         unsigned opnodes_n;                     /* nodes that probably result in an instruction */
108         unsigned do_invariant_opt;
109 #endif
110 } loop_info_t;
111
112 /* Information about the current loop */
113 static loop_info_t loop_info;
114
115 /* A walker may start visiting a condition chain with these nodes. */
116 static out_edge *cond_chain_entries;
117
118 /* Number of unrolling */
119 int unroll_times;
120
121 static unsigned head_inversion_node_count;
122 static unsigned inversion_head_node_limit;
123 static unsigned head_inversion_block_count;
124
125 static unsigned enable_peeling;
126 static unsigned enable_inversion;
127 static unsigned enable_unrolling;
128
129 /**
130  *
131  * ============= AUXILIARY FUNCTIONS =====================================
132  */
133
134
135 /**
136  * Creates object on the heap, and adds it to a linked list to free it later.
137  */
138 static node_info *new_node_info(void) {
139         node_info *l = XMALLOCZ(node_info);
140         l->freelistnext = link_node_state_list;
141         link_node_state_list = l;
142         l->copy = NULL;
143         l->invariant = 0;
144         return l;
145 }
146
147 static node_info *get_node_info(ir_node *n)
148 {
149         return ((node_info *)get_irn_link(n));
150 }
151
152 /* Allocates a node_info struct for the given node. For use with a walker. */
153 static void alloc_node_info(ir_node *node, void *env)
154 {
155         node_info *state;
156         (void) env;
157         state = new_node_info();
158         set_irn_link(node, (void *)state);
159 }
160
161 static void free_node_info(void)
162 {
163         int a = 0;
164         node_info *n;
165         n = link_node_state_list;
166         while(n) {
167                 node_info *next = n->freelistnext;
168                 ++a;
169                 xfree(n);
170                 n = next;
171         }
172         link_node_state_list = NULL;
173 }
174
175 /**
176  * Use the linked list to reset the reused values of all node_infos
177  * Reset in particular the copy attribute as copy_walk uses it to determine a present copy
178  */
179 static void reset_node_infos(void)
180 {
181         node_info *next;
182         next = link_node_state_list;
183         while(next->freelistnext) {
184                 node_info *cur = next;
185                 next = cur->freelistnext;
186                 cur->copy = NULL;
187                 cur->ins = NULL;
188                 cur->link = NULL;
189         }
190 }
191
192 /* Returns the nodes node_info link. */
193 static ir_node *get_link(ir_node *n)
194 {
195         return ((node_info *)get_irn_link(n))->link;
196 }
197
198 /* Sets the nodes node_info link. */
199 static void set_link(ir_node *n, ir_node *link)
200 {
201         ((node_info *)get_irn_link(n))->link = link;
202 }
203
204 /* Returns a nodes copy. */
205 static ir_node *get_copy(ir_node *n)
206 {
207         return ((node_info *)get_irn_link(n))->copy;
208 }
209
210 /* Sets a nodes copy. */
211 static void set_copy(ir_node *n, ir_node *copy)
212 {
213         ((node_info *)get_irn_link(n) )->copy = copy;
214 }
215
216 /**
217  * Convenience macro for iterating over every copy in a linked list
218  * of copies.
219  */
220 #define for_each_copy(node) \
221         for ( ; (node) ; (node) = get_copy(node))
222
223 /**
224  * Convenience macro for iterating over every copy in 2 linked lists
225  * of copies in parallel.
226  */
227 #define for_each_copy2(high1, low1, high2, low2) \
228         for ( ; (low1) && (low2); (high1) = (low1), (low1) = get_copy(low1), \
229                                                         (high2) = (low2), (low2) = get_copy(low2))
230
231 /*
232  * Returns 0 if the node or block is not in cur_loop.
233  */
234 static unsigned is_in_loop(ir_node *node)
235 {
236         return (get_irn_loop(get_block(node)) == cur_loop);
237 }
238
239 /* Returns if the given be is an alien edge. This is the case when the pred is not in the loop. */
240 static unsigned is_alien_edge(ir_node *n, int i)
241 {
242         return(!is_in_loop(get_irn_n(n, i)));
243 }
244
245 /* used for block walker */
246 static void reset_block_mark(ir_node *node, void * env)
247 {
248         (void) env;
249
250         if (is_Block(node))
251                 set_Block_mark(node, 0);
252 }
253
254 static unsigned is_nodesblock_marked(ir_node* node)
255 {
256         return (get_Block_mark(get_block(node)));
257 }
258
259 /* Returns the number of blocks in a loop. */
260 int get_loop_n_blocks(ir_loop *loop) {
261         int elements, e;
262         int blocks = 0;
263         elements = get_loop_n_elements(loop);
264
265         for(e=0; e<elements; e++) {
266                 loop_element elem = get_loop_element(loop, e);
267                 if  (is_ir_node(elem.kind) && is_Block(elem.node))
268                         ++blocks;
269         }
270         return blocks;
271 }
272
273 /**
274  * Add newpred at position pos to node and also add the corresponding value to the phis.
275  * Requires block phi list.
276  */
277 static int duplicate_preds(ir_node* node, unsigned pos, ir_node* newpred)
278 {
279         ir_node **ins;
280         /*int *is_be;*/
281         ir_node *phi;
282         int block_arity;
283         int i;
284
285         assert(is_Block(node) && "duplicate_preds is only allowed for blocks");
286
287         DB((dbg, LEVEL_5, "duplicate_preds(node %ld, pos %d, newpred %ld)\n",
288             get_irn_node_nr(node), pos, get_irn_node_nr(newpred)));
289
290         block_arity = get_irn_arity(node);
291
292         NEW_ARR_A(ir_node*, ins, block_arity + 1);
293
294         for (i = 0; i < block_arity; ++i) {
295                 ins[i] = get_irn_n(node, i);
296         }
297         ins[block_arity] = newpred;
298
299         set_irn_in(node, block_arity + 1, ins);
300
301         for_each_phi(node, phi) {
302                 int phi_arity = get_irn_arity(phi);
303                 DB((dbg, LEVEL_5, "duplicate_preds: fixing phi %ld\n", get_irn_node_nr(phi)));
304
305                 NEW_ARR_A(ir_node *, ins, block_arity + 1);
306                 for (i=0; i < phi_arity; ++i) {
307                         DB((dbg, LEVEL_5, "in %ld\n", get_irn_node_nr(get_irn_n(phi, i))));
308                         ins[i] = get_irn_n(phi, i);
309                 }
310                 ins[block_arity] = get_irn_n(phi, pos);
311                 set_irn_in(phi, block_arity + 1, ins);
312         }
313         return block_arity;
314 }
315
316 /**
317  * Finds loop head and loop_info.
318  */
319 static void get_loop_info(ir_node *node, void *env)
320 {
321         unsigned node_in_loop, pred_in_loop;
322         int i, arity;
323         (void) env;
324
325         arity = get_irn_arity(node);
326         for (i = 0; i < arity; i++) {
327                 ir_node *pred = get_irn_n(node, i);
328
329                 pred_in_loop = is_in_loop(pred);
330                 node_in_loop = is_in_loop(node);
331
332                 /* collect some loop information */
333                 if (node_in_loop) {
334                         if (is_Call(node))
335                                 ++loop_info.calls;
336                 }
337
338                 /* Find the loops head/the blocks with cfpred outside of the loop */
339                 if (is_Block(node) && node_in_loop && !pred_in_loop && loop_cf_head_valid) {
340                         ir_node *cfgpred = get_Block_cfgpred(node, i);
341
342                         if (!is_in_loop(cfgpred)) {
343                                 DB((dbg, LEVEL_5, "potential head %+F because inloop and pred %+F not inloop\n", node, pred));
344                                 /* another head? We do not touch this. */
345                                 if (loop_cf_head && loop_cf_head != node) {
346                                         loop_cf_head_valid = 0;
347                                 } else {
348                                         loop_cf_head = node;
349                                 }
350                         }
351                 }
352         }
353 }
354
355 /* Adds all nodes pointing into the loop to loop_entries and also finds the loops head */
356 static void get_loop_outs(ir_node *node, void *env)
357 {
358         unsigned node_in_loop, pred_in_loop;
359         int i, arity;
360         (void) env;
361
362         arity = get_irn_arity(node);
363         for (i = 0; i < arity; i++) {
364                 ir_node *pred = get_irn_n(node, i);
365
366                 pred_in_loop = is_in_loop(pred);
367                 node_in_loop = is_in_loop(node);
368
369                 if (pred_in_loop && !node_in_loop) {
370                         out_edge entry;
371                         entry.node = node;
372                         entry.pred_irn_n = i;
373                         ARR_APP1(out_edge, cur_loop_outs, entry);
374                 }
375         }
376 }
377
378 static ir_node *ssa_second_def;
379 static ir_node *ssa_second_def_block;
380
381 /**
382  * Walks the graph bottom up, searching for definitions and creates phis.
383  */
384 static ir_node *search_def_and_create_phis(ir_node *block, ir_mode *mode)
385 {
386         int i;
387         int n_cfgpreds;
388         ir_graph *irg;
389         ir_node *phi;
390         ir_node **in;
391
392         DB((dbg, LEVEL_5, "ssa search_def_and_create_phis: block %ld\n", get_irn_node_nr(block)));
393
394         /* Prevents creation of phi that would be bad anyway.
395          * Dead and bad blocks. */
396         if (get_irn_arity(block) < 1 || is_Bad(block))
397                 return new_Bad();
398
399         if (block == ssa_second_def_block) {
400                 DB((dbg, LEVEL_5, "ssa found second definition: use second def %ld\n", get_irn_node_nr(ssa_second_def)));
401                 return ssa_second_def;
402         }
403
404         /* already processed this block? */
405         if (irn_visited(block)) {
406                 ir_node *value = get_link(block);
407                 DB((dbg, LEVEL_5, "ssa already visited: use linked %ld\n", get_irn_node_nr(value)));
408                 return value;
409         }
410
411         irg = get_irn_irg(block);
412         assert(block != get_irg_start_block(irg));
413
414         /* a Block with only 1 predecessor needs no Phi */
415         n_cfgpreds = get_Block_n_cfgpreds(block);
416         if (n_cfgpreds == 1) {
417                 ir_node *pred_block = get_Block_cfgpred_block(block, 0);
418                 ir_node *value;
419
420                 DB((dbg, LEVEL_5, "ssa 1 pred: walk pred %ld\n", get_irn_node_nr(pred_block)));
421
422                 value = search_def_and_create_phis(pred_block, mode);
423                 set_link(block, value);
424                 mark_irn_visited(block);
425
426                 return value;
427         }
428
429         /* create a new Phi */
430         NEW_ARR_A(ir_node*, in, n_cfgpreds);
431         for(i = 0; i < n_cfgpreds; ++i)
432                 in[i] = new_Unknown(mode);
433
434         phi = new_r_Phi(block, n_cfgpreds, in, mode);
435
436         /* Important: always keep block phi list up to date. */
437         add_Block_phi(block, phi);
438         /* EVERY node is assumed to have a node_info linked. */
439         alloc_node_info(phi, NULL);
440
441         DB((dbg, LEVEL_5, "ssa phi creation: link new phi %ld to block %ld\n", get_irn_node_nr(phi), get_irn_node_nr(block)));
442
443         set_link(block, phi);
444         mark_irn_visited(block);
445
446         /* set Phi predecessors */
447         for(i = 0; i < n_cfgpreds; ++i) {
448                 ir_node *pred_val;
449                 ir_node *pred_block = get_Block_cfgpred_block(block, i);
450                 assert(pred_block != NULL);
451                 pred_val = search_def_and_create_phis(pred_block, mode);
452                 assert(pred_val != NULL);
453
454                 DB((dbg, LEVEL_5, "ssa phi pred:phi %ld, pred %ld\n", get_irn_node_nr(phi), get_irn_node_nr(pred_val)));
455                 set_irn_n(phi, i, pred_val);
456         }
457         return phi;
458 }
459
460 /**
461  * Given a set of values this function constructs SSA-form for the users of the
462  * first value (the users are determined through the out-edges of the value).
463  * Works without using the dominance tree.
464  */
465 static void construct_ssa(ir_node *orig_block, ir_node *orig_val,
466                           ir_node *second_block, ir_node *second_val)
467 {
468         ir_graph *irg;
469         ir_mode *mode;
470         const ir_edge_t *edge;
471         const ir_edge_t *next;
472
473         assert(orig_block && orig_val && second_block && second_val &&
474                         "no parameter of construct_ssa may be NULL");
475
476         /* no need to do anything */
477         if (orig_val == second_val)
478                 return;
479
480         irg = get_irn_irg(orig_val);
481
482         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
483         inc_irg_visited(irg);
484
485         mode = get_irn_mode(orig_val);
486         set_link(orig_block, orig_val);
487         mark_irn_visited(orig_block);
488
489         ssa_second_def_block = second_block;
490         ssa_second_def       = second_val;
491
492         /* Only fix the users of the first, i.e. the original node */
493         foreach_out_edge_safe(orig_val, edge, next) {
494                 ir_node *user = get_edge_src_irn(edge);
495                 int j = get_edge_src_pos(edge);
496                 ir_node *user_block = get_nodes_block(user);
497                 ir_node *newval;
498
499                 /* ignore keeps */
500                 if (is_End(user))
501                         continue;
502
503                 DB((dbg, LEVEL_5, "original user %ld\n", get_irn_node_nr(user)));
504
505                 if (is_Phi(user)) {
506                         ir_node *pred_block = get_Block_cfgpred_block(user_block, j);
507                         newval = search_def_and_create_phis(pred_block, mode);
508                 } else {
509                         newval = search_def_and_create_phis(user_block, mode);
510                 }
511
512                 /* If we get a bad node the user keeps the original in. No second definition needed. */
513                 if (newval != user && !is_Bad(newval))
514                         set_irn_n(user, j, newval);
515         }
516
517         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
518 }
519
520 /*
521  * Construct SSA for def and all of its copies.
522  */
523 static void construct_ssa_n(ir_node *def, ir_node *user)
524 {
525         ir_graph *irg;
526         ir_mode *mode;
527         ir_node *iter = def;
528         const ir_edge_t *edge;
529         const ir_edge_t *next;
530         irg = get_irn_irg(def);
531
532         ir_reserve_resources(irg, IR_RESOURCE_IRN_VISITED);
533         inc_irg_visited(irg);
534
535         mode = get_irn_mode(def);
536
537         for_each_copy(iter) {
538                 set_link(get_nodes_block(iter), iter);
539                 mark_irn_visited(get_nodes_block(iter));
540
541                 DB((dbg, LEVEL_5, "ssa_n:  Link def %ld to block %ld\n",
542                                                                         get_irn_node_nr(iter), get_irn_node_nr(get_nodes_block(iter))));
543         }
544
545         /* Need to search the outs, because we need the in-pos on the user node. */
546         foreach_out_edge_safe(def, edge, next) {
547                 ir_node *edge_user = get_edge_src_irn(edge);
548                 int edge_src = get_edge_src_pos(edge);
549                 ir_node *user_block = get_nodes_block(user);
550                 ir_node *newval;
551
552                 if (edge_user != user)
553                         continue;
554
555                 if (is_Phi(user)) {
556                         ir_node *pred_block = get_Block_cfgpred_block(user_block, edge_src);
557                         newval = search_def_and_create_phis(pred_block, mode);
558                 } else {
559                         newval = search_def_and_create_phis(user_block, mode);
560                 }
561
562                 if (newval != user && !is_Bad(newval))
563                         set_irn_n(user, edge_src, newval);
564         }
565
566         ir_free_resources(irg, IR_RESOURCE_IRN_VISITED);
567 }
568
569 /**
570  * Construct SSA for all definitions in arr.
571  */
572 void construct_ssa_foreach(ir_node **arr, int arr_n)
573 {
574         int i;
575         for(i = 0; i < arr_n; ++i) {
576                 ir_node *cppred, *block, *cpblock, *pred;
577
578                 pred = arr[i];
579                 cppred = get_copy(pred);
580                 block = get_nodes_block(pred);
581                 cpblock = get_nodes_block(cppred);
582                 construct_ssa(block, pred, cpblock, cppred);
583         }
584 }
585
586 /* get the number of backedges without alien bes */
587 static int get_backedge_n(ir_node *loophead, unsigned with_alien)
588 {
589         int i;
590         int be_n = 0;
591         int arity = get_irn_arity(loophead);
592         for (i = 0; i < arity; ++i) {
593                 ir_node *pred = get_irn_n(loophead, i);
594                 if (is_backedge(loophead, i) && (with_alien || is_in_loop(pred)))
595                         ++be_n;
596         }
597         return be_n;
598 }
599
600 /**
601  * Rewires the heads after peeling.
602  */
603 static void peel_fix_heads(void)
604 {
605         ir_node **loopheadnins, **peelheadnins;
606         ir_node *loophead = loop_cf_head;
607         ir_node *peelhead = get_copy(loophead);
608
609         int headarity = get_irn_arity(loophead);
610         ir_node *phi;
611         int i;
612
613         int lheadin_c = 0;
614         int pheadin_c = 0;
615
616         int backedges_n = get_backedge_n(loophead, 0);
617
618         int lhead_arity = 2 * backedges_n;
619         int phead_arity = headarity - backedges_n;
620
621         /* new in arrays */
622         NEW_ARR_A(ir_node *, loopheadnins, lhead_arity );
623         NEW_ARR_A(ir_node *, peelheadnins, phead_arity );
624
625         for_each_phi(loophead, phi) {
626                 NEW_ARR_A(ir_node *, get_node_info(phi)->ins, lhead_arity);
627         }
628         for_each_phi(peelhead, phi) {
629                 NEW_ARR_A(ir_node *, get_node_info(phi)->ins, phead_arity);
630         }
631
632         for (i = 0; i < headarity; i++)
633         {
634                 ir_node *orgjmp = get_irn_n(loophead, i);
635                 ir_node *copyjmp = get_copy(orgjmp);
636
637                 /**
638                  * Rewire the head blocks ins and their phi ins.
639                  * Requires phi list per block.
640                  */
641                 if (is_backedge(loophead, i) && !is_alien_edge(loophead, i)) {
642                         loopheadnins[lheadin_c] = orgjmp;
643                         for_each_phi(loophead, phi) {
644                                 get_node_info( phi )->ins[lheadin_c] =  get_irn_n( phi, i) ;
645                         }
646                         ++lheadin_c;
647
648                         /* former bes of the peeled code origin now from the loophead */
649                         loopheadnins[lheadin_c] = copyjmp;
650
651                         /* get_irn_n( get_copy_of(phi), i ) <!=> get_copy_of( get_irn_n( phi, i) )
652                          * Order is crucial! Predecessors outside of the loop are non existent.
653                          * The copy (cloned with its ins!) has pred i,
654                          * but phis pred i might not have a copy of itself.
655                          */
656                         for_each_phi(loophead, phi) {
657                                 get_node_info( phi )->ins[lheadin_c] =  get_irn_n( get_copy(phi), i) ;
658                         }
659                         ++lheadin_c;
660                 } else {
661                         peelheadnins[pheadin_c] = orgjmp;
662                         for_each_phi(peelhead, phi) {
663                                 get_node_info( phi )->ins[pheadin_c] = get_irn_n(phi, i);
664                         }
665                         ++pheadin_c;
666                 }
667         }/* for */
668
669         assert(pheadin_c == ARR_LEN(peelheadnins) &&
670                         lheadin_c == ARR_LEN(loopheadnins) &&
671                         "the constructed head arities do not match the predefined arities");
672
673         /* assign the ins to the nodes */
674         set_irn_in(loophead, ARR_LEN(loopheadnins), loopheadnins);
675         set_irn_in(peelhead, ARR_LEN(peelheadnins), peelheadnins);
676
677         for_each_phi(loophead, phi) {
678                 ir_node **ins = get_node_info( phi )->ins;
679                 set_irn_in(phi, lhead_arity, ins);
680         }
681
682         for_each_phi(peelhead, phi) {
683                 ir_node **ins = get_node_info( phi )->ins;
684                 set_irn_in(phi, phead_arity, ins);
685         }
686 }
687
688 /**
689  * Create a raw copy (ins are still the old ones) of the given node.
690  * We rely on copies to be NOT visited.
691  */
692 static ir_node *rawcopy_node(ir_node *node)
693 {
694         int i, arity;
695         ir_node *cp;
696         node_info *cpstate;
697
698         cp = exact_copy(node);
699
700         arity = get_irn_arity(node);
701
702         for (i = 0; i < arity; ++i) {
703                 if (is_backedge(node, i))
704                         set_backedge(cp, i);
705         }
706
707         set_copy(node, cp);
708         cpstate = new_node_info();
709         set_irn_link(cp, cpstate);
710
711         if (is_Block(cp)) {
712                 /* TODO
713                  * exact_copy already sets Macroblock.
714                  * Why do we need to do this anyway? */
715                 set_Block_MacroBlock(cp, cp);
716         }
717         return cp;
718 }
719
720 /**
721  * This walker copies all walked nodes.
722  * If the walk_condition is true for a node, it is walked.
723  * All nodes node_info->copy attributes has to be NULL prior to every to every walk.
724  */
725 static void copy_walk(ir_node *node, walker_condition *walk_condition, ir_loop *set_loop)
726 {
727         int i;
728         int arity;
729         ir_node *cp;
730         ir_node **cpin;
731         ir_graph *irg = current_ir_graph;
732         node_info *node_info = get_node_info(node);
733
734         /**
735          * break condition and cycle resolver, creating temporary node copies
736          */
737         if (get_irn_visited(node) >= get_irg_visited(irg)) {
738                 /* Here we rely on nodestate's copy being initialized with NULL */
739                 DB((dbg, LEVEL_5, "copy_walk: We have already visited %ld\n", get_irn_node_nr(node)));
740                 if (node_info->copy == NULL) {
741                         cp = rawcopy_node(node);
742                         DB((dbg, LEVEL_5, "The TEMP copy of %ld is created %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp)));
743                 }
744                 return;
745         }
746
747         /* Walk */
748         mark_irn_visited(node);
749
750         if (!is_Block(node)) {
751                 ir_node *pred = get_nodes_block(node);
752                 if (walk_condition(pred))
753                         DB((dbg, LEVEL_5, "walk block %ld\n", get_irn_node_nr(pred)));
754                         copy_walk(pred, walk_condition, set_loop);
755         }
756
757         arity = get_irn_arity(node);
758
759         NEW_ARR_A(ir_node *, cpin, arity);
760
761         for (i = get_irn_arity(node) - 1; i >= 0; --i) {
762                 ir_node *pred = get_irn_n(node, i);
763
764                 if (walk_condition(pred)) {
765                         DB((dbg, LEVEL_5, "walk node %ld\n", get_irn_node_nr(pred)));
766                         copy_walk(pred, walk_condition, set_loop);
767                         cpin[i] = get_copy(pred);
768                         DB((dbg, LEVEL_5, "copy of %ld gets new in %ld which is copy of %ld\n",
769                                 get_irn_node_nr(node), get_irn_node_nr(get_copy(pred)), get_irn_node_nr(pred)));
770                 } else {
771                         cpin[i] = pred;
772                 }
773         }
774
775         /* copy node / finalize temp node */
776         if (node_info->copy == NULL) {
777                 /* No temporary copy existent */
778                 cp = rawcopy_node(node);
779                 DB((dbg, LEVEL_5, "The FINAL copy of %ld is CREATED %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp)));
780         } else {
781                 /* temporary copy is existent but without correct ins */
782                 cp = get_copy(node);
783                 DB((dbg, LEVEL_5, "The FINAL copy of %ld is EXISTENT %ld\n", get_irn_node_nr(node), get_irn_node_nr(cp)));
784         }
785
786         if (!is_Block(node)) {
787                 ir_node *cpblock = get_copy(get_nodes_block(node));
788
789                 set_nodes_block(cp, cpblock );
790                 /* fix the phi information in attr.phis */
791                 if( is_Phi(cp) )
792                         add_Block_phi(cpblock, cp);
793         }
794
795         set_irn_loop(cp, set_loop);
796         set_irn_in(cp, ARR_LEN(cpin), cpin);
797 }
798
799 /**
800  * Loop peeling, and fix the cf for the loop entry nodes, which have now more preds
801  */
802 static void peel(out_edge *loop_outs)
803 {
804         int i;
805         ir_node **entry_buffer;
806         int entry_c = 0;
807
808         ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
809
810         NEW_ARR_A(ir_node *, entry_buffer, ARR_LEN(loop_outs));
811
812         /* duplicate loop walk */
813         inc_irg_visited(current_ir_graph);
814
815         for(i = 0; i < ARR_LEN(loop_outs); i++) {
816                 out_edge entry = loop_outs[i];
817                 ir_node *node = entry.node;
818                 ir_node *pred = get_irn_n(entry.node, entry.pred_irn_n);
819
820                 if (is_Block(node)) {
821                         copy_walk(pred, is_in_loop, NULL);
822                         duplicate_preds(node, entry.pred_irn_n, get_copy(pred) );
823                 } else {
824                         copy_walk(pred, is_in_loop, NULL);
825                         /* leave out keepalives */
826                         if (!is_End(node))
827                                 /* Node is user of a value defined inside the loop.
828                                  * We'll need a phi since we duplicated the loop. */
829                                 /* Cannot construct_ssa here, because it needs another walker. */
830                                 entry_buffer[entry_c++] = pred;
831                 }
832         }
833
834         ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
835
836         /* Rewires the 2 heads */
837         peel_fix_heads();
838
839         /* Generate phis for values from peeled code and original loop */
840         construct_ssa_foreach(entry_buffer, entry_c);
841         /*for(i = 0; i < entry_c; i++)
842         {
843                 ir_node *cppred, *block, *cpblock, *pred;
844
845                 pred = entry_buffer[i];
846                 cppred = get_copy(pred);
847                 block = get_nodes_block(pred);
848                 cpblock = get_nodes_block(cppred);
849                 construct_ssa(block, pred, cpblock, cppred);
850         }*/
851 }
852
853 /**
854  * Populates head_entries with (node, pred_pos) tuple
855  * whereas the node's pred at pred_pos is in the head but not the node itself.
856  * Head and condition chain blocks must be marked.
857  */
858 static void get_head_outs(ir_node *node, void *env)
859 {
860         int i;
861         int arity = get_irn_arity(node);
862         (void) env;
863
864         DB((dbg, LEVEL_5, "get head entries %ld \n", get_irn_node_nr(node)));
865
866         for(i = 0; i < arity; ++i) {
867                 /* node is not in the head, but the predecessor is.
868                  * (head or loop chain nodes are marked) */
869
870                 DB((dbg, LEVEL_5, "... "));
871                 DB((dbg, LEVEL_5, "node %ld  marked %d (0)  pred %d marked %d (1) \n",
872                     node->node_nr, is_nodesblock_marked(node),i, is_nodesblock_marked(get_irn_n(node, i))));
873
874                 if (!is_nodesblock_marked(node) && is_nodesblock_marked(get_irn_n(node, i))) {
875                         out_edge entry;
876                         entry.node = node;
877                         entry.pred_irn_n = i;
878                         DB((dbg, LEVEL_5,
879                                 "Found head chain entry %ld @%d because !inloop %ld and inloop %ld\n",
880                                 get_irn_node_nr(node), i, get_irn_node_nr(node), get_irn_node_nr(get_irn_n(node, i))));
881                         ARR_APP1(out_edge, cur_head_outs, entry);
882                 }
883         }
884 }
885
886 /**
887  * Find condition chains, and add them to be inverted, until the node count exceeds the limit.
888  * A block belongs to the chain if a condition branches out of the loop.
889  * Returns 1 if the given block belongs to the condition chain.
890  */
891 static unsigned find_condition_chains(ir_node *block) {
892         const ir_edge_t *edge;
893         unsigned mark = 0;
894         int nodes_n = 0;
895
896         DB((dbg, LEVEL_5, "condition_chains for block %ld\n", get_irn_node_nr(block)));
897
898         /* Collect all outs, including keeps.
899          * (TODO firm function for number of out edges?) */
900         foreach_out_edge_kind(block, edge, EDGE_KIND_NORMAL) {
901                 ++nodes_n;
902         }
903
904         /* We do not want to collect more nodes from condition chains, than the limit allows us to.
905          * Also, leave at least one block as body. */
906         if (head_inversion_node_count + nodes_n > inversion_head_node_limit
907                     || head_inversion_block_count + 1 == loop_info.blocks) {
908                 set_Block_mark(block, 0);
909
910                 return 0;
911         }
912
913         /* First: check our successors, and add all succs that are outside of the loop to the list */
914         foreach_block_succ(block, edge) {
915                 ir_node *src = get_edge_src_irn( edge );
916                 int pos = get_edge_src_pos( edge );
917
918                 if (!is_in_loop(src)) {
919                         out_edge entry;
920
921                         mark = 1;
922                         entry.node = src;
923                         entry.pred_irn_n = pos;
924                         ARR_APP1(out_edge, cond_chain_entries, entry);
925                         mark_irn_visited(src);
926                 }
927         }
928
929         if (mark == 0) {
930                 /* this block is not part of the chain,
931                  * because the chain would become too long or we have no successor outside of the loop */
932
933                 set_Block_mark(block, 0);
934                 return 0;
935         } else {
936                 set_Block_mark(block, 1);
937                 ++head_inversion_block_count;
938                 DB((dbg, LEVEL_5, "block %ld is part of condition chain\n", get_irn_node_nr(block)));
939                 head_inversion_node_count += nodes_n;
940         }
941
942         /* Second: walk all successors, and add them to the list if they are not part of the chain */
943         foreach_block_succ(block, edge) {
944                 unsigned inchain;
945                 ir_node *src = get_edge_src_irn( edge );
946                 int pos = get_edge_src_pos( edge );
947
948                 /* already done cases */
949                 if (!is_in_loop( src ) || (get_irn_visited(src) >= get_irg_visited(current_ir_graph))) {
950                         continue;
951                 }
952
953                 mark_irn_visited(src);
954                 DB((dbg, LEVEL_5, "condition chain walk %ld\n", get_irn_node_nr(src)));
955                 inchain = find_condition_chains(src);
956
957                 /* if successor is not part of chain we need to collect its outs */
958                 if (!inchain) {
959                         out_edge entry;
960                         entry.node = src;
961                         entry.pred_irn_n = pos;
962                         ARR_APP1(out_edge, cond_chain_entries, entry);
963                 }
964         }
965         return mark;
966 }
967
968 /**
969  * Rewire the loop head and inverted head for loop inversion.
970  */
971 static void inversion_fix_heads(void)
972 {
973         ir_node **loopheadnins, **invheadnins;
974         ir_node *loophead = loop_cf_head;
975         ir_node *invhead =      get_copy(loophead);
976
977         int headarity =         get_irn_arity(loophead);
978         ir_node *phi;
979         int i;
980
981         int lheadin_c = 0;
982         int iheadin_c = 0;
983
984         int backedges_n = get_backedge_n(loophead, 0);
985         int lhead_arity = backedges_n;
986         int ihead_arity = headarity - backedges_n;
987
988         assert(lhead_arity != 0 && "Loophead has arity 0. Probably wrong backedge informations.");
989         assert(ihead_arity != 0 && "Inversionhead has arity 0. Probably wrong backedge informations.");
990
991         /* new in arrays for all phis in the head blocks */
992         NEW_ARR_A(ir_node *, loopheadnins, lhead_arity);
993         NEW_ARR_A(ir_node *, invheadnins, ihead_arity);
994
995         for_each_phi(loophead, phi) {
996                 NEW_ARR_A(ir_node *, get_node_info(phi)->ins, lhead_arity);
997         }
998         for_each_phi(invhead, phi) {
999                 NEW_ARR_A(ir_node *, get_node_info(phi)->ins, ihead_arity);
1000         }
1001
1002         for (i = 0; i < headarity; i++) {
1003                 ir_node *pred = get_irn_n(loophead, i);
1004
1005                 /**
1006                  * Rewire the head blocks ins and their phi ins.
1007                  * Requires phi list per block.
1008                  */
1009                 if (is_backedge(loophead, i) && !is_alien_edge(loophead, i)) {
1010                         /* just copy these edges */
1011                         loopheadnins[lheadin_c] = pred;
1012                         for_each_phi(loophead, phi) {
1013                                 get_node_info(phi)->ins[lheadin_c] = get_irn_n(phi, i);
1014                         }
1015                         ++lheadin_c;
1016                 } else {
1017                         invheadnins[iheadin_c] = pred;
1018                         for_each_phi(invhead, phi) {
1019                                 get_node_info(phi)->ins[iheadin_c] = get_irn_n(phi, i) ;
1020                         }
1021                         ++iheadin_c;
1022                 }
1023         }
1024
1025         /* assign the ins to the head blocks */
1026         set_irn_in(loophead, ARR_LEN(loopheadnins), loopheadnins);
1027         set_irn_in(invhead, ARR_LEN(invheadnins), invheadnins);
1028
1029         /* assign the ins for the phis */
1030         for_each_phi(loophead, phi) {
1031                 ir_node **ins = get_node_info(phi)->ins;
1032                 set_irn_in(phi, lhead_arity, ins);
1033         }
1034
1035         for_each_phi(invhead, phi) {
1036                 ir_node **ins = get_node_info(phi)->ins;
1037                 set_irn_in(phi, ihead_arity, ins);
1038         }
1039 }
1040
1041 static void inversion_walk(out_edge *head_entries)
1042 {
1043         int i;
1044         ir_node *phi;
1045         int entry_c = 0;
1046         ir_node **entry_buffer;
1047         ir_node **head_phi_assign;
1048
1049         NEW_ARR_A(ir_node *, entry_buffer, ARR_LEN(head_entries));
1050
1051         head_phi_assign = NEW_ARR_F(ir_node *, 0);
1052
1053         /* Find assignments in the condition chain, to construct_ssa for them after the loop inversion. */
1054         for_each_phi(loop_cf_head , phi) {
1055                 for(i=0; i<get_irn_arity(phi); ++i) {
1056                         ir_node *def = get_irn_n(phi, i);
1057                         if (is_nodesblock_marked(def)) {
1058                                 ARR_APP1(ir_node *, head_phi_assign, def);
1059                         }
1060                 }
1061         }
1062
1063         ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
1064
1065         /**
1066          * duplicate condition chain
1067          **/
1068         inc_irg_visited(current_ir_graph);
1069
1070         for(i = 0; i < ARR_LEN(head_entries); ++i) {
1071                 out_edge entry = head_entries[i];
1072                 ir_node *node = entry.node;
1073                 ir_node *pred = get_irn_n(entry.node, entry.pred_irn_n);
1074
1075                 if (is_Block(node)) {
1076                         DB((dbg, LEVEL_5, "\nInit walk block %ld\n", get_irn_node_nr(pred)));
1077                         copy_walk(pred, is_nodesblock_marked, cur_loop);
1078                         duplicate_preds(node, entry.pred_irn_n, get_copy(pred) );
1079                 } else {
1080                         DB((dbg, LEVEL_5, "\nInit walk node  %ld\n", get_irn_node_nr(pred)));
1081                         copy_walk(pred, is_nodesblock_marked, cur_loop);
1082
1083                         /* ignore keepalives */
1084                         if (!is_End(node))
1085                                 /* Node is user of a value assigned inside the loop.
1086                                  * We will need a phi since we duplicated the head. */
1087                                 entry_buffer[entry_c++] = pred;
1088                 }
1089         }
1090
1091         ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
1092
1093         inversion_fix_heads();
1094
1095         /* Generate phis for users of values assigned in the condition chain
1096          * and read in the loops body */
1097         construct_ssa_foreach(entry_buffer, entry_c);
1098
1099         /* Generate phis for values that are assigned in the condition chain
1100          * but not read in the loops body. */
1101         construct_ssa_foreach(head_phi_assign, ARR_LEN(head_phi_assign));
1102
1103         loop_cf_head = get_copy(loop_cf_head);
1104 }
1105
1106 /* Loop peeling */
1107 void loop_peeling(void)
1108 {
1109         cur_loop_outs = NEW_ARR_F(out_edge, 0);
1110         irg_walk_graph( current_ir_graph, get_loop_outs, NULL, NULL );
1111
1112         peel(cur_loop_outs);
1113
1114         /* clean up */
1115         reset_node_infos();
1116
1117         set_irg_doms_inconsistent(current_ir_graph);
1118         set_irg_loopinfo_inconsistent(current_ir_graph);
1119         set_irg_outs_inconsistent(current_ir_graph);
1120
1121         DEL_ARR_F(cur_loop_outs);
1122 }
1123
1124 /* Loop inversion */
1125 void loop_inversion(void)
1126 {
1127         unsigned do_inversion = 1;
1128
1129         inversion_head_node_limit = INT_MAX;
1130
1131         /* Search for condition chains. */
1132         ir_reserve_resources(current_ir_graph, IR_RESOURCE_BLOCK_MARK);
1133
1134         irg_walk_graph(current_ir_graph, reset_block_mark, NULL, NULL);
1135
1136         loop_info.blocks = get_loop_n_blocks(cur_loop);
1137         cond_chain_entries = NEW_ARR_F(out_edge, 0);
1138
1139         head_inversion_node_count = 0;
1140         head_inversion_block_count = 0;
1141
1142         set_Block_mark(loop_cf_head, 1);
1143         mark_irn_visited(loop_cf_head);
1144         inc_irg_visited(current_ir_graph);
1145
1146         find_condition_chains(loop_cf_head);
1147
1148         DB((dbg, LEVEL_3, "Loop contains %d blocks.\n", loop_info.blocks));
1149         if (loop_info.blocks < 2) {
1150                 do_inversion = 0;
1151                 DB((dbg, LEVEL_3, "Loop contains %d (less than 2) blocks => No Inversion done.\n", loop_info.blocks));
1152         }
1153
1154         /* We also catch endless loops here,
1155          * because they do not have a condition chain. */
1156         if (head_inversion_block_count < 1) {
1157                 do_inversion = 0;
1158                 DB((dbg, LEVEL_3, "Loop contains %d (less than 1) invertible blocks => No Inversion done.\n", head_inversion_block_count));
1159         }
1160
1161         if (do_inversion) {
1162                 cur_head_outs = NEW_ARR_F(out_edge, 0);
1163
1164                 /* Get all edges pointing into the head or condition chain (outs). */
1165                 irg_walk_graph(current_ir_graph, get_head_outs, NULL, NULL);
1166                 inversion_walk(cur_head_outs);
1167
1168                 DEL_ARR_F(cur_head_outs);
1169
1170                 set_irg_doms_inconsistent(current_ir_graph);
1171                 set_irg_loopinfo_inconsistent(current_ir_graph);
1172                 set_irg_outs_inconsistent(current_ir_graph);
1173         }
1174
1175         /* free */
1176         DEL_ARR_F(cond_chain_entries);
1177         ir_free_resources(current_ir_graph, IR_RESOURCE_BLOCK_MARK);
1178 }
1179
1180 /**
1181  * Returns last element of linked list of copies by
1182  * walking the linked list.
1183  */
1184 ir_node *get_last_copy(ir_node *node)
1185 {
1186         ir_node *copy, *cur;
1187         cur = node;
1188         while ((copy = get_copy(cur))) {
1189                 cur = copy;
1190         }
1191         return cur;
1192 }
1193
1194 /**
1195  * Rewire floating copies of the current loop.
1196  */
1197 void unrolling_fix_cf(void)
1198 {
1199         ir_node *loophead = loop_cf_head;
1200         int headarity =         get_irn_arity(loophead);
1201         ir_node *phi, *headnode;
1202         /*ir_node *high, *low;*/
1203         int i;
1204
1205         int uhead_in_n = 0;
1206         int backedges_n = get_backedge_n(loophead, 0);
1207         int unroll_arity = backedges_n;
1208
1209         /* Create ins for all heads and their phis */
1210         headnode = get_copy(loophead);
1211         for_each_copy(headnode) {
1212                 NEW_ARR_A(ir_node *, get_node_info(headnode)->ins, unroll_arity);
1213                 for_each_phi(headnode, phi) {
1214                         NEW_ARR_A(ir_node *, get_node_info(phi)->ins, unroll_arity);
1215                 }
1216         }
1217
1218         /* Append the copies to the existing loop. */
1219         for (i = 0; i < headarity; i++) {
1220                 ir_node *upper_head = loophead;
1221                 ir_node *lower_head = get_copy(loophead);
1222
1223                 ir_node *upper_pred = get_irn_n(loophead, i);
1224                 ir_node *lower_pred = get_copy(get_irn_n(loophead, i));
1225
1226                 ir_node *last_pred;
1227
1228                 /**
1229                  * Build unrolled loop top down
1230                  */
1231                 if (is_backedge(loophead, i) && !is_alien_edge(loophead, i)) {
1232                         for_each_copy2(upper_head, lower_head, upper_pred, lower_pred) {
1233                                 get_node_info(lower_head)->ins[uhead_in_n] = upper_pred;
1234
1235                                 for_each_phi(upper_head, phi) {
1236                                         ir_node *phi_copy = get_copy(phi);
1237                                         get_node_info(phi_copy)->ins[uhead_in_n] = get_irn_n(phi, i);
1238                                 }
1239                         }
1240
1241                         last_pred = upper_pred;
1242                         ++uhead_in_n;
1243
1244                         /* Fix the topmost loop heads backedges. */
1245                         set_irn_n(loophead, i, last_pred);
1246                         for_each_phi(loophead, phi) {
1247                                 ir_node *last_phi = get_last_copy(phi);
1248                                 ir_node *pred = get_irn_n(last_phi, i);
1249                                 set_irn_n(phi, i, pred);
1250                         }
1251                 }
1252         }
1253
1254         headnode = get_copy(loophead);
1255         for_each_copy(headnode) {
1256                 set_irn_in(headnode, unroll_arity, get_node_info(headnode)->ins);
1257                 for_each_phi(headnode, phi) {
1258                         set_irn_in(phi, unroll_arity, get_node_info(phi)->ins);
1259                 }
1260         }
1261 }
1262
1263 #if 0
1264 static ir_node *add_phi(ir_node *node, int phi_pos)
1265 {
1266         ir_mode *mode;
1267         ir_node *phi;
1268         ir_node **in;
1269         mode = get_irn_mode(get_irn_n(node, phi_pos));
1270         ir_node *block = get_nodes_block(node);
1271         int n_cfgpreds = get_irn_arity(block);
1272         ir_node *pred = get_irn_n(node, phi_pos);
1273         int i;
1274
1275         /* create a new Phi */
1276         NEW_ARR_A(ir_node*, in, n_cfgpreds);
1277         for(i = 0; i < n_cfgpreds; ++i)
1278                 in[i] = new_Unknown(mode);  /*pred;*/
1279
1280         phi = new_r_Phi(block, n_cfgpreds, in, mode);
1281
1282         assert(phi && "phi null");
1283         assert(is_Bad(phi) && "phi bad");
1284
1285         /* Important: always keep block phi list up to date. */
1286         add_Block_phi(block, phi);
1287         /* EVERY node is assumed to have a node_info linked. */
1288         alloc_node_info(phi, NULL);
1289
1290         set_irn_n(node, phi_pos, phi);
1291         return phi;
1292 }
1293 #endif
1294
1295
1296 /**
1297  * Loop unrolling
1298  * Could be improved with variable range informations.
1299  */
1300 void loop_unrolling(void)
1301 {
1302         int i, j;
1303
1304         unroll_times = 8;
1305
1306         cur_loop_outs = NEW_ARR_F(out_edge, 0);
1307         irg_walk_graph( current_ir_graph, get_loop_outs, NULL, NULL );
1308
1309         ir_reserve_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
1310
1311         /* duplicate whole loop content */
1312         inc_irg_visited(current_ir_graph);
1313
1314         for(i = 0; i < ARR_LEN(cur_loop_outs); i++) {
1315                 out_edge entry = cur_loop_outs[i];
1316                 ir_node *node = entry.node;
1317                 ir_node *pred = get_irn_n(entry.node, entry.pred_irn_n);
1318
1319                 if (!is_Block(node)) {
1320
1321                         for (j = 0; j < unroll_times-1; ++j) {
1322                                 copy_walk(pred, is_in_loop, cur_loop);
1323
1324                                 pred = get_copy(pred);
1325                         }
1326                 }
1327         }
1328
1329         for(i = 0; i < ARR_LEN(cur_loop_outs); i++) {
1330                 out_edge entry = cur_loop_outs[i];
1331                 ir_node *node = entry.node;
1332                 ir_node *pred = get_irn_n(entry.node, entry.pred_irn_n);
1333
1334                 /* build linked list of copied nodes/blocks */
1335                 if (is_Block(node)) {
1336                         for (j = 0; j < unroll_times-1; ++j) {
1337                                 copy_walk(pred, is_in_loop, cur_loop);
1338                                 duplicate_preds(node, entry.pred_irn_n, get_copy(pred));
1339
1340                                 pred = get_copy(pred);
1341                         }
1342                 }
1343         }
1344
1345         ir_free_resources(current_ir_graph, IR_RESOURCE_IRN_VISITED);
1346
1347         /* Line up the floating copies. */
1348         unrolling_fix_cf();
1349
1350         /* Generate phis for all loop outs */
1351         for(i = 0; i < ARR_LEN(cur_loop_outs); i++) {
1352                 out_edge entry = cur_loop_outs[i];
1353                 ir_node *node = entry.node;
1354                 ir_node *pred = get_irn_n(entry.node, entry.pred_irn_n);
1355
1356                 if (!is_Block(node) && !is_End(node)) {
1357                         DB((dbg, LEVEL_1, "  construct_ssa_n def %ld  node %ld  pos %d\n",
1358                                         get_irn_node_nr(pred), get_irn_node_nr(node), entry.pred_irn_n));
1359                         construct_ssa_n(pred, node);
1360                 }
1361         }
1362
1363         DEL_ARR_F(cur_loop_outs);
1364
1365         set_irg_doms_inconsistent(current_ir_graph);
1366         set_irg_loopinfo_inconsistent(current_ir_graph);
1367         set_irg_outs_inconsistent(current_ir_graph);
1368 }
1369
1370 /* Initialization and */
1371 static void init_analyze(ir_loop *loop)
1372 {
1373         /* Init new for every loop */
1374         cur_loop = loop;
1375
1376         loop_cf_head = NULL;
1377         loop_cf_head_valid = 1;
1378         loop_inv_head = NULL;
1379         loop_peeled_head = NULL;
1380
1381         loop_info.outs = 0;
1382         loop_info.calls = 0;
1383         loop_info.loads = 0;
1384         loop_info.blocks = 0;
1385
1386         DB((dbg, LEVEL_2, "  >>>> current loop includes node %ld <<<\n", get_irn_node_nr(get_loop_node(loop, 0))));
1387
1388         irg_walk_graph(current_ir_graph, get_loop_info, NULL, NULL);
1389
1390         /* RETURN if there is no valid head */
1391         if (!loop_cf_head || !loop_cf_head_valid) {
1392                 DB((dbg, LEVEL_2,   "No valid loop head. Nothing done.\n"));
1393                 return;
1394         }
1395
1396         if (enable_peeling)
1397                 loop_peeling();
1398
1399         if (enable_inversion)
1400                 loop_inversion();
1401         if (enable_unrolling)
1402                 loop_unrolling();
1403
1404 #if 0
1405         /* RETURN if there is a call in the loop */
1406         if (loop_info.calls)
1407                 return;
1408 #endif
1409
1410         DB((dbg, LEVEL_2, "      <<<< end of loop with node %ld >>>>\n", get_irn_node_nr(get_loop_node(loop, 0))));
1411 }
1412
1413 /* Find most inner loops and send them to analyze_loop */
1414 static void find_most_inner_loop(ir_loop *loop)
1415 {
1416         /* descend into sons */
1417         int sons = get_loop_n_sons(loop);
1418
1419         if (sons == 0) {
1420                 loop_element elem;
1421                 int el_n, i;
1422
1423                 el_n = get_loop_n_elements(loop);
1424
1425                 for (i=0; i < el_n; ++i) {
1426                         elem = get_loop_element(loop, i);
1427                         /* We can only rely on the blocks,
1428                          * as the loop attribute of the nodes seems not to be set. */
1429                         if (is_ir_node(elem.kind) && is_Block(elem.node)) {
1430                                 ARR_APP1(ir_node *, loops, elem.node);
1431                                 DB((dbg, LEVEL_5, "Found most inner loop (contains block %+F)\n", elem.node));
1432                                 break;
1433                         }
1434                 }
1435         } else {
1436                 int s;
1437                 for(s=0; s<sons; s++) {
1438                         find_most_inner_loop(get_loop_son(loop, s));
1439                 }
1440         }
1441 }
1442
1443 /**
1444  * Assure preconditions are met and go through all loops.
1445  */
1446 void loop_optimization(ir_graph *irg)
1447 {
1448         ir_loop *loop;
1449         int     i, sons, nr;
1450
1451         /* Init */
1452         link_node_state_list = NULL;
1453         set_current_ir_graph(irg);
1454
1455         /* preconditions */
1456         edges_assure(irg);
1457         assure_irg_outs(irg);
1458
1459         /* NOTE: sets only the loop attribute of blocks, not nodes */
1460         /* NOTE: Kills links */
1461         assure_cf_loop(irg);
1462
1463         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK|IR_RESOURCE_PHI_LIST);
1464         collect_phiprojs(irg);
1465         ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
1466
1467         /* allocate node_info for additional information on nodes */
1468         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
1469         irg_walk_graph(current_ir_graph, alloc_node_info, NULL, NULL);
1470
1471         loop = get_irg_loop(irg);
1472         sons = get_loop_n_sons(loop);
1473
1474         loops = NEW_ARR_F(ir_node *, 0);
1475
1476         for (nr = 0; nr < sons; ++nr) {
1477                 find_most_inner_loop(get_loop_son(loop, nr));
1478         }
1479
1480 /* TODO Keep backedges during optimization to avoid
1481  * this ugly allocation and deallocation.
1482  * (set_irn_in seems to destroy them)
1483  */
1484 #if 0
1485         for (i = 0; i < ARR_LEN(loops); ++i) {
1486                 ir_loop *loop;
1487
1488                 loop = get_irn_loop(loops[i]);
1489                 init_analyze(loop);
1490         }
1491 #else
1492         /* This part is useful for testing
1493          * or has to be used if the backedge information is destroyed.
1494          * Which is the case at the moment, because the backedge information gets lost
1495          * before inversion_fix_heads/unrolling_fix_cf, which results in bads.
1496          * NOTE!: Testsuite runs successfully nevertheless...
1497          */
1498
1499         /**
1500          * assure_cf_loop() creates a completely new loop tree.
1501          * Thus we cannot optimize a loop, assure_cf_loop() and continue with the next loop,
1502          * as the next loop must be searched because it is not distinguishable from the
1503          * already done loops.
1504          * The links of the loops are also not available anymore (to store a "loop done" flag).
1505          * Therefore we save a block per loop.
1506          * NOTE: We rely on the loop optimizations not to remove any block from the loop.
1507          * Later, we fetch the blocks loop attribute, as it is updated by assure_cf_loop.
1508          */
1509         for (i = 0; i < ARR_LEN(loops); ++i) {
1510                 ir_loop *loop;
1511
1512                 free_node_info();
1513                 ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
1514
1515                 edges_assure(current_ir_graph);
1516                 assure_irg_outs(current_ir_graph);
1517
1518                 /* NOTE: sets only the loop attribute of blocks */
1519                 /* NOTE: Kills links */
1520                 assure_cf_loop(current_ir_graph);
1521
1522                 irg_walk_graph(current_ir_graph, alloc_node_info, NULL, NULL);
1523                 ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK);
1524
1525                 /* Get loop from block */
1526                 loop = get_irn_loop(loops[i]);
1527                 init_analyze(loop);
1528         }
1529 #endif
1530
1531         /* Free */
1532         DEL_ARR_F(loops);
1533
1534         free_node_info();
1535         ir_free_resources(irg, IR_RESOURCE_IRN_LINK);
1536         ir_free_resources(irg, IR_RESOURCE_PHI_LIST);
1537 }
1538
1539 void do_loop_unrolling(ir_graph *irg)
1540 {
1541         enable_unrolling = 1;
1542         enable_peeling = 0;
1543         enable_inversion = 0;
1544
1545         DB((dbg, LEVEL_2, " >>> unrolling (Startnode %ld) <<<\n",
1546                 get_irn_node_nr(get_irg_start(irg))));
1547
1548         loop_optimization(irg);
1549
1550         DB((dbg, LEVEL_2, " >>> unrolling done (Startnode %ld) <<<\n",
1551                 get_irn_node_nr(get_irg_start(irg))));
1552 }
1553
1554 void do_loop_inversion(ir_graph *irg)
1555 {
1556         enable_unrolling = 0;
1557         enable_peeling = 0;
1558         enable_inversion = 1;
1559
1560         DB((dbg, LEVEL_2, " >>> inversion (Startnode %ld) <<<\n",
1561                 get_irn_node_nr(get_irg_start(irg))));
1562
1563         loop_optimization(irg);
1564
1565         DB((dbg, LEVEL_2, " >>> inversion done (Startnode %ld) <<<\n",
1566                 get_irn_node_nr(get_irg_start(irg))));
1567 }
1568
1569 void do_loop_peeling(ir_graph *irg)
1570 {
1571         enable_unrolling = 0;
1572         enable_peeling = 1;
1573         enable_inversion = 0;
1574
1575         DB((dbg, LEVEL_2, " >>> peeling (Startnode %ld) <<<\n",
1576                 get_irn_node_nr(get_irg_start(irg))));
1577
1578         loop_optimization(irg);
1579
1580         DB((dbg, LEVEL_2, " >>> peeling done (Startnode %ld) <<<\n",
1581                 get_irn_node_nr(get_irg_start(irg))));
1582
1583 }
1584
1585 ir_graph_pass_t *loop_inversion_pass(const char *name) {
1586         return def_graph_pass(name ? name : "loop_inversion", do_loop_inversion);
1587 }
1588
1589 ir_graph_pass_t *loop_unroll_pass(const char *name) {
1590         return def_graph_pass(name ? name : "loop_unroll", do_loop_unrolling);
1591 }
1592
1593 ir_graph_pass_t *loop_peeling_pass(const char *name) {
1594         return def_graph_pass(name ? name : "loop_peeling", do_loop_peeling);
1595 }
1596
1597 void firm_init_loop_opt(void)
1598 {
1599         FIRM_DBG_REGISTER(dbg, "firm.opt.loop");
1600 }