hotspot/src/share/vm/opto/loopopts.cpp

Print this page
rev 611 : Merge

*** 1,10 **** #ifdef USE_PRAGMA_IDENT_SRC #pragma ident "@(#)loopopts.cpp 1.222 08/11/24 12:23:09 JVM" #endif /* ! * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,10 ---- #ifdef USE_PRAGMA_IDENT_SRC #pragma ident "@(#)loopopts.cpp 1.222 08/11/24 12:23:09 JVM" #endif /* ! * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 30,48 **** //============================================================================= //------------------------------split_thru_phi--------------------------------- // Split Node 'n' through merge point if there is enough win. Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { ! if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::BOTTOM) { // ConvI2L may have type information on it which is unsafe to push up // so disable this for now return NULL; } int wins = 0; assert( !n->is_CFG(), "" ); assert( region->is_Region(), "" ); ! Node *phi = new (C, region->req()) PhiNode( region, n->bottom_type() ); uint old_unique = C->unique(); for( uint i = 1; i < region->req(); i++ ) { Node *x; Node* the_clone = NULL; if( region->in(i) == C->top() ) { --- 30,59 ---- //============================================================================= //------------------------------split_thru_phi--------------------------------- // Split Node 'n' through merge point if there is enough win. Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) { ! if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::LONG) { // ConvI2L may have type information on it which is unsafe to push up // so disable this for now return NULL; } int wins = 0; assert( !n->is_CFG(), "" ); assert( region->is_Region(), "" ); ! ! const Type* type = n->bottom_type(); ! const TypeOopPtr *t_oop = _igvn.type(n)->isa_oopptr(); ! Node *phi; ! if( t_oop != NULL && t_oop->is_known_instance_field() ) { ! int iid = t_oop->instance_id(); ! int index = C->get_alias_index(t_oop); ! int offset = t_oop->offset(); ! phi = new (C,region->req()) PhiNode(region, type, NULL, iid, index, offset); ! } else { ! phi = new (C,region->req()) PhiNode(region, type); ! } uint old_unique = C->unique(); for( uint i = 1; i < region->req(); i++ ) { Node *x; Node* the_clone = NULL; if( region->in(i) == C->top() ) {
*** 86,95 **** --- 97,110 ---- // Note that some Identity methods call phase->type(this). // Make sure that the type array is big enough for // our new node, even though we may throw the node away. // (Note: This tweaking with igvn only works because x is a new node.) _igvn.set_type(x, t); + // If x is a TypeNode, capture any more-precise type permanently into Node + // othewise it will be not updated during igvn->transform since + // igvn->type(x) is set to x->Value() already. + x->raise_bottom_type(t); Node *y = x->Identity(&_igvn); if( y != x ) { wins++; x = y; } else {
*** 441,465 **** if( lp->outcnt() > 1 ) return NULL; if( rp->outcnt() > 1 ) return NULL; // Check profitability int cost = 0; for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { Node *out = region->fast_out(i); if( !out->is_Phi() ) continue; // Ignore other control edges, etc PhiNode* phi = out->as_Phi(); switch (phi->type()->basic_type()) { case T_LONG: cost++; // Probably encodes as 2 CMOV's case T_INT: // These all CMOV fine case T_FLOAT: case T_DOUBLE: case T_ADDRESS: // (RawPtr) cost++; break; case T_OBJECT: { // Base oops are OK, but not derived oops ! const TypeOopPtr *tp = phi->type()->isa_oopptr(); // Derived pointers are Bad (tm): what's the Base (for GC purposes) of a // CMOVE'd derived pointer? It's a CMOVE'd derived base. Thus // CMOVE'ing a derived pointer requires we also CMOVE the base. If we // have a Phi for the base here that we convert to a CMOVE all is well // and good. But if the base is dead, we'll not make a CMOVE. Later --- 456,483 ---- if( lp->outcnt() > 1 ) return NULL; if( rp->outcnt() > 1 ) return NULL; // Check profitability int cost = 0; + int phis = 0; for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { Node *out = region->fast_out(i); if( !out->is_Phi() ) continue; // Ignore other control edges, etc + phis++; PhiNode* phi = out->as_Phi(); switch (phi->type()->basic_type()) { case T_LONG: cost++; // Probably encodes as 2 CMOV's case T_INT: // These all CMOV fine case T_FLOAT: case T_DOUBLE: case T_ADDRESS: // (RawPtr) cost++; break; + case T_NARROWOOP: // Fall through case T_OBJECT: { // Base oops are OK, but not derived oops ! const TypeOopPtr *tp = phi->type()->make_ptr()->isa_oopptr(); // Derived pointers are Bad (tm): what's the Base (for GC purposes) of a // CMOVE'd derived pointer? It's a CMOVE'd derived base. Thus // CMOVE'ing a derived pointer requires we also CMOVE the base. If we // have a Phi for the base here that we convert to a CMOVE all is well // and good. But if the base is dead, we'll not make a CMOVE. Later
*** 486,504 **** for( uint k = 1; k < inp->req(); k++ ) if (get_ctrl(inp->in(k)) == proj) return NULL; // Too much speculative goo } } ! // See if the Phi is used by a Cmp. This will likely Split-If, a ! // higher-payoff operation. for (DUIterator_Fast kmax, k = phi->fast_outs(kmax); k < kmax; k++) { Node* use = phi->fast_out(k); ! if( use->is_Cmp() ) return NULL; } } if( cost >= ConditionalMoveLimit ) return NULL; // Too much goo // -------------- // Now replace all Phis with CMOV's Node *cmov_ctrl = iff->in(0); uint flip = (lp->Opcode() == Op_IfTrue); --- 504,528 ---- for( uint k = 1; k < inp->req(); k++ ) if (get_ctrl(inp->in(k)) == proj) return NULL; // Too much speculative goo } } ! // See if the Phi is used by a Cmp or Narrow oop Decode/Encode. ! // This will likely Split-If, a higher-payoff operation. for (DUIterator_Fast kmax, k = phi->fast_outs(kmax); k < kmax; k++) { Node* use = phi->fast_out(k); ! if( use->is_Cmp() || use->is_DecodeN() || use->is_EncodeP() ) return NULL; } } if( cost >= ConditionalMoveLimit ) return NULL; // Too much goo + Node* bol = iff->in(1); + assert( bol->Opcode() == Op_Bool, "" ); + int cmp_op = bol->in(1)->Opcode(); + // It is expensive to generate flags from a float compare. + // Avoid duplicated float compare. + if( phis > 1 && (cmp_op == Op_CmpF || cmp_op == Op_CmpD)) return NULL; // -------------- // Now replace all Phis with CMOV's Node *cmov_ctrl = iff->in(0); uint flip = (lp->Opcode() == Op_IfTrue);
*** 559,569 **** // Attempt to use a conditional move instead of a phi/branch if( ConditionalMoveLimit > 0 && n_op == Op_Region ) { Node *cmov = conditional_move( n ); if( cmov ) return cmov; } ! if( n->is_CFG() || n_op == Op_StorePConditional || n_op == Op_StoreLConditional || n_op == Op_CompareAndSwapI || n_op == Op_CompareAndSwapL ||n_op == Op_CompareAndSwapP) return n; if( n_op == Op_Opaque1 || // Opaque nodes cannot be mod'd n_op == Op_Opaque2 ) { if( !C->major_progress() ) // If chance of no more loop opts... _igvn._worklist.push(n); // maybe we'll remove them return n; --- 583,594 ---- // Attempt to use a conditional move instead of a phi/branch if( ConditionalMoveLimit > 0 && n_op == Op_Region ) { Node *cmov = conditional_move( n ); if( cmov ) return cmov; } ! if( n->is_CFG() || n->is_LoadStore() ) ! return n; if( n_op == Op_Opaque1 || // Opaque nodes cannot be mod'd n_op == Op_Opaque2 ) { if( !C->major_progress() ) // If chance of no more loop opts... _igvn._worklist.push(n); // maybe we'll remove them return n;
*** 908,918 **** // tried setting control edges on the x's to force them to // not combine, but the matching gets worried when it tries // to fold a StoreP and an AddP together (as part of an // address expression) and the AddP and StoreP have // different controls. ! if( !x->is_Load() ) _igvn._worklist.yank(x); } _igvn.remove_dead_node(n); } } } --- 933,943 ---- // tried setting control edges on the x's to force them to // not combine, but the matching gets worried when it tries // to fold a StoreP and an AddP together (as part of an // address expression) and the AddP and StoreP have // different controls. ! if( !x->is_Load() && !x->is_DecodeN() ) _igvn._worklist.yank(x); } _igvn.remove_dead_node(n); } } }
*** 1872,1893 **** // clone "n" and insert it between the inputs of "n" and the use outside the loop Node* n_clone = n->clone(); _igvn.hash_delete(use); use->set_req(j, n_clone); _igvn._worklist.push(use); if (!use->is_Phi()) { ! Node* use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); ! set_ctrl(n_clone, use_c); ! assert(!loop->is_member(get_loop(use_c)), "should be outside loop"); ! get_loop(use_c)->_body.push(n_clone); } else { // Use in a phi is considered a use in the associated predecessor block ! Node *prevbb = use->in(0)->in(j); ! set_ctrl(n_clone, prevbb); ! assert(!loop->is_member(get_loop(prevbb)), "should be outside loop"); ! get_loop(prevbb)->_body.push(n_clone); } _igvn.register_new_node_with_optimizer(n_clone); #if !defined(PRODUCT) if (TracePartialPeeling) { tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx); } --- 1897,1916 ---- // clone "n" and insert it between the inputs of "n" and the use outside the loop Node* n_clone = n->clone(); _igvn.hash_delete(use); use->set_req(j, n_clone); _igvn._worklist.push(use); + Node* use_c; if (!use->is_Phi()) { ! use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); } else { // Use in a phi is considered a use in the associated predecessor block ! use_c = use->in(0)->in(j); } + set_ctrl(n_clone, use_c); + assert(!loop->is_member(get_loop(use_c)), "should be outside loop"); + get_loop(use_c)->_body.push(n_clone); _igvn.register_new_node_with_optimizer(n_clone); #if !defined(PRODUCT) if (TracePartialPeeling) { tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx); }
*** 2239,2248 **** --- 2262,2274 ---- // v // exitA // bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { + if (!loop->_head->is_Loop()) { + return false; } + LoopNode *head = loop->_head->as_Loop(); if (head->is_partial_peel_loop() || head->partial_peel_has_failed()) { return false; }
*** 2639,2648 **** --- 2665,2678 ---- // trip-counter on the fall-out path (forces the pre-incremented // and post-incremented trip counter to be live at the same time). // Fix this by adjusting to use the post-increment trip counter. Node *phi = cl->phi(); if( !phi ) return; // Dead infinite loop + + // Shape messed up, probably by iteration_split_impl + if (phi->in(LoopNode::LoopBackControl) != cl->incr()) return; + bool progress = true; while (progress) { progress = false; for (DUIterator_Fast imax, i = phi->fast_outs(imax); i < imax; i++) { Node* use = phi->fast_out(i); // User of trip-counter
*** 2663,2673 **** if( dom_lca( exit, u_ctrl ) != exit ) continue; // protect against stride not being a constant if( !cle->stride_is_con() ) continue; // Hit! Refactor use to use the post-incremented tripcounter. // Compute a post-increment tripcounter. ! Node *opaq = new (C, 2) Opaque2Node( cle->incr() ); register_new_node( opaq, u_ctrl ); Node *neg_stride = _igvn.intcon(-cle->stride_con()); set_ctrl(neg_stride, C->root()); Node *post = new (C, 3) AddINode( opaq, neg_stride); register_new_node( post, u_ctrl ); --- 2693,2703 ---- if( dom_lca( exit, u_ctrl ) != exit ) continue; // protect against stride not being a constant if( !cle->stride_is_con() ) continue; // Hit! Refactor use to use the post-incremented tripcounter. // Compute a post-increment tripcounter. ! Node *opaq = new (C, 2) Opaque2Node( C, cle->incr() ); register_new_node( opaq, u_ctrl ); Node *neg_stride = _igvn.intcon(-cle->stride_con()); set_ctrl(neg_stride, C->root()); Node *post = new (C, 3) AddINode( opaq, neg_stride); register_new_node( post, u_ctrl );