/* Add local dominance frontiers */ foreach_block_succ(blk, edge) { ir_node *y = get_edge_src_irn(edge); if (get_idom(y) != blk) { ARR_APP1(ir_node *, df_list, y); } }
/** * implementation of create_set_func which produces a cond with control * flow */ static ir_node *create_cond_set(ir_node *cond_value, ir_mode *dest_mode) { ir_node *lower_block = part_block_edges(cond_value); ir_node *upper_block = get_nodes_block(cond_value); foreach_out_edge_safe(upper_block, edge) { /* The cached nodes might belong to the lower block, so we have * to clear the cache for moved nodes to avoid dominance problems. */ ir_node *node = get_edge_src_irn(edge); set_irn_link(node, NULL); }
/** * Check if a given value is last used (i.e. die after) the block of some * other node. */ static bool value_last_used_here(be_lv_t *lv, ir_node *here, ir_node *value) { ir_node *block = get_nodes_block(here); /* If the value is live end it is for sure it does not die here */ if (be_is_live_end(lv, block, value)) return false; /* if multiple nodes in this block use the value, then we cannot decide * whether the value will die here (because there is no schedule yet). * Assume it does not die in this case. */ foreach_out_edge(value, edge) { ir_node *user = get_edge_src_irn(edge); if (user != here && get_nodes_block(user) == block) { return false; } }
/** * 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); } }
/** * tests whether we can legally move node node after node after * (only works for nodes in same block) */ static bool can_move(ir_node *node, ir_node *after) { ir_node *node_block = get_nodes_block(node); assert(node_block == get_nodes_block(after)); /** all users have to be after the after node */ foreach_out_edge(node, edge) { ir_node *out = get_edge_src_irn(edge); if (get_nodes_block(out) != node_block) continue; /* phi represents a usage at block end */ if (is_Phi(out)) continue; if (arch_is_irn_not_scheduled(out)) { if (!can_move(out, after)) return false; } else { if (sched_get_time_step(out) <= sched_get_time_step(after)) return false; } }
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; } }
/** * Transforms a Div into the appropriate soft float function. */ static bool lower_Div(ir_node *const n) { ir_mode *const mode = get_Div_resmode(n); if (!mode_is_float(mode)) return false; ir_node *const left = get_Div_left(n); ir_node *const right = get_Div_right(n); ir_node *const in[] = { left, right }; ir_node *const result = make_softfloat_call(n, "div", ARRAY_SIZE(in), in); ir_node *const call = skip_Proj(skip_Proj(result)); set_irn_pinned(call, get_irn_pinned(n)); foreach_out_edge_safe(n, edge) { ir_node *proj = get_edge_src_irn(edge); if (!is_Proj(proj)) continue; switch ((pn_Div)get_Proj_num(proj)) { case pn_Div_M: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_M); continue; case pn_Div_X_regular: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_regular); continue; case pn_Div_X_except: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_except); continue; case pn_Div_res: exchange(proj, result); continue; } panic("unexpected Proj number"); }
/** * Emit a Compare with conditional branch. */ static void emit_amd64_Jcc(const ir_node *irn) { const ir_node *proj_true = NULL; const ir_node *proj_false = NULL; const ir_node *block; const ir_node *next_block; const char *suffix; const amd64_attr_t *attr = get_amd64_attr_const(irn); ir_relation relation = attr->ext.relation; ir_node *op1 = get_irn_n(irn, 0); const amd64_attr_t *cmp_attr = get_amd64_attr_const(op1); bool is_signed = !cmp_attr->data.cmp_unsigned; assert(is_amd64_Cmp(op1)); foreach_out_edge(irn, edge) { ir_node *proj = get_edge_src_irn(edge); long nr = get_Proj_proj(proj); if (nr == pn_Cond_true) { proj_true = proj; } else { proj_false = proj; } }
static void lower_divmod(ir_node *node, ir_node *left, ir_node *right, ir_node *mem, ir_mode *mode, int res_offset) { dbg_info *dbgi = get_irn_dbg_info(node); ir_node *block = get_nodes_block(node); ir_node *left_low = get_lowered_low(left); ir_node *left_high = get_lowered_high(left); ir_node *right_low = get_lowered_low(right); ir_node *right_high = get_lowered_high(right); ir_mode *node_mode = get_irn_mode(left); ir_entity *entity = mode_is_signed(node_mode) ? ldivmod : uldivmod; ir_type *mtp = get_entity_type(entity); ir_graph *irg = get_irn_irg(node); ir_node *addr = new_r_Address(irg, entity); ir_node *in[4]; if (arm_cg_config.big_endian) { in[0] = left_high; in[1] = left_low; in[2] = right_high; in[3] = right_low; } else { in[0] = left_low; in[1] = left_high; in[2] = right_low; in[3] = right_high; } ir_node *call = new_rd_Call(dbgi, block, mem, addr, ARRAY_SIZE(in), in, mtp); ir_node *resproj = new_r_Proj(call, mode_T, pn_Call_T_result); set_irn_pinned(call, get_irn_pinned(node)); foreach_out_edge_safe(node, edge) { ir_node *proj = get_edge_src_irn(edge); if (!is_Proj(proj)) continue; switch ((pn_Div)get_Proj_num(proj)) { case pn_Div_M: /* reroute to the call */ set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_M); break; case pn_Div_X_regular: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_regular); break; case pn_Div_X_except: set_Proj_pred(proj, call); set_Proj_num(proj, pn_Call_X_except); break; case pn_Div_res: { ir_mode *low_mode = get_irn_mode(left_low); if (arm_cg_config.big_endian) { ir_node *res_low = new_r_Proj(resproj, low_mode, res_offset+1); ir_node *res_high = new_r_Proj(resproj, mode, res_offset); ir_set_dw_lowered(proj, res_low, res_high); } else { ir_node *res_low = new_r_Proj(resproj, low_mode, res_offset); ir_node *res_high = new_r_Proj(resproj, mode, res_offset+1); ir_set_dw_lowered(proj, res_low, res_high); } break; } } /* mark this proj: we have handled it already, otherwise we might fall * into out new nodes. */ mark_irn_visited(proj); }