2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief analyze graph to provide value range information
15 #include "iroptimize.h"
17 #include "irgraph_t.h"
25 #include "irnodemap.h"
30 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
32 typedef struct vrp_env_t {
38 static vrp_attr *vrp_get_or_set_info(ir_vrp_info *info, const ir_node *node)
40 vrp_attr *attr = ir_nodemap_get(vrp_attr, &info->infos, node);
42 ir_mode *mode = get_irn_mode(node);
43 assert(mode_is_int(mode));
45 attr = OALLOCZ(&info->obst, vrp_attr);
46 attr->range_type = VRP_UNDEFINED;
47 attr->bits_set = get_mode_null(mode);
48 attr->bits_not_set = get_mode_all_one(mode);
49 attr->range_bottom = get_tarval_top();
50 attr->range_top = get_tarval_top();
52 ir_nodemap_insert(&info->infos, node, attr);
57 vrp_attr *vrp_get_info(const ir_node *node)
59 ir_graph *irg = get_irn_irg(node);
60 if (irg->vrp.infos.data == NULL)
62 return ir_nodemap_get(vrp_attr, &irg->vrp.infos, node);
65 static int vrp_update_node(ir_vrp_info *info, ir_node *node)
67 ir_tarval *new_bits_set = get_tarval_bad();
68 ir_tarval *new_bits_not_set = get_tarval_bad();
69 ir_tarval *new_range_bottom = get_tarval_bad();
70 ir_tarval *new_range_top = get_tarval_bad();
71 enum range_types new_range_type = VRP_UNDEFINED;
72 int something_changed = 0;
75 if (!mode_is_int(get_irn_mode(node))) {
76 return 0; /* we don't optimize for non-int-nodes*/
79 vrp = vrp_get_or_set_info(info, node);
81 /* TODO: Check if all predecessors have valid VRP information*/
83 switch (get_irn_opcode(node)) {
85 ir_tarval *tv = get_Const_tarval(node);
87 new_bits_not_set = tv;
88 new_range_bottom = tv;
90 new_range_type = VRP_RANGE;
94 const vrp_attr *vrp_left, *vrp_right;
95 const ir_node *left, *right;
97 left = get_And_left(node);
98 right = get_And_right(node);
99 vrp_left = vrp_get_or_set_info(info, left);
100 vrp_right = vrp_get_or_set_info(info, right);
101 new_bits_set = tarval_and(vrp_left->bits_set, vrp_right->bits_set);
102 new_bits_not_set = tarval_and(vrp_left->bits_not_set, vrp_right->bits_not_set);
108 const vrp_attr *vrp_left = vrp_get_or_set_info(info, get_Add_left(node));
109 const vrp_attr *vrp_right = vrp_get_or_set_info(info, get_Add_right(node));
111 if (vrp_left->range_type == VRP_UNDEFINED
112 || vrp_right->range_type == VRP_UNDEFINED
113 || vrp_left->range_type == VRP_VARYING
114 || vrp_right->range_type == VRP_VARYING) {
118 if (vrp_left->range_type == VRP_RANGE
119 && vrp_right->range_type == VRP_RANGE) {
120 tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
121 tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
123 = tarval_add(vrp_left->range_top, vrp_right->range_top);
124 ir_tarval *new_bottom
125 = tarval_add(vrp_left->range_bottom, vrp_right->range_bottom);
126 tarval_set_integer_overflow_mode(rem);
128 if (new_top != tarval_bad && new_bottom != tarval_bad) {
129 new_range_bottom = new_bottom;
130 new_range_top = new_top;
131 new_range_type = VRP_RANGE;
133 /* TODO Implement overflow handling*/
134 new_range_type = VRP_UNDEFINED;
141 ir_node *left = get_Sub_left(node);
142 ir_node *right = get_Sub_right(node);
144 if (!mode_is_int(get_irn_mode(left)))
147 const vrp_attr *vrp_left = vrp_get_or_set_info(info, left);
148 const vrp_attr *vrp_right = vrp_get_or_set_info(info, right);
150 if (vrp_left->range_type == VRP_UNDEFINED
151 || vrp_right->range_type == VRP_UNDEFINED
152 || vrp_left->range_type == VRP_VARYING
153 || vrp_right->range_type == VRP_VARYING) {
157 if (vrp_left->range_type == VRP_RANGE
158 && vrp_right->range_type == VRP_RANGE) {
159 tarval_int_overflow_mode_t rem = tarval_get_integer_overflow_mode();
160 tarval_set_integer_overflow_mode(TV_OVERFLOW_BAD);
161 ir_tarval *new_top = tarval_sub(vrp_left->range_top, vrp_right->range_top, NULL);
162 ir_tarval *new_bottom = tarval_sub(vrp_left->range_bottom, vrp_right->range_bottom, NULL);
163 tarval_set_integer_overflow_mode(rem);
165 if (new_top != tarval_bad && new_bottom != tarval_bad) {
166 new_range_bottom = new_bottom;
167 new_range_top = new_top;
168 new_range_type = VRP_RANGE;
170 /* TODO Implement overflow handling*/
171 new_range_type = VRP_UNDEFINED;
178 const vrp_attr *vrp_left, *vrp_right;
180 vrp_left = vrp_get_or_set_info(info, get_Or_left(node));
181 vrp_right = vrp_get_or_set_info(info, get_Or_right(node));
183 new_bits_set = tarval_or(vrp_left->bits_set, vrp_right->bits_set);
184 new_bits_not_set = tarval_or(vrp_left->bits_not_set, vrp_right->bits_not_set);
190 const vrp_attr *vrp_left;
191 const ir_node *right = get_Rotl_right(node);
193 vrp_left = vrp_get_or_set_info(info, get_Rotl_left(node));
195 /* We can only compute this if the right value is a constant*/
196 if (is_Const(right)) {
197 new_bits_set = tarval_rotl(vrp_left->bits_set, get_Const_tarval(right));
198 new_bits_not_set = tarval_rotl(vrp_left->bits_not_set, get_Const_tarval(right));
204 const vrp_attr *vrp_left;
205 const ir_node *right = get_Shl_right(node);
206 vrp_left = vrp_get_or_set_info(info, get_Shl_left(node));
208 /* We can only compute this if the right value is a constant*/
209 if (is_Const(right)) {
210 new_bits_set = tarval_shl(vrp_left->bits_set, get_Const_tarval(right));
211 new_bits_not_set = tarval_shl(vrp_left->bits_not_set, get_Const_tarval(right));
217 const vrp_attr *vrp_left;
218 const ir_node *right = get_Shr_right(node);
220 vrp_left = vrp_get_or_set_info(info, get_Shr_left(node));
222 /* We can only compute this if the right value is a constant*/
223 if (is_Const(right)) {
224 new_bits_set = tarval_shr(vrp_left->bits_set, get_Const_tarval(right));
225 new_bits_not_set = tarval_shr(vrp_left->bits_not_set, get_Const_tarval(right));
231 const vrp_attr *vrp_left;
232 const ir_node *right = get_Shrs_right(node);
234 vrp_left = vrp_get_or_set_info(info, get_Shrs_left(node));
236 /* We can only compute this if the right value is a constant*/
237 if (is_Const(right)) {
238 new_bits_set = tarval_shrs(vrp_left->bits_set, get_Const_tarval(right));
239 new_bits_not_set = tarval_shrs(vrp_left->bits_not_set, get_Const_tarval(right));
245 const vrp_attr *vrp_left, *vrp_right;
247 vrp_left = vrp_get_or_set_info(info, get_Eor_left(node));
248 vrp_right = vrp_get_or_set_info(info, get_Eor_right(node));
250 new_bits_set = tarval_or(
251 tarval_and(vrp_left->bits_set, tarval_not(vrp_right->bits_not_set)),
252 tarval_and(tarval_not(vrp_left->bits_not_set), vrp_right->bits_set));
254 new_bits_not_set = tarval_not(tarval_or(
255 tarval_and(vrp_left->bits_set,vrp_right->bits_set),
256 tarval_and(tarval_not(vrp_left->bits_not_set),
257 tarval_not(vrp_right->bits_not_set))));
263 const vrp_attr *vrp_pred = vrp_get_or_set_info(info, get_Id_pred(node));
264 new_bits_set = vrp_pred->bits_set;
265 new_bits_not_set = vrp_pred->bits_not_set;
266 new_range_top = vrp_pred->range_top;
267 new_range_bottom = vrp_pred->range_bottom;
268 new_range_type = vrp_pred->range_type;
273 const vrp_attr *vrp_pred = vrp_get_or_set_info(info, get_Not_op(node));
274 new_bits_set = tarval_not(vrp_pred->bits_not_set);
275 new_bits_not_set = tarval_not(vrp_pred->bits_set);
280 const ir_node *pred = get_Conv_op(node);
281 ir_mode *old_mode = get_irn_mode(pred);
282 const vrp_attr *vrp_pred;
286 if (!mode_is_int(old_mode))
289 vrp_pred = vrp_get_or_set_info(info, pred);
290 new_mode = get_irn_mode(node);
292 /* The second and is needed if target type is smaller*/
293 new_bits_not_set = tarval_convert_to(get_mode_all_one(old_mode), new_mode);
294 new_bits_not_set = tarval_and(new_bits_not_set, tarval_convert_to(vrp_pred->bits_not_set, new_mode));
295 new_bits_set = tarval_and(
296 new_bits_not_set, tarval_convert_to(vrp_pred->bits_set, new_mode));
298 /* Matze: TODO, BUGGY, tarval_cmp never returns ir_relation_less_equal */
299 if (tarval_cmp(vrp_pred->range_top, get_mode_max(new_mode)) == ir_relation_less_equal) {
300 vrp->range_top = vrp_pred->range_top;
303 /* Matze: TODO, BUGGY, tarval_cmp never returns ir_relation_greater_equal */
304 if (tarval_cmp(vrp_pred->range_bottom, get_mode_min(new_mode)) == ir_relation_greater_equal) {
305 vrp->range_bottom = vrp_pred->range_bottom;
311 const ir_relation relation = get_Confirm_relation(node);
312 const ir_node *bound = get_Confirm_bound(node);
315 if (relation == ir_relation_less_greater) {
316 /** @todo: Handle non-Const bounds */
317 if (is_Const(bound)) {
318 new_range_type = VRP_ANTIRANGE;
319 new_range_top = get_Const_tarval(bound);
320 new_range_bottom = get_Const_tarval(bound);
322 } else if (relation == ir_relation_less_equal) {
323 if (is_Const(bound)) {
324 new_range_type = VRP_RANGE;
325 new_range_top = get_Const_tarval(bound);
326 new_range_bottom = get_tarval_min(get_irn_mode(node));
333 /* combine all ranges*/
335 int num = get_Phi_n_preds(node);
336 ir_relation relation;
339 const ir_node *pred = get_Phi_pred(node,0);
340 const vrp_attr *vrp_pred = vrp_get_or_set_info(info, pred);
341 new_range_top = vrp_pred->range_top;
342 new_range_bottom = vrp_pred->range_bottom;
343 new_range_type = vrp_pred->range_type;
344 new_bits_set = vrp_pred->bits_set;
345 new_bits_not_set = vrp_pred->bits_not_set;
349 for (i = 1; i < num; i++) {
350 pred = get_Phi_pred(node, i);
351 vrp_pred = vrp_get_or_set_info(info, pred);
352 if (new_range_type == VRP_RANGE && vrp_pred->range_type ==
354 relation = tarval_cmp(new_range_top, vrp_pred->range_top);
355 if (relation == ir_relation_less) {
356 new_range_top = vrp_pred->range_top;
358 relation = tarval_cmp(new_range_bottom, vrp_pred->range_bottom);
359 if (relation == ir_relation_greater) {
360 new_range_bottom = vrp_pred->range_bottom;
363 new_range_type = VRP_VARYING;
365 new_bits_set = tarval_and(new_bits_set, vrp_pred->bits_set);
366 new_bits_not_set = tarval_or(new_bits_not_set,
367 vrp_pred->bits_not_set);
373 /* unhandled, therefore never updated */
379 /* TODO: Check, if there can be information derived from any of these:
380 is_Abs(node) is_Alloc(node) is_Anchor(node) is_Borrow(node) is_Bound(node)
381 is_Break(node) is_Builtin(node) is_Call(node)
382 is_Carry(node) is_Cmp(node) is_Cond(node)
383 is_CopyB(node) is_Div(node) is_Dummy(node)
384 is_End(node) is_Free(node)
385 is_IJmp(node) is_InstOf(node) is_Jmp(node) is_Load(node) is_Minus(node)
386 is_Mod(node) is_Mul(node) is_Mulh(node) is_Mux(node) is_NoMem(node)
387 is_Pin(node) is_Proj(node)
388 is_Raise(node) is_Return(node) is_Sel(node) is_Start(node) is_Store(node)
389 is_SymConst(node) is_Sync(node) is_Tuple(node)
392 /* @todo: At this place, we check if the mode of the variable changed. A
393 * better place for this might be in the convopt.c file
396 if (new_bits_set != tarval_bad && get_tarval_mode(new_bits_set) != get_tarval_mode(vrp->bits_set)) {
397 vrp->bits_set = tarval_convert_to(vrp->bits_set, get_irn_mode(node));
399 if (new_bits_not_set != tarval_bad && get_tarval_mode(new_bits_not_set) != get_tarval_mode(vrp->bits_not_set)) {
400 vrp->bits_not_set = tarval_convert_to(vrp->bits_not_set, get_irn_mode(node));
403 if (vrp->range_type != VRP_UNDEFINED && new_range_type != VRP_UNDEFINED && get_tarval_mode(new_range_top) != get_tarval_mode(vrp->range_top)) {
404 /* @todo: We might be able to preserve this range information if it
406 vrp->range_type = VRP_VARYING;
409 /* Merge the newly calculated values with those that might already exist*/
410 if (new_bits_set != tarval_bad) {
411 new_bits_set = tarval_or(new_bits_set, vrp->bits_set);
412 if (new_bits_set != vrp->bits_set) {
413 something_changed = 1;
414 vrp->bits_set = new_bits_set;
417 if (new_bits_not_set != tarval_bad) {
418 new_bits_not_set = tarval_and(new_bits_not_set, vrp->bits_not_set);
420 if (new_bits_not_set != vrp->bits_not_set) {
421 something_changed = 1;
422 vrp->bits_not_set = new_bits_not_set;
426 if (vrp->range_type == VRP_UNDEFINED &&
427 new_range_type != VRP_UNDEFINED) {
428 something_changed = 1;
429 vrp->range_type = new_range_type;
430 vrp->range_bottom = new_range_bottom;
431 vrp->range_top = new_range_top;
433 } else if (vrp->range_type == VRP_RANGE) {
434 if (new_range_type == VRP_RANGE) {
435 if (tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_less) {
436 something_changed = 1;
437 vrp->range_bottom = new_range_bottom;
439 if (tarval_cmp(vrp->range_top, new_range_top) == ir_relation_greater) {
440 something_changed = 1;
441 vrp->range_top = new_range_top;
445 if (new_range_type == VRP_ANTIRANGE) {
446 /* if they are overlapping, cut the range.*/
447 /* TODO: Maybe we can preserve more information here*/
448 if (tarval_cmp(vrp->range_bottom, new_range_top) == ir_relation_greater &&
449 tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_greater) {
450 something_changed = 1;
451 vrp->range_bottom = new_range_top;
453 } else if (tarval_cmp(vrp->range_top, new_range_bottom) == ir_relation_greater &&
454 tarval_cmp(vrp->range_top, new_range_top) == ir_relation_less) {
455 something_changed = 1;
456 vrp->range_top = new_range_bottom;
459 /* We can not handle the case where the anti range is in the*/
463 } else if (vrp->range_type == VRP_ANTIRANGE) {
464 if (new_range_type == VRP_ANTIRANGE) {
465 if (tarval_cmp(vrp->range_bottom, new_range_bottom) == ir_relation_greater) {
466 something_changed = 1;
467 vrp->range_bottom = new_range_bottom;
469 if (tarval_cmp(vrp->range_top, new_range_top) == ir_relation_less) {
470 something_changed = 1;
471 vrp->range_top = new_range_top;
475 if (new_range_type == VRP_RANGE) {
476 if (tarval_cmp(vrp->range_bottom, new_range_top) == ir_relation_greater) {
477 something_changed = 1;
478 vrp->range_bottom = new_range_top;
480 if (tarval_cmp(vrp->range_top, new_range_bottom) == ir_relation_less) {
481 something_changed = 1;
482 vrp->range_top = new_range_bottom;
487 assert(tarval_is_null(
488 tarval_and(vrp->bits_set, tarval_not(vrp->bits_not_set))));
489 return something_changed;
492 static void vrp_first_pass(ir_node *n, void *e)
495 vrp_env_t *env = (vrp_env_t*) e;
500 bitset_set(env->visited, get_irn_idx(n));
502 vrp_update_node(env->info, n);
504 for (i = get_irn_n_outs(n) - 1; i >=0; --i) {
505 ir_node *succ = get_irn_out(n, i);
506 if (bitset_is_set(env->visited, get_irn_idx(succ))) {
508 waitq_put(env->workqueue, succ);
513 static void dump_vrp_info(void *ctx, FILE *F, const ir_node *node)
518 if (!mode_is_int(get_irn_mode(node)))
521 vrp = vrp_get_info(node);
525 fprintf(F, "vrp range type: %d\n", (int) vrp->range_type);
526 if (vrp->range_type == VRP_RANGE || vrp->range_type == VRP_ANTIRANGE) {
527 ir_fprintf(F, "vrp range bottom: %T\n",vrp->range_bottom);
528 ir_fprintf(F, "vrp range top: %T\n", vrp->range_top);
530 ir_fprintf(F, "vrp bits set: %T\n", vrp->bits_set);
531 ir_fprintf(F, "vrp bits not set: %T\n", vrp->bits_not_set);
534 static hook_entry_t dump_hook;
536 void set_vrp_data(ir_graph *irg)
538 ir_node *succ, *node;
543 if (irg->vrp.infos.data != NULL)
546 FIRM_DBG_REGISTER(dbg, "ir.ana.vrp");
548 assure_irg_outs(irg); /* ensure that out edges are consistent*/
549 ir_nodemap_init(&irg->vrp.infos, irg);
550 obstack_init(&irg->vrp.obst);
553 if (dump_hook.hook._hook_node_info == NULL) {
554 dump_hook.hook._hook_node_info = dump_vrp_info;
555 register_hook(hook_node_info, &dump_hook);
558 env = OALLOCZ(&irg->vrp.obst, vrp_env_t);
559 env->workqueue = new_waitq();
562 env->visited = bitset_malloc(get_irg_last_idx(irg));
563 irg_walk_graph(irg, NULL, vrp_first_pass, env);
564 bitset_free(env->visited);
566 /* while there are entries in the worklist, continue*/
567 while (!waitq_empty(env->workqueue)) {
568 node = (ir_node*) waitq_get(env->workqueue);
570 if (vrp_update_node(info, node)) {
571 /* if something changed, add successors to worklist*/
572 for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
573 succ = get_irn_out(node, i);
574 waitq_put(env->workqueue, succ);
578 del_waitq(env->workqueue);
581 void free_vrp_data(ir_graph *irg)
583 if (irg->vrp.infos.data == NULL)
585 obstack_free(&irg->vrp.obst, NULL);
586 ir_nodemap_destroy(&irg->vrp.infos);
589 ir_graph_pass_t *set_vrp_pass(const char *name)
591 return def_graph_pass(name ? name : "set_vrp", set_vrp_data);
594 ir_relation vrp_cmp(const ir_node *left, const ir_node *right)
596 vrp_attr *vrp_left, *vrp_right;
598 if (!mode_is_int(get_irn_mode(left)))
599 return ir_relation_true;
601 vrp_left = vrp_get_info(left);
602 vrp_right = vrp_get_info(right);
604 if (!vrp_left || !vrp_right)
605 return ir_relation_true;
607 if (vrp_left->range_type == VRP_RANGE && vrp_right->range_type == VRP_RANGE) {
608 if (tarval_cmp(vrp_left->range_top, vrp_right->range_bottom) == ir_relation_less) {
609 return ir_relation_less;
611 if (tarval_cmp(vrp_left->range_bottom, vrp_right->range_top) == ir_relation_greater) {
612 return ir_relation_greater;
616 if (!tarval_is_null(tarval_and(vrp_left->bits_set, tarval_not(vrp_right->bits_not_set))) ||
617 !tarval_is_null(tarval_and(tarval_not(vrp_left->bits_not_set), vrp_right->bits_set))) {
618 return ir_relation_less_greater;
621 /* TODO: We can get way more information here*/
622 return ir_relation_true;