X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Fvrp.c;h=567f3839ace5a966c426a7679f94454b82f0c28a;hb=3da5ed2598245b896255bc444aaa1768f6098cfe;hp=a54bb803cce92c33fb63c94bda5b4a39a9c30876;hpb=7c36344d22a7c306a4e216f135c974bdb9f6b943;p=libfirm diff --git a/ir/ana/vrp.c b/ir/ana/vrp.c index a54bb803c..567f3839a 100644 --- a/ir/ana/vrp.c +++ b/ir/ana/vrp.c @@ -27,6 +27,7 @@ #include "irtypes.h" #include "vrp.h" +#include "iroptimize.h" #include "irouts.h" #include "irgraph_t.h" #include "irgopt.h" @@ -37,13 +38,14 @@ #include "irop.h" #include "pdeq.h" #include "irphase_t.h" -#include "irprintf.h" +#include "debug.h" static char v; static void *VISITED = &v; struct vrp_env_t { waitq *workqueue; + DEBUG_ONLY(firm_dbg_module_t *dbg); }; static vrp_attr *get_vrp_attr(const ir_node *node) @@ -65,7 +67,6 @@ static int vrp_update_node(ir_node *node) return 0; /* we don't optimize for non-int-nodes*/ } - ir_printf("update_vrp for %d called\n", get_irn_node_nr(node)); vrp = get_vrp_attr(node); /* TODO: Check if all predecessors have valid VRP information*/ @@ -74,23 +75,22 @@ static int vrp_update_node(ir_node *node) case iro_Const: { tarval *tv = get_Const_tarval(node); new_bits_set = tv; - new_bits_not_set = tarval_not(tv); + new_bits_not_set = tv; new_range_bottom = tv; new_range_top = tv; new_range_type = VRP_RANGE; break; } - case iro_And: { - vrp_attr *vrp_left, *vrp_right; - ir_node *left, *right; + const vrp_attr *vrp_left, *vrp_right; + const ir_node *left, *right; left = get_And_left(node); right = get_And_right(node); vrp_left = get_vrp_attr(left); vrp_right = get_vrp_attr(right); new_bits_set = tarval_and(vrp_left->bits_set, vrp_right->bits_set); - new_bits_not_set = tarval_or(vrp_left->bits_not_set, vrp_right->bits_not_set); + new_bits_not_set = tarval_and(vrp_left->bits_not_set, vrp_right->bits_not_set); break; } @@ -98,7 +98,7 @@ static int vrp_update_node(ir_node *node) case iro_Add: { int overflow_top, overflow_bottom; tarval *new_top, *new_bottom; - vrp_attr *vrp_left, *vrp_right; + const vrp_attr *vrp_left, *vrp_right; vrp_left = get_vrp_attr(get_Add_left(node)); vrp_right = get_vrp_attr(get_Add_right(node)); @@ -130,12 +130,13 @@ static int vrp_update_node(ir_node *node) case iro_Sub: { int overflow_top, overflow_bottom; tarval *new_top, *new_bottom; - vrp_attr *vrp_left, *vrp_right; + const vrp_attr *vrp_left, *vrp_right; vrp_left = get_vrp_attr(get_Sub_left(node)); vrp_right = get_vrp_attr(get_Sub_right(node)); if (vrp_left->range_type == VRP_UNDEFINED || vrp_right->range_type == - VRP_UNDEFINED) { + VRP_UNDEFINED || vrp_left->range_type == VRP_VARYING || + vrp_right->range_type == VRP_VARYING) { return 0; } @@ -158,24 +159,20 @@ static int vrp_update_node(ir_node *node) } case iro_Or: { - vrp_attr *vrp_left, *vrp_right; - ir_node *left, *right; - - left = get_Or_left(node); - right = get_Or_right(node); + const vrp_attr *vrp_left, *vrp_right; vrp_left = get_vrp_attr(get_Or_left(node)); vrp_right = get_vrp_attr(get_Or_right(node)); new_bits_set = tarval_or(vrp_left->bits_set, vrp_right->bits_set); - new_bits_not_set = tarval_and(vrp_left->bits_not_set, vrp_right->bits_not_set); + new_bits_not_set = tarval_or(vrp_left->bits_not_set, vrp_right->bits_not_set); break; } case iro_Rotl: { - vrp_attr *vrp_left, *vrp_right; - ir_node *right = get_Rotl_right(node); + const vrp_attr *vrp_left, *vrp_right; + const ir_node *right = get_Rotl_right(node); vrp_left = get_vrp_attr(get_Rotl_left(node)); vrp_right = get_vrp_attr(get_Rotl_right(node)); @@ -185,111 +182,74 @@ static int vrp_update_node(ir_node *node) tarval *bits_set, *bits_not_set; bits_set = tarval_rotl(vrp_left->bits_set, get_Const_tarval(right)); bits_not_set = tarval_rotl(vrp_left->bits_not_set, get_Const_tarval(right)); - - new_bits_set = tarval_or(bits_set, vrp->bits_set); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); } break; } case iro_Shl: { - vrp_attr *vrp_left, *vrp_right; - ir_node *right = get_Shl_right(node); + const vrp_attr *vrp_left, *vrp_right; + const ir_node *right = get_Shl_right(node); vrp_left = get_vrp_attr(get_Shl_left(node)); vrp_right = get_vrp_attr(get_Shl_right(node)); /* We can only compute this if the right value is a constant*/ if (is_Const(right)) { - tarval *bits_set, *bits_not_set; - ir_mode *m = get_tarval_mode(vrp->bits_not_set); - bits_set = tarval_shl(vrp_left->bits_set, get_Const_tarval(right)); - bits_not_set = tarval_shl(vrp_left->bits_not_set, get_Const_tarval(right)); - - new_bits_set = tarval_or(bits_set, vrp->bits_set); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); - - bits_not_set = tarval_not( tarval_shl( - get_mode_all_one(m), - get_Const_tarval(right))); - new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set); - + new_bits_set = tarval_shl(vrp_left->bits_set, get_Const_tarval(right)); + new_bits_not_set = tarval_shl(vrp_left->bits_not_set, get_Const_tarval(right)); } break; } case iro_Shr: { - vrp_attr *vrp_left, *vrp_right; - ir_node *right = get_Shr_right(node); + const vrp_attr *vrp_left, *vrp_right; + const ir_node *right = get_Shr_right(node); vrp_left = get_vrp_attr(get_Shr_left(node)); vrp_right = get_vrp_attr(get_Shr_right(node)); /* We can only compute this if the right value is a constant*/ if (is_Const(right)) { - tarval *bits_set, *bits_not_set; - ir_mode *m = get_tarval_mode(vrp->bits_not_set); - bits_set = tarval_shr(vrp_left->bits_set, get_Const_tarval(right)); - bits_not_set = tarval_shr(vrp_left->bits_not_set, get_Const_tarval(right)); - - new_bits_set = tarval_or(bits_set, vrp->bits_set); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); - - bits_not_set = tarval_not( tarval_shr( - get_mode_all_one(m), - get_Const_tarval(right))); - new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set); + new_bits_set = tarval_shr(vrp_left->bits_set, get_Const_tarval(right)); + new_bits_not_set = tarval_shr(vrp_left->bits_not_set, get_Const_tarval(right)); } break; } case iro_Shrs: { - vrp_attr *vrp_left, *vrp_right; - ir_node *right = get_Shrs_right(node); + const vrp_attr *vrp_left, *vrp_right; + const ir_node *right = get_Shrs_right(node); vrp_left = get_vrp_attr(get_Shrs_left(node)); vrp_right = get_vrp_attr(get_Shrs_right(node)); /* We can only compute this if the right value is a constant*/ if (is_Const(right)) { - tarval *bits_set, *bits_not_set; - ir_mode *m = get_tarval_mode(vrp->bits_not_set); - bits_set = tarval_shrs(vrp_left->bits_set, get_Const_tarval(right)); - bits_not_set = tarval_shrs(vrp_left->bits_not_set, get_Const_tarval(right)); - - new_bits_set = tarval_or(bits_set, vrp->bits_set); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); - - bits_not_set = tarval_not( tarval_shrs( - get_mode_all_one(m), - get_Const_tarval(right))); - new_bits_not_set = tarval_or(bits_not_set, new_bits_not_set); + new_bits_set = tarval_shrs(vrp_left->bits_set, get_Const_tarval(right)); + new_bits_not_set = tarval_shrs(vrp_left->bits_not_set, get_Const_tarval(right)); } break; } case iro_Eor: { - tarval *bits_set, *bits_not_set; - vrp_attr *vrp_left, *vrp_right; + const vrp_attr *vrp_left, *vrp_right; vrp_left = get_vrp_attr(get_Eor_left(node)); vrp_right = get_vrp_attr(get_Eor_right(node)); - bits_not_set = tarval_or( - tarval_and(vrp_left->bits_set, vrp_right->bits_set), - tarval_and(vrp_left->bits_not_set, - vrp_right->bits_not_set)); + new_bits_set = tarval_or( + tarval_and(vrp_left->bits_set, tarval_not(vrp_right->bits_not_set)), + tarval_and(tarval_not(vrp_left->bits_not_set), vrp_right->bits_set)); - bits_set = tarval_or( - tarval_and(vrp_left->bits_set, vrp_right->bits_not_set), - tarval_and(vrp_left->bits_not_set, vrp_right->bits_set)); + new_bits_not_set = tarval_not(tarval_or( + tarval_and(vrp_left->bits_set,vrp_right->bits_set), + tarval_and(tarval_not(vrp_left->bits_not_set), + tarval_not(vrp_right->bits_not_set)))); - new_bits_set = tarval_or(bits_set, vrp->bits_set); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); break; } case iro_Id: { - vrp_attr *vrp_pred = get_vrp_attr(get_Id_pred(node)); + const vrp_attr *vrp_pred = get_vrp_attr(get_Id_pred(node)); new_bits_set = vrp_pred->bits_set; new_bits_not_set = vrp_pred->bits_not_set; new_range_top = vrp_pred->range_top; @@ -299,19 +259,18 @@ static int vrp_update_node(ir_node *node) } case iro_Not: { - vrp_attr *vrp_pred = get_vrp_attr(get_Not_op(node)); - new_bits_set = tarval_or(vrp_pred->bits_not_set, vrp->bits_set); - new_bits_not_set = tarval_or(vrp_pred->bits_set, vrp->bits_not_set); + const vrp_attr *vrp_pred = get_vrp_attr(get_Not_op(node)); + new_bits_set = tarval_not(vrp_pred->bits_not_set); + new_bits_not_set = tarval_not(vrp_pred->bits_set); break; } case iro_Conv: { - ir_node *pred = get_Conv_op(node); + const ir_node *pred = get_Conv_op(node); ir_mode *old_mode = get_irn_mode(pred); - vrp_attr *vrp_pred = get_vrp_attr(pred); + const vrp_attr *vrp_pred = get_vrp_attr(pred); ir_mode *new_mode; - tarval *bits_not_set; if (!mode_is_int(old_mode)) return 0; @@ -319,14 +278,10 @@ static int vrp_update_node(ir_node *node) new_mode = get_irn_mode(node); /* The second and is needed if target type is smaller*/ - bits_not_set = tarval_not( - tarval_convert_to(get_mode_all_one(old_mode), - new_mode - )); - bits_not_set = tarval_or(bits_not_set, tarval_convert_to(vrp_pred->bits_not_set, new_mode)); - new_bits_not_set = tarval_or(bits_not_set, vrp->bits_not_set); + new_bits_not_set = tarval_convert_to(get_mode_all_one(old_mode), new_mode); + new_bits_not_set = tarval_and(new_bits_not_set, tarval_convert_to(vrp_pred->bits_not_set, new_mode)); new_bits_set = tarval_and( - tarval_not(bits_not_set), tarval_convert_to(vrp_pred->bits_set, new_mode)); + new_bits_not_set, tarval_convert_to(vrp_pred->bits_set, new_mode)); if (tarval_cmp(vrp_pred->range_top, get_mode_max(new_mode)) == pn_Cmp_Le) { vrp->range_top = vrp_pred->range_top; @@ -339,36 +294,22 @@ static int vrp_update_node(ir_node *node) } case iro_Confirm: { - pn_Cmp cmp = get_Confirm_cmp(node); - ir_node *bound = get_Confirm_bound(node); + const pn_Cmp cmp = get_Confirm_cmp(node); + const ir_node *bound = get_Confirm_bound(node); - /** @todo: Handle non-Const bounds */ if (cmp == pn_Cmp_Lg) { - /** @todo: Is there some way to preserve the information? */ - new_range_type = VRP_ANTIRANGE; + /** @todo: Handle non-Const bounds */ if (is_Const(bound)) { + new_range_type = VRP_ANTIRANGE; new_range_top = get_Const_tarval(bound); new_range_bottom = get_Const_tarval(bound); } } else if (cmp == pn_Cmp_Le) { - if (vrp->range_type == VRP_UNDEFINED) { + if (is_Const(bound)) { new_range_type = VRP_RANGE; - if (is_Const(bound)) { - new_range_top = get_Const_tarval(bound); - } + new_range_top = get_Const_tarval(bound); new_range_bottom = get_tarval_min(get_irn_mode(node)); - } else if (vrp->range_type == VRP_RANGE) { - if (is_Const(bound)) { - if (tarval_cmp(vrp->range_top, - get_Const_tarval(bound)) == pn_Cmp_Le) { - new_range_top = get_Const_tarval(bound); - } - new_range_bottom = get_tarval_min(get_irn_mode(node)); - - } else if (vrp->range_type == VRP_ANTIRANGE) { - /** @todo: How do we manage not to get a never ending loop? */ - } } } break; @@ -381,8 +322,8 @@ static int vrp_update_node(ir_node *node) pn_Cmp cmp; int i; - ir_node *pred = get_Phi_pred(node,0); - vrp_attr *vrp_pred = get_vrp_attr(pred); + const ir_node *pred = get_Phi_pred(node,0); + const vrp_attr *vrp_pred = get_vrp_attr(pred); new_range_top = vrp_pred->range_top; new_range_bottom = vrp_pred->range_bottom; new_range_type = vrp_pred->range_type; @@ -391,7 +332,6 @@ static int vrp_update_node(ir_node *node) assert(num > 0); - for (i = 1; i < num; i++) { pred = get_Phi_pred(node, i); vrp_pred = get_vrp_attr(pred); @@ -407,8 +347,10 @@ static int vrp_update_node(ir_node *node) } } else { new_range_type = VRP_VARYING; - break; } + new_bits_set = tarval_and(new_bits_set, vrp_pred->bits_set); + new_bits_not_set = tarval_or(new_bits_not_set, + vrp_pred->bits_not_set); } break; @@ -433,6 +375,23 @@ static int vrp_update_node(ir_node *node) is_SymConst(node) is_Sync(node) is_Tuple(node) */ + /* @todo: At this place, we check if the mode of the variable changed. A + * better place for this might be in the convopt.c file + */ + + if (new_bits_set != tarval_bad && get_tarval_mode(new_bits_set) != get_tarval_mode(vrp->bits_set)) { + vrp->bits_set = tarval_convert_to(vrp->bits_set, get_irn_mode(node)); + } + if (new_bits_not_set != tarval_bad && get_tarval_mode(new_bits_not_set) != get_tarval_mode(vrp->bits_not_set)) { + vrp->bits_not_set = tarval_convert_to(vrp->bits_not_set, get_irn_mode(node)); + } + + if (vrp->range_type != VRP_UNDEFINED && new_range_type != VRP_UNDEFINED && get_tarval_mode(new_range_top) != get_tarval_mode(vrp->range_top)) { + /* @todo: We might be able to preserve this range information if it + * fits in */ + vrp->range_type = VRP_VARYING; + } + /* Merge the newly calculated values with those that might already exist*/ if (new_bits_set != tarval_bad) { new_bits_set = tarval_or(new_bits_set, vrp->bits_set); @@ -441,9 +400,8 @@ static int vrp_update_node(ir_node *node) vrp->bits_set = new_bits_set; } } - if (new_bits_not_set != tarval_bad) { - new_bits_not_set = tarval_or(new_bits_not_set, vrp->bits_not_set); + new_bits_not_set = tarval_and(new_bits_not_set, vrp->bits_not_set); if (tarval_cmp(new_bits_not_set, vrp->bits_not_set) != pn_Cmp_Eq) { something_changed = 1; @@ -513,7 +471,7 @@ static int vrp_update_node(ir_node *node) } assert(tarval_is_null( - tarval_and(vrp->bits_set, vrp->bits_not_set))); + tarval_and(vrp->bits_set, tarval_not(vrp->bits_not_set)))); return something_changed; } @@ -530,11 +488,12 @@ static void vrp_first_pass(ir_node *n, void *e) vrp_update_node(n); + assure_irg_outs(get_current_ir_graph()); for (i = get_irn_n_outs(n) - 1; i >=0; --i) { succ = get_irn_out(n, i); if (get_irn_link(succ) == VISITED) { /* we found a loop*/ - waitq_put(env->workqueue, n); + waitq_put(env->workqueue, succ); } } } @@ -543,11 +502,10 @@ static void *vrp_init_node(ir_phase *phase, const ir_node *n, void *old) { ir_mode *mode; vrp_attr *vrp; + struct vrp_env_t *env = phase->priv; - ir_printf("initialized node nr: %d\n", get_irn_node_nr(n)); - if (old) { - assert(1==0 && "init called for node already initialized"); - } + DBG((env->dbg, LEVEL_2, "initialized node nr: %d\n", get_irn_node_nr(n))); + assert(old==NULL && "init called for node already initialized"); vrp = phase_alloc(phase, sizeof(vrp_attr)); memset(vrp, 0, sizeof(vrp_attr)); @@ -563,15 +521,15 @@ static void *vrp_init_node(ir_phase *phase, const ir_node *n, void *old) if (mode_is_int(mode)) { /* We are assuming that 0 is always represented as this modes null */ vrp->valid = 1; - vrp->bits_set = - vrp->bits_not_set = get_mode_null(mode); - vrp->range_bottom = + vrp->bits_set = get_mode_null(mode); + vrp->bits_not_set = get_mode_all_one(mode); + vrp->range_bottom = get_tarval_top(); vrp->range_top = get_tarval_top(); } else { vrp->valid = 0; - vrp->bits_set = - vrp->bits_not_set = - vrp->range_bottom = + vrp->bits_set = get_tarval_bad(); + vrp->bits_not_set = get_tarval_bad(); + vrp->range_bottom = get_tarval_bad(); vrp->range_top = get_tarval_bad(); } @@ -598,6 +556,7 @@ void set_vrp_data(ir_graph *irg) phase = new_phase(irg, vrp_init_node); irg_register_phase(irg, PHASE_VRP, phase); env = phase_alloc(phase, sizeof(*env)); + FIRM_DBG_REGISTER(env->dbg, "ir.ana.vrp"); phase->priv = env; } else { env = phase->priv; @@ -648,8 +607,8 @@ pn_Cmp vrp_cmp(const ir_node *left, const ir_node *right) } } - if (!tarval_is_null(tarval_and(vrp_left->bits_set, vrp_right->bits_not_set)) || - !tarval_is_null(tarval_and(vrp_left->bits_not_set, vrp_right->bits_set))) { + if (!tarval_is_null(tarval_and(vrp_left->bits_set, tarval_not(vrp_right->bits_not_set))) || + !tarval_is_null(tarval_and(tarval_not(vrp_left->bits_not_set), vrp_right->bits_set))) { return pn_Cmp_Lg; } /* TODO: We can get way more information here*/ @@ -661,11 +620,16 @@ vrp_attr *vrp_get_info(const ir_node *node) { const ir_graph *irg = get_irn_irg(node); const ir_phase *phase = irg_get_phase(irg, PHASE_VRP); + vrp_attr *vrp; if (phase == NULL) { /* phase has not yet been initialized */ return NULL; } - return phase_get_irn_data(phase, node); + vrp = phase_get_irn_data(phase, node); + if (vrp && vrp->valid) { + return vrp; + } + return NULL; }