X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fopt%2Fopt_osr.c;h=380973d64430da3f4358995ac1be9a787496586c;hb=9c456297552bb20d04e2fe76fd4a712afa8aa63f;hp=2165b59676f62ee4a7c47daef018ea120592caff;hpb=7a483ab981d403222150c320242adaad13d60af9;p=libfirm diff --git a/ir/opt/opt_osr.c b/ir/opt/opt_osr.c index 2165b5967..380973d64 100644 --- a/ir/opt/opt_osr.c +++ b/ir/opt/opt_osr.c @@ -49,7 +49,7 @@ #include "irtools.h" #include "irloop_t.h" #include "array.h" -#include "firmstat.h" +#include "firmstat_t.h" #include "error.h" #include "irpass_t.h" @@ -126,7 +126,7 @@ static int LFTR_cmp(const void *e1, const void *e2, size_t size) (void) size; return l1->src != l2->src; -} /* LFTR_cmp */ +} /** * Find a LFTR edge. @@ -139,8 +139,8 @@ static LFTR_edge *LFTR_find(ir_node *src, iv_env *env) key.src = src; - return (LFTR_edge*)set_find(env->lftr_edges, &key, sizeof(key), hash_ptr(src)); -} /* LFTR_find */ + return set_find(LFTR_edge, env->lftr_edges, &key, sizeof(key), hash_ptr(src)); +} /** * Add a LFTR edge. @@ -164,8 +164,8 @@ static void LFTR_add(ir_node *src, ir_node *dst, unsigned code, ir_node *rc, iv_ * There might be more than one edge here. This is rather bad * because we currently store only one. */ - set_insert(env->lftr_edges, &key, sizeof(key), hash_ptr(src)); -} /* LFTR_add */ + (void)set_insert(LFTR_edge, env->lftr_edges, &key, sizeof(key), hash_ptr(src)); +} /** * Gets the node_entry of a node. @@ -182,7 +182,7 @@ static node_entry *get_irn_ne(ir_node *irn, iv_env *env) set_irn_link(irn, e); } return e; -} /* get_irn_ne */ +} /** * Gets the scc from an induction variable. @@ -194,7 +194,7 @@ static scc *get_iv_scc(ir_node *iv, iv_env *env) { node_entry *e = get_irn_ne(iv, env); return e->pscc; -} /* get_iv_scc */ +} /** * Check if irn is an IV. @@ -207,7 +207,7 @@ static scc *get_iv_scc(ir_node *iv, iv_env *env) static ir_node *is_iv(ir_node *irn, iv_env *env) { return get_irn_ne(irn, env)->header; -} /* is_iv */ +} /** * Check if irn is a region constant. @@ -221,7 +221,7 @@ static int is_rc(ir_node *irn, ir_node *header_block) ir_node *block = get_nodes_block(irn); return (block != header_block) && block_dominates(block, header_block); -} /* is_rc */ +} /** * Set compare function for the quad set. @@ -233,7 +233,7 @@ static int quad_cmp(const void *e1, const void *e2, size_t size) (void) size; return c1->code != c2->code || c1->op1 != c2->op1 || c1->op2 != c2->op2; -} /* quad_cmp */ +} /** * Check if an reduced operation was already calculated. @@ -253,12 +253,11 @@ static ir_node *search(unsigned code, ir_node *op1, ir_node *op2, iv_env *env) key.op1 = op1; key.op2 = op2; - entry = (quadruple_t*)set_find(env->quad_map, &key, sizeof(key), - (code * 9) ^ hash_ptr(op1) ^hash_ptr(op2)); + entry = set_find(quadruple_t, env->quad_map, &key, sizeof(key), (code * 9) ^ hash_ptr(op1) ^ hash_ptr(op2)); if (entry) return entry->res; return NULL; -} /* search */ +} /** * Add an reduced operation. @@ -278,9 +277,8 @@ static void add(unsigned code, ir_node *op1, ir_node *op2, ir_node *result, iv_e key.op2 = op2; key.res = result; - set_insert(env->quad_map, &key, sizeof(key), - (code * 9) ^ hash_ptr(op1) ^hash_ptr(op2)); -} /* add */ + (void)set_insert(quadruple_t, env->quad_map, &key, sizeof(key), (code * 9) ^ hash_ptr(op1) ^ hash_ptr(op2)); +} /** * Find a location where to place a bin-op whose operands are in @@ -299,7 +297,7 @@ static ir_node *find_location(ir_node *block1, ir_node *block2) return block2; assert(block_dominates(block2, block1)); return block1; -} /* find_location */ +} /** * Create a node that executes an op1 code op1 operation. @@ -331,7 +329,7 @@ static ir_node *do_apply(unsigned code, dbg_info *db, ir_node *op1, ir_node *op2 panic("Unsupported opcode"); } return result; -} /* do_apply */ +} /** * The Apply operation. @@ -366,7 +364,7 @@ static ir_node *apply(ir_node *header, ir_node *orig, ir_node *op1, ir_node *op2 } } return result; -} /* apply */ +} /** * The Reduce operation. @@ -430,7 +428,7 @@ static ir_node *reduce(ir_node *orig, ir_node *iv, ir_node *rc, iv_env *env) get_irn_opname(orig), rc)); } return result; -} /* reduce */ +} /** * Update the scc for a newly created IV. @@ -467,7 +465,7 @@ static void update_scc(ir_node *iv, node_entry *e, iv_env *env) } while (! waitq_empty(wq)); del_waitq(wq); DB((dbg, LEVEL_2, "\n")); -} /* update_scc */ +} /** * The Replace operation. We found a node representing iv (+,-,*) rc @@ -500,7 +498,7 @@ static int replace(ir_node *irn, ir_node *iv, ir_node *rc, iv_env *env) return 1; } return 0; -} /* replace */ +} #if 0 /** @@ -528,7 +526,7 @@ static int is_x86_shift_const(ir_node *mul) } } return 0; -} /* is_x86_shift_const */ +} #endif /** @@ -595,7 +593,7 @@ static int is_counter_iv(ir_node *iv, iv_env *env) pscc->incr = get_Const_tarval(have_incr); pscc->code = code; return code != iro_Bad; -} /* is_counter_iv */ +} /** * Check the users of an induction variable for register pressure. @@ -615,8 +613,6 @@ static int check_users_for_reg_pressure(ir_node *iv, iv_env *env) scc *pscc = e->pscc; for (irn = pscc->head; irn != NULL; irn = e->next) { - const ir_edge_t *edge; - foreach_out_edge(irn, edge) { ir_node *user = get_edge_src_irn(edge); node_entry *ne = get_irn_ne(user, env); @@ -668,7 +664,7 @@ static int check_users_for_reg_pressure(ir_node *iv, iv_env *env) * to do a linear function test replacement, so go on. */ return 1; -} /* check_users_for_reg_pressure */ +} /** * Check if a node can be replaced (+, -, *). @@ -716,7 +712,7 @@ static int check_replace(ir_node *irn, iv_env *env) break; } return 0; -} /* check_replace */ +} /** * Check which SCC's are induction variables. @@ -760,8 +756,26 @@ static void classify_iv(scc *pscc, iv_env *env) next = e->next; switch (get_irn_opcode(irn)) { - case iro_Add: case iro_Sub: + only_phi = 0; + { + ir_node *left = get_Sub_left(irn); + node_entry *left_entry = get_irn_ne(left, env); + ir_node *right = get_Sub_right(irn); + node_entry *right_entry = get_irn_ne(right, env); + + if (left_entry->pscc != e->pscc || + (right_entry->pscc != e->pscc && !is_rc(right, header))) { + /* + * Not an induction variable. + * Region constant are only allowed on right hand side. + */ + goto fail; + } + } + break; + + case iro_Add: only_phi = 0; /* fall through */ case iro_Phi: @@ -822,7 +836,7 @@ fail: next = e->next; e->header = NULL; } -} /* classify_iv */ +} /** * Process an SCC for the operator strength reduction. @@ -857,7 +871,7 @@ static void process_scc(scc *pscc, iv_env *env) } else { classify_iv(pscc, env); } -} /* process_scc */ +} /** * If an SCC is a Phi only cycle, remove it. @@ -904,7 +918,7 @@ static void remove_phi_cycle(scc *pscc, iv_env *env) exchange(irn, out_rc); } ++env->replaced; -} /* remove_phi_cycle */ +} /** * Process a SCC for the Phi cycle remove. @@ -935,7 +949,7 @@ static void process_phi_only_scc(scc *pscc, iv_env *env) if (e->next != NULL) remove_phi_cycle(pscc, env); -} /* process_phi_only_scc */ +} /** @@ -955,7 +969,7 @@ static void push(iv_env *env, ir_node *n) env->stack[env->tos++] = n; e = get_irn_ne(n, env); e->in_stack = 1; -} /* push */ +} /** * Pop a node from the stack. @@ -971,7 +985,7 @@ static ir_node *pop(iv_env *env) e->in_stack = 0; return n; -} /* pop */ +} /** * Do Tarjan's SCC algorithm and drive OSR. @@ -1035,7 +1049,7 @@ static void dfs(ir_node *irn, iv_env *env) env->process_scc(pscc, env); } } -} /* dfs */ +} /** * Do the DFS by starting at the End node of a graph. @@ -1064,7 +1078,7 @@ static void do_dfs(ir_graph *irg, iv_env *env) } ir_free_resources(irg, IR_RESOURCE_IRN_VISITED); -} /* do_dfs */ +} /** * Post-block-walker: assign the post-order number. @@ -1075,7 +1089,7 @@ static void assign_po(ir_node *block, void *ctx) node_entry *e = get_irn_ne(block, env); e->POnum = env->POnum++; -} /* assign_po */ +} /** * Apply one LFTR edge operation. @@ -1178,7 +1192,7 @@ static ir_node *applyOneEdge(ir_node *iv, ir_node *rc, LFTR_edge *e, iv_env *env return new_r_Const(irg, tv); } return do_apply(e->code, NULL, rc, e->rc, get_irn_mode(e->dst)); -} /* applyOneEdge */ +} /** * Applies the operations represented by the LFTR edges to a @@ -1221,7 +1235,7 @@ static ir_node *applyEdges(ir_node **pIV, ir_node *rc, iv_env *env) DB((dbg, LEVEL_3, "\n")); *pIV = iv; return rc; -} /* applyEdges */ +} /** * Walker, finds Cmp(iv, rc) or Cmp(rc, iv) @@ -1261,7 +1275,7 @@ static void do_lftr(ir_node *cmp, void *ctx) set_Cmp_right(cmp, nright); ++env->lftr_replaced; } -} /* do_lftr */ +} /** * do linear function test replacement. @@ -1272,28 +1286,7 @@ static void do_lftr(ir_node *cmp, void *ctx) static void lftr(ir_graph *irg, iv_env *env) { irg_walk_graph(irg, NULL, do_lftr, env); -} /* lftr */ - -/** - * Pre-walker: set all node links to NULL and fix the - * block of Proj nodes. - */ -static void clear_and_fix(ir_node *irn, void *env) -{ - (void)env; - - set_irn_link(irn, NULL); - - if (is_Proj(irn)) { - ir_node *pred = get_Proj_pred(irn); - ir_node *pred_block = get_nodes_block(pred); - - if (get_nodes_block(irn) != pred_block) { - set_nodes_block(irn, pred_block); - } - } -} /* clear_and_fix */ - +} /* Remove any Phi cycles with only one real input. */ void remove_phi_cycles(ir_graph *irg) @@ -1326,7 +1319,7 @@ void remove_phi_cycles(ir_graph *irg) * the same block as their predecessors. * This can improve the placement of new nodes. */ - irg_walk_graph(irg, NULL, clear_and_fix, NULL); + irg_walk_graph(irg, NULL, firm_clear_link, NULL); /* calculate the post order number for blocks. */ irg_out_block_walk(get_irg_start_block(irg), NULL, assign_po, &env); @@ -1350,7 +1343,7 @@ void remove_phi_cycles(ir_graph *irg) ir_graph_pass_t *remove_phi_cycles_pass(const char *name) { return def_graph_pass(name ? name : "remove_phi_cycles", remove_phi_cycles); -} /* remove_phi_cycles_pass */ +} /** * Post-walker: fix Add and Sub nodes that where results of I<->P conversions. @@ -1418,7 +1411,7 @@ static void fix_adds_and_subs(ir_node *irn, void *ctx) } } } -} /* fix_adds_and_subs */ +} /* Performs Operator Strength Reduction for the passed graph. */ void opt_osr(ir_graph *irg, unsigned flags) @@ -1451,7 +1444,7 @@ void opt_osr(ir_graph *irg, unsigned flags) * the same block as its predecessors. * This can improve the placement of new nodes. */ - irg_walk_graph(irg, NULL, clear_and_fix, NULL); + irg_walk_graph(irg, NULL, firm_clear_link, NULL); irg_block_edges_walk(get_irg_start_block(irg), NULL, assign_po, &env); @@ -1492,7 +1485,7 @@ static int pass_wrapper(ir_graph *irg, void *context) pass_t *pass = (pass_t*)context; opt_osr(irg, pass->flags); return 0; -} /* pass_wrapper */ +} ir_graph_pass_t *opt_osr_pass(const char *name, unsigned flags) { @@ -1501,4 +1494,4 @@ ir_graph_pass_t *opt_osr_pass(const char *name, unsigned flags) pass->flags = flags; return def_graph_pass_constructor( &pass->pass, name ? name : "osr", pass_wrapper); -} /* opt_osr_pass */ +}