ir_node *be_new_Phi(ir_node *block, int n_ins, ir_node **ins, arch_register_req_t const *req) { ir_graph *irg = get_irn_irg(block); ir_node *phi = new_ir_node(NULL, irg, block, op_Phi, req->cls->mode, n_ins, ins); phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins); struct obstack *obst = be_get_be_obst(irg); backend_info_t *info = be_get_info(phi); info->out_infos = NEW_ARR_DZ(reg_out_info_t, obst, 1); info->in_reqs = be_allocate_in_reqs(irg, n_ins); info->out_infos[0].req = req; for (int i = 0; i < n_ins; ++i) { info->in_reqs[i] = req; } verify_new_node(phi); return optimize_node(phi); }
ir_node *be_complete_Phi(ir_node *const phi, unsigned const n_ins, ir_node **const ins) { assert(is_Phi(phi) && get_Phi_n_preds(phi) == 0); ir_graph *const irg = get_irn_irg(phi); phi->attr.phi.u.backedge = new_backedge_arr(get_irg_obstack(irg), n_ins); set_irn_in(phi, n_ins, ins); arch_register_req_t const **const in_reqs = be_allocate_in_reqs(irg, n_ins); arch_register_req_t const *const req = arch_get_irn_register_req(phi); for (unsigned i = 0; i < n_ins; ++i) { in_reqs[i] = req; } backend_info_t *const info = be_get_info(phi); info->in_reqs = in_reqs; verify_new_node(phi); return phi; }
void fix_backedges(struct obstack *obst, ir_node *n) { bitset_t *arr = mere_get_backarray(n); if (arr == NULL) return; int arity = get_irn_arity(n); if (bitset_size(arr) != (unsigned) arity) { arr = new_backedge_arr(obst, arity); unsigned opc = get_irn_opcode(n); if (opc == iro_Phi) n->attr.phi.u.backedge = arr; else if (opc == iro_Block) { n->attr.block.backedge = arr; } } assert(legal_backarray(n)); }
/** * 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; }