static void walk_topo_helper(ir_node* irn, std::function<void (ir_node*, void*)> walker, void* env) { if (irn_visited(irn)) return; /* only break loops at phi/block nodes */ const bool is_loop_breaker = is_Phi(irn) || is_Block(irn); if (is_loop_breaker) mark_irn_visited(irn); if (!is_Block(irn)) { ir_node* block = get_nodes_block(irn); if (block != NULL) walk_topo_helper(block, walker, env); } for (int i = 0; i < get_irn_arity(irn); ++i) { ir_node* pred = get_irn_n(irn, i); walk_topo_helper(pred, walker, env); } if (is_loop_breaker || !irn_visited(irn)) walker(irn, env); mark_irn_visited(irn); }
/** * Adds a control dependence from node to dep_on. */ static void add_cdep(ir_node *node, ir_node *dep_on) { ir_cdep *dep = find_cdep(node); assert(is_Block(dep_on)); if (dep == NULL) { ir_cdep *newdep = OALLOC(&cdep_data->obst, ir_cdep); newdep->node = dep_on; newdep->next = NULL; pmap_insert(cdep_data->cdep_map, node, newdep); } else { ir_cdep *newdep; for (;;) { if (get_cdep_node(dep) == dep_on) return; if (dep->next == NULL) break; dep = dep->next; } newdep = OALLOC(&cdep_data->obst, ir_cdep); newdep->node = dep_on; newdep->next = NULL; dep->next = newdep; } }
/** * Edge hook to dump the schedule edges. */ static void sched_edge_hook(FILE *F, const ir_node *irn) { ir_graph *irg = get_irn_irg(irn); if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) return; if (is_Proj(irn) || is_Block(irn) || !sched_is_scheduled(irn)) return; ir_node *const prev = sched_prev(irn); if (!sched_is_begin(prev)) { fprintf(F, "edge:{sourcename: "); print_nodeid(F, irn); fprintf(F, " targetname: "); print_nodeid(F, prev); fprintf(F, " color:magenta}\n"); } }
/** * Compute the height of a node in a block. * @param h The heights object. * @param irn The node. * @param bl The block. */ static unsigned compute_height(ir_heights_t *h, ir_node *irn, const ir_node *bl) { irn_height_t *ih = get_height_data(h, irn); /* bail out if we already visited that node. */ if (ih->visited >= h->visited) return ih->height; ih->visited = h->visited; ih->height = 0; foreach_out_edge(irn, edge) { ir_node *dep = get_edge_src_irn(edge); if (!is_Block(dep) && !is_Phi(dep) && get_nodes_block(dep) == bl) { unsigned dep_height = compute_height(h, dep, bl); ih->height = MAX(ih->height, dep_height+1); } }
/** * specialized version of irg_walk_2, called if only post callback exists */ static void irg_walk_2_post(ir_node *node, irg_walk_func *post, void *env) { ir_graph *irg = get_irn_irg(node); ir_visited_t visited = irg->visited; set_irn_visited(node, visited); if (!is_Block(node)) { ir_node *pred = get_nodes_block(node); if (pred->visited < visited) irg_walk_2_post(pred, post, env); } foreach_irn_in_r(node, i, pred) { if (pred->visited < visited) irg_walk_2_post(pred, post, env); } post(node, env); }
void instrument_initcall(ir_graph *irg, ir_entity *ent) { ir_node *initial_exec; ir_node *first_block = NULL; int i, idx, need_new_block; symconst_symbol sym; assure_edges(irg); /* find the first block */ initial_exec = get_irg_initial_exec(irg); foreach_out_edge(initial_exec, edge) { ir_node *succ = get_edge_src_irn(edge); if (is_Block(succ)) { /* found the first block */ first_block = succ; break; } }
static void dump_backend_info_hook(void *context, FILE *F, const ir_node *node) { (void)context; ir_graph *const irg = get_irn_irg(node); if (!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) return; be_dump_reqs_and_registers(F, node); if (is_Block(node)) { be_lv_t *const lv = be_get_irg_liveness(irg); if (lv->sets_valid) be_dump_liveness_block(lv, F, node); } #ifndef NDEBUG if (!is_Proj(node)) { char const *const orig = be_get_info(node)->orig_node; fprintf(F, "orig node = %s\n", orig ? orig : "n/a"); } #endif }
void exchange_cdep(ir_node *old, const ir_node *nw) { ir_cdep *cdep = find_cdep(nw); assert(is_Block(old)); pmap_insert(cdep_data->cdep_map, old, cdep); }
ir_cdep *find_cdep(const ir_node *block) { assert(is_Block(block)); return pmap_get(ir_cdep, cdep_data->cdep_map, block); }
static ir_node *get_irn_safe_n(const ir_node *node, int n) { if (n == -1 && is_Block(node)) return NULL; return get_irn_n(node, n); }
static inline const ir_dom_info *get_pdom_info_const(const ir_node *block) { assert(is_Block(block)); return &block->attr.block.pdom; }
static inline ir_dom_info *get_dom_info(ir_node *block) { assert(is_Block(block)); return &block->attr.block.dom; }
/** * Pre-walker for connecting DAGs and counting. */ static void connect_dags(ir_node *node, void *env) { dag_env_t *dag_env = (dag_env_t*)env; int i, arity; ir_node *block; dag_entry_t *entry; ir_mode *mode; if (is_Block(node)) return; block = get_nodes_block(node); /* ignore start end end blocks */ ir_graph *const irg = get_Block_irg(block); if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg)) return; /* ignore Phi nodes */ if (is_Phi(node)) return; if (dag_env->options & FIRMSTAT_ARGS_ARE_ROOTS && is_arg(node)) return; mode = get_irn_mode(node); if (mode == mode_X || mode == mode_M) { /* do NOT count mode_X and mode_M nodes */ return; } /* if this option is set, Loads are always leaves */ if (dag_env->options & FIRMSTAT_LOAD_IS_LEAVE && is_Load(node)) return; if (dag_env->options & FIRMSTAT_CALL_IS_LEAVE && is_Call(node)) return; entry = get_irn_dag_entry(node); if (! entry) { /* found an unassigned node, maybe a new root */ entry = new_dag_entry(dag_env, node); } /* put the predecessors into the same DAG as the current */ for (i = 0, arity = get_irn_arity(node); i < arity; ++i) { ir_node *prev = get_irn_n(node, i); ir_mode *mode = get_irn_mode(prev); if (is_Phi(prev)) continue; if (mode == mode_X || mode == mode_M) continue; /* * copy constants if requested into the DAG's * beware, do NOT add a link, as this will result in * wrong intersections */ if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) { if (is_irn_constlike(prev)) { ++entry->num_nodes; ++entry->num_inner_nodes; } } /* only nodes from the same block goes into the DAG */ if (get_nodes_block(prev) == block) { dag_entry_t *prev_entry = get_irn_dag_entry(prev); if (! prev_entry) { /* not assigned node, put it into the same DAG */ set_irn_dag_entry(prev, entry); ++entry->num_nodes; ++entry->num_inner_nodes; } else { if (prev_entry == entry) { /* We found a node that is already assigned to this DAG. This DAG is not a tree. */ entry->is_tree = 0; } else { /* two DAGs intersect: copy the data to one of them and kill the other */ entry->num_roots += prev_entry->num_roots; entry->num_nodes += prev_entry->num_nodes; entry->num_inner_nodes += prev_entry->num_inner_nodes; entry->is_tree &= prev_entry->is_tree; --dag_env->num_of_dags; prev_entry->is_dead = 1; prev_entry->link = entry; } } } } }
/** * Post-walker to detect DAG roots that are referenced form other blocks */ static void find_dag_roots(ir_node *node, void *env) { dag_env_t *dag_env = (dag_env_t*)env; int i, arity; dag_entry_t *entry; ir_node *block; if (is_Block(node)) return; block = get_nodes_block(node); /* ignore start end end blocks */ ir_graph *const irg = get_Block_irg(block); if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg)) return; /* Phi nodes always references nodes from "other" block */ if (is_Phi(node)) { if (get_irn_mode(node) != mode_M) { for (i = 0, arity = get_irn_arity(node); i < arity; ++i) { ir_node *prev = get_irn_n(node, i); if (is_Phi(prev)) continue; if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) { if (is_irn_constlike(prev)) continue; } entry = get_irn_dag_entry(prev); if (! entry) { /* found an unassigned node, a new root */ entry = new_dag_entry(dag_env, node); entry->is_ext_ref = 1; } } } } else { for (i = 0, arity = get_irn_arity(node); i < arity; ++i) { ir_node *prev = get_irn_n(node, i); ir_mode *mode = get_irn_mode(prev); if (mode == mode_X || mode == mode_M) continue; if (is_Phi(prev)) continue; if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) { if (is_irn_constlike(prev)) continue; } if (get_nodes_block(prev) != block) { /* The predecessor is from another block. It forms a root. */ entry = get_irn_dag_entry(prev); if (! entry) { /* found an unassigned node, a new root */ entry = new_dag_entry(dag_env, node); entry->is_ext_ref = 1; } } } } }