X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana%2Fvrp.c;h=567f3839ace5a966c426a7679f94454b82f0c28a;hb=3da5ed2598245b896255bc444aaa1768f6098cfe;hp=ce4e747ae67e8ab13a7c817136a6a7465e641889;hpb=4400fa157315b9028d3791eba8abc574f017042a;p=libfirm diff --git a/ir/ana/vrp.c b/ir/ana/vrp.c index ce4e747ae..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*/ @@ -81,8 +82,8 @@ static int vrp_update_node(ir_node *node) 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); @@ -97,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)); @@ -129,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; } @@ -157,7 +159,7 @@ static int vrp_update_node(ir_node *node) } case iro_Or: { - vrp_attr *vrp_left, *vrp_right; + 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)); @@ -169,8 +171,8 @@ static int vrp_update_node(ir_node *node) } 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,8 +187,8 @@ static int vrp_update_node(ir_node *node) } 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)); @@ -199,8 +201,8 @@ static int vrp_update_node(ir_node *node) } 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)); @@ -214,8 +216,8 @@ static int vrp_update_node(ir_node *node) } 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)); @@ -229,8 +231,7 @@ static int vrp_update_node(ir_node *node) } 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)); @@ -248,7 +249,7 @@ static int vrp_update_node(ir_node *node) } 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; @@ -258,16 +259,16 @@ static int vrp_update_node(ir_node *node) } case iro_Not: { - vrp_attr *vrp_pred = get_vrp_attr(get_Not_op(node)); + 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; @@ -293,8 +294,8 @@ 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); if (cmp == pn_Cmp_Lg) { @@ -321,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; @@ -331,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); @@ -375,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); @@ -471,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); } } } @@ -484,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)); @@ -539,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; @@ -602,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; }