removed unused header
[libfirm] / ir / opt / opt_osr.c
1 /*
2  * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * Project:     libFIRM
22  * File name:   ir/opt/opt_osr.c
23  * Purpose:     Operator Strength Reduction, based on
24  *              Keith D. Cooper, L. Taylor Simpson, Christopher A. Vick
25  * Author:      Michael Beck
26  * Modified by:
27  * Created:     12.5.2006
28  * CVS-ID:      $Id$
29  * Copyright:   (c) 2006 Universität Karlsruhe
30  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include "opt_osr.h"
36 #include "irgraph.h"
37 #include "ircons.h"
38 #include "irop_t.h"
39 #include "irloop.h"
40 #include "irdom.h"
41 #include "irgmod.h"
42 #include "irflag_t.h"
43 #include "irgwalk.h"
44 #include "irouts.h"
45 #include "debug.h"
46 #include "obst.h"
47 #include "set.h"
48 #include "tv.h"
49 #include "hashptr.h"
50 #include "irtools.h"
51 #include "irloop_t.h"
52 #include "array.h"
53 #include "firmstat.h"
54 #include "xmalloc.h"
55
56 /** The debug handle. */
57 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
58
59 /** A scc. */
60 typedef struct scc {
61         ir_node *head;          /**< the head of the list */
62 } scc;
63
64 /** A node entry */
65 typedef struct node_entry {
66         unsigned DFSnum;    /**< the DFS number of this node */
67         unsigned low;       /**< the low number of this node */
68         ir_node  *header;   /**< the header of this node */
69         int      in_stack;  /**< flag, set if the node is on the stack */
70         ir_node  *next;     /**< link to the next node the the same scc */
71         scc      *pscc;     /**< the scc of this node */
72         unsigned POnum;     /**< the post order number for blocks */
73 } node_entry;
74
75 /** The environment. */
76 typedef struct iv_env {
77         struct obstack obst;    /**< an obstack for allocations */
78         ir_node  **stack;       /**< the node stack */
79         int      tos;           /**< tos index */
80         unsigned nextDFSnum;    /**< the current DFS number */
81         unsigned POnum;         /**< current post order number */
82         set      *quad_map;     /**< a map from (op, iv, rc) to node */
83         set      *lftr_edges;   /**< the set of lftr edges */
84         unsigned replaced;      /**< number of replaced ops */
85         unsigned lftr_replaced; /**< number of applied linear function test replacements */
86         unsigned flags;         /**< additional flags */
87         /** Function called to process a SCC. */
88         void (*process_scc)(scc *pscc, struct iv_env *env);
89 } iv_env;
90
91 /**
92  * An entry in the (op, node, node) -> node map.
93  */
94 typedef struct quadruple_t {
95         ir_opcode code;  /**< the opcode of the reduced operation */
96         ir_node   *op1;  /**< the first operand the reduced operation */
97         ir_node   *op2;  /**< the second operand of the reduced operation */
98
99         ir_node   *res; /**< the reduced operation */
100 } quadruple_t;
101
102 /**
103  * A LFTR edge.
104  */
105 typedef struct LFTR_edge {
106         ir_node   *src;   /**< the source node */
107         ir_node   *dst;   /**< the destination node */
108         ir_opcode code;   /**< the opcode that must be applied */
109         ir_node   *rc;    /**< the region const that must be applied */
110 } LFTR_edge;
111
112 /* forward */
113 static ir_node *reduce(ir_node *orig, ir_node *iv, ir_node *rc, iv_env *env);
114
115 /**
116  * Compare two LFTR edges.
117  */
118 static int LFTR_cmp(const void *e1, const void *e2, size_t size) {
119         const LFTR_edge *l1 = e1;
120         const LFTR_edge *l2 = e2;
121
122         return l1->src != l2->src;
123 }
124
125 #if 0
126 /**
127  * Find a LFTR edge.
128  */
129 static LFTR_edge *LFTR_find(ir_node *src, iv_env *env) {
130         LFTR_edge key;
131
132         key.src  = src;
133
134         return set_find(env->lftr_edges, &key, sizeof(key), HASH_PTR(src));
135 }
136 #endif
137
138 /**
139  * Add a LFTR edge.
140  */
141 static void LFTR_add(ir_node *src, ir_node *dst, ir_opcode code, ir_node *rc, iv_env *env) {
142         LFTR_edge key;
143
144         key.src  = src;
145         key.dst  = dst;
146         key.code = code;
147         key.rc   = rc;
148
149         /*
150          * There might be more than one edge here. This is rather bad
151          * because we currently store only one.
152          */
153 //      assert(LFTR_find(src, env) == NULL);
154         set_insert(env->lftr_edges, &key, sizeof(key), HASH_PTR(src));
155 }
156
157 /**
158  * Gets the node_entry of a node
159  */
160 static node_entry *get_irn_ne(ir_node *irn, iv_env *env) {
161         node_entry *e = get_irn_link(irn);
162
163         if (! e) {
164                 e = obstack_alloc(&env->obst, sizeof(*e));
165                 memset(e, 0, sizeof(*e));
166                 set_irn_link(irn, e);
167         }
168         return e;
169 }
170
171 /**
172  * Check if irn is an IV.
173  *
174  * @param irn  the node to check
175  * @param env  the environment
176  *
177  * @returns the header if it is one, NULL else
178  */
179 static ir_node *is_iv(ir_node *irn, iv_env *env) {
180         return get_irn_ne(irn, env)->header;
181 }
182
183 /**
184  * Check if irn is a region constant.
185  * The block or irn must strictly dominate the header block.
186  *
187  * @param irn           the node to check
188  * @param header_block  the header block of the induction variable
189  */
190 static int is_rc(ir_node *irn, ir_node *header_block) {
191         ir_node *block = get_nodes_block(irn);
192
193         return (block != header_block) && block_dominates(block, header_block);
194 }
195
196 /**
197  * Set compare function for the quad set.
198  */
199 static int quad_cmp(const void *e1, const void *e2, size_t size) {
200         const quadruple_t *c1 = e1;
201         const quadruple_t *c2 = e2;
202
203         return c1->code != c2->code || c1->op1 != c2->op1 || c1->op2 != c2->op2;
204 }
205
206 /**
207  * Check if an reduced operation was already calculated.
208  *
209  * @param code  the opcode of the operation
210  * @param op1   the first operand of the operation
211  * @param op2   the second operand of the operation
212  * @param env   the environment
213  *
214  * @return the already reduced node or NULL if this operation is not yet reduced
215  */
216 static ir_node *search(ir_opcode code, ir_node *op1, ir_node *op2, iv_env *env) {
217         quadruple_t key, *entry;
218
219         key.code = code;
220         key.op1 = op1;
221         key.op2 = op2;
222
223         entry = set_find(env->quad_map, &key, sizeof(key),
224                          (code * 9) ^ HASH_PTR(op1) ^HASH_PTR(op2));
225         if (entry)
226                 return entry->res;
227         return NULL;
228 }
229
230 /**
231  * Add an reduced operation.
232  *
233  * @param code    the opcode of the operation
234  * @param op1     the first operand of the operation
235  * @param op2     the second operand of the operation
236  * @param result  the result of the reduced operation
237  * @param env     the environment
238  */
239 static void add(ir_opcode code, ir_node *op1, ir_node *op2, ir_node *result, iv_env *env) {
240         quadruple_t key;
241
242         key.code = code;
243         key.op1  = op1;
244         key.op2  = op2;
245         key.res  = result;
246
247         set_insert(env->quad_map, &key, sizeof(key),
248                    (code * 9) ^ HASH_PTR(op1) ^HASH_PTR(op2));
249 }
250
251 /**
252  * Find a location where to place a bin-op whose operands are in
253  * block1 and block2.
254  *
255  * @param block1  the block of the first operand
256  * @param block2  the block of the second operand
257  *
258  * Note that we know here that such a place must exists. Moreover, this means
259  * that either block1 dominates block2 or vice versa. So, just return
260  * the "smaller" one.
261  */
262 static ir_node *find_location(ir_node *block1, ir_node *block2) {
263         if (block_dominates(block1, block2))
264                 return block2;
265         assert(block_dominates(block2, block1));
266         return block1;
267 }
268
269 /**
270  * Create a node that executes an op1 code op1 operation.
271  *
272  * @param code   the opcode to execute
273  * @param db     debug info to add to the new node
274  * @param op1    the first operand
275  * @param op2    the second operand
276  * @param mode   the mode of the new operation
277  *
278  * @return the newly created node
279  */
280 static ir_node *do_apply(ir_opcode code, dbg_info *db, ir_node *op1, ir_node *op2, ir_mode *mode) {
281         ir_graph *irg = current_ir_graph;
282         ir_node *result;
283         ir_node *block = find_location(get_nodes_block(op1), get_nodes_block(op2));
284
285         switch (code) {
286         case iro_Mul:
287                 result = new_rd_Mul(db, irg, block, op1, op2, mode);
288                 break;
289         case iro_Add:
290                 result = new_rd_Add(db, irg, block, op1, op2, mode);
291                 break;
292         case iro_Sub:
293                 result = new_rd_Sub(db, irg, block, op1, op2, mode);
294                 break;
295         default:
296                 assert(0);
297                 result = NULL;
298         }
299         return result;
300 }
301
302 /**
303  * The Apply operation.
304  *
305  * @param orig   the node that represent the original operation and determines
306  *               the opcode, debug-info and mode of a newly created one
307  * @param op1    the first operand
308  * @param op2    the second operand
309  * @param env    the environment
310  *
311  * @return the newly created node
312  */
313 static ir_node *apply(ir_node *orig, ir_node *op1, ir_node *op2, iv_env *env) {
314         ir_opcode code = get_irn_opcode(orig);
315         ir_node *result = search(code, op1, op2, env);
316
317         if (! result) {
318                 dbg_info *db = get_irn_dbg_info(orig);
319                 ir_node *op1_header = get_irn_ne(op1, env)->header;
320                 ir_node *op2_header = get_irn_ne(op2, env)->header;
321
322                 if (op1_header != NULL && is_rc(op2, op1_header)) {
323                         result = reduce(orig, op1, op2, env);
324                 }
325                 else if (op2_header != NULL && is_rc(op1, op2_header)) {
326                         result = reduce(orig, op2, op1, env);
327                 }
328                 else {
329                         result = do_apply(code, db, op1, op2, get_irn_mode(orig));
330                         get_irn_ne(result, env)->header = NULL;         }
331         }
332         return result;
333 }
334
335 /**
336  * The Reduce operation.
337  *
338  * @param orig   the node that represent the original operation and determines
339  *               the opcode, debug-info and mode of a newly created one
340  * @param iv     the induction variable
341  * @param rc     the region constant
342  * @param env    the environment
343  *
344  * @return the reduced node
345  */
346 static ir_node *reduce(ir_node *orig, ir_node *iv, ir_node *rc, iv_env *env) {
347         ir_opcode code = get_irn_opcode(orig);
348         ir_node *result = search(code, iv, rc, env);
349
350         if (! result) {
351                 node_entry *e, *iv_e;
352                 int i, n;
353                 ir_mode *mode = get_irn_mode(orig);
354
355                 result = exact_copy(iv);
356
357                 /* Beware: we must always create a new nduction variable with the same mode
358                    as the node we are replacing. Espicially this means the mode might be changed
359                    from P to I and back. This is always possible, because we have only Phi, Add
360                    and Sub nodes. */
361                 set_irn_mode(result, mode);
362                 add(code, iv, rc, result, env);
363                 DB((dbg, LEVEL_3, "   Created new %+F for %+F (%s %+F)\n", result, iv,
364                         get_irn_opname(orig), rc));
365
366                 iv_e = get_irn_ne(iv, env);
367                 e    = get_irn_ne(result, env);
368                 e->header = iv_e->header;
369
370                 /* create the LFTR edge */
371                 LFTR_add(iv, result, code, rc, env);
372
373                 n = get_irn_arity(result);
374                 for (i = 0; i < n; ++i) {
375                         ir_node *o = get_irn_n(result, i);
376
377                         e = get_irn_ne(o, env);
378                         if (e->header == iv_e->header)
379                                 o = reduce(orig, o, rc, env);
380                         else if (is_Phi(result))
381                                 o = apply(orig, o, rc, env);
382                         else {
383                                 if (code == iro_Mul)
384                                         o = apply(orig, o, rc, env);
385                         }
386                         set_irn_n(result, i, o);
387                 }
388         }
389         else {
390                 DB((dbg, LEVEL_3, "   Already Created %+F for %+F (%s %+F)\n", result, iv,
391                         get_irn_opname(orig), rc));
392         }
393         return result;
394 }
395
396 /**
397  * The Replace operation.
398  *
399  * @param irn   the node that will be replaced
400  * @param iv    the induction variable
401  * @param rc    the region constant
402  * @param env   the environment
403  */
404 static int replace(ir_node *irn, ir_node *iv, ir_node *rc, iv_env *env) {
405         ir_node *result;
406         ir_loop *iv_loop  = get_irn_loop(get_nodes_block(iv));
407         ir_loop *irn_loop = get_irn_loop(get_nodes_block(irn));
408
409         /* only replace nodes that are in the same (or deeper loops) */
410         if (get_loop_depth(irn_loop) >= get_loop_depth(iv_loop)) {
411                 DB((dbg, LEVEL_2, "  Replacing %+F\n", irn));
412
413                 result = reduce(irn, iv, rc, env);
414                 if (result != irn) {
415                         node_entry *e, *iv_e;
416
417                         hook_strength_red(current_ir_graph, irn);
418                         exchange(irn, result);
419                         e = get_irn_ne(result, env);
420                         iv_e = get_irn_ne(iv, env);
421                         e->header = iv_e->header;
422                 }
423                 return 1;
424         }
425         return 0;
426 }
427
428 /**
429  * Check if a node can be replaced (+, -, *).
430  *
431  * @param irn   the node to check
432  * @param env   the environment
433  *
434  * @return non-zero if irn should be Replace'd
435  */
436 static int check_replace(ir_node *irn, iv_env *env) {
437         ir_node   *left, *right, *iv, *rc;
438         ir_op     *op  = get_irn_op(irn);
439         ir_opcode code = get_op_code(op);
440         ir_node   *liv, *riv;
441
442         switch (code) {
443         case iro_Mul:
444         case iro_Add:
445         case iro_Sub:
446                 iv = rc = NULL;
447
448                 left  = get_binop_left(irn);
449                 right = get_binop_right(irn);
450
451                 liv = is_iv(left, env);
452                 riv = is_iv(right, env);
453                 if (liv && is_rc(right, liv)) {
454                         iv = left; rc = right;
455                 }
456                 else if (riv && is_op_commutative(op) &&
457                                     is_rc(left, riv)) {
458                         iv = right; rc = left;
459                 }
460
461                 if (iv) {
462                         if (code == iro_Mul && env->flags & osr_flag_ignore_x86_shift) {
463                                 if (is_Const(rc)) {
464                                         tarval *tv = get_Const_tarval(rc);
465
466                                         if (tarval_is_long(tv)) {
467                                                 long value = get_tarval_long(tv);
468
469                                                 if (value == 2 || value == 4 || value == 8) {
470                                                         /* do not reduce multiplications by 2, 4, 8 */
471                                                         break;
472                                                 }
473                                         }
474                                 }
475                         }
476
477                         return replace(irn, iv, rc, env);
478                 }
479                 break;
480         default:
481                 break;
482         }
483         return 0;
484 }
485
486 /**
487  * Check which SCC's are induction variables.
488  *
489  * @param pscc  a SCC
490  * @param env   the environment
491  */
492 static void classify_iv(scc *pscc, iv_env *env) {
493         ir_node *irn, *next, *header = NULL;
494         node_entry *b, *h = NULL;
495         int j, only_phi, num_outside;
496         ir_node *out_rc;
497
498         /* find the header block for this scc */
499         for (irn = pscc->head; irn; irn = next) {
500                 node_entry *e = get_irn_link(irn);
501                 ir_node *block = get_nodes_block(irn);
502
503                 next = e->next;
504                 b = get_irn_ne(block, env);
505
506                 if (header) {
507                         if (h->POnum < b->POnum) {
508                                 header = block;
509                                 h      = b;
510                         }
511                 }
512                 else {
513                         header = block;
514                         h      = b;
515                 }
516         }
517
518         /* check if this scc contains only Phi, Add or Sub nodes */
519         only_phi    = 1;
520         num_outside = 0;
521         out_rc      = NULL;
522         for (irn = pscc->head; irn; irn = next) {
523                 node_entry *e = get_irn_ne(irn, env);
524
525                 next = e->next;
526                 switch (get_irn_opcode(irn)) {
527                 case iro_Add:
528                 case iro_Sub:
529                         only_phi = 0;
530                         /* fall through */
531                 case iro_Phi:
532                         for (j = get_irn_arity(irn) - 1; j >= 0; --j) {
533                                 ir_node *pred  = get_irn_n(irn, j);
534                                 node_entry *pe = get_irn_ne(pred, env);
535
536                                 if (pe->pscc != e->pscc) {
537                                         /* not in the same SCC, must be a region const */
538                                         if (! is_rc(pred, header)) {
539                                                 /* not an induction variable */
540                                                 goto fail;
541                                         }
542                                         if (! out_rc) {
543                                                 out_rc = pred;
544                                                 ++num_outside;
545                                         } else if (out_rc != pred) {
546                                                 ++num_outside;
547                                         }
548                                 }
549                         }
550                         break;
551                 default:
552                         /* not an induction variable */
553                         goto fail;
554                 }
555         }
556         /* found an induction variable */
557         DB((dbg, LEVEL_2, "  Found an induction variable:\n  "));
558         if (only_phi && num_outside == 1) {
559                 /* a phi cycle with only one real predecessor can be collapsed */
560                 DB((dbg, LEVEL_2, "  Found an USELESS Phi cycle:\n  "));
561
562                 for (irn = pscc->head; irn; irn = next) {
563                         node_entry *e = get_irn_ne(irn, env);
564                         next = e->next;
565                         e->header = NULL;
566                         exchange(irn, out_rc);
567                 }
568                 ++env->replaced;
569                 return;
570         }
571
572         /* set the header for every node in this scc */
573         for (irn = pscc->head; irn; irn = next) {
574                 node_entry *e = get_irn_ne(irn, env);
575                 e->header = header;
576                 next = e->next;
577                 DB((dbg, LEVEL_2, " %+F,", irn));
578         }
579         DB((dbg, LEVEL_2, "\n"));
580         return;
581
582 fail:
583         for (irn = pscc->head; irn; irn = next) {
584                 node_entry *e = get_irn_ne(irn, env);
585
586                 next = e->next;
587                 if (! check_replace(irn, env))
588                         e->header = NULL;
589         }
590 }
591
592 /**
593  * Process a SCC for the operator strength reduction.
594  *
595  * @param pscc  the SCC
596  * @param env   the environment
597  */
598 static void process_scc(scc *pscc, iv_env *env) {
599         ir_node *head = pscc->head;
600         node_entry *e = get_irn_link(head);
601
602 #ifdef DEBUG_libfirm
603         {
604                 ir_node *irn, *next;
605
606                 DB((dbg, LEVEL_4, " SCC at %p:\n ", pscc));
607                 for (irn = pscc->head; irn; irn = next) {
608                         node_entry *e = get_irn_link(irn);
609
610                         next = e->next;
611
612                         DB((dbg, LEVEL_4, " %+F,", irn));
613                 }
614                 DB((dbg, LEVEL_4, "\n"));
615         }
616 #endif
617
618         if (e->next == NULL) {
619                 /* this SCC has only a single member */
620                 check_replace(head, env);
621         } else {
622                 classify_iv(pscc, env);
623         }
624 }
625
626 /**
627  * If an SCC is a Phi only cycle, remove it.
628  */
629 static void remove_phi_cycle(scc *pscc, iv_env *env) {
630         ir_node *irn, *next;
631         int j;
632         ir_node *out_rc;
633
634         /* check if this scc contains only Phi, Add or Sub nodes */
635         out_rc      = NULL;
636         for (irn = pscc->head; irn; irn = next) {
637                 node_entry *e = get_irn_ne(irn, env);
638
639                 next = e->next;
640                 if (! is_Phi(irn))
641                         return;
642
643                 for (j = get_irn_arity(irn) - 1; j >= 0; --j) {
644                         ir_node *pred  = get_irn_n(irn, j);
645                         node_entry *pe = get_irn_ne(pred, env);
646
647                         if (pe->pscc != e->pscc) {
648                                 /* not in the same SCC, must be the only input */
649                                 if (! out_rc) {
650                                         out_rc = pred;
651                                 } else if (out_rc != pred) {
652                                         return;
653                                 }
654                         }
655                 }
656         }
657         /* found a Phi cycle */
658         DB((dbg, LEVEL_2, "  Found an USELESS Phi cycle:\n  "));
659
660         for (irn = pscc->head; irn; irn = next) {
661                 node_entry *e = get_irn_ne(irn, env);
662                 next = e->next;
663                 e->header = NULL;
664                 exchange(irn, out_rc);
665         }
666         ++env->replaced;
667 }
668
669 /**
670  * Process a SCC for the Phi cycle removement.
671  *
672  * @param pscc  the SCC
673  * @param env   the environment
674  */
675 static void process_phi_only_scc(scc *pscc, iv_env *env) {
676         ir_node *head = pscc->head;
677         node_entry *e = get_irn_link(head);
678
679 #ifdef DEBUG_libfirm
680         {
681                 ir_node *irn, *next;
682
683                 DB((dbg, LEVEL_4, " SCC at %p:\n ", pscc));
684                 for (irn = pscc->head; irn; irn = next) {
685                         node_entry *e = get_irn_link(irn);
686
687                         next = e->next;
688
689                         DB((dbg, LEVEL_4, " %+F,", irn));
690                 }
691                 DB((dbg, LEVEL_4, "\n"));
692         }
693 #endif
694
695         if (e->next != NULL)
696                 remove_phi_cycle(pscc, env);
697 }
698
699
700 /**
701  * Push a node onto the stack.
702  *
703  * @param env   the environment
704  * @param n     the node to push
705  */
706 static void push(iv_env *env, ir_node *n) {
707         node_entry *e;
708
709         if (env->tos == ARR_LEN(env->stack)) {
710                 int nlen = ARR_LEN(env->stack) * 2;
711                 ARR_RESIZE(ir_node *, env->stack, nlen);
712         }
713         env->stack[env->tos++] = n;
714         e = get_irn_ne(n, env);
715         e->in_stack = 1;
716 }
717
718 /**
719  * pop a node from the stack
720  *
721  * @param env   the environment
722  *
723  * @return  The topmost node
724  */
725 static ir_node *pop(iv_env *env)
726 {
727         ir_node *n = env->stack[--env->tos];
728         node_entry *e = get_irn_ne(n, env);
729
730         e->in_stack = 0;
731         return n;
732 }
733
734 /**
735  * Do Tarjan's SCC algorithm and drive OSR.
736  *
737  * @param irn  start at this node
738  * @param env  the environment
739  */
740 static void dfs(ir_node *irn, iv_env *env)
741 {
742         int i, n;
743         node_entry *node = get_irn_ne(irn, env);
744
745         mark_irn_visited(irn);
746
747         /* do not put blocks into the scc */
748         if (is_Block(irn)) {
749                 n = get_irn_arity(irn);
750                 for (i = 0; i < n; ++i) {
751                         ir_node *pred = get_irn_n(irn, i);
752
753                         if (irn_not_visited(pred))
754                                 dfs(pred, env);
755                 }
756         }
757         else {
758                 ir_node *block = get_nodes_block(irn);
759
760                 node->DFSnum = env->nextDFSnum++;
761                 node->low    = node->DFSnum;
762                 push(env, irn);
763
764                 /* handle the block */
765                 if (irn_not_visited(block))
766                         dfs(block, env);
767
768                 n = get_irn_arity(irn);
769                 for (i = 0; i < n; ++i) {
770                         ir_node *pred = get_irn_n(irn, i);
771                         node_entry *o = get_irn_ne(pred, env);
772
773                         if (irn_not_visited(pred)) {
774                                 dfs(pred, env);
775                                 node->low = MIN(node->low, o->low);
776                         }
777                         if (o->DFSnum < node->DFSnum && o->in_stack)
778                                 node->low = MIN(o->DFSnum, node->low);
779                 }
780                 if (node->low == node->DFSnum) {
781                         scc *pscc = obstack_alloc(&env->obst, sizeof(*pscc));
782                         ir_node *x;
783
784                         pscc->head = NULL;
785                         do {
786                                 node_entry *e;
787
788                                 x = pop(env);
789                                 e = get_irn_ne(x, env);
790                                 e->pscc    = pscc;
791                                 e->next    = pscc->head;
792                                 pscc->head = x;
793                         } while (x != irn);
794
795                         env->process_scc(pscc, env);
796                 }
797         }
798 }
799
800 /**
801  * Do the DFS by starting at the End node of a graph.
802  *
803  * @param irg  the graph to process
804  * @param env  the environment
805  */
806 static void do_dfs(ir_graph *irg, iv_env *env) {
807         ir_graph *rem = current_ir_graph;
808         ir_node *end = get_irg_end(irg);
809         int i, n;
810
811         current_ir_graph = irg;
812         inc_irg_visited(irg);
813
814         /* visit all visible nodes */
815         dfs(end, env);
816
817         /* visit the keep-alives */
818         n = get_End_n_keepalives(end);
819         for (i = 0; i < n; ++i) {
820                 ir_node *ka = get_End_keepalive(end, i);
821
822                 if (irn_not_visited(ka))
823                         dfs(ka, env);
824         }
825
826         current_ir_graph = rem;
827 }
828
829 /**
830  * Post-block-walker: assign the post-order number.
831  */
832 static void assign_po(ir_node *block, void *ctx) {
833         iv_env *env = ctx;
834         node_entry *e = get_irn_ne(block, env);
835
836         e->POnum = env->POnum++;
837 }
838
839 #if 0
840 /**
841  * Follows the LFTR edges and return the last node in the chain.
842  *
843  * @param irn  the node that should be followed
844  * @param env  the IV environment
845  *
846  * @note
847  * In the current implementation only the last edge is stored, so
848  * only one chain exists. That's why we might miss some opportunities.
849  */
850 static ir_node *followEdges(ir_node *irn, iv_env *env) {
851         for (;;) {
852                 LFTR_edge *e = LFTR_find(irn, env);
853                 if (e)
854                         irn = e->dst;
855                 else
856                         return irn;
857         }
858 }
859
860 /**
861  * Apply one LFTR edge operation.
862  * Return NULL if the transformation cannot be done safely without
863  * an Overflow.
864  *
865  * @param rc   the IV node that should be translated
866  * @param e    the LFTR edge
867  * @param env  the IV environment
868  *
869  * @return the translated region constant or NULL
870  *         if the translation was not possible
871  *
872  * @note
873  * In the current implementation only the last edge is stored, so
874  * only one chain exists. That's why we might miss some opportunities.
875  */
876 static ir_node *applyOneEdge(ir_node *rc, LFTR_edge *e, iv_env *env) {
877         if (env->flags & osr_flag_lftr_with_ov_check) {
878                 tarval *tv_l, *tv_r, *tv;
879                 tarval_int_overflow_mode_t ovmode;
880
881                 /* overflow can only be decided for Consts */
882                 if (! is_Const(e->rc)) {
883                         DB((dbg, LEVEL_4, " = UNKNOWN (%+F)", e->rc));
884                         return NULL;
885                 }
886
887                 tv_l = get_Const_tarval(rc);
888                 tv_r = get_Const_tarval(e->rc);
889
890                 ovmode = tarval_get_integer_overflow_mode();
891                 tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
892
893                 switch (e->code) {
894                 case iro_Mul:
895                         tv = tarval_mul(tv_l, tv_r);
896                         DB((dbg, LEVEL_4, " * %+F", tv_r));
897                         break;
898                 case iro_Add:
899                         tv = tarval_add(tv_l, tv_r);
900                         DB((dbg, LEVEL_4, " + %+F", tv_r));
901                         break;
902                 case iro_Sub:
903                         tv = tarval_sub(tv_l, tv_r);
904                         DB((dbg, LEVEL_4, " - %+F", tv_r));
905                         break;
906                 default:
907                         assert(0);
908                         tv = tarval_bad;
909                 }
910                 tarval_set_integer_overflow_mode(ovmode);
911
912                 if (tv == tarval_bad) {
913                         DB((dbg, LEVEL_4, " = OVERFLOW"));
914                         return NULL;
915                 }
916                 return new_r_Const(current_ir_graph, get_irn_n(rc, -1), get_tarval_mode(tv), tv);
917         }
918         return do_apply(e->code, NULL, rc, e->rc, get_irn_mode(rc));
919 }
920
921 /**
922  * Applies the operations represented by the LFTR edges to a
923  * region constant and returns the value.
924  * Return NULL if the transformation cannot be done safely without
925  * an Overflow.
926  *
927  * @param iv   the IV node that starts the LFTR edge chain
928  * @param rc   the region constant that should be translated
929  * @param env  the IV environment
930  *
931  * @return the translated region constant or NULL
932  *         if the translation was not possible
933  */
934 static ir_node *applyEdges(ir_node *iv, ir_node *rc, iv_env *env) {
935         ir_node *irn = iv;
936
937         if (env->flags & osr_flag_lftr_with_ov_check) {
938                 /* overflow can only be decided for Consts */
939                 if (! is_Const(rc)) {
940                         DB((dbg, LEVEL_4, " = UNKNOWN (%+F)\n", rc));
941                         return NULL;
942                 }
943                 DB((dbg, LEVEL_4, "%+F", get_Const_tarval(rc)));
944         }
945
946         for (irn = iv; rc;) {
947                 LFTR_edge *e = LFTR_find(irn, env);
948                 if (e) {
949                         rc = applyOneEdge(rc, e, env);
950                         irn = e->dst;
951                 }
952                 else
953                         break;
954         }
955         DB((dbg, LEVEL_3, "\n"));
956         return rc;
957 }
958
959 /**
960  * Walker, finds Cmp(iv, rc) or Cmp(rc, iv)
961  * and tries to optimize them.
962  */
963 static void do_lftr(ir_node *cmp, void *ctx) {
964         iv_env *env = ctx;
965         ir_node *left, *right, *liv, *riv;
966         ir_node *iv, *rc;
967         ir_node *nleft = NULL, *nright = NULL;
968
969         if (get_irn_op(cmp) != op_Cmp)
970                 return;
971
972         left  = get_Cmp_left(cmp);
973         right = get_Cmp_right(cmp);
974
975         liv = is_iv(left, env);
976         riv = is_iv(right, env);
977         if (liv && is_rc(right, liv)) {
978                 iv = left; rc = right;
979
980                 nright = applyEdges(iv, rc, env);
981                 if (nright && nright != rc) {
982                         nleft = followEdges(iv, env);
983                 }
984         }
985         else if (riv && is_rc(left, riv)) {
986                 iv = right; rc = left;
987
988                 nleft = applyEdges(iv, rc, env);
989                 if (nleft && nleft != rc) {
990                         nright = followEdges(iv, env);
991                 }
992         }
993
994         if (nleft && nright) {
995                 DB((dbg, LEVEL_2, "  LFTR for %+F\n", cmp));
996                 set_Cmp_left(cmp, nleft);
997                 set_Cmp_right(cmp, nright);
998                 ++env->lftr_replaced;
999         }
1000 }
1001
1002 /**
1003  * do linear function test replacement.
1004  *
1005  * @param irg   the graph that should be optimized
1006  * @param env   the IV environment
1007  */
1008 static void lftr(ir_graph *irg, iv_env *env) {
1009         irg_walk_graph(irg, NULL, do_lftr, env);
1010 }
1011 #endif
1012
1013 /**
1014  * Pre-walker: set all node links to NULL and fix the
1015  * block of Proj nodes.
1016  */
1017 static void clear_and_fix(ir_node *irn, void *env)
1018 {
1019         set_irn_link(irn, NULL);
1020
1021         if (is_Proj(irn)) {
1022                 ir_node *pred = get_Proj_pred(irn);
1023                 set_irn_n(irn, -1, get_irn_n(pred, -1));
1024         }
1025 }
1026
1027 /* Performs Operator Strength Reduction for the passed graph. */
1028 void opt_osr(ir_graph *irg, unsigned flags) {
1029         iv_env   env;
1030         ir_graph *rem;
1031
1032         if (! get_opt_strength_red()) {
1033                 /* only kill Phi cycles  */
1034                 remove_phi_cycles(irg);
1035                 return;
1036         }
1037
1038         rem = current_ir_graph;
1039         current_ir_graph = irg;
1040
1041         FIRM_DBG_REGISTER(dbg, "firm.opt.osr");
1042
1043         DB((dbg, LEVEL_1, "Doing Operator Strength Reduction for %+F\n", irg));
1044
1045         obstack_init(&env.obst);
1046         env.stack         = NEW_ARR_F(ir_node *, 128);
1047         env.tos           = 0;
1048         env.nextDFSnum    = 0;
1049         env.POnum         = 0;
1050         env.quad_map      = new_set(quad_cmp, 64);
1051         env.lftr_edges    = new_set(LFTR_cmp, 64);
1052         env.replaced      = 0;
1053         env.lftr_replaced = 0;
1054         env.flags         = flags;
1055         env.process_scc   = process_scc;
1056
1057         /* Clear all links and move Proj nodes into the
1058            the same block as it's predecessors.
1059            This can improve the placement of new nodes.
1060          */
1061         irg_walk_graph(irg, NULL, clear_and_fix, NULL);
1062
1063         /* we need dominance */
1064         assure_doms(irg);
1065         assure_irg_outs(irg);
1066
1067         /* calculate the post order number for blocks. */
1068         irg_out_block_walk(get_irg_start_block(irg), NULL, assign_po, &env);
1069
1070         /* calculate the SCC's and drive OSR. */
1071         do_dfs(irg, &env);
1072
1073         if (env.replaced) {
1074                 /* try linear function test replacements */
1075                 //lftr(irg, &env);
1076
1077                 set_irg_outs_inconsistent(irg);
1078                 DB((dbg, LEVEL_1, "Replacements: %u + %u (lftr)\n\n", env.replaced, env.lftr_replaced));
1079         }
1080
1081         del_set(env.lftr_edges);
1082         del_set(env.quad_map);
1083         DEL_ARR_F(env.stack);
1084         obstack_free(&env.obst, NULL);
1085
1086         current_ir_graph = rem;
1087 }
1088
1089 /* Remove any Phi cycles with only one real input. */
1090 void remove_phi_cycles(ir_graph *irg) {
1091         iv_env   env;
1092         ir_graph *rem;
1093
1094         rem = current_ir_graph;
1095         current_ir_graph = irg;
1096
1097         FIRM_DBG_REGISTER(dbg, "firm.opt.remove_phi");
1098
1099         DB((dbg, LEVEL_1, "Doing Phi cycle removement for %+F\n", irg));
1100
1101         obstack_init(&env.obst);
1102         env.stack         = NEW_ARR_F(ir_node *, 128);
1103         env.tos           = 0;
1104         env.nextDFSnum    = 0;
1105         env.POnum         = 0;
1106         env.quad_map      = NULL;
1107         env.lftr_edges    = NULL;
1108         env.replaced      = 0;
1109         env.lftr_replaced = 0;
1110         env.flags         = 0;
1111         env.process_scc   = process_phi_only_scc;
1112
1113         /* Clear all links and move Proj nodes into the
1114            the same block as it's predecessors.
1115            This can improve the placement of new nodes.
1116          */
1117         irg_walk_graph(irg, NULL, clear_and_fix, NULL);
1118
1119         /* we need dominance */
1120         assure_irg_outs(irg);
1121
1122         /* calculate the post order number for blocks. */
1123         irg_out_block_walk(get_irg_start_block(irg), NULL, assign_po, &env);
1124
1125         /* calculate the SCC's and drive OSR. */
1126         do_dfs(irg, &env);
1127
1128         if (env.replaced) {
1129                 set_irg_outs_inconsistent(irg);
1130                 DB((dbg, LEVEL_1, "remove_phi_cycles: %u Cycles removed\n\n", env.replaced));
1131         }
1132
1133         DEL_ARR_F(env.stack);
1134         obstack_free(&env.obst, NULL);
1135
1136         current_ir_graph = rem;
1137 }