-static void duplicate_deps(ia32_transform_env_t *env, ir_node *old_node,
- ir_node *new_node)
-{
- int i;
- int deps = get_irn_deps(old_node);
-
- for(i = 0; i < deps; ++i) {
- ir_node *dep = get_irn_dep(old_node, i);
- ir_node *new_dep = transform_node(env, dep);
-
- add_irn_dep(new_node, new_dep);
- }
-}
-
-static ir_node *duplicate_node(ia32_transform_env_t *env, ir_node *node)
-{
- ir_graph *irg = env->irg;
- dbg_info *dbgi = get_irn_dbg_info(node);
- ir_mode *mode = get_irn_mode(node);
- ir_op *op = get_irn_op(node);
- ir_node *block;
- ir_node *new_node;
- int i, arity;
-
- block = transform_node(env, get_nodes_block(node));
-
- arity = get_irn_arity(node);
- if(op->opar == oparity_dynamic) {
- new_node = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
- for(i = 0; i < arity; ++i) {
- ir_node *in = get_irn_n(node, i);
- in = transform_node(env, in);
- add_irn_n(new_node, in);
- }
- } else {
- ir_node **ins = alloca(arity * sizeof(ins[0]));
- for(i = 0; i < arity; ++i) {
- ir_node *in = get_irn_n(node, i);
- ins[i] = transform_node(env, in);
- }
-
- new_node = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
- }
-
- copy_node_attr(node, new_node);
- duplicate_deps(env, node, new_node);
-
- return new_node;
-}
-
-static ir_node *transform_node(ia32_transform_env_t *env, ir_node *node)
-{
- ir_node *new_node;
- ir_op *op = get_irn_op(node);
-
- if(irn_visited(node)) {
- assert(get_new_node(node) != NULL);
- return get_new_node(node);
- }
-
- mark_irn_visited(node);
- DEBUG_ONLY(set_new_node(node, NULL));
-
- if (op->ops.generic) {
- transform_func *transform = (transform_func *)op->ops.generic;
-
- new_node = (*transform)(env, node);
- assert(new_node != NULL);
- } else {
- new_node = duplicate_node(env, node);
- }
- //ir_fprintf(stderr, "%+F -> %+F\n", node, new_node);
-
- set_new_node(node, new_node);
- mark_irn_visited(new_node);
- hook_dead_node_elim_subst(current_ir_graph, node, new_node);
- return new_node;
-}
-
-static void fix_loops(ia32_transform_env_t *env, ir_node *node)
-{
- int i, arity;
-
- if(irn_visited(node))
- return;
- mark_irn_visited(node);
-
- assert(node_is_in_irgs_storage(env->irg, node));
-
- if(!is_Block(node)) {
- ir_node *block = get_nodes_block(node);
- ir_node *new_block = (ir_node*) get_irn_link(block);
-
- if(new_block != NULL) {
- set_nodes_block(node, new_block);
- block = new_block;
- }
-
- fix_loops(env, block);
- }
-
- arity = get_irn_arity(node);
- for(i = 0; i < arity; ++i) {
- ir_node *in = get_irn_n(node, i);
- ir_node *new = (ir_node*) get_irn_link(in);
-
- if(new != NULL && new != in) {
- set_irn_n(node, i, new);
- in = new;
- }
-
- fix_loops(env, in);
- }
-
- arity = get_irn_deps(node);
- for(i = 0; i < arity; ++i) {
- ir_node *in = get_irn_dep(node, i);
- ir_node *new = (ir_node*) get_irn_link(in);
-
- if(new != NULL && new != in) {
- set_irn_dep(node, i, new);
- in = new;
- }
-
- fix_loops(env, in);
- }
-}
-
-static void pre_transform_node(ir_node **place, ia32_transform_env_t *env)
-{
- if(*place == NULL)
- return;
-
- *place = transform_node(env, *place);
-}
-
-static void transform_nodes(ia32_code_gen_t *cg)
-{
- int i;
- ir_graph *irg = cg->irg;
- ir_node *old_end;
- ia32_transform_env_t env;
-
- hook_dead_node_elim(irg, 1);
-
- inc_irg_visited(irg);
-
- env.irg = irg;
- env.cg = cg;
- env.visited = get_irg_visited(irg);
- env.worklist = new_pdeq();
- env.old_anchors = alloca(anchor_max * sizeof(env.old_anchors[0]));
-
- old_end = get_irg_end(irg);
-
- /* put all anchor nodes in the worklist */
- for(i = 0; i < anchor_max; ++i) {
- ir_node *anchor = irg->anchors[i];
- if(anchor == NULL)
- continue;
- pdeq_putr(env.worklist, anchor);
-
- // remember anchor
- env.old_anchors[i] = anchor;
- // and set it to NULL to make sure we don't accidently use it
- irg->anchors[i] = NULL;
- }
-
- // pre transform some anchors (so they are available in the other transform
- // functions)
- set_irg_bad(irg, transform_node(&env, env.old_anchors[anchor_bad]));
- set_irg_no_mem(irg, transform_node(&env, env.old_anchors[anchor_no_mem]));
- set_irg_start_block(irg, transform_node(&env, env.old_anchors[anchor_start_block]));
- set_irg_start(irg, transform_node(&env, env.old_anchors[anchor_start]));
- set_irg_frame(irg, transform_node(&env, env.old_anchors[anchor_frame]));
-
- pre_transform_node(&cg->unknown_gp, &env);
- pre_transform_node(&cg->unknown_vfp, &env);
- pre_transform_node(&cg->unknown_xmm, &env);
- pre_transform_node(&cg->noreg_gp, &env);
- pre_transform_node(&cg->noreg_vfp, &env);
- pre_transform_node(&cg->noreg_xmm, &env);
-
- /* process worklist (this should transform all nodes in the graph) */
- while(!pdeq_empty(env.worklist)) {
- ir_node *node = pdeq_getl(env.worklist);
- transform_node(&env, node);
- }
-
- /* fix loops and set new anchors*/
- inc_irg_visited(irg);
- for(i = 0; i < anchor_max; ++i) {
- ir_node *anchor = env.old_anchors[i];
- if(anchor == NULL)
- continue;
-
- anchor = get_irn_link(anchor);
- fix_loops(&env, anchor);
- assert(irg->anchors[i] == NULL || irg->anchors[i] == anchor);
- irg->anchors[i] = anchor;
- }
-
- del_pdeq(env.worklist);
- free_End(old_end);
- hook_dead_node_elim(irg, 0);
-}
-
-void ia32_transform_graph(ia32_code_gen_t *cg)
-{
- ir_graph *irg = cg->irg;
- be_irg_t *birg = cg->birg;
- ir_graph *old_current_ir_graph = current_ir_graph;
- int old_interprocedural_view = get_interprocedural_view();
- struct obstack *old_obst = NULL;
- struct obstack *new_obst = NULL;
-
- current_ir_graph = irg;
- set_interprocedural_view(0);
- register_transformers();
-
- /* most analysis info is wrong after transformation */
- free_callee_info(irg);
- free_irg_outs(irg);
- irg->outs_state = outs_none;
- free_trouts();
- free_loop_information(irg);
- set_irg_doms_inconsistent(irg);
- be_invalidate_liveness(birg);
- be_invalidate_dom_front(birg);
-
- /* create a new obstack */
- old_obst = irg->obst;
- new_obst = xmalloc(sizeof(*new_obst));
- obstack_init(new_obst);
- irg->obst = new_obst;
- irg->last_node_idx = 0;
-
- /* create new value table for CSE */
- del_identities(irg->value_table);
- irg->value_table = new_identities();
-
- /* do the main transformation */
- transform_nodes(cg);
-
- /* we don't want the globals anchor anymore */
- set_irg_globals(irg, new_r_Bad(irg));
-
- /* free the old obstack */
- obstack_free(old_obst, 0);
- xfree(old_obst);
-
- /* restore state */
- current_ir_graph = old_current_ir_graph;
- set_interprocedural_view(old_interprocedural_view);
-
- /* recalculate edges */
- edges_deactivate(irg);
- edges_activate(irg);
-}
-