LoopNode* PhaseIdealLoop::create_reserve_version_of_loop(IdealLoopTree *loop, CountedLoopReserveKit* lk) { Node_List old_new; LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); Node* entry = head->in(LoopNode::EntryControl); _igvn.rehash_node_delayed(entry); IdealLoopTree* outer_loop = loop->_parent; ConINode* const_1 = _igvn.intcon(1); set_ctrl(const_1, C->root()); IfNode* iff = new IfNode(entry, const_1, PROB_MAX, COUNT_UNKNOWN); register_node(iff, outer_loop, entry, dom_depth(entry)); ProjNode* iffast = new IfTrueNode(iff); register_node(iffast, outer_loop, iff, dom_depth(iff)); ProjNode* ifslow = new IfFalseNode(iff); register_node(ifslow, outer_loop, iff, dom_depth(iff)); // Clone the loop body. The clone becomes the fast loop. The // original pre-header will (illegally) have 3 control users // (old & new loops & new if). clone_loop(loop, old_new, dom_depth(head), iff); assert(old_new[head->_idx]->is_Loop(), "" ); LoopNode* slow_head = old_new[head->_idx]->as_Loop(); #ifndef PRODUCT if (TraceLoopOpts) { tty->print_cr("PhaseIdealLoop::create_reserve_version_of_loop:"); tty->print("\t iff = %d, ", iff->_idx); iff->dump(); tty->print("\t iffast = %d, ", iffast->_idx); iffast->dump(); tty->print("\t ifslow = %d, ", ifslow->_idx); ifslow->dump(); tty->print("\t before replace_input_of: head = %d, ", head->_idx); head->dump(); tty->print("\t before replace_input_of: slow_head = %d, ", slow_head->_idx); slow_head->dump(); } #endif // Fast (true) control _igvn.replace_input_of(head, LoopNode::EntryControl, iffast); // Slow (false) control _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow); recompute_dom_depth(); lk->set_iff(iff); #ifndef PRODUCT if (TraceLoopOpts ) { tty->print("\t after replace_input_of: head = %d, ", head->_idx); head->dump(); tty->print("\t after replace_input_of: slow_head = %d, ", slow_head->_idx); slow_head->dump(); } #endif return slow_head->as_Loop(); }
//-------------------------create_slow_version_of_loop------------------------ // Create a slow version of the loop by cloning the loop // and inserting an if to select fast-slow versions. // Return control projection of the entry to the fast version. ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, Node_List &old_new, int opcode) { LoopNode* head = loop->_head->as_Loop(); bool counted_loop = head->is_CountedLoop(); Node* entry = head->in(LoopNode::EntryControl); _igvn.rehash_node_delayed(entry); IdealLoopTree* outer_loop = loop->_parent; Node *cont = _igvn.intcon(1); set_ctrl(cont, C->root()); Node* opq = new Opaque1Node(C, cont); register_node(opq, outer_loop, entry, dom_depth(entry)); Node *bol = new Conv2BNode(opq); register_node(bol, outer_loop, entry, dom_depth(entry)); IfNode* iff = (opcode == Op_RangeCheck) ? new RangeCheckNode(entry, bol, PROB_MAX, COUNT_UNKNOWN) : new IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN); register_node(iff, outer_loop, entry, dom_depth(entry)); ProjNode* iffast = new IfTrueNode(iff); register_node(iffast, outer_loop, iff, dom_depth(iff)); ProjNode* ifslow = new IfFalseNode(iff); register_node(ifslow, outer_loop, iff, dom_depth(iff)); // Clone the loop body. The clone becomes the fast loop. The // original pre-header will (illegally) have 3 control users // (old & new loops & new if). clone_loop(loop, old_new, dom_depth(head), iff); assert(old_new[head->_idx]->is_Loop(), "" ); // Fast (true) control Node* iffast_pred = clone_loop_predicates(entry, iffast, !counted_loop); _igvn.replace_input_of(head, LoopNode::EntryControl, iffast_pred); set_idom(head, iffast_pred, dom_depth(head)); // Slow (false) control Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); LoopNode* slow_head = old_new[head->_idx]->as_Loop(); _igvn.replace_input_of(slow_head, LoopNode::EntryControl, ifslow_pred); set_idom(slow_head, ifslow_pred, dom_depth(slow_head)); recompute_dom_depth(); return iffast; }
//-------------------------create_slow_version_of_loop------------------------ // Create a slow version of the loop by cloning the loop // and inserting an if to select fast-slow versions. // Return control projection of the entry to the fast version. ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, Node_List &old_new) { LoopNode* head = loop->_head->as_Loop(); Node* entry = head->in(LoopNode::EntryControl); _igvn.hash_delete(entry); _igvn._worklist.push(entry); IdealLoopTree* outer_loop = loop->_parent; Node *cont = _igvn.intcon(1); set_ctrl(cont, C->root()); Node* opq = new (C, 2) Opaque1Node(C, cont); register_node(opq, outer_loop, entry, dom_depth(entry)); Node *bol = new (C, 2) Conv2BNode(opq); register_node(bol, outer_loop, entry, dom_depth(entry)); IfNode* iff = new (C, 2) IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN); register_node(iff, outer_loop, entry, dom_depth(entry)); ProjNode* iffast = new (C, 1) IfTrueNode(iff); register_node(iffast, outer_loop, iff, dom_depth(iff)); ProjNode* ifslow = new (C, 1) IfFalseNode(iff); register_node(ifslow, outer_loop, iff, dom_depth(iff)); // Clone the loop body. The clone becomes the fast loop. The // original pre-header will (illegally) have 2 control users (old & new loops). clone_loop(loop, old_new, dom_depth(head), iff); assert(old_new[head->_idx]->is_Loop(), "" ); // Fast (true) control _igvn.hash_delete(head); head->set_req(LoopNode::EntryControl, iffast); set_idom(head, iffast, dom_depth(head)); _igvn._worklist.push(head); // Slow (false) control LoopNode* slow_head = old_new[head->_idx]->as_Loop(); _igvn.hash_delete(slow_head); slow_head->set_req(LoopNode::EntryControl, ifslow); set_idom(slow_head, ifslow, dom_depth(slow_head)); _igvn._worklist.push(slow_head); recompute_dom_depth(); return iffast; }