bugfix: is_fragile_op expected an IR-node
[libfirm] / ir / opt / loop_unrolling.c
1 /**
2  *
3  * @file loop_unrolling.c
4  *
5  * Project:     libFIRM
6  * File name:   ir/opt/loop_unrolling.c
7  * Purpose:     Make loop unrolling.
8  * Author:      Beyhan Veliev
9  * Modified by:
10  * Created:     16.11.2004
11  * CVS-ID:      $Id$
12  * Copyright:   (c) 2004 Universität Karlsruhe
13  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
14  */
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #ifdef HAVE_STRING_H
20 #include <string.h>
21 #endif
22 #ifdef HAVE_MALLOC_H
23 #include <malloc.h>
24 #endif
25 #ifdef HAVE_ALLOCA_H
26 #include <alloca.h>
27 #endif
28
29 # include "loop_unrolling.h"
30
31 # include "irgwalk.h"
32 # include "ircons.h"
33 # include "irgmod.h"
34 # include "irloop_t.h"
35 # include "irgopt_t.h"
36 # include "irnode_t.h"
37 # include "irouts.h"
38 # include "hashptr.h"
39 # include "pset.h"
40 # include "strength_red.h"
41
42 /* We will unroll maximal 4-times.  */
43 #define MAX_UNROLL 4
44
45 /* We will know if the head of the loop to be copy.
46  * Default "0"  don't copy.*/
47 static int copy_loop_head;
48
49 typedef struct {
50   ir_node *irn ;                /* Node of the loop to be unrolling*/
51   ir_node *copy[MAX_UNROLL] ;   /* The copy of the node */
52 } copies_t;
53
54 /**
55  * Compare two elements of the copies_t set
56  */
57 static int set_cmp(const void *elt, const void *key, size_t size)
58 {
59   const copies_t *c1 = elt;
60   const copies_t *c2 = key;
61
62   return c1->irn != c2->irn;
63 }
64
65 static INLINE int * new_backedge_arr(struct obstack *obst, int size)
66 {
67   int *res = NEW_ARR_D (int, obst, size);
68   memset(res, 0, sizeof(int) * size);
69   return res;
70 }
71
72 static INLINE void new_backedge_info(ir_node *n) {
73   switch(get_irn_opcode(n)) {
74   case iro_Block:
75     n->attr.block.cg_backedge = NULL;
76     n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
77     break;
78   case iro_Phi:
79     n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
80     break;
81   case iro_Filter:
82     n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
83     break;
84   default: ;
85   }
86 }
87
88 /**
89  * Remember the new node in the old node by using a field all nodes have.
90  */
91 static INLINE void
92 set_new_node (ir_node *old, ir_node *new)
93 {
94   old->link = new;
95 }
96
97 /**
98  * Copies the node to the new obstack. The Ins of the new node point to
99  * the predecessors on the old obstack.  For block/phi nodes not all
100  * predecessors might be copied.  n->link points to the new node.
101  * For Phi and Block nodes the function allocates in-arrays with an arity
102  * only for useful predecessors.  The arity is determined by counting
103  * the non-bad predecessors of the block.
104  *
105  * @param n    The node to be copied
106  * @param env  if non-NULL, the node number attribute will be copied to the new node
107  */
108 static void
109 copy_node (ir_node *n, void *env)
110 {
111   ir_node *nn;
112   int new_arity;
113   ir_op *op = get_irn_op(n);
114   int copy_node_nr = false;
115
116   /* The end node looses it's flexible in array.  This doesn't matter,
117      as dead node elimination builds End by hand, inlineing doesn't use
118      the End node. */
119   /* assert(op == op_End ||  ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
120
121   if (op == op_Bad)
122     /* node copied already */
123     return;
124
125   new_arity = get_irn_arity(n);
126
127   nn = new_ir_node(get_irn_dbg_info(n),
128            current_ir_graph,
129            NULL,            /* no block yet, will be set later */
130            op,
131            get_irn_mode(n),
132            new_arity,
133            get_irn_in(n));
134
135
136   /* Copy the attributes.  These might point to additional data.  If this
137      was allocated on the old obstack the pointers now are dangling.  This
138      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
139   copy_node_attr(n, nn);
140   new_backedge_info(nn);
141   set_new_node(n, nn);
142
143 #if DEBUG_libfirm
144   if (copy_node_nr) {
145     /* for easier debugging, we want to copy the node numbers too */
146     nn->node_nr = n->node_nr;
147   }
148 #endif
149
150 }
151 /*Check if phi in the loop head is.
152  *
153  * @param phi               Must be a phi node from the loop.
154  * @param loop_head         The loop head .
155  */
156 static int is_Phi_in_loop_head(ir_node *phi, ir_node *loop_head) {
157   assert(is_Block(loop_head));
158   return is_Phi(phi) && (get_nodes_block(phi) == loop_head);
159 }
160
161 /**
162  * Copies predecessors of node to copies of node.
163  * If the predecessor is a loop invariant, then the copy get it
164  * as predecessor, else the copy of the predecessor.
165  *
166  * @param l_n                A set, where the node of the loop are saved.
167  * @param value              A element of the set.
168  * @param info               Contains information about the induction variable.
169  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
170  * @param env                Free environment pointer.
171  */
172 static void
173 set_preds (set *l_n, copies_t *value, induct_var_info *info, int unroll_factor, void *env)
174 {
175   int i, p, irn_arity;
176   copies_t key, *value_pred;
177   // The head of the unrolling loop.
178   ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
179
180   irn_arity = get_irn_arity(value->irn);
181
182   for (i = 0; i < irn_arity; i++) {
183     ir_node *pred = get_irn_n(value->irn, i);
184
185     key.irn = pred;
186     value_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(pred));
187
188     if (value->irn != loop_head && !is_Phi_in_loop_head(value->irn, loop_head)) {
189       if (value_pred == NULL) {
190               /* Is loop invariant. */
191               for (p = 0; p < unroll_factor - 1; p++)
192                 set_irn_n(value->copy[p], i, pred);
193               /* pred is a loop invariant. The copies of the successors get it as predecessor. */
194       }
195       else {
196               for (p = 0; p < unroll_factor - 1; p++)
197                 set_irn_n(value->copy[p], i, value_pred->copy[p]);
198           /* value_pred->irn is a node from the unrolling loop.
199            * The copies of the successors get the
200                  * copies of value_pred as predecessor.
201            */
202       }
203     }
204   }
205 }
206
207 /* Set the backedge of phi in the loop head.The backedge of phis in the loop head
208  * must now point to the value defined
209  * in the last copy of the loop body.
210  *
211  * @param l_n                A set, where the node of the loop are saved.
212  * @param value              A phi in the loop head.
213  * @param info               Contains information about the induction variable.
214  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
215  */
216 static void
217 set_phi_backedge(set *l_n, copies_t *value, induct_var_info *info, int unroll_factor)
218 {
219   copies_t key, *value_pred;
220
221   /* info->op_pred_pos is the backedge position. */
222   key.irn = get_irn_n(value->irn, info->op_pred_pos);
223   value_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
224
225   /* value->copy[unroll_factor - 2] is the last copy. */
226   set_Phi_pred(value->irn, info->op_pred_pos, value_pred->copy[unroll_factor - 2]);
227 }
228
229 /**
230  * Test for a loop head.
231  *
232  * Returns true if the node has predecessors in the loop _and_ out of
233  * the loop.  Then it is a loop head: The loop can be entered through
234  * this node.
235  *
236  * @param n      The node to be tested. Must be a block.
237  * @param info   Contains the loop information.
238  */
239 static int
240 is_loop_head(ir_node *n, induct_var_info *info)
241 {
242   int i, arity;
243   int some_outof_loop = 0, some_in_loop = 0;
244
245   assert(get_irn_op(n) == op_Block);
246   arity = get_Block_n_cfgpreds(n);
247
248   for (i = 0; i < arity; i++) {
249     ir_node *pred = get_Block_cfgpred(n, i);
250     assert(pred);
251     if (is_loop_invariant(pred, get_loop_node(info->l_itervar_phi, 0))) {
252       some_outof_loop = 1;
253     } else
254       some_in_loop = 1;
255   }
256
257   return some_outof_loop && some_in_loop;
258 }
259
260
261 /**
262  * Test whether the passed loop is a natural loop.
263  *
264  * Returns true if the loop has only one loop header and only a single
265  * back edge.
266  *
267  * @param info  Contains the loop information.
268  */
269 static int
270 is_natural_loop(induct_var_info *info)
271 {
272   ir_node *l_node;
273   int l_n_node = 0, i;
274
275   l_n_node = get_loop_n_nodes (info->l_itervar_phi);
276
277   for (i = 1; i < (l_n_node); i ++) {
278     l_node = get_loop_node (info->l_itervar_phi, i);
279     if (is_loop_head(l_node, info)) return 0;
280
281     if (has_backedges(l_node) && i != l_n_node-1) return 0;
282   }
283
284   return 1;
285 }
286
287 /**
288  * Search for all nodes of a loop.
289  *
290  * @param node       The induction variable of the loop.
291  * @param loop_head  The head of the loop.
292  * @param l_n        A set, where the node of the loop are saved.
293  */
294 static void
295 find_loop_nodes(ir_node *node, ir_node *loop_head, set *l_n)
296 {
297   int i;
298   copies_t key, *value;
299
300   /* Add this node to the list. */
301   key.irn  = node;
302
303   /* Initialize all copies of the added node with NULL.*/
304   for (i = 0; i < 4; ++i)
305     key.copy[i] = NULL;
306   value = set_insert(l_n, &key, sizeof(key), HASH_PTR(key.irn));
307
308   /* Add all outs of this node to the list, if they are within the loop. */
309   for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
310     ir_node *pred = get_irn_out(node, i);
311
312     key.irn = pred;
313     if (!is_loop_invariant(pred, loop_head)         &&
314             set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL ) {
315       find_loop_nodes(pred, loop_head, l_n);
316     }
317   }
318
319   /* Add all ins if they are within the loop. */
320   for (i = get_irn_arity(node) - 1; i >=0; --i) {
321     ir_node *pred = get_irn_n(node, i);
322
323     key.irn = pred;
324     if (!is_loop_invariant(pred, loop_head)         &&
325               set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL ) {
326       find_loop_nodes(pred, loop_head, l_n);
327     }
328   }
329 }
330
331 /**
332  * Make a new loop head if copy_head = 1.
333  *
334  * @param l_n              A set, where the node of the loop are saved.
335  * @param info             Contains the loop information.
336  * @param value            A element of the set.
337  * @param unroll_factor    A integer 2 <= unroll_factor <= 4.
338  * @param copy_head        if non-zero, the loop head will be copied
339  *
340  */
341 static void
342 new_loop_head(set *l_n, induct_var_info *info, copies_t *value, int unroll_factor, int copy_head)
343 {
344   int i;
345   copies_t block, *value_backedge_jmp, *backedge_jmp_block;
346   /* The  predecessor of the loop head in the  backedge position */
347   ir_node *backedge_jmp = get_Block_cfgpred(value->irn, info->op_pred_pos);
348
349   block.irn          = backedge_jmp;
350   value_backedge_jmp = set_find(l_n, &block, sizeof(block), HASH_PTR(block.irn));
351
352   if (copy_head) {
353     /* The first copy of the loop head must point to the loop head.*/
354     value->copy[0] = new_Block(1, &backedge_jmp);
355
356     for (i = 1; i < unroll_factor - 1; ++i) {
357       /* all other copies must point to the copy before it in the array. */
358       value->copy[i] = new_Block(1, &value_backedge_jmp->copy[i-1]);
359     }
360   }
361   else {
362     /* If the loop head must not be copy. block.irn is the successor of the loop head.*/
363     block.irn          = get_nodes_block(backedge_jmp);
364     backedge_jmp_block = set_find(l_n, &block, sizeof(block), HASH_PTR(block.irn));
365
366     /* The first copy of block.irn point to it.
367       The another copies muss point to the copy before it in the array.*/
368     set_irn_n(backedge_jmp_block->copy[0], 0, value_backedge_jmp->irn) ;
369
370     for (i = 1; i < unroll_factor - 1; ++i)
371       set_irn_n(backedge_jmp_block->copy[i], 0, value_backedge_jmp->copy[i - 1]);
372   }
373 }
374
375 /* Set all copies of the induction variable.
376  *
377  * @param phi             A phi node in the loop head block.
378  * @param phi_pred        The predecessor of the phi along the backedge.
379  * @param unroll_factor   A integer 2 <= unroll_factor <= 4.
380  */
381 static void
382 set_Phi_copies(copies_t *phi, copies_t *phi_pred, int unroll_factor)
383 {
384   int p;
385
386   /* The first copy of Phi node get the node along the backedge as predecessor. The next copies
387      the copies of this node.*/
388   phi->copy[0] = phi_pred->irn;
389   for (p = 1; p < unroll_factor - 1; ++p) {
390     /* If two phi nodes are in cycle.  */
391     if (phi_pred->copy[p - 1] == NULL && get_irn_op(phi_pred->irn) == op_Phi) {
392       if (p & 1)
393               phi->copy[p] =  phi->irn;
394       else
395               phi->copy[p] =  phi_pred->irn;
396     } else
397       phi->copy[p] =  phi_pred->copy[p - 1];
398   }
399 }
400
401 /**
402  * Decide if the loop head must be copied. A head with important nodes
403  * must be copied.
404  *
405  * @param l_n         A set, where the node of the loop are saved.
406  * @param info        Contains information about the induction variable.
407  *
408  * @return non-zero if the loop head must be copied
409  */
410 static int
411 loop_head_nodes(set *l_n, induct_var_info *info)
412 {
413   int must_copy = 0;
414   copies_t *value;
415   ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
416
417   for (value = set_first(l_n); value != NULL; value = set_next(l_n))
418     if (is_no_Block(value->irn) && get_nodes_block(value->irn) == loop_head)
419       /* If the loop head contains just this nodes, than must not be copy. */
420       switch (get_irn_opcode(value->irn)) {
421       case iro_Cond:
422               break;
423       case iro_Phi:
424               break;
425       case iro_Proj:
426               break;
427       case iro_Const:
428               break;
429       case iro_Cmp:
430               break;
431       default:
432               must_copy = 1;
433       }
434     return must_copy;
435 }
436
437 /** Copy all loop nodes.
438  *
439  * @param l_n             Contains all nodes of the loop.
440  * @param info            Contains the loop information.
441  * @param unroll_factor   A integer 2 <= unroll_factor <= 4.
442  */
443 static void
444 copy_loop_body(set *l_n, induct_var_info *info, int unroll_factor)
445 {
446   int i;
447   copies_t *value, *info_op, *phi, *loop_h, key, *value_block;
448
449   ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
450
451   for (value = set_first(l_n); value != NULL; value = set_next(l_n)) {
452     if(value->irn == loop_head)
453       loop_h = value;
454     else if (is_Phi_in_loop_head(value->irn, loop_head))
455       phi = value;
456     else if (copy_loop_head){
457       /* If the loop head must be copied. */
458       for (i = 0; i < unroll_factor - 1; i++){
459               copy_node(value->irn, NULL);
460               value->copy[i] = get_irn_link(value->irn);
461       }
462     } else {
463       /* If the loop head and its nodes mustn't be copied. */
464       if((value->irn->op == op_Block             &&
465                 value->irn != loop_head)               ||
466                (value->irn->op != op_Block             &&
467                 get_nodes_block(value->irn) != loop_head)) {
468               for (i = 0; i<unroll_factor -1; i++){
469                 copy_node(value->irn, NULL);
470                 value->copy[i] = get_irn_link(value->irn);
471               }
472       }
473     }
474   }
475   /* Treat the loop head block */
476   new_loop_head(l_n, info, loop_h, unroll_factor, copy_loop_head);
477
478   /* Similarly treat the Phis in the loop head block. info->op is the node
479      along the backedges. */
480   key.irn = info->op;
481   info_op = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
482   assert(info_op->irn == get_Phi_pred(info->itervar_phi, info->op_pred_pos));
483   for (i = 0; i < get_irn_n_outs(loop_head); ++i) {
484     ir_node *phi = get_irn_out(loop_head, i);
485
486     if (is_Phi(phi)) {
487       copies_t *phi_pred, *phi_op;
488
489       key.irn  = get_Phi_pred(phi, info->op_pred_pos); // info->op;
490       phi_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
491       key.irn  = phi;
492       phi_op   = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
493       set_Phi_copies(phi_op, phi_pred, unroll_factor);
494     }
495   }
496
497   for (value = set_first(l_n); value != NULL; value = set_next(l_n)) {
498     /* Set the predecessors of the copies. */
499     if (copy_loop_head)
500       set_preds(l_n, value, info, unroll_factor, NULL);
501     else if ((value->irn->op != op_Block) && get_nodes_block(value->irn) != loop_head)
502       set_preds(l_n, value, info, unroll_factor, NULL);
503
504     if (is_Phi_in_loop_head(value->irn, loop_head))
505       /* Set the backedge of phis in the loop head. */
506       set_phi_backedge(l_n, value, info, unroll_factor);
507
508     if ((value->irn->op != op_Block) && !is_Phi_in_loop_head(value->irn, loop_head)) {
509       ir_node *nodes_block = get_nodes_block(value->irn);
510
511       if (!copy_loop_head && nodes_block == loop_head)
512         continue;
513
514       key.irn = nodes_block;
515       value_block = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
516       /* Set the copy of the node in the accordant copy of its block. */
517       for(i = 0; i < unroll_factor - 1; i++){
518         set_nodes_block(value->copy[i], value_block->copy[i]);
519         //add_End_keepalive(get_irg_end(current_ir_graph), value->copy[p]);
520       }
521     }
522   }
523 }
524 /**
525  * Returns non-zero if a Proj node from the loop has a predecessor that
526  * can throw an exception.
527  *
528  * @param node  A Proj node from the loop.
529  *
530  * @return non-zero if the predecessor of the Proj node can throw an exception
531  */
532 static int is_exception_possible(ir_node *node)
533 {
534   ir_node *pred = get_Proj_pred(node);
535
536   /* only fragile ops can throw an exception */
537   if (! is_fragile_op(pred))
538     return 0;
539
540   /*
541    * fragile ops that are known NOT to throw
542    * an exception if their pin_state is op_pin_state_floats
543    */
544   return get_irn_pinned(pred) != op_pin_state_floats;
545 }
546
547 /**
548  * If a node from the loop is predecessor of the end block, then the end block must get all copies
549  * of this node as predecessors. This is possible with function calls in the unrolling loop.
550  *
551  * @param end_block          The end block.
552  * @param loop_head          The head of the unrolling loop.
553  * @param l_n                Contains all nodes of the loop.
554  * @param loop_endblock_outs The set loop_endblock_outs contains all predecessors
555  *                           of the end block from the unrolling loop.
556  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
557  */
558 static void
559 new_end_block(ir_node *end_block, ir_node *loop_head, set *l_n, set *loop_endblock_outs, int unroll_factor)
560 {
561   copies_t key, *value;
562   int set_el, new_preds, all_new_preds, i, q;
563   int old_preds = get_Block_n_cfgpreds(end_block);   /* All old predecessors of the end block. */
564   ir_node **all_in;
565
566   for (i = 0; i < old_preds; i++) {
567     ir_node *pred = get_Block_cfgpred(end_block, i);
568      key.irn = pred;
569      value = NULL;
570      value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
571
572      /* If a predecessor of the end block is a Proj from the unrolling loop (for function calls) .*/
573      if (get_irn_op(pred) == op_Proj && is_exception_possible(pred) && value != NULL &&
574                !(!copy_loop_head && get_nodes_block(pred) == loop_head))
575        value =  set_insert(loop_endblock_outs, &key, sizeof(key), HASH_PTR(key.irn));
576   }
577
578   /* The set loop_endblock_outs contains all predecessors of the end block from the unrolling loop,
579    * set_el the amount of such nodes.
580    */
581   set_el = set_count (loop_endblock_outs);
582
583   /* If the end block haven't such predecessors, we are finished. */
584   if (!set_el) return;
585
586   new_preds = (unroll_factor - 1) * set_el;          /* All new predecessors of the end block */
587   all_new_preds = old_preds + new_preds;             /* All predecessors of this block. */
588   all_in = alloca(sizeof(*all_in) * all_new_preds);  /* A array with size for all predecessors of this block. */
589
590   for (i = 0; i < old_preds; i++)
591     all_in[i] = get_Block_cfgpred(end_block, i);    /* The old predecessors. */
592
593   value = set_first(loop_endblock_outs);
594
595   for (; value != NULL; value = set_next(loop_endblock_outs)) {
596     key.irn = value->irn;
597     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
598     for (q = 0; q < unroll_factor - 1 ; q++) {
599       all_in[i++] = value->copy[q];                 /* The new predecessors. */
600     }
601
602   }
603
604   /* Replace the old predecessors of the end block wit´h the new ones. */
605   set_irn_in(end_block, all_new_preds, all_in);
606 }
607
608 /** new_after_loop_block
609  *
610  * The after loop block must examine the possible exceptions in the loop.
611  * If a (Proj) node from the loop is predecessor of this block, then the
612  * after loop block must have as well all copies of this node as predecessors.
613  *
614  * @param l_n             Contains all nodes of the loop.
615  * @block block           A block after the loop.
616  * @param loop_in         A node from the loop, that is predecessor of the end block.
617  * @param unroll_factor   An integer 2 <= unroll_factor <= 4.
618  */
619 static void
620 new_after_loop_block (set *l_n, ir_node* block, copies_t *loop_in, int unroll_factor)
621 {
622   copies_t key, *value;
623   int i, p, q, s, old_preds, new_preds, all_new_preds ;
624   ir_node **all_in;
625
626   /* The node from the unrolling loop must be a Proj. */
627   if (loop_in->irn->op != op_Proj) return;
628
629   old_preds = get_Block_n_cfgpreds(block);     /* All old predecessors of this block. */
630   new_preds = old_preds * (unroll_factor - 1); /* All new predecessors of this block. */
631   all_new_preds = old_preds + new_preds;       /* All predecessors of this block. */
632
633   all_in = alloca(sizeof(*all_in) * all_new_preds); /* An array with size for all predecessors of this block. */
634
635   for (i = 0 ; i < old_preds; i++)
636     all_in[i] = get_Block_cfgpred(block, i);      /* The old predecessors. */
637
638   q = old_preds;
639   for (i = 0; i < old_preds; i++){
640     key.irn = all_in[i];
641     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
642     p = 0;
643     for (s = 0; s < (unroll_factor - 1); s++) {
644       all_in[q++] = value->copy[p++];          /* The new predecessors. */
645     }
646   }
647   /* Replace the old predecessors of the end block whit the new one. */
648   set_irn_in(block, all_new_preds, all_in);
649 }
650
651 /** new_after_loop_node
652  *
653  * An after loop node (phi or call) must examine the possible exceptions in the loop.
654  * If a (Proj) node from the loop is predecessor of this node, then the after loop
655  * node must have as well all copies of this node as predecessors.
656  *
657  * @param l_n             Contains all nodes of the loop.
658  * @param loop_outs       Contains nodes after the loop,that have as predecessor a node from the loop.
659  * @block node            A node after the loop.
660  * @param loop_in         A node (Proj) from the loop, that is predecessor of *node.
661  * @param unroll_factor   An integer 2 <= unroll_factor <= 4.
662  */
663 static void
664 new_after_loop_node(set *l_n, set *loop_outs, ir_node *node, copies_t *loop_in, int unroll_factor)
665 {
666   ir_node *pred, *block_pred, *node_block, *new_phi;
667   int phi = 0, old_preds, new_preds, all_new_preds, p, q, i, s;
668   copies_t key, *value = NULL;
669   ir_node **all_in;
670
671   old_preds = get_irn_arity(node);            /* All old predecessors of this node. */
672   new_preds =old_preds * (unroll_factor - 1); /* All new predecessors of this block. */
673   all_new_preds = old_preds + new_preds;      /* All predecessors of this block. */
674
675   all_in  = alloca(sizeof(*all_in) * all_new_preds); /* An array with size for all predecessors of this block. */
676
677   /* Verification Predecessors, successors and operation of node and loop_in.
678    * loop_in must be a Proj node.
679    */
680   if (loop_in->irn->op != op_Proj) return;
681   /* Node must be operation Phi with mode memory or a Call node. */
682   if (get_irn_op(node) == op_Phi  &&
683       get_irn_mode(node) == mode_M){
684     /* If node is a Phi node,then must have a Call node as successor. */
685     for (i = 0; i < get_irn_n_outs(node); i++)
686       if (get_irn_op(get_irn_out(node, i)) == op_Call) {
687               phi = 1;
688         break;
689       }
690
691     if (!phi) return;
692   }
693
694   /* The predecessor of loop_in must not be a loop invariant. */
695   pred = get_Proj_pred(loop_in->irn);
696   key.irn = pred;
697   value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
698   if (! value) return;
699
700   node_block = get_nodes_block(node);
701
702   /* The block of node must also have a (Proj) predecessor from the unrolling loop. */
703   for (i = 0; i < get_Block_n_cfgpreds(node_block); i++) {
704     block_pred = get_Block_cfgpred(node_block, i);
705
706     if (get_irn_op(block_pred) == op_Proj) {
707       if (get_Proj_pred(block_pred) == pred)
708               break;
709     }
710     else
711       block_pred = NULL;
712   }
713
714   if (! block_pred) return;
715
716   key.irn = block_pred;
717   value   = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
718
719   if (! value)
720     return;
721   else
722     new_after_loop_block(l_n, node_block, value, unroll_factor);
723
724   for (i = 0; i < old_preds; ++i)
725     all_in[i] = get_irn_n(node, i);  /* The old predecessors. */
726
727   q = old_preds;
728   for (i = 0; i < old_preds; ++i) {
729     key.irn = all_in[i];
730     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
731     p = 0;
732     for (s = 0; s < (unroll_factor - 1); ++s) {
733       all_in[q] = value->copy[p];  /* The new predecessors. */
734       p++;
735       q++;
736     }
737   }
738   /* A new phi node with the new predecessors. */
739   new_phi = new_r_Phi(current_ir_graph, get_nodes_block(node), all_new_preds,all_in,
740                        get_irn_mode(node));
741
742   if (phi)
743     exchange(node, new_phi);
744   else{
745     for (i = 0; i < get_irn_arity(node); ++i)
746       if (get_irn_n(node, i) == pred)
747         set_irn_n(node, i, new_phi);
748   }
749
750   /* The set loop_outs contains the visited nodes and their blocks. */
751   key.irn = node;
752   value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
753   key.irn = get_nodes_block(node);
754   value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
755 }
756
757
758 /* Set the outs of the unrolling loop. All loop outs of a node muss now
759  * point to the last copy of it. Just phi nodes in the loop head and proj
760  * nodes save it outs. The all copies of some Projs  have too outs.
761  *
762  * @param l_n                Contains all nodes of the loop.
763  * @param loop_outs          The set contains the visited and changed loop outs.
764  * @param loop_endblock_outs The set loop_endblock_outs contains all predecessors
765  *                           of the end block from the unrolling loop.
766  * @param info               Contains the loop information.
767  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
768  */
769 static void
770 set_loop_outs(set *l_n, set *loop_outs, set *loop_endblock_outs, induct_var_info *info, int unroll_factor)
771 {
772   copies_t *value, key;
773   int i, p;
774   ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
775   ir_node *end_block = get_irg_end_block(current_ir_graph);
776
777   for (value = set_first(l_n); value != NULL; value = set_next(l_n))
778     if (! is_Phi_in_loop_head(value->irn, loop_head) &&
779         (get_irn_opcode(value->irn) == iro_Proj && value->copy[0] != NULL))
780       for (i = 0; i < get_irn_n_outs(value->irn); ++i) {
781         key.irn = get_irn_out(value->irn, i);
782
783         /* Search for loop outs. */
784         if (set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL)
785           if ((key.irn->op == op_Block && get_Block_dom_depth(key.irn)  >
786                get_Block_dom_depth(loop_head))                          ||
787               (key.irn->op != op_Block && get_Block_dom_depth(get_nodes_block(key.irn)) >
788                get_Block_dom_depth(loop_head))) {
789
790             for (p = 0; p < get_irn_arity(key.irn); p++)
791               if (value->irn == get_irn_n(key.irn, p)) {
792                               if (get_irn_op(value->irn) == op_Proj && is_exception_possible(value->irn)) {
793                     if (set_find(loop_outs, &key, sizeof(key), HASH_PTR(key.irn)) == NULL) {
794                       /* If the loop out is for exceptions in the loop. */
795                       if ((get_irn_op(key.irn) == op_Phi && get_irn_mode(key.irn) == mode_M) ||
796                         get_irn_op(key.irn) == op_Call)
797                         new_after_loop_node(l_n,loop_outs, key.irn, value, unroll_factor);
798                       else
799                         continue;
800                     } else
801                       continue;
802                   } else
803                     set_irn_n(key.irn, p, value->copy[unroll_factor-2]);
804               }
805           }
806       }
807   /* This function searches for loop outs associated with function call in the unrolling loop. */
808   new_end_block (end_block, loop_head, l_n, loop_endblock_outs, unroll_factor);
809 }
810
811 /**
812  * Unroll the loop body with a factor that must be power of two.
813  * Called from a post walker.
814  *
815  * @param n        An IR node.
816  * @param env      Free environment pointer.
817  */
818 static void do_loop_unroll(ir_node *n, void *env)
819 {
820   induct_var_info info;
821   copies_t *value;
822   set *loop_nodes, *loop_outs, *loop_endblock_outs;
823   ir_node *cmp_out, *phi_init, *loop_head;
824   ir_node *backedge_jmp;
825   int l_sons = 0, unroll_factor = 0;
826   int cmp_typ, init, iter_end, iter_increment, diff, iter_number;
827   int backedge_pos;
828
829   copy_loop_head = 0;
830   info.itervar_phi = n;
831
832   /* The IR node must be a induction variable. */
833   if (get_irn_op(n) == op_Phi) {
834     if (is_induction_variable (&info) == NULL)
835       return;
836   }
837   else
838     return;
839
840   /* Brute force limiting of loop body size. */
841   if (get_loop_n_nodes(info.l_itervar_phi) > 2 ) return;
842
843   /* Only unroll loops that compare against a constant for exiting. */
844   if (info.cmp == NULL) return;
845
846   /* We only want to unroll innermost loops. */
847   l_sons = get_loop_n_sons(info.l_itervar_phi);
848   if ( l_sons != 0)
849     return;
850
851   cmp_out  = get_irn_out(info.cmp, 0);
852   phi_init = get_Phi_pred(info.itervar_phi, info.init_pred_pos);
853
854   if (! is_Proj(cmp_out)) return;
855   if (get_irn_op(info.increment) != op_Const   ||
856       get_irn_op(phi_init) != op_Const         ||
857       get_irn_op(info.cmp_const) != op_Const) return;
858
859   cmp_typ        = get_Proj_proj(cmp_out);
860   init           = get_tarval_long(get_Const_tarval(phi_init));
861   iter_end       = get_tarval_long(get_Const_tarval(info.cmp_const));
862   iter_increment = get_tarval_long(get_Const_tarval(info.increment));
863
864   if (iter_end < init){
865     int p = iter_end;
866     iter_end = init;
867     init = p;
868   }
869
870   iter_increment = iter_increment < 0 ? -iter_increment : iter_increment;
871   diff = iter_end - init;
872
873   if (diff == 0 || iter_increment == 0) return;
874   /* Test for the value of unroll factor. */
875   iter_number = diff/iter_increment;
876   if ((cmp_typ == pn_Cmp_Le || cmp_typ == pn_Cmp_Ge) && (iter_end % iter_increment == 0))
877     iter_number ++;
878
879   if ((iter_number & 3) == 0)
880     unroll_factor = 4;
881   else if ((iter_number % 3) == 0)
882     unroll_factor = 3;
883   else if ((iter_number & 1) == 0)
884     unroll_factor = 2;
885   else return;
886
887   printf("\nloop unrolling with factor %d \n", unroll_factor);
888
889   DDMG(get_irn_irg(n));
890
891   /* The unroll factor must be less than 4. */
892   assert(unroll_factor <= MAX_UNROLL);
893
894   loop_head = (is_natural_loop(&info)) ? get_loop_node(info.l_itervar_phi, 0) : NULL;
895
896   assert(loop_head != NULL && is_Block(loop_head));
897
898   /* We assume, the loop head has exactly one backedge.  The position of
899      the backedge is in the following variable: */
900   backedge_pos = (is_backedge(loop_head, 0)) ? 0:1;
901
902   /* A set with the nodes to copy. */
903   loop_nodes = new_set(set_cmp, 8);
904   /* A set with the loop outs for exceptions. */
905   loop_outs =  new_set(set_cmp, 8);
906
907   /* A set containing all predecessors
908      of the end block from the unrolling loop. */
909   loop_endblock_outs = new_set(set_cmp, 8);
910
911   /* Find all nodes of the unrolling loop. */
912   find_loop_nodes(info.itervar_phi, get_loop_node(info.l_itervar_phi, 0), loop_nodes);
913
914   /* Decide if the loop head to be copy.*/
915   copy_loop_head = loop_head_nodes(loop_nodes, &info);
916
917   /* Copy all nodes of the unrolling loop, that muss be copy. */
918   copy_loop_body(loop_nodes, &info, unroll_factor);
919
920   backedge_jmp = get_Block_cfgpred(loop_head, backedge_pos);
921
922   /* Set the backedge of the loop head. */
923   for (value = set_first(loop_nodes); value != NULL; value = set_next(loop_nodes)) {
924     if(value->irn == backedge_jmp){
925
926       set_Block_cfgpred(loop_head, backedge_pos, value->copy[unroll_factor-2]);
927     }
928   }
929   set_loop_outs(loop_nodes, loop_outs, loop_endblock_outs, &info, unroll_factor);
930 }
931
932 /* Performs loop unrolling for the passed graph. */
933 void optimize_loop_unrolling(ir_graph *irg /* unroll factor, max body size */)
934 {
935   ir_graph *rem;
936
937   if ( !get_opt_loop_unrolling()) return;
938
939   rem = current_ir_graph;
940   current_ir_graph = irg;
941
942   /* -- Precompute some information -- */
943
944   /* Call algorithm that computes the backedges */
945   construct_cf_backedges(irg);
946
947   /* Call algorithm that computes the dominator trees. */
948   compute_doms(irg);
949
950   /* Call algorithm that computes the out edges */
951   compute_outs(irg);
952
953   collect_phiprojs(irg);
954
955   /* -- Search expressions that can be optimized -- */
956   irg_walk_graph(irg, NULL, do_loop_unroll, NULL);
957
958   current_ir_graph = rem;
959 }