2 * Copyright (C) 1995-2009 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
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.
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.
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
22 * @brief analyze graph to provide value range information
32 #include "irgraph_t.h"
42 static void *VISITED = &v;
44 typedef struct worklist_t worklist_t;
46 struct list_head nodes;
54 int update_vrp_data(ir_node *node)
57 tarval *new_bits_set = get_tarval_bad();
58 tarval *new_bits_not_set = get_tarval_bad();
59 tarval *new_range_bottom = get_tarval_bad();
60 tarval *new_range_top = get_tarval_bad();
61 ir_node *new_bits_node = NULL;
62 ir_node *new_range_node = NULL;
63 enum range_types new_range_type = VRP_UNDEFINED;
64 enum range_ops new_range_op = VRP_NONE;
65 int something_changed = 0;
67 ir_node *left, *right, *pred, *bound;
68 int overflow_top, overflow_bottom;
69 tarval *new_top, *new_bottom;
74 /* TODO: Check if all predecessors have valid VRP information*/
77 if (!mode_is_int(get_irn_mode(node))) {
78 return 0; /* we don't optimize for non-int-nodes*/
81 switch (get_irn_opcode(node)) {
83 tv = get_Const_tarval(node);
86 new_bits_not_set = tarval_not(tv);
87 new_range_bottom = tv;
89 new_range_type = VRP_RANGE;
93 left = get_And_left(node);
94 right = get_And_right(node);
96 new_bits_set = tarval_and(left->vrp.bits_set, right->vrp.bits_set);
97 new_bits_not_set = tarval_or(left->vrp.bits_not_set, right->vrp.bits_not_set);
99 tmp_tv = tarval_not(left->vrp.bits_set);
100 tmp_tv = tarval_eor(left->vrp.bits_not_set, tmp_tv);
101 /*check if one of the predecessors is completely determined*/
102 if (tarval_is_null(tmp_tv)) {
103 new_bits_node = right;
106 tmp_tv = tarval_not(right->vrp.bits_set);
107 tmp_tv = tarval_eor(right->vrp.bits_not_set, tmp_tv);
108 if (tarval_is_null(tmp_tv)) {
109 new_bits_node = left;
114 left = get_Add_left(node);
115 right = get_Add_right(node);
118 if (left->vrp.range_type == VRP_UNDEFINED || right->vrp.range_type ==
119 VRP_UNDEFINED || left->vrp.range_type == VRP_VARYING ||
120 right->vrp.range_type == VRP_VARYING) {
124 new_top = tarval_add(left->vrp.range_top, right->vrp.range_top);
125 overflow_top = tarval_carry();
126 new_bottom = tarval_add(left->vrp.range_bottom, right->vrp.range_bottom);
127 overflow_bottom = tarval_carry();
129 if (!overflow_top && !overflow_bottom && left->vrp.range_type == VRP_RANGE
130 &&right->vrp.range_type == VRP_RANGE) {
131 new_range_bottom = new_bottom;
132 new_range_top = new_top;
133 new_range_type = VRP_RANGE;
136 if (overflow_top || overflow_bottom) {
137 /* TODO Implement overflow handling*/
138 new_range_type = VRP_UNDEFINED;
143 left = get_Sub_left(node);
144 right = get_Sub_right(node);
146 if (left->vrp.range_type == VRP_UNDEFINED || right->vrp.range_type ==
151 new_top = tarval_sub(left->vrp.range_top, right->vrp.range_top, NULL);
152 overflow_top = tarval_carry();
153 new_bottom = tarval_sub(left->vrp.range_bottom, right->vrp.range_bottom, NULL);
154 overflow_bottom = tarval_carry();
156 if (!overflow_top && !overflow_bottom && left->vrp.range_type == VRP_RANGE
157 &&right->vrp.range_type == VRP_RANGE) {
158 new_range_bottom = new_bottom;
159 new_range_top = new_top;
160 new_range_type = VRP_RANGE;
163 if (overflow_top || overflow_bottom) {
164 /* TODO Implement overflow handling*/
169 left = get_Or_left(node);
170 right = get_Or_right(node);
172 new_bits_set = tarval_or(left->vrp.bits_set, right->vrp.bits_set);
173 new_bits_not_set = tarval_and(left->vrp.bits_not_set, right->vrp.bits_not_set);
175 tmp_tv = tarval_not(left->vrp.bits_set);
176 tmp_tv = tarval_eor(left->vrp.bits_not_set, tmp_tv);
177 /*check if one of the predecessors is completely determined*/
178 if (tarval_is_null(tmp_tv)) {
179 new_bits_node = right;
182 tmp_tv = tarval_not(right->vrp.bits_set);
183 tmp_tv = tarval_eor(right->vrp.bits_not_set, tmp_tv);
184 if (tarval_is_null(tmp_tv)) {
185 new_bits_node = left;
190 left = get_Rotl_left(node);
191 right = get_Rotl_right(node);
193 /* We can only compute this if the right value is a constant*/
194 if (is_Const(right)) {
195 tarval *bits_set, *bits_not_set;
196 bits_set = tarval_rotl(left->vrp.bits_set, get_Const_tarval(right));
197 bits_not_set = tarval_rotl(left->vrp.bits_not_set, get_Const_tarval(right));
199 new_bits_set = tarval_or(bits_set, node->vrp.bits_set);
200 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
205 left = get_Shl_left(node);
206 right = get_Shl_right(node);
208 /* We can only compute this if the right value is a constant*/
209 if (is_Const(right)) {
210 tarval *bits_set, *bits_not_set;
211 ir_mode *m = get_tarval_mode(node->vrp.bits_not_set);
212 bits_set = tarval_shl(left->vrp.bits_set, get_Const_tarval(right));
213 bits_not_set = tarval_shl(left->vrp.bits_not_set, get_Const_tarval(right));
215 new_bits_set = tarval_or(bits_set, node->vrp.bits_set);
216 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
218 bits_not_set = tarval_not( tarval_shl(
220 get_Const_tarval(right)));
221 new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set);
227 left = get_Shr_left(node);
228 right = get_Shr_right(node);
230 /* We can only compute this if the right value is a constant*/
231 if (is_Const(right)) {
232 tarval *bits_set, *bits_not_set;
233 ir_mode *m = get_tarval_mode(node->vrp.bits_not_set);
234 bits_set = tarval_shr(left->vrp.bits_set, get_Const_tarval(right));
235 bits_not_set = tarval_shr(left->vrp.bits_not_set, get_Const_tarval(right));
237 new_bits_set = tarval_or(bits_set, node->vrp.bits_set);
238 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
240 bits_not_set = tarval_not( tarval_shr(
242 get_Const_tarval(right)));
243 new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set);
248 left = get_Shrs_left(node);
249 right = get_Shrs_right(node);
251 /* We can only compute this if the right value is a constant*/
252 if (is_Const(right)) {
253 tarval *bits_set, *bits_not_set;
254 ir_mode *m = get_tarval_mode(node->vrp.bits_not_set);
255 bits_set = tarval_shrs(left->vrp.bits_set, get_Const_tarval(right));
256 bits_not_set = tarval_shrs(left->vrp.bits_not_set, get_Const_tarval(right));
258 new_bits_set = tarval_or(bits_set, node->vrp.bits_set);
259 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
261 bits_not_set = tarval_not( tarval_shrs(
263 get_Const_tarval(right)));
264 new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set);
269 left = get_Eor_left(node);
270 right = get_Eor_right(node);
272 tarval *bits_set, *bits_not_set;
273 bits_not_set = tarval_or(
274 tarval_and(left->vrp.bits_set, right->vrp.bits_set),
275 tarval_and(left->vrp.bits_not_set,
276 right->vrp.bits_not_set));
278 bits_set = tarval_or(
279 tarval_and(left->vrp.bits_set, right->vrp.bits_not_set),
280 tarval_and(left->vrp.bits_not_set, right->vrp.bits_set));
282 new_bits_set = tarval_or(bits_set, node->vrp.bits_set);
283 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
287 pred = get_Id_pred(node);
288 new_bits_set = pred->vrp.bits_set;
289 new_bits_not_set = pred->vrp.bits_not_set;
290 new_range_top = pred->vrp.range_top;
291 new_range_bottom = pred->vrp.range_bottom;
292 new_range_type = pred->vrp.range_type;
296 pred = get_Not_op(node);
297 new_bits_set = tarval_or(pred->vrp.bits_not_set, node->vrp.bits_set);
298 new_bits_not_set = tarval_or(pred->vrp.bits_set, node->vrp.bits_not_set);
302 pred = get_Conv_op(node);
303 ir_mode *old_mode = get_irn_mode(pred);
306 if (!mode_is_int(old_mode))
309 new_mode = get_irn_mode(node);
311 /* The second and is needed if target type is smaller*/
312 bits_not_set = tarval_not(
313 tarval_convert_to(get_mode_all_one(old_mode),
316 bits_not_set = tarval_or(bits_not_set, tarval_convert_to(pred->vrp.bits_not_set, new_mode));
317 new_bits_not_set = tarval_or(bits_not_set, node->vrp.bits_not_set);
318 new_bits_set = tarval_and(
319 tarval_not(bits_not_set), tarval_convert_to(pred->vrp.bits_set, new_mode));
321 if (tarval_cmp(pred->vrp.range_top, get_mode_max(new_mode)) == pn_Cmp_Le) {
322 node->vrp.range_top = pred->vrp.range_top;
325 if (tarval_cmp(pred->vrp.range_bottom, get_mode_min(new_mode)) == pn_Cmp_Ge) {
326 node->vrp.range_bottom = pred->vrp.range_bottom;
331 cmp = get_Confirm_cmp(node);
332 bound = get_Confirm_bound(node);
334 /** @todo: Handle non-Const bounds */
336 if (cmp == pn_Cmp_Lg) {
337 /** @todo: Is there some way to preserve the information? */
338 new_range_type = VRP_ANTIRANGE;
339 if (is_Const(bound)) {
340 new_range_top = get_Const_tarval(bound);
341 new_range_bottom = get_Const_tarval(bound);
343 } else if (cmp == pn_Cmp_Le) {
344 if (node->vrp.range_type == VRP_UNDEFINED) {
345 new_range_type = VRP_RANGE;
346 if (is_Const(bound)) {
347 new_range_top = get_Const_tarval(bound);
349 new_range_bottom = get_tarval_min(get_irn_mode(node));
350 } else if (node->vrp.range_type == VRP_RANGE) {
351 if (is_Const(bound)) {
352 if (tarval_cmp(node->vrp.range_top,
353 get_Const_tarval(bound)) == pn_Cmp_Le) {
354 new_range_top = get_Const_tarval(bound);
356 new_range_bottom = get_tarval_min(get_irn_mode(node));
358 } else if (node->vrp.range_type == VRP_ANTIRANGE) {
359 /** @todo: How do we manage not to get a never ending loop? */
366 /* combine all ranges*/
368 pred = get_Phi_pred(node,0);
369 new_range_top = pred->vrp.range_top;
370 new_range_bottom = pred->vrp.range_bottom;
371 new_range_type = pred->vrp.range_type;
372 new_bits_set = pred->vrp.bits_set;
373 new_bits_not_set = pred->vrp.bits_not_set;
375 int num = get_Phi_n_preds(node);
382 for (i = 1; i < num; i++) {
383 pred = get_Phi_pred(node, i);
384 if (new_range_type == VRP_RANGE && pred->vrp.range_type ==
386 cmp = tarval_cmp(new_range_top, pred->vrp.range_top);
387 if (cmp == pn_Cmp_Lt) {
388 new_range_top = pred->vrp.range_top;
390 cmp = tarval_cmp(new_range_bottom, pred->vrp.range_bottom);
391 if (cmp == pn_Cmp_Gt) {
392 new_range_bottom = pred->vrp.range_bottom;
395 new_range_type = VRP_VARYING;
404 /* unhandled, therefore never updated */
410 /* TODO: Check, if there can be information derived from any of these:
411 is_Abs(node) is_Alloc(node) is_Anchor(node) is_Borrow(node) is_Bound(node)
412 is_Break(node) is_Builtin(node) is_Call(node) is_CallBegin(node)
413 is_Carry(node) is_Cast(node) is_Cmp(node) is_Cond(node)
414 is_CopyB(node) is_Div(node) is_DivMod(node) is_Dummy(node)
415 is_End(node) is_EndExcept(node) is_EndReg(node) is_Filter(node) is_Free(node)
416 is_IJmp(node) is_InstOf(node) is_Jmp(node) is_Load(node) is_Minus(node)
417 is_Mod(node) is_Mul(node) is_Mulh(node) is_Mux(node) is_NoMem(node)
418 is_Pin(node) is_Proj(node) is_Quot(node)
419 is_Raise(node) is_Return(node) is_Sel(node) is_Start(node) is_Store(node)
420 is_SymConst(node) is_Sync(node) is_Tuple(node)
423 /* Merge the newly calculated values with those that might already exist*/
425 if (new_bits_set != tarval_bad) {
426 new_bits_set = tarval_or(new_bits_set, node->vrp.bits_set);
427 if (tarval_cmp(new_bits_set, node->vrp.bits_set) != pn_Cmp_Eq) {
428 something_changed = 1;
429 node->vrp.bits_set = new_bits_set;
433 if (new_bits_not_set != tarval_bad) {
434 new_bits_not_set = tarval_or(new_bits_not_set, node->vrp.bits_not_set);
436 if (tarval_cmp(new_bits_not_set, node->vrp.bits_not_set) != pn_Cmp_Eq) {
437 something_changed = 1;
438 node->vrp.bits_not_set = new_bits_not_set;
442 if (node->vrp.bits_node == NULL && new_bits_node != NULL) {
443 something_changed = 1;
444 node->vrp.bits_node = new_bits_node;
447 if (node->vrp.range_type == VRP_UNDEFINED &&
448 new_range_type != VRP_UNDEFINED) {
449 something_changed = 1;
450 node->vrp.range_type = new_range_type;
451 node->vrp.range_bottom = new_range_bottom;
452 node->vrp.range_top = new_range_top;
453 node->vrp.range_op = new_range_op;
454 node->vrp.range_node = new_range_node;
456 } else if (node->vrp.range_type == VRP_RANGE) {
457 if (new_range_type == VRP_RANGE) {
458 if ((new_range_node == NULL && node->vrp.range_node == NULL) ||
459 (new_range_node == node->vrp.range_node &&
460 new_range_op == node->vrp.range_op)) {
461 if (tarval_cmp(node->vrp.range_bottom, new_range_bottom) == pn_Cmp_Lt) {
462 something_changed = 1;
463 node->vrp.range_bottom = new_range_bottom;
465 if (tarval_cmp(node->vrp.range_top, new_range_top) == pn_Cmp_Gt) {
466 something_changed = 1;
467 node->vrp.range_top = new_range_top;
471 /* prefer the absolute value*/
472 if (new_range_node == NULL && node->vrp.range_node != NULL) {
473 something_changed = 1;
474 node->vrp.range_node = NULL;
475 node->vrp.range_top = new_range_top;
476 node->vrp.range_bottom = new_range_bottom;
480 if (new_range_type == VRP_ANTIRANGE) {
481 /* if they are overlapping, cut the range.*/
482 /* TODO: Maybe we can preserve more information here*/
483 if (new_range_node == NULL && node->vrp.range_node == NULL) {
484 if (tarval_cmp(node->vrp.range_bottom, new_range_top) == pn_Cmp_Gt &&
485 tarval_cmp(node->vrp.range_bottom, new_range_bottom) == pn_Cmp_Gt) {
486 something_changed = 1;
487 node->vrp.range_bottom = new_range_top;
489 } else if (tarval_cmp(node->vrp.range_top, new_range_bottom) == pn_Cmp_Gt &&
490 tarval_cmp(node->vrp.range_top, new_range_top) == pn_Cmp_Lt) {
491 something_changed = 1;
492 node->vrp.range_top = new_range_bottom;
495 /* We can not handle the case where the anti range is in the*/
499 /* prefer the absolute value*/
500 if (new_range_node == NULL && node->vrp.range_node != NULL) {
501 something_changed = 1;
502 node->vrp.range_node = NULL;
503 node->vrp.range_top = new_range_top;
504 node->vrp.range_bottom = new_range_bottom;
507 } else if (node->vrp.range_type == VRP_ANTIRANGE) {
508 if (new_range_type == VRP_ANTIRANGE) {
509 if ((new_range_node == NULL && node->vrp.range_node == NULL) ||
510 (new_range_node == node->vrp.range_node &&
511 new_range_op == node->vrp.range_op)) {
512 if (tarval_cmp(node->vrp.range_bottom, new_range_bottom) == pn_Cmp_Gt) {
513 something_changed = 1;
514 node->vrp.range_bottom = new_range_bottom;
516 if (tarval_cmp(node->vrp.range_top, new_range_top) == pn_Cmp_Lt) {
517 something_changed = 1;
518 node->vrp.range_top = new_range_top;
522 /* prefer the absolute value*/
523 if (new_range_node == NULL && node->vrp.range_node != NULL) {
524 something_changed = 1;
525 node->vrp.range_node = NULL;
526 node->vrp.range_top = new_range_top;
527 node->vrp.range_bottom = new_range_bottom;
531 if (new_range_type == VRP_RANGE) {
532 if ((new_range_node == NULL && node->vrp.range_node == NULL) ||
533 (new_range_node == node->vrp.range_node &&
534 new_range_op == node->vrp.range_op)) {
535 if (tarval_cmp(node->vrp.range_bottom, new_range_top) == pn_Cmp_Gt) {
536 something_changed = 1;
537 node->vrp.range_bottom = new_range_top;
539 if (tarval_cmp(node->vrp.range_top, new_range_bottom) == pn_Cmp_Lt) {
540 something_changed = 1;
541 node->vrp.range_top = new_range_bottom;
545 /* prefer the absolute value*/
546 if (new_range_node == NULL && node->vrp.range_node != NULL) {
547 something_changed = 1;
548 node->vrp.range_node = NULL;
549 node->vrp.range_top = new_range_top;
550 node->vrp.range_bottom = new_range_bottom;
555 assert(tarval_is_null(
556 tarval_and(node->vrp.bits_set, node->vrp.bits_not_set)));
558 return something_changed;
561 void vrp_first_pass(ir_node *n, void *e)
564 worklist_t *tmp_entry;
566 struct vrp_env_t *env = e;
571 set_irn_link(n, VISITED);
575 for (i = get_irn_n_outs(n) - 1; i >=0; --i) {
576 succ = get_irn_out(n, i);
577 if (get_irn_link(succ) == VISITED) {
580 tmp_entry = XMALLOC(worklist_t);
582 list_add(&(tmp_entry->nodes), &(env->worklist->nodes));
590 void set_vrp_data(ir_graph *irg)
596 worklist_t *tmp_entry, *tmp_entry2;
597 struct vrp_env_t env;
604 assure_irg_outs(irg); /* ensure that out edges are consistent*/
606 /* edges_activate(irg);*/
608 INIT_LIST_HEAD(&worklist.nodes);
610 env.worklist = &worklist;
611 irg_walk_graph(irg, NULL, vrp_first_pass, &env);
615 /* while there are entries in the worklist, continue*/
616 while ( !list_empty(&worklist.nodes) ) {
618 list_head *pos, *next;
619 list_for_each_safe(pos, next, &worklist.nodes) {
621 tmp_entry = list_entry(pos, worklist_t, nodes);
623 if (update_vrp_data(tmp_entry->node)) {
624 /* if something changed, add successors to worklist*/
625 for (i = get_irn_n_outs(tmp_entry->node) - 1; i >=0; --i) {
626 succ = get_irn_out(tmp_entry->node, i);
628 tmp_entry2 = XMALLOC(worklist_t);
629 tmp_entry2->node = succ;
630 list_add(&(tmp_entry2->nodes), &worklist.nodes);
641 ir_graph_pass_t *set_vrp_pass(const char *name)
643 return def_graph_pass(name ? name : "set_vrp", set_vrp_data);
646 pn_Cmp vrp_cmp(ir_node *left, ir_node *right)
648 if (!left->vrp.valid || !right->vrp.valid) {
652 if (left->vrp.range_type == VRP_RANGE && right->vrp.range_type == VRP_RANGE) {
653 if (tarval_cmp(left->vrp.range_top, right->vrp.range_bottom) == pn_Cmp_Lt) {
656 if (tarval_cmp(left->vrp.range_bottom, right->vrp.range_top) == pn_Cmp_Gt) {
661 if (!tarval_is_null(tarval_and(left->vrp.bits_set, right->vrp.bits_not_set)) ||
662 !tarval_is_null(tarval_and(left->vrp.bits_not_set, right->vrp.bits_set))) {
665 /* TODO: We can get way more information here*/