1f31a17aa01b1df0669ecc2b6dc86321365ac41d
[libfirm] / ir / opt / opt_confirms.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/opt/opt_confirms.c
4  * Purpose:     Optimizations regarding Confirm nodes
5  * Author:      Michael Beck
6  * Modified by:
7  * Created:
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 1998-2005 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
16
17 #include "tv_t.h"
18 #include "iropt_t.h"
19 #include "opt_confirms.h"
20
21 enum range_tags {
22   MIN_INCLUDED = 0x00,  /**< [min, ... */
23   MAX_INCLUDED = 0x00,  /**< ..., max] */
24   MIN_EXCLUDED = 0x01,  /**< (min, ... */
25   MAX_EXCLUDED = 0x02   /**< ..., max) */
26 };
27
28 /**
29  * An interval. We could use
30  * intervals that ALWAYS include its borders, even for
31  * floating point, as the precision is limited.
32  * However, as our tarval module did not support
33  * such kind of operation, we use border flags allowing
34  * all intervals.
35  */
36 typedef struct _interval_t {
37   tarval        *min;   /**< lowest border */
38   tarval        *max;   /**< highest border */
39   unsigned char flags;  /**< border flags */
40 } interval_t;
41
42 /**
43  * Check, if the value of a node is != 0.
44  *
45  * This is a often needed case, so we handle here Confirm
46  * nodes too.
47  */
48 int value_not_zero(ir_node *n)
49 {
50 #define RET_ON(x)  if (x) return 1; break
51
52   tarval *tv;
53   ir_mode *mode;
54   pn_Cmp pnc;
55
56   while (get_irn_op(n) == op_Confirm) {
57     /*
58      * Note: A Confirm is never after a Const. So,
59      * we simply can check the bound for beeing a Const
60      * without the fear that is might be hidden by a further Confirm.
61      */
62     tv = value_of(get_Confirm_bound(n));
63     if (tv == tarval_bad)
64       return 0;
65
66     mode = get_tarval_mode(tv);
67     pnc  = tarval_cmp(tv, get_mode_null(mode));
68
69     switch (get_Confirm_cmp(n)) {
70     case pn_Cmp_Eq: /* n == C /\ C != 0 ==> n != 0, should never happen, but simple */
71       RET_ON(pnc != pn_Cmp_Eq);
72     case pn_Cmp_Lg: /* n != C /\ C == 0 ==> n != 0 */
73       RET_ON(pnc == pn_Cmp_Eq);
74     case pn_Cmp_Lt: /* n <  C /\ C <= 0 ==> n != 0 */
75       RET_ON(pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq);
76     case pn_Cmp_Le: /* n <= C /\ C <  0 ==> n != 0 */
77       RET_ON(pnc == pn_Cmp_Lt);
78     case pn_Cmp_Ge: /* n >= C /\ C >  0 ==> n != 0 */
79       RET_ON(pnc == pn_Cmp_Gt);
80     case pn_Cmp_Gt: /* n >  C /\ C >= 0 ==> n != 0 */
81       RET_ON(pnc == pn_Cmp_Gt || pnc == pn_Cmp_Eq);
82     default:
83       break;
84         }
85
86     /* there might be several Confirms one after other that form an interval */
87     n = get_Confirm_value(n);
88   }
89   tv = value_of(n);
90
91   return (tv != tarval_bad) && (classify_tarval(tv) != TV_CLASSIFY_NULL);
92
93 #undef RET_ON
94 }
95
96 /*
97  * Check, if the value of a node can be confirmed >= 0 or <= 0,
98  * If the mode of the value did not honor signed zeros, else
99  * check for >= 0 or < 0.
100  */
101 value_classify classify_value_sign(ir_node *n)
102 {
103   tarval *tv, *c;
104   ir_mode *mode;
105   pn_Cmp cmp, ncmp;
106
107   if (get_irn_op(n) != op_Confirm)
108     return VALUE_UNKNOWN;
109
110   tv  = value_of(get_Confirm_bound(n));
111   if (tv == tarval_bad)
112     return VALUE_UNKNOWN;
113
114   mode = get_irn_mode(n);
115
116   /*
117    * We can handle only >=, >, <, <= cases.
118    * We could handle == too, but this will be optimized into
119    * a constant either.
120    *
121    * Note that for integer modes we have a slightly better
122    * optimization possibilities, so we handle this
123    * different.
124    */
125   cmp = get_Confirm_cmp(n);
126
127   switch (cmp) {
128   case pn_Cmp_Lt:
129     /*
130      * must be x < c <= 1 to be useful if integer mode and -0 = 0
131      *         x < c <= 0 to be useful else
132      */
133   case pn_Cmp_Le:
134     /*
135      * must be x <= c < 1 to be useful if integer mode and -0 = 0
136      *         x <= c < 0 to be useful else
137      */
138     c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ?
139       get_mode_one(mode) : get_mode_null(mode);
140
141     ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
142     if (cmp != ncmp)
143       return VALUE_UNKNOWN;
144
145     /* yep, negative */
146     return VALUE_NEGATIVE;
147
148   case pn_Cmp_Ge:
149     /*
150      * must be x >= c > -1 to be useful if integer mode
151      *         x >= c >= 0 to be useful else
152      */
153   case pn_Cmp_Gt:
154     /*
155      * must be x > c >= -1 to be useful if integer mode
156      *         x > c >= 0 to be useful else
157      */
158     if (mode_is_int(mode)) {
159       c = get_mode_minus_one(mode);
160
161       ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
162       if (cmp != ncmp)
163         return VALUE_UNKNOWN;
164     }
165     else {
166       c = get_mode_minus_one(mode);
167
168       ncmp = tarval_cmp(tv, c);
169
170       if (ncmp != pn_Cmp_Eq && ncmp != pn_Cmp_Gt)
171         return VALUE_UNKNOWN;
172     }
173
174     /* yep, positive */
175     return VALUE_POSITIVE;
176
177   default:
178     return VALUE_UNKNOWN;
179   }
180 }
181
182 /**
183  * construct an interval from a value
184  */
185 static interval_t *get_interval_from_tv(interval_t *iv, tarval *tv)
186 {
187   ir_mode *mode = get_tarval_mode(tv);
188
189   if (tv == tarval_bad) {
190     /* [-oo, +oo] */
191     iv->min   = get_mode_min(mode);
192     iv->max   = get_mode_max(mode);
193     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
194
195     return iv;
196   }
197
198   /* [tv, tv] */
199   iv->min   = tv;
200   iv->max   = tv;
201   iv->flags = MIN_INCLUDED | MAX_INCLUDED;
202
203   return iv;
204 }
205
206 /**
207  * construct an interval from a Confirm
208  */
209 static interval_t *get_interval(interval_t *iv, ir_node *bound, pn_Cmp pnc)
210 {
211   ir_mode *mode = get_irn_mode(bound);
212   tarval  *tv   = value_of(bound);
213
214   if (tv == tarval_bad) {
215     /* [-oo, +oo] */
216     iv->min   = get_mode_min(mode);
217     iv->max   = get_mode_max(mode);
218     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
219
220     return iv;
221   }
222
223   /* check which side is known */
224   switch (pnc) {
225   case pn_Cmp_Eq:
226     /* [tv, tv] */
227     iv->min   =
228     iv->max   = tv;
229     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
230     return iv;
231
232   case pn_Cmp_Le:
233     /* [-oo, tv] */
234     iv->min   = get_mode_min(mode);
235     iv->max   = tv;
236     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
237     return iv;
238
239   case pn_Cmp_Lt:
240     /* [-oo, tv) */
241     iv->min   = get_mode_min(mode);
242     iv->max   = tv;
243     iv->flags = MIN_INCLUDED | MAX_EXCLUDED;
244     return iv;
245
246   case pn_Cmp_Gt:
247     /* (tv, +oo] */
248     iv->min   = tv;
249     iv->max   = get_mode_max(mode);
250     iv->flags = MIN_EXCLUDED | MAX_INCLUDED;
251     return iv;
252
253   case pn_Cmp_Ge:
254     /* [tv, +oo] */
255     iv->min   = tv;
256     iv->max   = get_mode_max(mode);
257     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
258     return iv;
259
260   default:
261     /*
262      * We did not handle UNORDERED yet. It is not
263      * clear, if this could give any gain.
264      */
265
266     /* [-oo, +oo] */
267     iv->min   = get_mode_min(mode);
268     iv->max   = get_mode_max(mode);
269     iv->flags = MIN_INCLUDED | MAX_INCLUDED;
270     return iv;
271   }
272 }
273
274 /**
275  * Try to evaluate l_iv pnc r_iv.
276  *
277  * @param l_iv   the left interval
278  * @param r_iv   the right interval
279  * @param pnc    the compare relation
280  *
281  * @return
282  *   tarval_b_true or tarval_b_false it it can be evaluated,
283  *   tarval_bad else
284  */
285 static tarval *compare_iv(const interval_t *l_iv, const interval_t *r_iv, pn_Cmp pnc)
286 {
287   pn_Cmp res;
288   unsigned flags;
289   tarval *tv_true = tarval_b_true, *tv_false = tarval_b_false;
290
291   /*
292    * save some cases: we invert all cases with a >
293    * Note that this turn Lg into Eq also (which is desired).
294    */
295   if (pnc & pn_Cmp_Gt) {
296     pnc = get_inversed_pnc(pnc);
297
298     tv_true  = tarval_b_false;
299     tv_false = tarval_b_true;
300   }
301
302   switch (pnc) {
303   case pn_Cmp_Eq:
304     /* two intervals can be compared for equality only if they are a single value */
305     if (l_iv->min == l_iv->max && r_iv->min == r_iv->max)
306       return l_iv->min == r_iv->min ? tv_true : tv_false;
307     break;
308
309   case pn_Cmp_Lt:
310     res = tarval_cmp(l_iv->max, r_iv->min);
311
312     /* [a, b] < [c, d] */
313     if (res == pn_Cmp_Lt)
314       return tv_true;
315     /* if one border is excluded, <= is ok */
316     if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) &&
317         res == pn_Cmp_Eq)
318       return tv_true;
319
320     /* [a, b) >= [c, d] or [a, b] >= (c, d] */
321     flags = (l_iv->flags & MAX_EXCLUDED) | (r_iv->flags & MIN_EXCLUDED);
322
323     if (flags) {
324       res = tarval_cmp(l_iv->max, r_iv->min);
325
326       if (res == pn_Cmp_Gt || res == pn_Cmp_Eq)
327         return tv_false;
328     }
329     break;
330
331   case pn_Cmp_Le:
332     /* [a, b) <= [c, d] or [a, b] <= (c, d] */
333     flags = (l_iv->flags & MAX_EXCLUDED) | (r_iv->flags & MIN_EXCLUDED);
334
335     if (flags) {
336       res = tarval_cmp(l_iv->max, r_iv->min);
337
338       if (res == pn_Cmp_Lt || res == pn_Cmp_Eq)
339         return tv_true;
340     }
341
342     res = tarval_cmp(l_iv->max, r_iv->min);
343
344     /* [a, b] > [c, d] */
345     if (res == pn_Cmp_Gt)
346       return tv_false;
347     /* if one border is excluded, >= is ok */
348     if ((l_iv->flags & MAX_EXCLUDED || r_iv->flags & MIN_EXCLUDED) &&
349         res == pn_Cmp_Eq)
350       return tv_false;
351     break;
352
353   default:
354     return tarval_bad;
355   }
356   return tarval_bad;
357 }
358
359 /**
360  * Return the value of a Cmp if one or both predecessors
361  * are Confirm nodes.
362  *
363  * @param left   the left operand of the Cmp
364  * @param right  the right operand of the Cmp
365  */
366 tarval *computed_value_Cmp_Confirm(ir_node *left, ir_node *right, pn_Cmp pnc)
367 {
368   ir_node    *l_bound;
369   pn_Cmp     l_pnc;
370   interval_t l_iv, r_iv;
371   tarval     *tv;
372
373   if (get_irn_op(right) == op_Confirm) {
374     ir_node *t;
375
376     /* we want the Confirm on the left side */
377     t     = left;
378     left  = right;
379     right = t;
380
381     pnc = get_inversed_pnc(pnc);
382   }
383   else if (get_irn_op(left) != op_Confirm) {
384     /* no Confirm on either one side, finish */
385     return tarval_bad;
386   }
387
388   /* ok, here at least left is a Confirm, right might be */
389   l_bound = get_Confirm_bound(left);
390   l_pnc   = get_Confirm_cmp(left);
391
392   if (get_irn_op(right) == op_Confirm) {
393     /*
394      * both sides are Confirm's. Check some rare cases first.
395      */
396     ir_node *r_bound = get_Confirm_bound(right);
397     pn_Cmp  r_pnc = get_Confirm_cmp(right);
398
399     /* check for == or != can sometime be made WITHOUT constant bounds */
400     if (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) {
401       /* l == r if bound(l) == bound(r) AND pnc(l) == pnc(r) == '=' */
402       if (r_bound == l_bound && r_pnc == l_pnc && r_pnc == pn_Cmp_Eq) {
403         return pnc == pn_Cmp_Eq ? tarval_b_true : tarval_b_false;
404       }
405
406       /*
407        * Here, we check only the right Confirm, as the left Confirms are
408        * checked later anyway.
409        */
410
411       if (left == r_bound && (r_pnc == pn_Cmp_Eq || r_pnc == pn_Cmp_Lg)) {
412         /* l == bound(r) AND pnc(r) == pnc */
413         if (r_pnc == pnc)
414           return tarval_b_true;
415
416         /* l == bound(r) AND pnc(r) != pnc */
417         else
418           return tarval_b_false;
419       }
420     }
421
422     /* now, try interval magic */
423     get_interval(&r_iv, r_bound, r_pnc);
424     get_interval(&l_iv, l_bound, l_pnc);
425
426     tv = compare_iv(&l_iv, &r_iv, pnc);
427     if (tv != tarval_bad)
428       return tv;
429   }
430
431   /* from Here, check only left Confirm */
432
433   /* check for == or != can sometime be made WITHOUT constant bounds */
434   if (pnc == pn_Cmp_Eq || pnc == pn_Cmp_Lg) {
435     if (right == l_bound && (l_pnc == pn_Cmp_Eq || l_pnc == pn_Cmp_Lg)) {
436       /* r == bound(l) AND pnc(l) == pnc */
437       if (l_pnc == pnc)
438         return tarval_b_true;
439
440       /* r == bound(l) AND pnc(l) != pnc */
441       else
442         return tarval_b_false;
443     }
444   }
445
446   /* now, only right == Const can help */
447   tv = value_of(right);
448
449   if (tv != tarval_bad) {
450     get_interval_from_tv(&r_iv, tv);
451     get_interval(&l_iv, l_bound, l_pnc);
452
453     return compare_iv(&l_iv, &r_iv, pnc);
454   }
455
456   return tarval_bad;
457 }