3 * @file loop_unrolling.c
6 * File name: ir/opt/loop_unrolling.c
7 * Purpose: Make loop unrolling.
8 * Author: Beyhan Veliev
12 * Copyright: (c) 2004 Universität Karlsruhe
13 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
18 # include "loop_unrolling.h"
23 # include "irloop_t.h"
24 # include "irgopt_t.h"
25 # include "irnode_t.h"
29 # include "strength_red.h"
31 /* We will unroll maximal 4-times. */
34 /*We will know if the head of the loop to be copy.
35 * Default "0" don't copy.*/
36 static int copy_loop_head;
39 ir_node *irn ; /* Node of the loop to be unrolling*/
40 ir_node *copy[MAX_UNROLL] ; /* The copy of the node */
44 * Compare two elements of the copies_t set
46 static int set_cmp(const void *elt, const void *key, size_t size)
48 const copies_t *c1 = elt;
49 const copies_t *c2 = key;
51 return c1->irn != c2->irn;
54 static INLINE int * new_backedge_arr(struct obstack *obst, int size)
56 int *res = NEW_ARR_D (int, obst, size);
57 memset(res, 0, sizeof(int) * size);
61 static INLINE void new_backedge_info(ir_node *n) {
62 switch(get_irn_opcode(n)) {
64 n->attr.block.cg_backedge = NULL;
65 n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
68 n->attr.phi_backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
71 n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
78 * Remember the new node in the old node by using a field all nodes have.
82 set_new_node (ir_node *old, ir_node *new)
88 * Copies the node to the new obstack. The Ins of the new node point to
89 * the predecessors on the old obstack. For block/phi nodes not all
90 * predecessors might be copied. n->link points to the new node.
91 * For Phi and Block nodes the function allocates in-arrays with an arity
92 * only for useful predecessors. The arity is determined by counting
93 * the non-bad predecessors of the block.
95 * @param n The node to be copied
96 * @param env if non-NULL, the node number attribute will be copied to the new node
100 copy_node (ir_node *n, void *env)
104 opcode op = get_irn_opcode(n);
105 int copy_node_nr = false;
107 /* The end node looses it's flexible in array. This doesn't matter,
108 as dead node elimination builds End by hand, inlineing doesn't use
110 /* assert(n->op == op_End || ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
113 /* node copied already */
116 new_arity = get_irn_arity(n);
118 nn = new_ir_node(get_irn_dbg_info(n),
127 /* Copy the attributes. These might point to additional data. If this
128 was allocated on the old obstack the pointers now are dangling. This
129 frees e.g. the memory of the graph_arr allocated in new_immBlock. */
130 copy_node_attr(n, nn);
131 new_backedge_info(nn);
136 /* for easier debugging, we want to copy the node numbers too */
137 nn->node_nr = n->node_nr;
142 /*Check if phi in the loop head is.
144 * @param *phi Muss to be a phi node from the loop.
145 * @param *loop_head The loop head .
147 static int is_Phi_in_loop_head(ir_node *phi, ir_node *loop_head) {
148 assert(is_Block(loop_head));
149 return is_Phi(phi) && (get_nodes_block(phi) == loop_head);
153 * Copies predecessors of node to copies of node.
154 * If the predecessor is a loop invariant, then the copy get it
155 * as predecessor, else the copy of the predecessor.
157 * @param *l_n A set, where the node of the loop are saved.
158 * @param *value A element of the set.
159 * @param *info Contains information about the induction variable.
160 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
161 * @param *env Free environment pointer.
164 set_preds (set *l_n, copies_t *value, induct_var_info *info, int unroll_factor, void *env)
167 copies_t key, *value_pred;
168 // The head of the unrolling loop.
169 ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
171 irn_arity = get_irn_arity(value->irn);
173 for (i = 0; i < irn_arity; i++) {
174 ir_node *pred = get_irn_n(value->irn, i);
177 value_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(pred));
179 if (value->irn != loop_head && !is_Phi_in_loop_head(value->irn, loop_head)) {
180 if (value_pred == NULL) {
181 /* Is loop invariant. */
182 for(p = 0; p < unroll_factor -1; p++)
183 set_irn_n (value->copy[p], i, pred);
184 // pred is a loop invariant. The copies of the successors get it as predecessor.
187 for(p = 0; p < unroll_factor -1; p++)
188 set_irn_n (value->copy[p], i, value_pred->copy[p]);
189 /* value_pred->irn is a node from the unrolling loop. The copies of the successors get the
190 copies of value_pred as predecessor.*/
195 /* Set the backedge of phi in the loop head.The backedge of phis in the loop head
196 * must now point to the value defined
197 * in the last copie of the loop body.
199 * @param *l_n A set, where the node of the loop are saved.
200 * @param *value A phi in the loop head.
201 * @param *info Contains information about the induction variable.
202 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
205 set_phi_backedge(set *l_n, copies_t *value, induct_var_info *info, int unroll_factor)
207 copies_t key, *value_pred;
208 /*info->op_pred_pos is the backedge position. */
209 key.irn = get_irn_n(value->irn, info->op_pred_pos);
210 value_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
212 /*value->copy[unroll_factor - 2] is the last copie. */
213 set_Phi_pred(value->irn, info->op_pred_pos, value_pred->copy[unroll_factor - 2]);
216 /** Test for a loop head.
218 * Returns true if the node has predecessors in the loop _and_ out of
219 * the loop. Then it is a loop head: The loop can be entered through
222 * @param *n The node to be tested. Muss be a block.
223 * @param *info Contains the loop information.
226 is_loop_head(ir_node *n, induct_var_info *info)
229 int some_outof_loop = 0, some_in_loop = 0;
231 assert(get_irn_op(n) == op_Block);
232 arity = get_Block_n_cfgpreds(n);
234 for (i = 0; i < arity; i++) {
235 ir_node *pred = get_Block_cfgpred(n, i);
237 if (is_loop_invariant(pred, get_loop_node(info->l_itervar_phi, 0))) {
243 return some_outof_loop && some_in_loop;
247 /** Test wether the passed loop is a natural loop.
249 * Returns true if the loop has only one loop header and only a single
252 * @param *info Contains the loop information.
255 is_natural_loop ( induct_var_info *info)
259 l_n_node = get_loop_n_nodes (info->l_itervar_phi);
261 for (i = 1; i < (l_n_node); i ++) {
262 l_node = get_loop_node (info->l_itervar_phi, i);
263 if (is_loop_head(l_node, info)) return 0;
265 if (has_backedges(l_node) && i != l_n_node-1) return 0;
271 /** Serch for all nodes of a loop.
273 * @param *node The induction variable of the loop.
274 * @param *loop_head The head of the loop.
275 * @param *l_n A set, where the node of the loop are saved.
278 find_loop_nodes(ir_node *node, ir_node *loop_head, set *l_n)
281 copies_t key, *value;
283 /* Add this node to the list. */
285 for(i = 0; i < 4 ;i++)
286 /* Initialize all copies of the added node with NULL.*/
288 value = set_insert(l_n, &key, sizeof(key), HASH_PTR(key.irn));
290 /* Add all outs of this node to the list, if they are within the loop. */
291 for (i = get_irn_n_outs(node) - 1; i >= 0; i--) {
292 ir_node *pred = get_irn_out(node, i);
294 if (!is_loop_invariant(pred, loop_head) &&
295 set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL ) {
296 find_loop_nodes(pred, loop_head, l_n);
300 /* Add all ins if they are within the loop. */
301 for(i = get_irn_arity(node) -1; i >=0; i--) {
302 ir_node *pred = get_irn_n(node, i);
304 if (!is_loop_invariant(pred, loop_head) &&
305 set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL ){
306 find_loop_nodes(pred, loop_head, l_n);
311 /* Make a new loop head if copy_loop_head = 1.
313 * @param *l_n A set, where the node of the loop are saved.
314 * @param *info Contains the loop information.
315 * @param *value A element of the set.
316 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
320 new_loop_head (set *l_n, induct_var_info *info, copies_t *value, int unroll_factor)
323 copies_t block, *value_backedge_jmp, *backedge_jmp_block;
324 /* The predecessor of the loop head in the backedge position*/
325 ir_node *backedge_jmp = get_Block_cfgpred(value->irn, info->op_pred_pos);
326 block.irn = backedge_jmp;
328 value_backedge_jmp = set_find( l_n, &block, sizeof(block), HASH_PTR(block.irn));
331 /* The first copy of the loop head muss point to the loop head.*/
332 ir_node *new_loop_head = new_Block(1, &backedge_jmp);
333 value->copy[0] = new_loop_head;
335 for(i = 1; i<unroll_factor - 1; i++){
336 /* The another copies muss point to the copy befor it in the array. */
337 ir_node *new_loop_head = new_Block(1, &value_backedge_jmp->copy[i-1]);
338 value->copy[i] = new_loop_head;
341 /* If the loop haed muss't be copy. block.irn is the successor of the loop head.*/
342 block.irn = get_nodes_block(backedge_jmp);
343 backedge_jmp_block = set_find( l_n, &block, sizeof(block), HASH_PTR(block.irn));
344 /*The first copy of block.irn point to it.
345 The another copies muss point to the copy befor it in the array.*/
346 set_irn_n(backedge_jmp_block->copy[0], 0, value_backedge_jmp->irn) ;
348 for(i = 1; i<unroll_factor - 1; i++)
349 set_irn_n(backedge_jmp_block->copy[i], 0, value_backedge_jmp->copy[i - 1]);
354 /* Set all copies of the induction variable.
356 * @param *phi A phi node in the loop head block.
357 * @param *phi_pred The predecessor of the phi along the backedge.
358 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
362 set_Phi_copies(copies_t *phi, copies_t *phi_pred, int unroll_factor)
365 /* The first copy of Phi node get the node along the backedge as predecessor. The next copies
366 the copies of this node.*/
367 phi->copy[0] = phi_pred->irn;
368 for(p = 1; p < unroll_factor -1; p++){
369 // If two phi nodes are in cycle.
370 if(phi_pred->copy[p - 1] == NULL && get_irn_op(phi_pred->irn) == op_Phi){
372 phi->copy[p] = phi->irn;
374 phi->copy[p] = phi_pred->irn;
376 phi->copy[p] = phi_pred->copy[p -1];
380 /* Decide if the loop head to be copy. A head with important nodes
383 * @param *l_n A set, where the node of the loop are saved.
384 * @param *info Contains information about the induction variable.
387 loop_head_nodes(set *l_n, induct_var_info *info)
390 ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
392 for (value = set_first(l_n); value != NULL; value = set_next(l_n))
393 if(value->irn->op != op_Block &&
394 get_nodes_block(value->irn) == loop_head)
395 /* If the loop head contains just this nodes, than muss't be copy. */
396 switch(get_irn_opcode(value->irn)) {
412 /** Copy all loop nodes.
414 * @param *l_n Contains all nodes of the loop.
415 * @param *info Contains the loop information.
416 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
419 copy_loop_body(set *l_n, induct_var_info *info, int unroll_factor)
422 copies_t *value, *info_op, *phi, *loop_h, key, *value_block;
424 ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
427 for (value = set_first(l_n); value != NULL; value = set_next(l_n)) {
428 if(value->irn == loop_head)
430 else if (is_Phi_in_loop_head(value->irn, loop_head))
432 else if(copy_loop_head){
433 /* If the loop head muss be copy. */
434 for (i = 0; i < unroll_factor - 1; i++){
435 copy_node(value->irn, NULL);
436 value->copy[i] = get_irn_link(value->irn);
439 /* If the loop head and its nodes muss't be copy. */
440 if((value->irn->op == op_Block &&
441 value->irn != loop_head) ||
442 (value->irn->op != op_Block &&
443 get_nodes_block(value->irn) != loop_head))
444 for (i = 0; i<unroll_factor -1; i++){
445 copy_node(value->irn, NULL);
446 value->copy[i] = get_irn_link(value->irn);
450 /* Treat the loop head block */
451 new_loop_head (l_n, info, loop_h, unroll_factor);
453 /* Similarily treat the Phis in the loop head block. info->op is the node
454 along the backadge.*/
456 info_op = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
457 assert(info_op->irn == get_Phi_pred(info->itervar_phi, info->op_pred_pos));
458 for (i = 0; i < get_irn_n_outs(loop_head); ++i) {
459 ir_node *phi = get_irn_out(loop_head, i);
462 key.irn = get_Phi_pred(phi, info->op_pred_pos); // info->op;
463 copies_t *phi_pred = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
465 copies_t *phi_op = set_find(l_n, &key, sizeof(key), HASH_PTR(key.irn));
466 set_Phi_copies(phi_op, phi_pred, unroll_factor);
471 for (value = set_first(l_n); value != NULL; value = set_next(l_n)) {
472 /* Set the predecessors of the copies. */
474 set_preds(l_n, value, info, unroll_factor, NULL);
475 else if((value->irn->op != op_Block) && get_nodes_block(value->irn) != loop_head)
476 set_preds(l_n, value, info, unroll_factor, NULL);
478 if (is_Phi_in_loop_head(value->irn, loop_head))
479 /* Set the backedge of phis in the loop head. */
480 set_phi_backedge(l_n, value, info, unroll_factor);
482 if ((value->irn->op != op_Block) && !is_Phi_in_loop_head(value->irn, loop_head)) {
483 ir_node *nodes_block = get_nodes_block(value->irn);
485 if(!copy_loop_head && nodes_block == loop_head)
488 key.irn = nodes_block;
489 value_block = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
490 /* Set the copy of the node in the accordant copy of its block. */
491 for(i = 0; i < unroll_factor - 1; i++){
492 set_nodes_block(value->copy[i], value_block->copy[i]);
493 //add_End_keepalive(get_irg_end(current_ir_graph), value->copy[p]);
498 /** is_exception_possible
500 * If a Proj node from the loop have as predecessor a Call, Div or Load node, then is a
501 * exception possible.
503 * @param *node A Proj node form the loop.
506 is_exception_possible(ir_node *node)
509 ir_node *pred = get_Proj_pred(node);
511 switch(get_irn_opcode(pred)){
528 * If a node from the loop is predecessor of the end block,then muss have the end block all copies
529 * of this node as predecessors.This is possible with funktions calls in the unrolling loop.
531 * @param *end_block The end block.
532 * @param *loop_head The head of the unrolling loop.
533 * @param *l_n Contains all nodes of the loop.
534 * @param *loop_endblock_outs The set loop_endblock_outs contains all predecessors
535 * of the end block from the unrolling loop.
536 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
540 new_end_block (ir_node* end_block,ir_node *loop_head, set *l_n, set *loop_endblock_outs, int unroll_factor)
543 copies_t key, *value;
544 int set_el, new_preds, all_new_preds, i, q;
545 int old_preds = get_Block_n_cfgpreds(end_block); // All old predecessors of the end block.
547 for(int i = 0; i < old_preds; i++){
548 ir_node *pred = get_Block_cfgpred(end_block, i);
551 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
552 // If a predecessor of the end block is a Proj from the unrolling loop (for funktion calls) .
553 if( get_irn_op(pred) == op_Proj && is_exception_possible(pred) && value != NULL &&
554 !(!copy_loop_head && get_nodes_block(pred) == loop_head))
555 value = set_insert(loop_endblock_outs, &key, sizeof(key), HASH_PTR(key.irn));
557 /* The set loop_endblock_outs contains all predecessors of the end block from the unrolling loop.
558 set_el their number.*/
559 set_el = set_count (loop_endblock_outs);
560 // If the end block haven't such predecessors.Nothing muss be do.
563 new_preds = (unroll_factor - 1) * set_el; //All new predecessors of the end block.
564 all_new_preds = old_preds + new_preds; //All predecessors of this block.
565 ir_node *all_in[all_new_preds]; //A array with size for all predecessors of this block.
567 for (i = 0; i < old_preds; i++)
568 all_in[i] = get_Block_cfgpred(end_block, i); // The old predecessors.
570 value = set_first(loop_endblock_outs);
572 for( ; value != NULL; value = set_next(loop_endblock_outs)){
573 key.irn = value->irn;
574 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
575 for(q = 0; q < unroll_factor - 1 ; q++){
576 all_in[i] = value->copy[q];
577 i++; // The new predecessors.
581 /* Replace the old predecessors of the end block whit the new one. */
582 set_irn_in(end_block, all_new_preds, all_in);
585 /** new_after_loop_block
587 * This after loop block muss examine the possible exceptions in the loop.If a (Proj) node from the loop
588 * is predecessor of this block,then muss have the after loop block as well all copies
589 * of this node as predecessors.
591 * @param *l_n Contains all nodes of the loop.
592 * @block *block A block afte the loop.
593 * @param *loop_in A node from the loop, that is predecessor of the end block.
594 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
598 new_after_loop_block (set *l_n, ir_node* block, copies_t *loop_in, int unroll_factor)
600 copies_t key, *value;
601 int i, p, q, s, old_preds, new_preds, all_new_preds ;
603 // The node from the unrolling loop muss be a Proj.
604 if(loop_in->irn->op != op_Proj) return;
606 old_preds = get_Block_n_cfgpreds(block); // All old predecessors of this block.
607 new_preds = old_preds * (unroll_factor - 1); //All new predecessors of this block.
608 all_new_preds = old_preds + new_preds; //All predecessors of this block.
610 ir_node *all_in[all_new_preds]; //A array with size for all predecessors of this block.
612 for (i = 0 ; i < old_preds; i++)
613 all_in[i] = get_Block_cfgpred(block, i); //The old predecessors.
616 for(i = 0; i < old_preds; i++){
618 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
620 for(s = 0; s < (unroll_factor - 1); s++){
621 all_in[q] = value->copy[p]; //The new predecessors.
627 /* Replace the old predecessors of the end block whit the new one. */
628 set_irn_in(block, all_new_preds, all_in);
631 /** new_after_loop_node
633 * This after loop node (phi or call) muss examine the possible exceptions in the loop.If a (Proj) node
634 * from the loop is predecessor of this node,then muss have the after loop node as well all copies
635 * of this node as predecessors.
637 * @param *l_n Contains all nodes of the loop.
638 * @param *loop_outs Contains nodes after the loop,that have as predecessor a node from the loop.
639 * @block *node A node afte the loop.
640 * @param *loop_in A node (Proj) from the loop, that is predecessor of *node.
641 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
645 new_after_loop_node(set *l_n, set *loop_outs, ir_node *node, copies_t *loop_in, int unroll_factor)
647 ir_node *pred, *block_pred, *node_block, *new_phi;
648 int phi = 0, old_preds, new_preds, all_new_preds, p, q, i, s;
649 copies_t key, *value = NULL;
651 old_preds = get_irn_arity(node); // All old predecessors of this node.
652 new_preds =old_preds * (unroll_factor - 1); //All new predecessors of this block.
653 all_new_preds = old_preds + new_preds; //All predecessors of this block.
654 ir_node *all_in [all_new_preds]; //A array with size for all predecessors of this block.
657 // Verification Predecessors, successors and operation of node and loop_in.
658 //loop_in muss be a Proj node.
659 if(loop_in->irn->op != op_Proj) return;
660 // Node muss be operation Phi with mode memory or a Call node.
661 if(get_irn_op(node) == op_Phi &&
662 get_irn_mode(node) == mode_M){
663 // If node is a Phi node,then muss have a Call node as successor.
664 for (i = 0; i < get_irn_n_outs(node); i++)
665 if(get_irn_opcode(get_irn_out(node, i)) == iro_Call)
670 // The predecessor of loop_in muss't be a loop invariant.
671 pred = get_Proj_pred(loop_in->irn);
673 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
674 if(value == NULL)return;
676 node_block = get_nodes_block(node);
678 // The block of node muss have too a (Proj) predecessor from the unrolling loop.
679 for(i = 0; i < get_Block_n_cfgpreds(node_block); i++){
680 block_pred = get_Block_cfgpred( node_block, i);
682 if(get_irn_op(block_pred) == op_Proj){
683 if(get_Proj_pred(block_pred) == pred)
689 if(block_pred == NULL) return;
691 key.irn = block_pred;
692 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
697 new_after_loop_block(l_n, node_block, value, unroll_factor);
701 for ( ; i < old_preds; i++)
702 all_in[i] = get_irn_n(node, i); //The old predecessors.
706 for(; i < old_preds; i++){
708 value = set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn));
710 for(s = 0; s < (unroll_factor - 1); s++){
711 all_in[q] = value->copy[p]; //The new predecessors.
716 // A new phi node with the new predecessors.
717 new_phi = new_r_Phi(current_ir_graph, get_nodes_block(node), all_new_preds,all_in,
721 exchange(node, new_phi);
724 for( ; i < get_irn_arity(node) ; i++)
725 if (get_irn_n(node, i) == pred)
726 set_irn_n(node, i, new_phi);
728 // The set loop_outs contains the visited nodes and their blocks.
730 value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
731 key.irn = get_nodes_block(node);
732 value = set_insert(loop_outs, &key, sizeof(key), HASH_PTR(key.irn));
736 /* Set the outs of the unrolling loop. All loop outs of a node muss now
737 * point to the last copy of it. Just phi nodes in the loop head and proj
738 * nodes save it outs. The all copies of some Projs have too outs.
740 * @param *l_n Contains all nodes of the loop.
741 * @param *loop_outs The set contains the visited and changed loop outs.
742 * @param *loop_endblock_outs The set loop_endblock_outs contains all predecessors
743 * of the end block from the unrolling loop.
744 * @param *info Contains the loop information.
745 * @param *unroll_factor A integer 2 <= unroll_factor <= 4.
748 set_loop_outs(set *l_n,set * loop_outs, set *loop_endblock_outs,induct_var_info *info, int unroll_factor)
750 copies_t *value, key;
752 ir_node *loop_head = get_loop_node(info->l_itervar_phi, 0);
753 ir_node *end_block = get_irg_end_block(current_ir_graph);
754 value = set_first(l_n);
756 for( ; value != NULL; value = set_next(l_n))
757 if(!is_Phi_in_loop_head(value->irn, loop_head) &&
758 (get_irn_opcode(value->irn) == iro_Proj && value->copy[0] != NULL))
759 for(i = 0; i < get_irn_n_outs(value->irn); i++){
760 key.irn = get_irn_out(value->irn, i);
761 // Search for loop outs.
762 if(set_find( l_n, &key, sizeof(key), HASH_PTR(key.irn)) == NULL)
763 if((key.irn->op == op_Block && get_Block_dom_depth(key.irn) >
764 get_Block_dom_depth(loop_head)) ||
765 (key.irn->op != op_Block && get_Block_dom_depth(get_nodes_block(key.irn)) >
766 get_Block_dom_depth(loop_head))){
768 for(p = 0; p < get_irn_arity(key.irn); p++)
769 if(value->irn == get_irn_n(key.irn, p)){
770 if(get_irn_opcode(value->irn) == iro_Proj && is_exception_possible(value->irn)){
771 if(set_find( loop_outs, &key, sizeof(key), HASH_PTR(key.irn)) == NULL){
772 // If the loop out is for exceptions in the loop.
773 if((key.irn->op == op_Phi && get_irn_mode(key.irn) == mode_M) ||
774 get_irn_opcode(key.irn) == iro_Call)
775 new_after_loop_node(l_n,loop_outs, key.irn, value, unroll_factor);
781 set_irn_n (key.irn, p, value->copy[unroll_factor-2]);
785 // The funktion search for loop outs associated with funktion call in the unrolling loop.
786 new_end_block (end_block, loop_head, l_n, loop_endblock_outs, unroll_factor);
788 /** Unroll the loop boby with a factor that must be power of two.
790 * @param *n A ir node.
791 * @param *env Free environment pointer.
793 static void do_loop_unroll(ir_node *n, void *env){
795 induct_var_info info;
796 info.itervar_phi = n;
797 int l_sons = 0, unroll_factor = 0;
800 /* The ir node must be a induction varible. */
802 if (get_irn_op (n) == op_Phi) {
803 if (is_induction_variable (&info) == NULL) return;
806 /* Brute force limiting of loop body size. */
807 if (get_loop_n_nodes(info.l_itervar_phi) > 2 ) return;
809 /* Only unroll loops that compare against a constant for exiting. */
810 if (info.cmp == NULL) return;
812 /* We only want to unroll innermost loops. */
813 l_sons = get_loop_n_sons (info.l_itervar_phi);
817 ir_node* cmp_out = get_irn_out(info.cmp, 0);
818 ir_node *phi_init = get_Phi_pred(info.itervar_phi, info.init_pred_pos);
820 if(!is_Proj(cmp_out)) return;
821 if(get_irn_op(info.increment) != op_Const ||
822 get_irn_op(phi_init) != op_Const ||
823 get_irn_op(info.cmp_const) != op_Const) return;
825 int cmp_typ = get_Proj_proj(cmp_out);
826 int init = get_tarval_long(get_Const_tarval(phi_init));
827 int iter_end = get_tarval_long(get_Const_tarval(info.cmp_const));
828 int iter_increment = get_tarval_long(get_Const_tarval(info.increment));
829 int diff, iter_number;
837 iter_increment = iter_increment < 0 ? -iter_increment : iter_increment;
838 diff = iter_end - init;
840 if (diff == 0 || iter_increment == 0) return;
841 /*Test for the value of unroll factor. */
842 iter_number = diff/iter_increment;
843 if((cmp_typ == 3 || cmp_typ == 5) && (iter_end % iter_increment == 0))
846 if(iter_number % 4 == 0)
848 else if(iter_number % 3 == 0)
850 else if(iter_number % 2 == 0)
855 printf("\nloop unrolling with factor %d \n", unroll_factor);
857 DDMG(get_irn_irg(n));
858 // The unrollfactor muss less than 4.
859 assert(unroll_factor <= MAX_UNROLL);
863 loop_head = (is_natural_loop(&info)) ? get_loop_node(info.l_itervar_phi, 0) : NULL;
865 assert(loop_head != NULL && is_Block(loop_head));
867 /* We assume, the loop head has exactly one backedge. The position of
868 the backedge is in the following variable: */
870 backedge_pos = (is_backedge(loop_head, 0)) ? 0:1;
873 set *loop_nodes, *loop_outs, *loop_endblock_outs;
874 /* A set with the nodes to copy. */
875 loop_nodes = new_set(set_cmp, 8);
876 // A set with the loop outs for exceptions.
877 loop_outs = new_set(set_cmp, 8);
878 /* The set contains all predecessors
879 of the end block from the unrolling loop.*/
880 loop_endblock_outs = new_set(set_cmp, 8);
882 /* Find all nodes of the unrolling loop. */
883 find_loop_nodes(info.itervar_phi, get_loop_node(info.l_itervar_phi, 0), loop_nodes);
884 /* Decide if the loop head to be copy.*/
885 loop_head_nodes(loop_nodes, &info);
886 /* Copy all nodes of the unrolling loop, that muss be copy. */
887 copy_loop_body(loop_nodes, &info, unroll_factor);
889 ir_node *backedge_jmp = get_Block_cfgpred(loop_head, backedge_pos);
891 /* Set the backedge of the loop head. */
892 for (value = set_first(loop_nodes); value != NULL; value = set_next(loop_nodes)) {
893 if(value->irn == backedge_jmp){
895 set_Block_cfgpred(loop_head, backedge_pos, value->copy[unroll_factor-2]);
898 set_loop_outs(loop_nodes, loop_outs, loop_endblock_outs, &info, unroll_factor);
902 /* Performs loop unrolling for the passed graph. */
903 void optimize_loop_unrolling(ir_graph *irg /* unroll factor, max body size */) {
904 ir_graph *rem = current_ir_graph;
905 current_ir_graph = irg;
907 if ( !get_opt_loop_unrolling()) return;
909 /* -- Precompute some information -- */
910 /* Call algorithm that computes the backedges */
911 construct_cf_backedges(irg);
912 /* Call algorithm that computes the dominator trees. */
914 /* Call algorithm that computes the out edges */
916 collect_phiprojs(irg);
918 /* -- Search expressions that can be optimized -- */
919 irg_walk_graph(irg, NULL, do_loop_unroll, NULL);
921 current_ir_graph = rem;