5927a37ea07b5d266e2e1f15bd7bfcfcec492592
[libfirm] / ir / opt / reassoc.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Reassociation
23  * @author  Michael Beck
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include "iropt_t.h"
29 #include "irnode_t.h"
30 #include "irgraph_t.h"
31 #include "irmode_t.h"
32 #include "ircons_t.h"
33 #include "irgmod.h"
34 #include "iropt_dbg.h"
35 #include "irflag_t.h"
36 #include "irgwalk.h"
37 #include "irouts.h"
38 #include "reassoc_t.h"
39 #include "opt_init.h"
40 #include "irhooks.h"
41 #include "irloop.h"
42 #include "pdeq.h"
43 #include "debug.h"
44 #include "irpass.h"
45
46 //#define NEW_REASSOC
47
48 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
49
50 typedef struct _walker_t {
51         int   changes;        /**< set, if a reassociation take place */
52         waitq *wq;            /**< a wait queue */
53 } walker_t;
54
55 typedef enum {
56         NO_CONSTANT   = 0,    /**< node is not constant */
57         REAL_CONSTANT = 1,    /**< node is a Const that is suitable for constant folding */
58         REGION_CONST  = 4     /**< node is a constant expression in the current context,
59                                    use 4 here to simplify implementation of get_comm_Binop_ops() */
60 } const_class_t;
61
62 /**
63  * returns whether a node is constant ie is a constant or
64  * is loop invariant (called region constant)
65  *
66  * @param n     the node to be checked for constant
67  * @param block a block that might be in a loop
68  */
69 static const_class_t get_const_class(const ir_node *n, const ir_node *block)
70 {
71         if (is_Const(n))
72                 return REAL_CONSTANT;
73
74         /* constant nodes which can't be folded are region constants */
75         if (is_irn_constlike(n))
76                 return REGION_CONST;
77
78         /*
79          * Beware: Bad nodes are always loop-invariant, but
80          * cannot handled in later code, so filter them here.
81          */
82         if (! is_Bad(n) && is_loop_invariant(n, block))
83                 return REGION_CONST;
84
85         return NO_CONSTANT;
86 }  /* get_const_class */
87
88 /**
89  * returns the operands of a commutative bin-op, if one operand is
90  * a region constant, it is returned as the second one.
91  *
92  * Beware: Real constants must be returned with higher priority than
93  * region constants, because they might be folded.
94  */
95 static void get_comm_Binop_ops(ir_node *binop, ir_node **a, ir_node **c)
96 {
97         ir_node *op_a = get_binop_left(binop);
98         ir_node *op_b = get_binop_right(binop);
99         ir_node *block = get_nodes_block(binop);
100         int class_a = get_const_class(op_a, block);
101         int class_b = get_const_class(op_b, block);
102
103         assert(is_op_commutative(get_irn_op(binop)));
104
105         switch (class_a + 2*class_b) {
106         case REAL_CONSTANT + 2*REAL_CONSTANT:
107                 /* if both are constants, one might be a
108                  * pointer constant like NULL, return the other
109                  */
110                 if (mode_is_reference(get_irn_mode(op_a))) {
111                         *a = op_a;
112                         *c = op_b;
113                 } else {
114                         *a = op_b;
115                         *c = op_a;
116                 }
117                 break;
118         case REAL_CONSTANT + 2*NO_CONSTANT:
119         case REAL_CONSTANT + 2*REGION_CONST:
120         case REGION_CONST  + 2*NO_CONSTANT:
121                 *a = op_b;
122                 *c = op_a;
123                 break;
124         default:
125                 *a = op_a;
126                 *c = op_b;
127                 break;
128         }
129 }  /* get_comm_Binop_ops */
130
131 /**
132  * reassociate a Sub: x - c = x + (-c)
133  */
134 static int reassoc_Sub(ir_node **in)
135 {
136         ir_node *n = *in;
137         ir_node *right = get_Sub_right(n);
138         ir_mode *rmode = get_irn_mode(right);
139         ir_node *block;
140
141         /* cannot handle SubIs(P, P) */
142         if (mode_is_reference(rmode))
143                 return 0;
144
145         block = get_nodes_block(n);
146
147         /* handles rule R6:
148          * convert x - c => x + (-c)
149          */
150         if (get_const_class(right, block) == REAL_CONSTANT) {
151                 ir_node *left  = get_Sub_left(n);
152                 ir_mode *mode;
153                 dbg_info *dbi;
154                 ir_node *irn;
155
156                 switch (get_const_class(left, block)) {
157                 case REAL_CONSTANT:
158                         irn = optimize_in_place(n);
159                         if (irn != n) {
160                                 exchange(n, irn);
161                                 *in = irn;
162                                 return 1;
163                         }
164                         return 0;
165                 case NO_CONSTANT:
166                         break;
167                 default:
168                         /* already constant, nothing to do */
169                         return 0;
170                 }
171
172                 mode = get_irn_mode(n);
173                 dbi  = get_irn_dbg_info(n);
174
175                 /* Beware of SubP(P, Is) */
176                 irn = new_rd_Minus(dbi, block, right, rmode);
177                 irn = new_rd_Add(dbi, block, left, irn, mode);
178
179                 DBG((dbg, LEVEL_5, "Applied: %n - %n => %n + (-%n)\n",
180                         get_Sub_left(n), right, get_Sub_left(n), right));
181
182                 if (n == irn)
183                         return 0;
184
185                 exchange(n, irn);
186                 *in = irn;
187
188                 return 1;
189         }
190         return 0;
191 }  /* reassoc_Sub */
192
193 /** Retrieve a mode from the operands. We need this, because
194  * Add and Sub are allowed to operate on (P, Is)
195  */
196 static ir_mode *get_mode_from_ops(ir_node *op1, ir_node *op2)
197 {
198         ir_mode *m1, *m2;
199
200         m1 = get_irn_mode(op1);
201         if (mode_is_reference(m1))
202                 return m1;
203
204         m2 = get_irn_mode(op2);
205         if (mode_is_reference(m2))
206                 return m2;
207
208         assert(m1 == m2);
209
210         return m1;
211 }  /* get_mode_from_ops */
212
213 #ifndef NEW_REASSOC
214
215 /**
216  * reassociate a commutative Binop
217  *
218  * BEWARE: this rule leads to a potential loop, if
219  * two operands are region constants and the third is a
220  * constant, so avoid this situation.
221  */
222 static int reassoc_commutative(ir_node **node)
223 {
224         ir_node *n     = *node;
225         ir_op   *op    = get_irn_op(n);
226         ir_node *block = get_nodes_block(n);
227         ir_node *t1, *c1;
228
229         get_comm_Binop_ops(n, &t1, &c1);
230
231         if (get_irn_op(t1) == op) {
232                 ir_node *t2, *c2;
233                 const_class_t c_c1, c_c2, c_t2;
234
235                 get_comm_Binop_ops(t1, &t2, &c2);
236
237                 /* do not optimize Bad nodes, will fail later */
238                 if (is_Bad(t2))
239                         return 0;
240
241                 c_c1 = get_const_class(c1, block);
242                 c_c2 = get_const_class(c2, block);
243                 c_t2 = get_const_class(t2, block);
244
245                 if ( ((c_c1 > NO_CONSTANT) & (c_t2 > NO_CONSTANT)) &&
246                      ((((c_c1 ^ c_c2 ^ c_t2) & REGION_CONST) == 0) || ((c_c1 & c_c2 & c_t2) == REGION_CONST)) ) {
247                         /* All three are constant and either all are constant expressions
248                          * or two of them are:
249                          * then applying this rule would lead into a cycle
250                          *
251                          * Note that if t2 is a constant so is c2 hence we save one test.
252                          */
253                         return 0;
254                 }
255
256                 if ((c_c1 != NO_CONSTANT) /* & (c_c2 != NO_CONSTANT) */) {
257                         /* handles rules R7, R8, R9, R10:
258                          * convert c1 .OP. (c2 .OP. x) => x .OP. (c1 .OP. c2)
259                          */
260                         ir_node *irn, *in[2];
261                         ir_mode *mode, *mode_c1 = get_irn_mode(c1), *mode_c2 = get_irn_mode(c2);
262
263                         /* It might happen, that c1 and c2 have different modes, for
264                          * instance Is and Iu.
265                          * Handle this here.
266                          */
267                         if (mode_c1 != mode_c2) {
268                                 if (mode_is_int(mode_c1) && mode_is_int(mode_c2)) {
269                                         /* get the bigger one */
270                                         if (get_mode_size_bits(mode_c1) > get_mode_size_bits(mode_c2))
271                                                 c2 = new_r_Conv(block, c2, mode_c1);
272                                         else if (get_mode_size_bits(mode_c1) < get_mode_size_bits(mode_c2))
273                                                 c1 = new_r_Conv(block, c1, mode_c2);
274                                         else {
275                                                 /* Try to cast the real const */
276                                                 if (c_c1 == REAL_CONSTANT)
277                                                         c1 = new_r_Conv(block, c1, mode_c2);
278                                                 else
279                                                         c2 = new_r_Conv(block, c2, mode_c1);
280                                         }
281                                 }
282                         }
283
284                         in[0] = c1;
285                         in[1] = c2;
286
287                         mode  = get_mode_from_ops(in[0], in[1]);
288                         in[1] = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
289                         in[0] = t2;
290
291                         mode = get_mode_from_ops(in[0], in[1]);
292                         irn   = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
293
294                         DBG((dbg, LEVEL_5, "Applied: %n .%s. (%n .%s. %n) => %n .%s. (%n .%s. %n)\n",
295                              c1, get_irn_opname(n), c2, get_irn_opname(n), t2,
296                              t2, get_irn_opname(n), c1, get_irn_opname(n), c2));
297                         /*
298                          * In some rare cases it can really happen that we get the same
299                          * node back. This might be happen in dead loops, were the Phi
300                          * nodes are already gone away. So check this.
301                          */
302                         if (n != irn) {
303                                 exchange(n, irn);
304                                 *node = irn;
305                                 return 1;
306                         }
307                 }
308         }
309         if (get_irn_op(c1) == op) {
310                 ir_node *t = c1;
311                 c1 = t1;
312                 t1 = t;
313         }
314         if (get_irn_op(t1) == op) {
315                 ir_node *l = get_binop_left(t1);
316                 ir_node *r = get_binop_right(t1);
317                 const_class_t c_r;
318
319                 if (r == c1) {
320                         ir_node *t = r;
321                         r = l;
322                         l = t;
323                 }
324                 c_r = get_const_class(r, block);
325                 if (c_r != NO_CONSTANT) {
326                         /*
327                          * Beware: don't do the following op if a constant was
328                          * placed below, else we will fall into a loop.
329                          */
330                         return 0;
331                 }
332
333                 if (l == c1) {
334                         /* convert x .OP. (x .OP. y) => y .OP. (x .OP. x) */
335                         ir_mode *mode_res = get_irn_mode(n);
336                         ir_mode *mode_c1  = get_irn_mode(c1);
337                         ir_node *irn, *in[2];
338
339                         in[0] = c1;
340                         in[1] = c1;
341
342                         in[1] = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode_c1, 2, in));
343                         in[0] = r;
344
345                         irn   = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode_res, 2, in));
346
347                         DBG((dbg, LEVEL_5, "Applied: %n .%s. (%n .%s. %n) => %n .%s. (%n .%s. %n)\n",
348                                 c1, get_irn_opname(n), l, get_irn_opname(n), r,
349                                 r, get_irn_opname(n), c1, get_irn_opname(n), c1));
350
351                         if (n != irn) {
352                                 exchange(n, irn);
353                                 *node = irn;
354                                 return 1;
355                         }
356                 }
357         }
358         return 0;
359 }  /* reassoc_commutative */
360
361 #else
362
363 static ir_op          *commutative_op;
364 static ir_node        *commutative_block;
365 static struct obstack  commutative_args;
366
367 static void collect_args(ir_node *node)
368 {
369         ir_node *left  = get_binop_left(node);
370         ir_node *right = get_binop_right(node);
371
372         if (get_irn_op(left) == commutative_op
373                         && (!get_irn_outs_computed(left) || get_irn_n_outs(left) == 1)) {
374                 collect_args(left);
375         } else {
376                 obstack_ptr_grow(&commutative_args, left);
377         }
378
379         if (get_irn_op(right) == commutative_op
380                         && (!get_irn_outs_computed(right) || get_irn_n_outs(right) == 1)) {
381                 collect_args(right);
382         } else {
383                 obstack_ptr_grow(&commutative_args, right);
384         }
385
386 #ifndef NDEBUG
387         {
388                 ir_mode *mode = get_irn_mode(node);
389                 if (is_Add(node) && mode_is_reference(mode)) {
390                         assert(get_irn_mode(left) == mode || get_irn_mode(right) == mode);
391                 } else {
392                         assert(get_irn_mode(left) == mode);
393                         assert(get_irn_mode(right) == mode);
394                 }
395         }
396 #endif
397 }
398
399 static int compare_nodes(const ir_node *node1, const ir_node *node2)
400 {
401         const_class_t class1 = get_const_class(node1, commutative_block);
402         const_class_t class2 = get_const_class(node2, commutative_block);
403
404         if (class1 == class2)
405                 return 0;
406         // return get_irn_idx(node1) - get_irn_idx(node2);
407
408         if (class1 < class2)
409                 return -1;
410
411         assert(class1 > class2);
412         return 1;
413 }
414
415 static int compare_node_ptr(const void *e1, const void *e2)
416 {
417         const ir_node *node1  = *((const ir_node *const*) e1);
418         const ir_node *node2  = *((const ir_node *const*) e2);
419         return compare_nodes(node1, node2);
420 }
421
422 static int reassoc_commutative(ir_node **n)
423 {
424         int       i;
425         int       n_args;
426         ir_node  *last;
427         ir_node **args;
428         ir_mode  *mode;
429         ir_node  *node = *n;
430
431         commutative_op    = get_irn_op(node);
432         commutative_block = get_nodes_block(node);
433
434         /* collect all nodes with same op type */
435         collect_args(node);
436
437         n_args = obstack_object_size(&commutative_args) / sizeof(ir_node*);
438         args   = obstack_finish(&commutative_args);
439
440         /* shortcut: in most cases there's nothing to do */
441         if (n_args == 2 && compare_nodes(args[0], args[1]) <= 0) {
442                 obstack_free(&commutative_args, args);
443                 return 0;
444         }
445
446         /* sort the arguments */
447         qsort(args, n_args, sizeof(ir_node*), compare_node_ptr);
448
449         /* build new tree */
450         last = args[n_args-1];
451         mode = get_irn_mode(last);
452         for (i = n_args-2; i >= 0; --i) {
453                 ir_mode *mode_right;
454                 ir_node *new_node;
455                 ir_node *in[2];
456
457                 in[0] = last;
458                 in[1] = args[i];
459
460                 /* AddP violates the assumption that all modes in args are equal...
461                  * we need some hacks to cope with this */
462                 mode_right = get_irn_mode(in[1]);
463                 if (mode_is_reference(mode_right)) {
464                         assert(is_Add(node) && mode_is_reference(get_irn_mode(node)));
465                         mode = get_irn_mode(in[1]);
466                 }
467                 if (mode_right != mode) {
468                         assert(is_Add(node) && mode_is_reference(get_irn_mode(node)));
469                         in[1] = new_r_Conv(current_ir_graph, commutative_block,in[1], mode);
470                 }
471
472                 /* TODO: produce useful debug info! */
473                 new_node = new_ir_node(NULL, current_ir_graph, commutative_block,
474                                        commutative_op, mode, 2, in);
475                 new_node = optimize_node(new_node);
476                 last     = new_node;
477         }
478
479         /* CSE often returns the old node again, only exchange if needed */
480         if (last != node) {
481                 exchange(node, last);
482                 *n = last;
483                 return 1;
484         }
485         return 0;
486 }
487
488 #endif
489
490 #define reassoc_Add  reassoc_commutative
491 #define reassoc_And  reassoc_commutative
492 #define reassoc_Or   reassoc_commutative
493 #define reassoc_Eor  reassoc_commutative
494
495 /**
496  * Reassociate using commutative law for Mul and distributive law for Mul and Add/Sub:
497  */
498 static int reassoc_Mul(ir_node **node)
499 {
500         ir_node *n = *node;
501         ir_node *add_sub, *c;
502         ir_op *op;
503
504         if (reassoc_commutative(&n))
505                 return 1;
506
507         get_comm_Binop_ops(n, &add_sub, &c);
508         op = get_irn_op(add_sub);
509
510         /* handles rules R11, R12, R13, R14, R15, R16, R17, R18, R19, R20 */
511         if (op == op_Add || op == op_Sub) {
512                 ir_mode *mode = get_irn_mode(n);
513                 ir_node *irn, *block, *t1, *t2, *in[2];
514
515                 block = get_nodes_block(n);
516                 t1 = get_binop_left(add_sub);
517                 t2 = get_binop_right(add_sub);
518
519                 /* we can only multiplication rules on integer arithmetic */
520                 if (mode_is_int(get_irn_mode(t1)) && mode_is_int(get_irn_mode(t2))) {
521                         in[0] = new_rd_Mul(NULL, block, c, t1, mode);
522                         in[1] = new_rd_Mul(NULL, block, c, t2, mode);
523
524                         irn   = optimize_node(new_ir_node(NULL, current_ir_graph, block, op, mode, 2, in));
525
526                         /* In some cases it might happen that the new irn is equal the old one, for
527                          * instance in:
528                          * (x - 1) * y == x * y - y
529                          * will be transformed back by simpler optimization
530                          * We could switch simple optimizations off, but this only happens iff y
531                          * is a loop-invariant expression and that it is not clear if the new form
532                          * is better.
533                          * So, we let the old one.
534                          */
535                         if (irn != n) {
536                                 DBG((dbg, LEVEL_5, "Applied: (%n .%s. %n) %n %n => (%n %n %n) .%s. (%n %n %n)\n",
537                                         t1, get_op_name(op), t2, n, c, t1, n, c, get_op_name(op), t2, n, c));
538                                 exchange(n, irn);
539                                 *node = irn;
540
541                                 return 1;
542                         }
543                 }
544         }
545         return 0;
546 }  /* reassoc_Mul */
547
548 /**
549  * Reassociate Shl. We transform Shl(x, const) into Mul's if possible.
550  */
551 static int reassoc_Shl(ir_node **node) {
552         ir_node *n = *node;
553         ir_node *c = get_Shl_right(n);
554         ir_node *x, *blk, *irn;
555         ir_mode *mode;
556         tarval *tv;
557
558         if (! is_Const(c))
559                 return 0;
560
561         x = get_Shl_left(n);
562         mode = get_irn_mode(x);
563
564         tv = get_mode_one(mode);
565         tv = tarval_shl(tv, get_Const_tarval(c));
566
567         if (tv == tarval_bad)
568                 return 0;
569
570         blk = get_nodes_block(n);
571         c   = new_Const(tv);
572         irn = new_rd_Mul(get_irn_dbg_info(n), blk, x, c, mode);
573
574         if (irn != n) {
575                 exchange(n, irn);
576                 *node = irn;
577                 return 1;
578         }
579         return 0;
580 }  /* reassoc_Shl */
581
582 /**
583  * The walker for the reassociation.
584  */
585 static void wq_walker(ir_node *n, void *env)
586 {
587         walker_t *wenv = env;
588
589         set_irn_link(n, NULL);
590         if (is_no_Block(n)) {
591                 ir_node *blk = get_nodes_block(n);
592
593                 if (is_Block_dead(blk) || get_Block_dom_depth(blk) < 0) {
594                         /* We are in a dead block, do not optimize or we may fall into an endless
595                            loop. We check this here instead of requiring that all dead blocks are removed
596                            which or cf_opt do not guarantee yet. */
597                         return;
598                 }
599                 waitq_put(wenv->wq, n);
600                 set_irn_link(n, wenv->wq);
601         }
602 }  /* wq_walker */
603
604 /**
605  * The walker for the reassociation.
606  */
607 static void do_reassociation(walker_t *wenv)
608 {
609         int i, res, changed;
610         ir_node *n, *blk;
611
612         while (! waitq_empty(wenv->wq)) {
613                 n = waitq_get(wenv->wq);
614                 set_irn_link(n, NULL);
615
616                 blk = get_nodes_block(n);
617                 if (is_Block_dead(blk) || get_Block_dom_depth(blk) < 0) {
618                         /* We are in a dead block, do not optimize or we may fall into an endless
619                            loop. We check this here instead of requiring that all dead blocks are removed
620                            which or cf_opt do not guarantee yet. */
621                         continue;
622                 }
623
624
625                 hook_reassociate(1);
626
627                 /* reassociation must run until a fixpoint is reached. */
628                 changed = 0;
629                 do {
630                         ir_op   *op    = get_irn_op(n);
631                         ir_mode *mode  = get_irn_mode(n);
632
633                         res = 0;
634
635                         /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
636                         if (mode_is_float(mode) && get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)
637                                 break;
638
639                         if (op->ops.reassociate) {
640                                 res = op->ops.reassociate(&n);
641
642                                 changed |= res;
643                         }
644                 } while (res == 1);
645                 hook_reassociate(0);
646
647                 wenv->changes |= changed;
648
649                 if (changed) {
650                         for (i = get_irn_arity(n) - 1; i >= 0; --i) {
651                                 ir_node *pred = get_irn_n(n, i);
652
653                                 if (get_irn_link(pred) != wenv->wq) {
654                                         waitq_put(wenv->wq, pred);
655                                         set_irn_link(pred, wenv->wq);
656                                 }
657                         }
658                 }
659         }
660 }  /* do_reassociation */
661
662 /**
663  * Returns the earliest were a,b are available.
664  * Note that we know that a, b both dominate
665  * the block of the previous operation, so one must dominate the other.
666  *
667  * If the earliest block is the start block, return curr_blk instead
668  */
669 static ir_node *earliest_block(ir_node *a, ir_node *b, ir_node *curr_blk) {
670         ir_node *blk_a = get_nodes_block(a);
671         ir_node *blk_b = get_nodes_block(b);
672         ir_node *res;
673
674         /* if blk_a != blk_b, one must dominate the other */
675         if (block_dominates(blk_a, blk_b))
676                 res = blk_b;
677         else
678                 res = blk_a;
679         if (res == get_irg_start_block(current_ir_graph))
680                 return curr_blk;
681         return res;
682 }  /* earliest_block */
683
684 /**
685  * Checks whether a node is a Constant expression.
686  * The following trees are constant expressions:
687  *
688  * Const, SymConst, Const + SymConst
689  *
690  * Handling SymConsts as const might be not a good idea for all
691  * architectures ...
692  */
693 static int is_constant_expr(ir_node *irn) {
694         ir_op *op;
695
696         switch (get_irn_opcode(irn)) {
697         case iro_Const:
698         case iro_SymConst:
699                 return 1;
700         case iro_Add:
701                 op = get_irn_op(get_Add_left(irn));
702                 if (op != op_Const && op != op_SymConst)
703                         return 0;
704                 op = get_irn_op(get_Add_right(irn));
705                 if (op != op_Const && op != op_SymConst)
706                         return 0;
707                 return 1;
708         default:
709                 return 0;
710         }
711 }  /* is_constant_expr */
712
713 /**
714  * Apply distributive Law for Mul and Add/Sub
715  */
716 static int reverse_rule_distributive(ir_node **node) {
717         ir_node *n = *node;
718         ir_node *left  = get_binop_left(n);
719         ir_node *right = get_binop_right(n);
720         ir_node *x, *blk, *curr_blk;
721         ir_node *a, *b, *irn;
722         ir_op *op;
723         ir_mode *mode;
724         dbg_info *dbg;
725
726         op = get_irn_op(left);
727         if (op != get_irn_op(right))
728                 return 0;
729
730         if (op == op_Shl) {
731                 x = get_Shl_right(left);
732
733                 if (x == get_Shl_right(right)) {
734                         /* (a << x) +/- (b << x) ==> (a +/- b) << x */
735                         a = get_Shl_left(left);
736                         b = get_Shl_left(right);
737                         goto transform;
738                 }
739         } else if (op == op_Mul) {
740                 x = get_Mul_left(left);
741
742                 if (x == get_Mul_left(right)) {
743                         /* (x * a) +/- (x * b) ==> (a +/- b) * x */
744                         a = get_Mul_right(left);
745                         b = get_Mul_right(right);
746                         goto transform;
747                 } else if (x == get_Mul_right(right)) {
748                         /* (x * a) +/- (b * x) ==> (a +/- b) * x */
749                         a = get_Mul_right(left);
750                         b = get_Mul_left(right);
751                         goto transform;
752                 }
753
754                 x = get_Mul_right(left);
755
756                 if (x == get_Mul_right(right)) {
757                         /* (a * x) +/- (b * x) ==> (a +/- b) * x */
758                         a = get_Mul_left(left);
759                         b = get_Mul_left(right);
760                         goto transform;
761                 } else if (x == get_Mul_left(right)) {
762                         /* (a * x) +/- (x * b) ==> (a +/- b) * x */
763                         a = get_Mul_left(left);
764                         b = get_Mul_right(right);
765                         goto transform;
766                 }
767         }
768         return 0;
769
770 transform:
771         curr_blk = get_nodes_block(n);
772
773         blk = earliest_block(a, b, curr_blk);
774
775         dbg  = get_irn_dbg_info(n);
776         mode = get_irn_mode(n);
777
778         if (is_Add(n))
779                 irn = new_rd_Add(dbg, blk, a, b, mode);
780         else
781                 irn = new_rd_Sub(dbg, blk, a, b, mode);
782
783         blk  = earliest_block(irn, x, curr_blk);
784
785         if (op == op_Mul)
786                 irn = new_rd_Mul(dbg, blk, irn, x, mode);
787         else
788                 irn = new_rd_Shl(dbg, blk, irn, x, mode);
789
790         exchange(n, irn);
791         *node = irn;
792         return 1;
793 }  /* reverse_rule_distributive */
794
795 /**
796  * Move Constants towards the root.
797  */
798 static int move_consts_up(ir_node **node) {
799         ir_node *n = *node;
800         ir_op *op;
801         ir_node *l, *r, *a, *b, *c, *blk, *irn, *in[2];
802         ir_mode *mode, *ma, *mb;
803         dbg_info *dbg;
804
805         l = get_binop_left(n);
806         r = get_binop_right(n);
807
808         /* check if one is already a constant expression */
809         if (is_constant_expr(l) || is_constant_expr(r))
810                 return 0;
811
812         dbg = get_irn_dbg_info(n);
813         op = get_irn_op(n);
814         if (get_irn_op(l) == op) {
815                 /* (a .op. b) .op. r */
816                 a = get_binop_left(l);
817                 b = get_binop_right(l);
818
819                 if (is_constant_expr(a)) {
820                         /* (C .op. b) .op. r ==> (r .op. b) .op. C */
821                         c = a;
822                         a = r;
823                         blk = get_nodes_block(l);
824                         dbg = dbg == get_irn_dbg_info(l) ? dbg : NULL;
825                         goto transform;
826                 } else if (is_constant_expr(b)) {
827                         /* (a .op. C) .op. r ==> (a .op. r) .op. C */
828                         c = b;
829                         b = r;
830                         blk = get_nodes_block(l);
831                         dbg = dbg == get_irn_dbg_info(l) ? dbg : NULL;
832                         goto transform;
833                 }
834         }
835         if (get_irn_op(r) == op) {
836                 /* l .op. (a .op. b) */
837                 a = get_binop_left(r);
838                 b = get_binop_right(r);
839
840                 if (is_constant_expr(a)) {
841                         /* l .op. (C .op. b) ==> (l .op. b) .op. C */
842                         c = a;
843                         a = l;
844                         blk = get_nodes_block(r);
845                         dbg = dbg == get_irn_dbg_info(r) ? dbg : NULL;
846                         goto transform;
847                 } else if (is_constant_expr(b)) {
848                         /* l .op. (a .op. C) ==> (a .op. l) .op. C */
849                         c = b;
850                         b = l;
851                         blk = get_nodes_block(r);
852                         dbg = dbg == get_irn_dbg_info(r) ? dbg : NULL;
853                         goto transform;
854                 }
855         }
856         return 0;
857
858 transform:
859         /* In some cases a and b might be both of different integer mode, and c a SymConst.
860          * in that case we could either
861          * 1.) cast into unsigned mode
862          * 2.) ignore
863          * we implement the second here
864          */
865         ma = get_irn_mode(a);
866         mb = get_irn_mode(b);
867         if (ma != mb && mode_is_int(ma) && mode_is_int(mb))
868                 return 0;
869
870         /* check if (a .op. b) can be calculated in the same block is the old instruction */
871         if (! block_dominates(get_nodes_block(a), blk))
872                 return 0;
873         if (! block_dominates(get_nodes_block(b), blk))
874                 return 0;
875         /* ok */
876         in[0] = a;
877         in[1] = b;
878
879         mode = get_mode_from_ops(a, b);
880         in[0] = irn = optimize_node(new_ir_node(dbg, current_ir_graph, blk, op, mode, 2, in));
881
882         /* beware: optimize_node might have changed the opcode, check again */
883         if (is_Add(irn) || is_Sub(irn)) {
884                 reverse_rule_distributive(&in[0]);
885         }
886         in[1] = c;
887
888         mode = get_mode_from_ops(in[0], in[1]);
889         irn = optimize_node(new_ir_node(dbg, current_ir_graph, blk, op, mode, 2, in));
890
891         exchange(n, irn);
892         *node = irn;
893         return 1;
894 }  /* move_consts_up */
895
896 /**
897  * Apply the rules in reverse order, removing code that was not collapsed
898  */
899 static void reverse_rules(ir_node *node, void *env) {
900         walker_t *wenv = env;
901         ir_mode *mode = get_irn_mode(node);
902         int res;
903
904         /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */
905         if (mode_is_float(mode) && get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)
906                 return;
907
908         do {
909                 ir_op *op = get_irn_op(node);
910
911                 res = 0;
912                 if (is_op_commutative(op)) {
913                         wenv->changes |= res = move_consts_up(&node);
914                 }
915                 /* beware: move_consts_up might have changed the opcode, check again */
916                 if (is_Add(node) || is_Sub(node)) {
917                         wenv->changes |= res = reverse_rule_distributive(&node);
918                 }
919         } while (res);
920 }
921
922 /*
923  * do the reassociation
924  */
925 int optimize_reassociation(ir_graph *irg)
926 {
927         walker_t env;
928         irg_loopinfo_state state;
929         ir_graph *rem;
930
931         assert(get_irg_phase_state(irg) != phase_building);
932         assert(get_irg_pinned(irg) != op_pin_state_floats &&
933                 "Reassociation needs pinned graph to work properly");
934
935         rem = current_ir_graph;
936         current_ir_graph = irg;
937
938         /* we use dominance to detect dead blocks */
939         assure_doms(irg);
940
941 #ifdef NEW_REASSOC
942         assure_irg_outs(irg);
943         obstack_init(&commutative_args);
944 #endif
945
946         /*
947          * Calculate loop info, so we could identify loop-invariant
948          * code and threat it like a constant.
949          * We only need control flow loops here but can handle generic
950          * INTRA info as well.
951          */
952         state = get_irg_loopinfo_state(irg);
953         if ((state & loopinfo_inter) ||
954                 (state & (loopinfo_constructed | loopinfo_valid)) != (loopinfo_constructed | loopinfo_valid))
955                 construct_cf_backedges(irg);
956
957         env.changes = 0;
958         env.wq      = new_waitq();
959
960         /* disable some optimizations while reassoc is running to prevent endless loops */
961         set_reassoc_running(1);
962         {
963                 /* now we have collected enough information, optimize */
964                 irg_walk_graph(irg, NULL, wq_walker, &env);
965                 do_reassociation(&env);
966
967                 /* reverse those rules that do not result in collapsed constants */
968                 irg_walk_graph(irg, NULL, reverse_rules, &env);
969         }
970         set_reassoc_running(0);
971
972         /* Handle graph state */
973         if (env.changes) {
974                 set_irg_outs_inconsistent(irg);
975                 set_irg_loopinfo_inconsistent(irg);
976         }
977
978 #ifdef NEW_REASSOC
979         obstack_free(&commutative_args, NULL);
980 #endif
981
982         del_waitq(env.wq);
983         current_ir_graph = rem;
984         return env.changes;
985 }  /* optimize_reassociation */
986
987 /* create a pass for the reassociation */
988 ir_graph_pass_t *optimize_reassociation_pass(const char *name) {
989         return def_graph_pass_ret(name ? name : "reassoc", optimize_reassociation);
990 }  /* optimize_reassociation_pass */
991
992 /* Sets the default reassociation operation for an ir_op_ops. */
993 ir_op_ops *firm_set_default_reassoc(ir_opcode code, ir_op_ops *ops)
994 {
995 #define CASE(a) case iro_##a: ops->reassociate  = reassoc_##a; break
996
997         switch (code) {
998         CASE(Mul);
999         CASE(Add);
1000         CASE(Sub);
1001         CASE(And);
1002         CASE(Or);
1003         CASE(Eor);
1004         CASE(Shl);
1005         default:
1006                 /* leave NULL */;
1007         }
1008
1009         return ops;
1010 #undef CASE
1011 }  /* firm_set_default_reassoc */
1012
1013 /* initialize the reassociation by adding operations to some opcodes */
1014 void firm_init_reassociation(void)
1015 {
1016         FIRM_DBG_REGISTER(dbg, "firm.opt.reassoc");
1017 }  /* firm_init_reassociation */