--- old/src/share/vm/opto/loopnode.cpp 2016-02-15 09:59:19.583887627 +0100 +++ new/src/share/vm/opto/loopnode.cpp 2016-02-15 09:59:18.524727248 +0100 @@ -1743,11 +1743,13 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { assert(loop->_head->is_CountedLoop(), ""); CountedLoopNode *cl = loop->_head->as_CountedLoop(); - if (!cl->is_valid_counted_loop()) + if (!cl->is_valid_counted_loop()) { return; // skip malformed counted loop + } Node *incr = cl->incr(); - if (incr == NULL) + if (incr == NULL) { return; // Dead loop? + } Node *init = cl->init_trip(); Node *phi = cl->phi(); int stride_con = cl->stride_con(); @@ -1756,26 +1758,32 @@ for (DUIterator i = cl->outs(); cl->has_out(i); i++) { Node *out = cl->out(i); // Look for other phis (secondary IVs). Skip dead ones - if (!out->is_Phi() || out == phi || !has_node(out)) + if (!out->is_Phi() || out == phi || !has_node(out)) { continue; + } PhiNode* phi2 = out->as_Phi(); - Node *incr2 = phi2->in( LoopNode::LoopBackControl ); + Node *incr2 = phi2->in(LoopNode::LoopBackControl); + int op2 = incr2->Opcode(); // Look for induction variables of the form: X += constant if (phi2->region() != loop->_head || incr2->req() != 3 || incr2->in(1) != phi2 || incr2 == incr || - incr2->Opcode() != Op_AddI || - !incr2->in(2)->is_Con()) + (op2 != Op_AddI && op2 != Op_AddL) || + !incr2->in(2)->is_Con()) { continue; + } + assert(op2 == Op_AddI || op2 == Op_AddL, "no other operation supported"); + BasicType bt = (op2 == Op_AddI) ? T_INT : T_LONG; // Check for parallel induction variable (parallel to trip counter) // via an affine function. In particular, count-down loops with // count-up array indices are common. We only RCE references off // the trip-counter, so we need to convert all these to trip-counter // expressions. - Node *init2 = phi2->in( LoopNode::EntryControl ); - int stride_con2 = incr2->in(2)->get_int(); + Node *init2 = phi2->in(LoopNode::EntryControl); + Node* stride2 = incr2->in(2); + jlong stride_con2 = (bt == T_INT) ? (jlong)stride2->get_int() : stride2->get_long(); // The general case here gets a little tricky. We want to find the // GCD of all possible parallel IV's and make a new IV using this @@ -1784,7 +1792,7 @@ // Instead we require 'stride_con2' to be a multiple of 'stride_con', // where +/-1 is the common case, but other integer multiples are // also easy to handle. - int ratio_con = stride_con2/stride_con; + jlong ratio_con = stride_con2/stride_con; if ((ratio_con * stride_con) == stride_con2) { // Check for exact #ifndef PRODUCT @@ -1797,21 +1805,33 @@ // variable differs from the trip counter by a loop-invariant // amount, the difference between their respective initial values. // It is scaled by the 'ratio_con'. - Node* ratio = _igvn.intcon(ratio_con); + Node* ratio = (bt == T_INT) ? (Node*)_igvn.intcon((int)ratio_con) : (Node*)_igvn.longcon(ratio_con); set_ctrl(ratio, C->root()); - Node* ratio_init = new MulINode(init, ratio); - _igvn.register_new_node_with_optimizer(ratio_init, init); + Node* conv_init = init; + if (bt == T_LONG) { + conv_init = new ConvI2LNode(init); + _igvn.register_new_node_with_optimizer(conv_init, init); + set_early_ctrl(conv_init); + } + Node* ratio_init = MulNode::make(bt, conv_init, ratio); + _igvn.register_new_node_with_optimizer(ratio_init, conv_init); set_early_ctrl(ratio_init); - Node* diff = new SubINode(init2, ratio_init); + Node* diff = SubNode::make(bt, init2, ratio_init); _igvn.register_new_node_with_optimizer(diff, init2); set_early_ctrl(diff); - Node* ratio_idx = new MulINode(phi, ratio); - _igvn.register_new_node_with_optimizer(ratio_idx, phi); + Node* conv_phi = phi; + if (bt == T_LONG) { + conv_phi = new ConvI2LNode(phi); + _igvn.register_new_node_with_optimizer(conv_phi, phi); + set_ctrl(conv_phi, cl); + } + Node* ratio_idx = MulINode::make(bt, conv_phi, ratio); + _igvn.register_new_node_with_optimizer(ratio_idx, conv_phi); set_ctrl(ratio_idx, cl); - Node* add = new AddINode(ratio_idx, diff); + Node* add = AddNode::make(bt, ratio_idx, diff); _igvn.register_new_node_with_optimizer(add); set_ctrl(add, cl); - _igvn.replace_node( phi2, add ); + _igvn.replace_node(phi2, add); // Sometimes an induction variable is unused if (add->outcnt() == 0) { _igvn.remove_dead_node(add);