added missing parentesis
[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   ir_op *op = get_irn_op(pred);
536
537   /* only fragile ops can throw an exception */
538   if (! is_fragile_op(op))
539     return 0;
540
541   /*
542    * fragile ops that are known NOT to throw
543    * an exception if their pin_state is op_pin_state_floats
544    */
545   return get_irn_pinned(pred) != op_pin_state_floats;
546 }
547
548 /**
549  * If a node from the loop is predecessor of the end block, then the end block must get all copies
550  * of this node as predecessors. This is possible with function calls in the unrolling loop.
551  *
552  * @param end_block          The end block.
553  * @param loop_head          The head of the unrolling loop.
554  * @param l_n                Contains all nodes of the loop.
555  * @param loop_endblock_outs The set loop_endblock_outs contains all predecessors
556  *                           of the end block from the unrolling loop.
557  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
558  */
559 static void
560 new_end_block(ir_node *end_block, ir_node *loop_head, set *l_n, set *loop_endblock_outs, int unroll_factor)
561 {
562   copies_t key, *value;
563   int set_el, new_preds, all_new_preds, i, q;
564   int old_preds = get_Block_n_cfgpreds(end_block);   /* All old predecessors of the end block. */
565   ir_node **all_in;
566
567   for (i = 0; i < old_preds; i++) {
568     ir_node *pred = get_Block_cfgpred(end_block, i);
569      key.irn = pred;
570      value = NULL;
571      value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
572
573      /* If a predecessor of the end block is a Proj from the unrolling loop (for function calls) .*/
574      if (get_irn_op(pred) == op_Proj && is_exception_possible(pred) && value != NULL &&
575                !(!copy_loop_head && get_nodes_block(pred) == loop_head))
576        value =  set_insert(loop_endblock_outs, &key, sizeof(key), HASH_PTR(key.irn));
577   }
578
579   /* The set loop_endblock_outs contains all predecessors of the end block from the unrolling loop,
580    * set_el the amount of such nodes.
581    */
582   set_el = set_count (loop_endblock_outs);
583
584   /* If the end block haven't such predecessors, we are finished. */
585   if (!set_el) return;
586
587   new_preds = (unroll_factor - 1) * set_el;          /* All new predecessors of the end block */
588   all_new_preds = old_preds + new_preds;             /* All predecessors of this block. */
589   all_in = alloca(sizeof(*all_in) * all_new_preds);  /* A array with size for all predecessors of this block. */
590
591   for (i = 0; i < old_preds; i++)
592     all_in[i] = get_Block_cfgpred(end_block, i);    /* The old predecessors. */
593
594   value = set_first(loop_endblock_outs);
595
596   for (; value != NULL; value = set_next(loop_endblock_outs)) {
597     key.irn = value->irn;
598     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
599     for (q = 0; q < unroll_factor - 1 ; q++) {
600       all_in[i++] = value->copy[q];                 /* The new predecessors. */
601     }
602
603   }
604
605   /* Replace the old predecessors of the end block wit´h the new ones. */
606   set_irn_in(end_block, all_new_preds, all_in);
607 }
608
609 /** new_after_loop_block
610  *
611  * The after loop block must examine the possible exceptions in the loop.
612  * If a (Proj) node from the loop is predecessor of this block, then the
613  * after loop block must have as well all copies of this node as predecessors.
614  *
615  * @param l_n             Contains all nodes of the loop.
616  * @block block           A block after the loop.
617  * @param loop_in         A node from the loop, that is predecessor of the end block.
618  * @param unroll_factor   An integer 2 <= unroll_factor <= 4.
619  */
620 static void
621 new_after_loop_block (set *l_n, ir_node* block, copies_t *loop_in, int unroll_factor)
622 {
623   copies_t key, *value;
624   int i, p, q, s, old_preds, new_preds, all_new_preds ;
625   ir_node **all_in;
626
627   /* The node from the unrolling loop must be a Proj. */
628   if (loop_in->irn->op != op_Proj) return;
629
630   old_preds = get_Block_n_cfgpreds(block);     /* All old predecessors of this block. */
631   new_preds = old_preds * (unroll_factor - 1); /* All new predecessors of this block. */
632   all_new_preds = old_preds + new_preds;       /* All predecessors of this block. */
633
634   all_in = alloca(sizeof(*all_in) * all_new_preds); /* An array with size for all predecessors of this block. */
635
636   for (i = 0 ; i < old_preds; i++)
637     all_in[i] = get_Block_cfgpred(block, i);      /* The old predecessors. */
638
639   q = old_preds;
640   for (i = 0; i < old_preds; i++){
641     key.irn = all_in[i];
642     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
643     p = 0;
644     for (s = 0; s < (unroll_factor - 1); s++) {
645       all_in[q++] = value->copy[p++];          /* The new predecessors. */
646     }
647   }
648   /* Replace the old predecessors of the end block whit the new one. */
649   set_irn_in(block, all_new_preds, all_in);
650 }
651
652 /** new_after_loop_node
653  *
654  * An after loop node (phi or call) must examine the possible exceptions in the loop.
655  * If a (Proj) node from the loop is predecessor of this node, then the after loop
656  * node must have as well all copies of this node as predecessors.
657  *
658  * @param l_n             Contains all nodes of the loop.
659  * @param loop_outs       Contains nodes after the loop,that have as predecessor a node from the loop.
660  * @block node            A node after the loop.
661  * @param loop_in         A node (Proj) from the loop, that is predecessor of *node.
662  * @param unroll_factor   An integer 2 <= unroll_factor <= 4.
663  */
664 static void
665 new_after_loop_node(set *l_n, set *loop_outs, ir_node *node, copies_t *loop_in, int unroll_factor)
666 {
667   ir_node *pred, *block_pred, *node_block, *new_phi;
668   int phi = 0, old_preds, new_preds, all_new_preds, p, q, i, s;
669   copies_t key, *value = NULL;
670   ir_node **all_in;
671
672   old_preds = get_irn_arity(node);            /* All old predecessors of this node. */
673   new_preds =old_preds * (unroll_factor - 1); /* All new predecessors of this block. */
674   all_new_preds = old_preds + new_preds;      /* All predecessors of this block. */
675
676   all_in  = alloca(sizeof(*all_in) * all_new_preds); /* An array with size for all predecessors of this block. */
677
678   /* Verification Predecessors, successors and operation of node and loop_in.
679    * loop_in must be a Proj node.
680    */
681   if (loop_in->irn->op != op_Proj) return;
682   /* Node must be operation Phi with mode memory or a Call node. */
683   if (get_irn_op(node) == op_Phi  &&
684       get_irn_mode(node) == mode_M){
685     /* If node is a Phi node,then must have a Call node as successor. */
686     for (i = 0; i < get_irn_n_outs(node); i++)
687       if (get_irn_op(get_irn_out(node, i)) == op_Call) {
688               phi = 1;
689         break;
690       }
691
692     if (!phi) return;
693   }
694
695   /* The predecessor of loop_in must not be a loop invariant. */
696   pred = get_Proj_pred(loop_in->irn);
697   key.irn = pred;
698   value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
699   if (! value) return;
700
701   node_block = get_nodes_block(node);
702
703   /* The block of node must also have a (Proj) predecessor from the unrolling loop. */
704   for (i = 0; i < get_Block_n_cfgpreds(node_block); i++) {
705     block_pred = get_Block_cfgpred(node_block, i);
706
707     if (get_irn_op(block_pred) == op_Proj) {
708       if (get_Proj_pred(block_pred) == pred)
709               break;
710     }
711     else
712       block_pred = NULL;
713   }
714
715   if (! block_pred) return;
716
717   key.irn = block_pred;
718   value   = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
719
720   if (! value)
721     return;
722   else
723     new_after_loop_block(l_n, node_block, value, unroll_factor);
724
725   for (i = 0; i < old_preds; ++i)
726     all_in[i] = get_irn_n(node, i);  /* The old predecessors. */
727
728   q = old_preds;
729   for (i = 0; i < old_preds; ++i) {
730     key.irn = all_in[i];
731     value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
732     p = 0;
733     for (s = 0; s < (unroll_factor - 1); ++s) {
734       all_in[q] = value->copy[p];  /* The new predecessors. */
735       p++;
736       q++;
737     }
738   }
739   /* A new phi node with the new predecessors. */
740   new_phi = new_r_Phi(current_ir_graph, get_nodes_block(node), all_new_preds,all_in,
741                        get_irn_mode(node));
742
743   if (phi)
744     exchange(node, new_phi);
745   else{
746     for (i = 0; i < get_irn_arity(node); ++i)
747       if (get_irn_n(node, i) == pred)
748         set_irn_n(node, i, new_phi);
749   }
750
751   /* The set loop_outs contains the visited nodes and their blocks. */
752   key.irn = node;
753   value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
754   key.irn = get_nodes_block(node);
755   value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
756 }
757
758
759 /* Set the outs of the unrolling loop. All loop outs of a node muss now
760  * point to the last copy of it. Just phi nodes in the loop head and proj
761  * nodes save it outs. The all copies of some Projs  have too outs.
762  *
763  * @param l_n                Contains all nodes of the loop.
764  * @param loop_outs          The set contains the visited and changed loop outs.
765  * @param loop_endblock_outs The set loop_endblock_outs contains all predecessors
766  *                           of the end block from the unrolling loop.
767  * @param info               Contains the loop information.
768  * @param unroll_factor      A integer 2 <= unroll_factor <= 4.
769  */
770 static void
771 set_loop_outs(set *l_n, set *loop_outs, set *loop_endblock_outs, induct_var_info *info, int unroll_factor)
772 {
773   copies_t *value, key;
774   int i, p;
775   ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
776   ir_node *end_block = get_irg_end_block(current_ir_graph);
777
778   for (value = set_first(l_n); value != NULL; value = set_next(l_n))
779     if (! is_Phi_in_loop_head(value->irn, loop_head) &&
780         (get_irn_opcode(value->irn) == iro_Proj && value->copy[0] != NULL))
781       for (i = 0; i < get_irn_n_outs(value->irn); ++i) {
782         key.irn = get_irn_out(value->irn, i);
783
784         /* Search for loop outs. */
785         if (set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL)
786           if ((key.irn->op == op_Block && get_Block_dom_depth(key.irn)  >
787                get_Block_dom_depth(loop_head))                          ||
788               (key.irn->op != op_Block && get_Block_dom_depth(get_nodes_block(key.irn)) >
789                get_Block_dom_depth(loop_head))) {
790
791             for (p = 0; p < get_irn_arity(key.irn); p++)
792               if (value->irn == get_irn_n(key.irn, p)) {
793                               if (get_irn_op(value->irn) == op_Proj && is_exception_possible(value->irn)) {
794                     if (set_find(loop_outs, &key, sizeof(key), HASH_PTR(key.irn)) == NULL) {
795                       /* If the loop out is for exceptions in the loop. */
796                       if ((get_irn_op(key.irn) == op_Phi && get_irn_mode(key.irn) == mode_M) ||
797                         get_irn_op(key.irn) == op_Call)
798                         new_after_loop_node(l_n,loop_outs, key.irn, value, unroll_factor);
799                       else
800                         continue;
801                     } else
802                       continue;
803                   } else
804                     set_irn_n(key.irn, p, value->copy[unroll_factor-2]);
805               }
806           }
807       }
808   /* This function searches for loop outs associated with function call in the unrolling loop. */
809   new_end_block (end_block, loop_head, l_n, loop_endblock_outs, unroll_factor);
810 }
811
812 /**
813  * Unroll the loop body with a factor that must be power of two.
814  * Called from a post walker.
815  *
816  * @param n        An IR node.
817  * @param env      Free environment pointer.
818  */
819 static void do_loop_unroll(ir_node *n, void *env)
820 {
821   induct_var_info info;
822   copies_t *value;
823   set *loop_nodes, *loop_outs, *loop_endblock_outs;
824   ir_node *cmp_out, *phi_init, *loop_head;
825   ir_node *backedge_jmp;
826   int l_sons = 0, unroll_factor = 0;
827   int cmp_typ, init, iter_end, iter_increment, diff, iter_number;
828   int backedge_pos;
829
830   copy_loop_head = 0;
831   info.itervar_phi = n;
832
833   /* The IR node must be a induction variable. */
834   if (get_irn_op(n) == op_Phi) {
835     if (is_induction_variable (&info) == NULL)
836       return;
837   }
838   else
839     return;
840
841   /* Brute force limiting of loop body size. */
842   if (get_loop_n_nodes(info.l_itervar_phi) > 2 ) return;
843
844   /* Only unroll loops that compare against a constant for exiting. */
845   if (info.cmp == NULL) return;
846
847   /* We only want to unroll innermost loops. */
848   l_sons = get_loop_n_sons(info.l_itervar_phi);
849   if ( l_sons != 0)
850     return;
851
852   cmp_out  = get_irn_out(info.cmp, 0);
853   phi_init = get_Phi_pred(info.itervar_phi, info.init_pred_pos);
854
855   if (! is_Proj(cmp_out)) return;
856   if (get_irn_op(info.increment) != op_Const   ||
857       get_irn_op(phi_init) != op_Const         ||
858       get_irn_op(info.cmp_const) != op_Const) return;
859
860   cmp_typ        = get_Proj_proj(cmp_out);
861   init           = get_tarval_long(get_Const_tarval(phi_init));
862   iter_end       = get_tarval_long(get_Const_tarval(info.cmp_const));
863   iter_increment = get_tarval_long(get_Const_tarval(info.increment));
864
865   if (iter_end < init){
866     int p = iter_end;
867     iter_end = init;
868     init = p;
869   }
870
871   iter_increment = iter_increment < 0 ? -iter_increment : iter_increment;
872   diff = iter_end - init;
873
874   if (diff == 0 || iter_increment == 0) return;
875   /* Test for the value of unroll factor. */
876   iter_number = diff/iter_increment;
877   if ((cmp_typ == pn_Cmp_Le || cmp_typ == pn_Cmp_Ge) && (iter_end % iter_increment == 0))
878     iter_number ++;
879
880   if ((iter_number & 3) == 0)
881     unroll_factor = 4;
882   else if ((iter_number % 3) == 0)
883     unroll_factor = 3;
884   else if ((iter_number & 1) == 0)
885     unroll_factor = 2;
886   else return;
887
888   printf("\nloop unrolling with factor %d \n", unroll_factor);
889
890   DDMG(get_irn_irg(n));
891
892   /* The unroll factor must be less than 4. */
893   assert(unroll_factor <= MAX_UNROLL);
894
895   loop_head = (is_natural_loop(&info)) ? get_loop_node(info.l_itervar_phi, 0) : NULL;
896
897   assert(loop_head != NULL && is_Block(loop_head));
898
899   /* We assume, the loop head has exactly one backedge.  The position of
900      the backedge is in the following variable: */
901   backedge_pos = (is_backedge(loop_head, 0)) ? 0:1;
902
903   /* A set with the nodes to copy. */
904   loop_nodes = new_set(set_cmp, 8);
905   /* A set with the loop outs for exceptions. */
906   loop_outs =  new_set(set_cmp, 8);
907
908   /* A set containing all predecessors
909      of the end block from the unrolling loop. */
910   loop_endblock_outs = new_set(set_cmp, 8);
911
912   /* Find all nodes of the unrolling loop. */
913   find_loop_nodes(info.itervar_phi, get_loop_node(info.l_itervar_phi, 0), loop_nodes);
914
915   /* Decide if the loop head to be copy.*/
916   copy_loop_head = loop_head_nodes(loop_nodes, &info);
917
918   /* Copy all nodes of the unrolling loop, that muss be copy. */
919   copy_loop_body(loop_nodes, &info, unroll_factor);
920
921   backedge_jmp = get_Block_cfgpred(loop_head, backedge_pos);
922
923   /* Set the backedge of the loop head. */
924   for (value = set_first(loop_nodes); value != NULL; value = set_next(loop_nodes)) {
925     if(value->irn == backedge_jmp){
926
927       set_Block_cfgpred(loop_head, backedge_pos, value->copy[unroll_factor-2]);
928     }
929   }
930   set_loop_outs(loop_nodes, loop_outs, loop_endblock_outs, &info, unroll_factor);
931 }
932
933 /* Performs loop unrolling for the passed graph. */
934 void optimize_loop_unrolling(ir_graph *irg /* unroll factor, max body size */)
935 {
936   ir_graph *rem;
937
938   if ( !get_opt_loop_unrolling()) return;
939
940   rem = current_ir_graph;
941   current_ir_graph = irg;
942
943   /* -- Precompute some information -- */
944
945   /* Call algorithm that computes the backedges */
946   construct_cf_backedges(irg);
947
948   /* Call algorithm that computes the dominator trees. */
949   compute_doms(irg);
950
951   /* Call algorithm that computes the out edges */
952   compute_outs(irg);
953
954   collect_phiprojs(irg);
955
956   /* -- Search expressions that can be optimized -- */
957   irg_walk_graph(irg, NULL, do_loop_unroll, NULL);
958
959   current_ir_graph = rem;
960 }