also do unreachable code elimination during gcse
[libfirm] / ir / opt / fp-vrp.c
1 /*
2  * Copyright (C) 1995-2010 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   Data-flow driven minimal fixpoint value range propagation
23  * @author  Christoph Mallon
24  * @version $Id$
25  */
26 #include "config.h"
27
28 #include "adt/pdeq.h"
29 #include "adt/obst.h"
30 #include "adt/xmalloc.h"
31 #include "debug.h"
32 #include "ircons.h"
33 #include "irdom.h"
34 #include "iredges.h"
35 #include "irgmod.h"
36 #include "irgraph.h"
37 #include "irgwalk.h"
38 #include "irnode.h"
39 #include "iroptimize.h"
40 #include "irtools.h"
41 #include "tv.h"
42 #include "irpass.h"
43 #include "irmemory.h"
44
45 /* TODO:
46  * - Implement cleared/set bit calculation for Add, Sub, Minus, Mul, Div, Mod, Shl, Shr, Shrs, Rotl
47  * - Implement min/max calculation for And, Eor, Or, Not, Conv, Shl, Shr, Shrs, Rotl, Mux
48  * - Implement min/max calculation for Add, Sub, Minus, Mul, Div, Mod, Conv, Shl, Shr, Shrs, Rotl, Mux
49  */
50
51 /* Tables of the cleared/set bit lattice
52  *
53  * Encoding of the lattice
54  * zo
55  * 00 0 zero
56  * 01 - impossible state, is zero /and/ one
57  * 10 T top, may be either zero or one
58  * 11 1 one
59  *
60  * S = Sum
61  * c = Carry
62  * D = Difference
63  * b = Borrow
64  *
65  * Not
66  * A ~
67  * 0 1
68  * 1 0
69  * T T
70  *
71  * Half adder, half subtractor, and, xor, or, Mux
72  * AB  Sc  Db  &  ^  |  M
73  * 00  00  00  0  0  0  0
74  * 01  10  11  0  1  1  T
75  * 0T  T0  TT  0  T  T  T
76  * 10  10  10  0  1  1  T
77  * 11  01  00  1  0  1  1
78  * 1T  TT  T0  T  T  1  T
79  * T0  T0  T0  0  T  T  T
80  * T1  TT  TT  T  T  1  T
81  * TT  TT  TT  T  T  T  T
82  *
83  * Full adder, full subtractor
84  * ABc-1  Sc  Db
85  * 000    00  00
86  * 001    10  11
87  * 00T    T0  TT
88  * 010    10  11
89  * 011    01  01
90  * 01T    TT  T1
91  * 0T0    T0  TT
92  * 0T1    TT  T1
93  * 0TT    TT  TT
94  * 100    10  10
95  * 101    01  00
96  * 10T    TT  T0
97  * 110    01  00
98  * 111    11  11
99  * 11T    T1  TT
100  * 1T0    TT  T0
101  * 1T1    T1  TT
102  * 1TT    TT  TT
103  * T00    T0  T0
104  * T01    TT  TT
105  * T0T    TT  TT
106  * T10    TT  TT
107  * T11    T1  T1
108  * T1T    TT  TT
109  * TT0    TT  TT
110  * TT1    TT  TT
111  * TTT    TT  TT
112  *
113  *
114  * Assume: Xmin <= Xmax and no overflow
115  * A + B = (Amin + Bmin, Amax + Bmax)
116  *    -A = (-Amax, -Amin)
117  * A - B = A + -B = (Amin (-B)min, Amax + (-B)max) = (Amin - Bmax, Amax - Bmin)
118  */
119
120 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
121
122 static struct obstack obst;
123
124 typedef struct bitinfo
125 {
126         ir_tarval* z; // safe zeroes, 0 = bit is zero,       1 = bit maybe is 1
127         ir_tarval* o; // safe ones,   0 = bit maybe is zero, 1 = bit is 1
128 } bitinfo;
129
130 typedef struct environment_t {
131         unsigned modified:1;     /**< Set, if the graph was modified. */
132 } environment_t;
133
134 static inline bitinfo* get_bitinfo(ir_node const* const irn)
135 {
136         return (bitinfo*)get_irn_link(irn);
137 }
138
139 static int set_bitinfo(ir_node* const irn, ir_tarval* const z, ir_tarval* const o)
140 {
141         bitinfo* b = get_bitinfo(irn);
142         if (b == NULL) {
143                 b = OALLOCZ(&obst, bitinfo);
144                 set_irn_link(irn, b);
145         } else if (z == b->z && o == b->o) {
146                 return 0;
147         }
148         b->z = z;
149         b->o = o;
150         DB((dbg, LEVEL_3, "%+F: 0:%T 1:%T\n", irn, z, o));
151         return 1;
152 }
153
154 static int mode_is_intb(ir_mode const* const m)
155 {
156         return mode_is_int(m) || m == mode_b;
157 }
158
159 static int transfer(ir_node* const irn)
160 {
161         ir_mode* const m = get_irn_mode(irn);
162         ir_tarval*     z;
163         ir_tarval*     o;
164
165         if (m == mode_X) {
166                 ir_tarval* const f = get_tarval_b_false();
167                 bitinfo*   const b = get_bitinfo(get_nodes_block(irn));
168
169                 DB((dbg, LEVEL_3, "transfer %+F\n", irn));
170
171                 if (b->z == f && b->o == f) {
172                         z = f;
173                         o = f;
174                 } else switch (get_irn_opcode(irn)) {
175                         case iro_Proj: {
176                                 ir_node* const pred = get_Proj_pred(irn);
177                                 if (is_Start(pred)) {
178                                         goto result_unknown_X;
179                                 } else if (is_Cond(pred)) {
180                                         ir_node*   const selector = get_Cond_selector(pred);
181                                         bitinfo*   const b        = get_bitinfo(selector);
182                                         ir_tarval* const bz       = b->z;
183                                         ir_tarval* const bo       = b->o;
184                                         if (get_irn_mode(selector) == mode_b) {
185                                                 if (bz == bo) {
186                                                         if ((bz == get_tarval_b_true()) == get_Proj_proj(irn)) {
187                                                                 z = o = get_tarval_b_true();
188                                                         } else {
189                                                                 z = o = get_tarval_b_false();
190                                                         }
191                                                 } else {
192                                                         goto result_unknown_X;
193                                                 }
194                                         } else {
195                                                 long const val = get_Proj_proj(irn);
196                                                 if (val != get_Cond_default_proj(pred)) {
197                                                         ir_tarval* const tv = new_tarval_from_long(val, get_irn_mode(selector));
198                                                         if (!tarval_is_null(tarval_andnot(tv, bz)) ||
199                                                                         !tarval_is_null(tarval_andnot(bo, tv))) {
200                                                                 // At least one bit differs.
201                                                                 z = o = get_tarval_b_false();
202 #if 0 // TODO must handle default Proj
203                                                         } else if (bz == bo && bz == tv) {
204                                                                 z = o = get_tarval_b_true();
205 #endif
206                                                         } else {
207                                                                 goto result_unknown_X;
208                                                         }
209                                                 } else {
210                                                         goto cannot_analyse_X;
211                                                 }
212                                         }
213                                 } else {
214                                         goto cannot_analyse_X;
215                                 }
216                                 break;
217                         }
218
219                         case iro_Jmp:
220                                 goto result_unknown_X;
221
222                         default:
223 cannot_analyse_X:
224                                 DB((dbg, LEVEL_4, "cannot analyse %+F\n", irn));
225 result_unknown_X:
226                                 z = get_tarval_b_true();
227                                 o = get_tarval_b_false();
228                                 break;
229                 }
230         } else if (is_Block(irn)) {
231                 int       reachable = 0;
232                 int const arity     = get_Block_n_cfgpreds(irn);
233                 int       i;
234
235                 DB((dbg, LEVEL_3, "transfer %+F\n", irn));
236                 for (i = 0; i != arity; ++i) {
237                         bitinfo* const b = get_bitinfo(get_Block_cfgpred(irn, i));
238                         if (b != NULL && b->z == get_tarval_b_true()) {
239                                 reachable = 1;
240                                 break;
241                         }
242                 }
243
244                 if (!reachable) {
245                         ir_graph *const irg = get_Block_irg(irn);
246                         reachable =
247                                 irn == get_irg_start_block(irg) ||
248                                 irn == get_irg_end_block(irg);
249                 }
250
251                 o = get_tarval_b_false();
252                 z = reachable ? get_tarval_b_true() : o;
253         } else if (mode_is_intb(m)) {
254                 DB((dbg, LEVEL_3, "transfer %+F\n", irn));
255                 switch (get_irn_opcode(irn)) {
256                         case iro_Const: {
257                                 z = o = get_Const_tarval(irn);
258                                 break;
259                         }
260
261                         case iro_Confirm: {
262                                 ir_node* const v = get_Confirm_value(irn);
263                                 bitinfo* const b = get_bitinfo(v);
264                                 /* TODO Use bound and relation. */
265                                 z = b->z;
266                                 o = b->o;
267                                 break;
268                         }
269
270                         case iro_Shl: {
271                                 bitinfo*   const l  = get_bitinfo(get_Shl_left(irn));
272                                 bitinfo*   const r  = get_bitinfo(get_Shl_right(irn));
273                                 ir_tarval* const rz = r->z;
274                                 if (rz == r->o) {
275                                         z = tarval_shl(l->z, rz);
276                                         o = tarval_shl(l->o, rz);
277                                 } else {
278                                         goto cannot_analyse;
279                                 }
280                                 break;
281                         }
282
283                         case iro_Shr: {
284                                 bitinfo*   const l  = get_bitinfo(get_Shr_left(irn));
285                                 bitinfo*   const r  = get_bitinfo(get_Shr_right(irn));
286                                 ir_tarval* const rz = r->z;
287                                 if (rz == r->o) {
288                                         z = tarval_shr(l->z, rz);
289                                         o = tarval_shr(l->o, rz);
290                                 } else {
291                                         goto cannot_analyse;
292                                 }
293                                 break;
294                         }
295
296                         case iro_Shrs: {
297                                 bitinfo*   const l  = get_bitinfo(get_Shrs_left(irn));
298                                 bitinfo*   const r  = get_bitinfo(get_Shrs_right(irn));
299                                 ir_tarval* const rz = r->z;
300                                 if (rz == r->o) {
301                                         z = tarval_shrs(l->z, rz);
302                                         o = tarval_shrs(l->o, rz);
303                                 } else {
304                                         goto cannot_analyse;
305                                 }
306                                 break;
307                         }
308
309                         case iro_Rotl: {
310                                 bitinfo*   const l  = get_bitinfo(get_Rotl_left(irn));
311                                 bitinfo*   const r  = get_bitinfo(get_Rotl_right(irn));
312                                 ir_tarval* const rz = r->z;
313                                 if (rz == r->o) {
314                                         z = tarval_rotl(l->z, rz);
315                                         o = tarval_rotl(l->o, rz);
316                                 } else {
317                                         goto cannot_analyse;
318                                 }
319                                 break;
320                         }
321
322                         case iro_Add: {
323                                 bitinfo*   const l  = get_bitinfo(get_Add_left(irn));
324                                 bitinfo*   const r  = get_bitinfo(get_Add_right(irn));
325                                 ir_tarval* const lz = l->z;
326                                 ir_tarval* const lo = l->o;
327                                 ir_tarval* const rz = r->z;
328                                 ir_tarval* const ro = r->o;
329                                 if (lz == lo && rz == ro) {
330                                         z = o = tarval_add(lz, rz);
331                                 } else {
332                                         // TODO improve: can only do lower disjoint bits
333                                         /* Determine where any of the operands has zero bits, i.e. where no
334                                          * carry out is generated if there is not carry in */
335                                         ir_tarval* const no_c_in_no_c_out = tarval_and(lz, rz);
336                                         /* Generate a mask of the lower consecutive zeroes: x | -x.  In this
337                                          * range the addition is disjoint and therefore Add behaves like Or.
338                                          */
339                                         ir_tarval* const low_zero_mask = tarval_or(no_c_in_no_c_out, tarval_neg(no_c_in_no_c_out));
340                                         ir_tarval* const low_one_mask  = tarval_not(low_zero_mask);
341                                         z = tarval_or( tarval_or(lz, rz), low_zero_mask);
342                                         o = tarval_and(tarval_or(lo, ro), low_one_mask);
343                                 }
344                                 break;
345                         }
346
347                         case iro_Sub: {
348                                 bitinfo* const l = get_bitinfo(get_Sub_left(irn));
349                                 bitinfo* const r = get_bitinfo(get_Sub_right(irn));
350                                 if (l != NULL && r != NULL) { // Sub might subtract pointers.
351                                         ir_tarval* const lz = l->z;
352                                         ir_tarval* const lo = l->o;
353                                         ir_tarval* const rz = r->z;
354                                         ir_tarval* const ro = r->o;
355                                         if (lz == lo && rz == ro) {
356                                                 z = o = tarval_sub(lz, rz, NULL);
357                                         } else if (tarval_is_null(tarval_andnot(rz, lo))) {
358                                                 /* Every possible one of the subtrahend is backed by a safe one of the
359                                                  * minuend, i.e. there are no borrows. */
360                                                 // TODO extend no-borrow like carry for Add above
361                                                 z = tarval_andnot(lz, ro);
362                                                 o = tarval_andnot(lo, rz);
363                                         } else {
364                                                 goto cannot_analyse;
365                                         }
366                                 } else {
367                                         goto cannot_analyse;
368                                 }
369                                 break;
370                         }
371
372                         case iro_Mul: {
373                                 bitinfo*   const l  = get_bitinfo(get_Mul_left(irn));
374                                 bitinfo*   const r  = get_bitinfo(get_Mul_right(irn));
375                                 ir_tarval* const lz = l->z;
376                                 ir_tarval* const lo = l->o;
377                                 ir_tarval* const rz = r->z;
378                                 ir_tarval* const ro = r->o;
379                                 if (lz == lo && rz == ro) {
380                                         z = o = tarval_mul(lz, rz);
381                                 } else {
382                                         // TODO improve
383                                         // Determine safe lower zeroes: x | -x.
384                                         ir_tarval* const lzn = tarval_or(lz, tarval_neg(lz));
385                                         ir_tarval* const rzn = tarval_or(rz, tarval_neg(rz));
386                                         // Concatenate safe lower zeroes.
387                                         if (tarval_cmp(lzn, rzn) == ir_relation_less) {
388                                                 z = tarval_mul(tarval_eor(lzn, tarval_shl(lzn, get_tarval_one(m))), rzn);
389                                         } else {
390                                                 z = tarval_mul(tarval_eor(rzn, tarval_shl(rzn, get_tarval_one(m))), lzn);
391                                         }
392                                         o = get_tarval_null(m);
393                                 }
394                                 break;
395                         }
396
397                         case iro_Minus: {
398                                 bitinfo* const b = get_bitinfo(get_Minus_op(irn));
399                                 if (b->z == b->o) {
400                                         z = o = tarval_neg(b->z);
401                                 } else {
402                                         goto cannot_analyse;
403                                 }
404                                 break;
405                         }
406
407                         case iro_And: {
408                                 bitinfo* const l = get_bitinfo(get_And_left(irn));
409                                 bitinfo* const r = get_bitinfo(get_And_right(irn));
410                                 z = tarval_and(l->z, r->z);
411                                 o = tarval_and(l->o, r->o);
412                                 break;
413                         }
414
415                         case iro_Or: {
416                                 bitinfo* const l = get_bitinfo(get_Or_left(irn));
417                                 bitinfo* const r = get_bitinfo(get_Or_right(irn));
418                                 z = tarval_or(l->z, r->z);
419                                 o = tarval_or(l->o, r->o);
420                                 break;
421                         }
422
423                         case iro_Eor: {
424                                 bitinfo*   const l  = get_bitinfo(get_Eor_left(irn));
425                                 bitinfo*   const r  = get_bitinfo(get_Eor_right(irn));
426                                 ir_tarval* const lz = l->z;
427                                 ir_tarval* const lo = l->o;
428                                 ir_tarval* const rz = r->z;
429                                 ir_tarval* const ro = r->o;
430                                 z = tarval_or(tarval_andnot(lz, ro), tarval_andnot(rz, lo));
431                                 o = tarval_or(tarval_andnot(ro, lz), tarval_andnot(lo, rz));
432                                 break;
433                         }
434
435                         case iro_Not: {
436                                 bitinfo* const b = get_bitinfo(get_Not_op(irn));
437                                 z = tarval_not(b->o);
438                                 o = tarval_not(b->z);
439                                 break;
440                         }
441
442                         case iro_Conv: {
443                                 bitinfo* const b = get_bitinfo(get_Conv_op(irn));
444                                 if (b == NULL) // Happens when converting from float values.
445                                         goto result_unknown;
446                                 z = tarval_convert_to(b->z, m);
447                                 o = tarval_convert_to(b->o, m);
448                                 break;
449                         }
450
451                         case iro_Mux: {
452                                 bitinfo* const f = get_bitinfo(get_Mux_false(irn));
453                                 bitinfo* const t = get_bitinfo(get_Mux_true(irn));
454                                 bitinfo* const c = get_bitinfo(get_Mux_sel(irn));
455                                 if (c->o == get_tarval_b_true()) {
456                                         z = t->z;
457                                         o = t->o;
458                                 } else if (c->z == get_tarval_b_false()) {
459                                         z = f->z;
460                                         o = f->o;
461                                 } else {
462                                         z = tarval_or( f->z, t->z);
463                                         o = tarval_and(f->o, t->o);
464                                 }
465                                 break;
466                         }
467
468                         case iro_Phi: {
469                                 ir_node* const block = get_nodes_block(irn);
470                                 int      const arity = get_Phi_n_preds(irn);
471                                 int            i;
472
473                                 z = get_tarval_null(m);
474                                 o = get_tarval_all_one(m);
475                                 for (i = 0; i != arity; ++i) {
476                                         bitinfo* const b_cfg = get_bitinfo(get_Block_cfgpred(block, i));
477                                         if (b_cfg != NULL && b_cfg->z != get_tarval_b_false()) {
478                                                 bitinfo* const b = get_bitinfo(get_Phi_pred(irn, i));
479                                                 z = tarval_or( z, b->z);
480                                                 o = tarval_and(o, b->o);
481                                         }
482                                 }
483                                 break;
484                         }
485
486                         case iro_Cmp: {
487                                 bitinfo* const l = get_bitinfo(get_Cmp_left(irn));
488                                 bitinfo* const r = get_bitinfo(get_Cmp_right(irn));
489                                 if (l == NULL || r == NULL) {
490                                         goto result_unknown; // Cmp compares something we cannot evaluate.
491                                 } else {
492                                         ir_tarval*  const lz       = l->z;
493                                         ir_tarval*  const lo       = l->o;
494                                         ir_tarval*  const rz       = r->z;
495                                         ir_tarval*  const ro       = r->o;
496                                         ir_relation const relation = get_Cmp_relation(irn);
497                                         switch (relation) {
498                                                 case ir_relation_less_greater:
499                                                         if (!tarval_is_null(tarval_andnot(ro, lz)) ||
500                                                                         !tarval_is_null(tarval_andnot(lo, rz))) {
501                                                                 // At least one bit differs.
502                                                                 z = o = get_tarval_b_true();
503                                                         } else if (lz == lo && rz == ro && lz == rz) {
504                                                                 z = o = get_tarval_b_false();
505                                                         } else {
506                                                                 goto result_unknown;
507                                                         }
508                                                         break;
509
510                                                 case ir_relation_equal:
511                                                         if (!tarval_is_null(tarval_andnot(ro, lz)) ||
512                                                                         !tarval_is_null(tarval_andnot(lo, rz))) {
513                                                                 // At least one bit differs.
514                                                                 z = o = get_tarval_b_false();
515                                                         } else if (lz == lo && rz == ro && lz == rz) {
516                                                                 z = o = get_tarval_b_true();
517                                                         } else {
518                                                                 goto result_unknown;
519                                                         }
520                                                         break;
521
522                                                 case ir_relation_less_equal:
523                                                 case ir_relation_less:
524                                                         /* TODO handle negative values */
525                                                         if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
526                                                                         tarval_is_negative(rz) || tarval_is_negative(ro))
527                                                                 goto result_unknown;
528
529                                                         if (tarval_cmp(lz, ro) & relation) {
530                                                                 /* Left upper bound is smaller(/equal) than right lower bound. */
531                                                                 z = o = get_tarval_b_true();
532                                                         } else if (!(tarval_cmp(lo, rz) & relation)) {
533                                                                 /* Left lower bound is not smaller(/equal) than right upper bound. */
534                                                                 z = o = get_tarval_b_false();
535                                                         } else {
536                                                                 goto result_unknown;
537                                                         }
538                                                         break;
539
540                                                 case ir_relation_greater_equal:
541                                                 case ir_relation_greater:
542                                                         /* TODO handle negative values */
543                                                         if (tarval_is_negative(lz) || tarval_is_negative(lo) ||
544                                                                         tarval_is_negative(rz) || tarval_is_negative(ro))
545                                                                 goto result_unknown;
546
547                                                         if (!(tarval_cmp(lz, ro) & relation)) {
548                                                                 /* Left upper bound is not greater(/equal) than right lower bound. */
549                                                                 z = o = get_tarval_b_false();
550                                                         } else if (tarval_cmp(lo, rz) & relation) {
551                                                                 /* Left lower bound is greater(/equal) than right upper bound. */
552                                                                 z = o = get_tarval_b_true();
553                                                         } else {
554                                                                 goto result_unknown;
555                                                         }
556                                                         break;
557
558                                                 default:
559                                                         goto cannot_analyse;
560                                         }
561                                 }
562                                 break;
563                         }
564
565                         default: {
566 cannot_analyse:
567                                 DB((dbg, LEVEL_4, "cannot analyse %+F\n", irn));
568 result_unknown:
569                                 z = get_tarval_all_one(m);
570                                 o = get_tarval_null(m);
571                                 break;
572                         }
573                 }
574         } else {
575                 return 0;
576         }
577
578         return set_bitinfo(irn, z, o);
579 }
580
581 static void first_round(ir_node* const irn, void* const env)
582 {
583         pdeq* const q = (pdeq*)env;
584
585         transfer(irn);
586         if (is_Phi(irn) || is_Block(irn)) {
587                 /* Only Phis (and their users) need another round, if we did not have
588                  * information about all their inputs in the first round, i.e. in loops. */
589                 /* TODO inserts all Phis, should only insert Phis, which did no have all
590                  * predecessors available */
591                 pdeq_putr(q, irn);
592         }
593 }
594
595 static void apply_result(ir_node* const irn, void* ctx)
596 {
597         environment_t* env = (environment_t*)ctx;
598         ir_node*       block;
599         bitinfo*       b;
600         ir_tarval*     z;
601         ir_tarval*     o;
602
603         if (is_Block(irn)) {
604                 bitinfo* const block_b = get_bitinfo(irn);
605                 /* Trivially unreachable blocks have no info. */
606                 if (block_b == NULL || block_b->z == get_tarval_b_false()) {
607                         exchange(irn, get_irg_bad(get_Block_irg(irn)));
608                         env->modified = 1;
609                 }
610                 return;
611         }
612
613         /* Unreachable blocks are replaced before the nodes in them. */
614         block = get_nodes_block(irn);
615         if (is_Bad(block)) {
616                 exchange(irn, block);
617                 env->modified = 1;
618                 return;
619         }
620
621         b = get_bitinfo(irn);
622         if (!b) return;
623         if (is_Const(irn)) return; // It cannot get any better than a Const.
624
625         z = b->z;
626         o = b->o;
627         // Only display information if we could find out anything about the value.
628         DEBUG_ONLY(if (!tarval_is_all_one(z) || !tarval_is_null(o)))
629                 DB((dbg, LEVEL_2, "%+F: 0:%T 1:%T%s\n", irn, z, o, z == o ? " --- constant" : ""));
630
631         // Replace node with constant value by Const.
632         if (z == o) {
633                 ir_mode* const m = get_irn_mode(irn);
634                 ir_node*       n;
635                 if (mode_is_intb(m)) {
636                         ir_graph *irg = get_irn_irg(irn);
637                         n = new_r_Const(irg, z);
638                 } else if (m == mode_X) {
639                         ir_graph* const irg = get_Block_irg(block);
640                         if (z == get_tarval_b_true()) {
641                                 // Might produce an endless loop, so keep the block.
642                                 add_End_keepalive(get_irg_end(irg), block);
643                                 n = new_r_Jmp(block);
644                         } else {
645                                 n = new_r_Bad(irg);
646                                 /* Transferring analysis information to the bad node makes it a
647                                  * candidate for replacement. */
648                                 goto exchange_only;
649                         }
650                 } else {
651                         return;
652                 }
653                 set_irn_link(n, b);
654 exchange_only:
655                 exchange(irn, n);
656                 env->modified = 1;
657         }
658
659         switch (get_irn_opcode(irn)) {
660                 case iro_And: {
661                         ir_node*       const l  = get_And_left(irn);
662                         ir_node*       const r  = get_And_right(irn);
663                         bitinfo const* const bl = get_bitinfo(l);
664                         bitinfo const* const br = get_bitinfo(r);
665                         if (bl->z == bl->o) {
666                                 if (tarval_is_null(tarval_andnot(br->z, bl->z))) {
667                                         DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
668                                         exchange(irn, r);
669                                         env->modified = 1;
670                                 }
671                         } else if (br->z == br->o) {
672                                 if (tarval_is_null(tarval_andnot(bl->z, br->z))) {
673                                         DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
674                                         exchange(irn, l);
675                                         env->modified = 1;
676                                 }
677                         }
678                         break;
679                 }
680
681                 case iro_Or: {
682                         ir_node*       const l  = get_Or_left(irn);
683                         ir_node*       const r  = get_Or_right(irn);
684                         bitinfo const* const bl = get_bitinfo(l);
685                         bitinfo const* const br = get_bitinfo(r);
686                         if (bl->z == bl->o) {
687                                 if (tarval_is_null(tarval_andnot(bl->o, br->o))) {
688                                         DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
689                                         exchange(irn, r);
690                                         env->modified = 1;
691                                 }
692                         } else if (br->z == br->o) {
693                                 if (tarval_is_null(tarval_andnot(br->o, bl->o))) {
694                                         DB((dbg, LEVEL_2, "%+F(%+F, %+F) is superfluous\n", irn, l, r));
695                                         exchange(irn, l);
696                                         env->modified = 1;
697                                 }
698                         }
699                         break;
700                 }
701         }
702 }
703
704 static void queue_users(pdeq* const q, ir_node* const n)
705 {
706         if (get_irn_mode(n) == mode_X) {
707                 /* When the state of a control flow node changes, not only queue its
708                  * successor blocks, but also the Phis in these blocks, because the Phis
709                  * must reconsider this input path. */
710                 ir_edge_t const* e;
711                 foreach_out_edge(n, e) {
712                         ir_node*  const  src = get_edge_src_irn(e);
713                         pdeq_putr(q, src);
714                         /* should always be a block */
715                         if (is_Block(src)) {
716                                 ir_node *phi;
717                                 for (phi = get_Block_phis(src); phi; phi = get_Phi_next(phi))
718                                         pdeq_putr(q, phi);
719                         }
720                 }
721         } else {
722                 ir_edge_t const* e;
723                 foreach_out_edge(n, e) {
724                         ir_node* const src = get_edge_src_irn(e);
725                         if (get_irn_mode(src) == mode_T) {
726                                 queue_users(q, src);
727                         } else {
728                                 pdeq_putr(q, src);
729                         }
730                 }
731         }
732 }
733
734 static void clear_links(ir_node *irn, void *env)
735 {
736         (void) env;
737         set_irn_link(irn, NULL);
738         if (is_Block(irn))
739                 set_Block_phis(irn, NULL);
740 }
741
742 static void build_phi_lists(ir_node *irn, void *env)
743 {
744         (void) env;
745         if (is_Phi(irn))
746                 add_Block_phi(get_nodes_block(irn), irn);
747 }
748
749 void fixpoint_vrp(ir_graph* const irg)
750 {
751         environment_t env;
752
753         FIRM_DBG_REGISTER(dbg, "firm.opt.fp-vrp");
754         DB((dbg, LEVEL_1, "===> Performing constant propagation on %+F\n", irg));
755
756         obstack_init(&obst);
757
758         /* HACK: to avoid finding dead code */
759         edges_deactivate(irg);
760         edges_activate(irg);
761
762         edges_assure(irg);
763         assure_doms(irg);
764
765         ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
766
767         {
768                 pdeq* const q = new_pdeq();
769
770                 /* We need this extra step because the dom tree does not contain unreachable
771                    blocks in Firm. Moreover build phi list. */
772                 irg_walk_anchors(irg, clear_links, build_phi_lists, NULL);
773
774                 /* TODO Improve iteration order. Best is reverse postorder in data flow
775                  * direction and respecting loop nesting for fastest convergence. */
776                 irg_walk_blkwise_dom_top_down(irg, NULL, first_round, q);
777
778                 while (!pdeq_empty(q)) {
779                         ir_node* const n = (ir_node*)pdeq_getl(q);
780                         if (transfer(n))
781                                 queue_users(q, n);
782                 }
783
784                 del_pdeq(q);
785         }
786
787         DB((dbg, LEVEL_2, "---> Applying analysis results\n"));
788         env.modified = 0;
789         irg_walk_graph(irg, NULL, apply_result, &env);
790
791         if (env.modified) {
792                 /* control flow might changed */
793                 set_irg_outs_inconsistent(irg);
794                 set_irg_extblk_inconsistent(irg);
795                 set_irg_doms_inconsistent(irg);
796                 set_irg_loopinfo_inconsistent(irg);
797                 set_irg_entity_usage_state(irg, ir_entity_usage_not_computed);
798         }
799
800         ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
801
802         obstack_free(&obst, NULL);
803 }
804
805 ir_graph_pass_t *fixpoint_vrp_irg_pass(const char *name)
806 {
807         return def_graph_pass(name ? name : "fixpoint_vrp", fixpoint_vrp);
808 }