ir_node *get_Block_idom(const ir_node *block) { assert(irg_has_properties(get_irn_irg(block), IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE)); if (get_Block_dom_depth(block) == -1) { /* This block is not reachable from Start */ ir_graph *irg = get_irn_irg(block); return new_r_Bad(irg, mode_BB); } return get_dom_info_const(block)->idom; }
/** * This function returns the last definition of a value. In case * this value was last defined in a previous block, Phi nodes are * inserted. If the part of the firm graph containing the definition * is not yet constructed, a dummy Phi node is returned. * * @param block the current block * @param pos the value number of the value searched * @param mode the mode of this value (needed for Phi construction) */ static ir_node *get_r_value_internal(ir_node *block, int pos, ir_mode *mode) { ir_node *res = block->attr.block.graph_arr[pos]; if (res != NULL) return res; /* in a matured block we can immediately determine the phi arguments */ if (get_Block_matured(block)) { ir_graph *const irg = get_irn_irg(block); int const arity = get_irn_arity(block); /* no predecessors: use unknown value */ if (arity == 0) { if (block == get_irg_start_block(irg)) { if (default_initialize_local_variable != NULL) { ir_node *rem = get_r_cur_block(irg); set_r_cur_block(irg, block); res = default_initialize_local_variable(irg, mode, pos - 1); set_r_cur_block(irg, rem); } else { res = new_r_Unknown(irg, mode); } } else { goto bad; /* unreachable block, use Bad */ } /* one predecessor just use its value */ } else if (arity == 1) { ir_node *cfgpred = get_Block_cfgpred(block, 0); if (is_Bad(cfgpred)) { bad: res = new_r_Bad(irg, mode); } else { ir_node *cfgpred_block = get_nodes_block(cfgpred); res = get_r_value_internal(cfgpred_block, pos, mode); } } else { /* multiple predecessors construct Phi */ res = new_rd_Phi0(NULL, block, mode, pos); /* enter phi0 into our variable value table to break cycles * arising from set_phi_arguments */ block->attr.block.graph_arr[pos] = res; res = set_phi_arguments(res, pos); } } else { /* in case of immature block we have to keep a Phi0 */ res = new_rd_Phi0(NULL, block, mode, pos); /* enqueue phi so we can set arguments once the block matures */ res->attr.phi.next = block->attr.block.phis; block->attr.block.phis = res; } block->attr.block.graph_arr[pos] = res; return res; }
ir_graph *new_const_code_irg(void) { ir_graph *const res = new_r_ir_graph(NULL, 0); mature_immBlock(get_irg_end_block(res)); /* There is no Start node in the const_code_irg */ set_irg_start(res, new_r_Bad(res, mode_T)); set_irg_frame(res, new_r_Bad(res, mode_BAD)); set_irg_args(res, new_r_Bad(res, mode_T)); set_irg_initial_mem(res, new_r_Bad(res, mode_M)); set_r_store(res, get_irg_no_mem(res)); /* Set the visited flag high enough that the blocks will never be * visited. */ ir_node *const body_block = get_r_cur_block(res); set_irn_visited(body_block, -1); set_Block_block_visited(body_block, -1); ir_node *const start_block = get_irg_start_block(res); set_Block_block_visited(start_block, -1); set_irn_visited(start_block, -1); return res; }
void mature_immBlock(ir_node *block) { if (get_Block_matured(block)) return; set_Block_matured(block, 1); /* Create final in-array for the block. */ ir_graph *const irg = get_irn_irg(block); if (block->attr.block.dynamic_ins) { /* Attach a Bad predecessor if there is no other. This is necessary to * fulfill the invariant that all nodes can be found through reverse * edges from the start block. */ ir_node **new_in; struct obstack *const obst = get_irg_obstack(irg); size_t n_preds = ARR_LEN(block->in) - 1; if (n_preds == 0) { n_preds = 1; new_in = NEW_ARR_D(ir_node*, obst, 2); new_in[0] = NULL; new_in[1] = new_r_Bad(irg, mode_X); } else {
/** * Computes the predecessors for the real phi node, and then * allocates and returns this node. The routine called to allocate the * node might optimize it away and return a real value. * This function must be called with an in-array of proper size. */ static ir_node *set_phi_arguments(ir_node *phi, int pos) { ir_node *block = get_nodes_block(phi); ir_graph *irg = get_irn_irg(block); int arity = get_irn_arity(block); ir_node **in = ALLOCAN(ir_node*, arity); ir_mode *mode = get_irn_mode(phi); /* This loop goes to all predecessor blocks of the block the Phi node * is in and there finds the operands of the Phi node by calling * get_r_value_internal. */ for (int i = 0; i < arity; ++i) { ir_node *cfgpred = get_Block_cfgpred_block(block, i); ir_node *value; if (cfgpred == NULL) { value = new_r_Bad(irg, mode); } else { value = get_r_value_internal(cfgpred, pos, mode); } in[i] = value; } phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), arity); set_irn_in(phi, arity, in); verify_new_node(phi); try_remove_unnecessary_phi(phi); /* To solve the problem of (potentially) endless loops being observable * behaviour we add a keep-alive edge too all PhiM nodes. */ if (mode == mode_M && !is_Id(phi)) { phi->attr.phi.loop = true; keep_alive(phi); } return phi; }