src/share/vm/opto/matcher.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/opto

src/share/vm/opto/matcher.cpp

Print this page
rev 9087 : 8136820: Generate better code for some Unsafe addressing patterns
Summary: reshape address computation to move invariant part out of loops
Reviewed-by:


2028     if (m->Opcode() == Op_LoadI) {
2029       FusedPatternMatcher<TypeInt> bmii(n, m, Op_ConI);
2030       return bmii.match(Op_AndI, -1, Op_SubI,  1,  0)  ||
2031              bmii.match(Op_AndI, -1, Op_AddI, -1, -1)  ||
2032              bmii.match(Op_XorI, -1, Op_AddI, -1, -1);
2033     } else if (m->Opcode() == Op_LoadL) {
2034       FusedPatternMatcher<TypeLong> bmil(n, m, Op_ConL);
2035       return bmil.match(Op_AndL, -1, Op_SubL,  1,  0) ||
2036              bmil.match(Op_AndL, -1, Op_AddL, -1, -1) ||
2037              bmil.match(Op_XorL, -1, Op_AddL, -1, -1);
2038     }
2039   }
2040   return false;
2041 }
2042 #endif // X86
2043 
2044 // A method-klass-holder may be passed in the inline_cache_reg
2045 // and then expanded into the inline_cache_reg and a method_oop register
2046 //   defined in ad_<arch>.cpp
2047 



























2048 
2049 //------------------------------find_shared------------------------------------
2050 // Set bits if Node is shared or otherwise a root
2051 void Matcher::find_shared( Node *n ) {
2052   // Allocate stack of size C->unique() * 2 to avoid frequent realloc
2053   MStack mstack(C->live_nodes() * 2);
2054   // Mark nodes as address_visited if they are inputs to an address expression
2055   VectorSet address_visited(Thread::current()->resource_area());
2056   mstack.push(n, Visit);     // Don't need to pre-visit root node
2057   while (mstack.is_nonempty()) {
2058     n = mstack.node();       // Leave node on stack
2059     Node_State nstate = mstack.state();
2060     uint nop = n->Opcode();
2061     if (nstate == Pre_Visit) {
2062       if (address_visited.test(n->_idx)) { // Visited in address already?
2063         // Flag as visited and shared now.
2064         set_visited(n);
2065       }
2066       if (is_visited(n)) {   // Visited already?
2067         // Node is shared and has no reason to clone.  Flag it as shared.


2188           mstack.push(m, Visit);
2189           continue; // for(int i = ...)
2190         }
2191 
2192         if( mop == Op_AddP && m->in(AddPNode::Base)->is_DecodeNarrowPtr()) {
2193           // Bases used in addresses must be shared but since
2194           // they are shared through a DecodeN they may appear
2195           // to have a single use so force sharing here.
2196           set_shared(m->in(AddPNode::Base)->in(1));
2197         }
2198 
2199         // if 'n' and 'm' are part of a graph for BMI instruction, clone this node.
2200 #ifdef X86
2201         if (UseBMI1Instructions && is_bmi_pattern(n, m)) {
2202           mstack.push(m, Visit);
2203           continue;
2204         }
2205 #endif
2206 
2207         // Clone addressing expressions as they are "free" in memory access instructions
2208         if( mem_op && i == MemNode::Address && mop == Op_AddP ) {



2209           // Some inputs for address expression are not put on stack
2210           // to avoid marking them as shared and forcing them into register
2211           // if they are used only in address expressions.
2212           // But they should be marked as shared if there are other uses
2213           // besides address expressions.
2214 
2215           Node *off = m->in(AddPNode::Offset);
2216           if( off->is_Con() &&
2217               // When there are other uses besides address expressions
2218               // put it on stack and mark as shared.
2219               !is_visited(m) ) {
2220             address_visited.test_set(m->_idx); // Flag as address_visited
2221             Node *adr = m->in(AddPNode::Address);
2222 
2223             // Intel, ARM and friends can handle 2 adds in addressing mode
2224             if( clone_shift_expressions && adr->is_AddP() &&
2225                 // AtomicAdd is not an addressing expression.
2226                 // Cheap to find it by looking for screwy base.
2227                 !adr->in(AddPNode::Base)->is_top() &&
2228                 // Are there other uses besides address expressions?
2229                 !is_visited(adr) ) {
2230               address_visited.set(adr->_idx); // Flag as address_visited
2231               Node *shift = adr->in(AddPNode::Offset);
2232               // Check for shift by small constant as well
2233               if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() &&
2234                   shift->in(2)->get_int() <= 3 &&
2235                   // Are there other uses besides address expressions?
2236                   !is_visited(shift) ) {
2237                 address_visited.set(shift->_idx); // Flag as address_visited
2238                 mstack.push(shift->in(2), Visit);
2239                 Node *conv = shift->in(1);
2240 #ifdef _LP64
2241                 // Allow Matcher to match the rule which bypass
2242                 // ConvI2L operation for an array index on LP64
2243                 // if the index value is positive.
2244                 if( conv->Opcode() == Op_ConvI2L &&
2245                     conv->as_Type()->type()->is_long()->_lo >= 0 &&
2246                     // Are there other uses besides address expressions?
2247                     !is_visited(conv) ) {
2248                   address_visited.set(conv->_idx); // Flag as address_visited
2249                   mstack.push(conv->in(1), Pre_Visit);
2250                 } else
2251 #endif
2252                 mstack.push(conv, Pre_Visit);
2253               } else {
2254                 mstack.push(shift, Pre_Visit);
2255               }
2256               mstack.push(adr->in(AddPNode::Address), Pre_Visit);
2257               mstack.push(adr->in(AddPNode::Base), Pre_Visit);
2258             } else {  // Sparc, Alpha, PPC and friends
2259               mstack.push(adr, Pre_Visit);
2260             }
2261 
2262             // Clone X+offset as it also folds into most addressing expressions
2263             mstack.push(off, Visit);
2264             mstack.push(m->in(AddPNode::Base), Pre_Visit);
2265             continue; // for(int i = ...)






2266           } // if( off->is_Con() )
2267         }   // if( mem_op &&
2268         mstack.push(m, Pre_Visit);
2269       }     // for(int i = ...)
2270     }
2271     else if (nstate == Alt_Post_Visit) {
2272       mstack.pop(); // Remove node from stack
2273       // We cannot remove the Cmp input from the Bool here, as the Bool may be
2274       // shared and all users of the Bool need to move the Cmp in parallel.
2275       // This leaves both the Bool and the If pointing at the Cmp.  To
2276       // prevent the Matcher from trying to Match the Cmp along both paths
2277       // BoolNode::match_edge always returns a zero.
2278 
2279       // We reorder the Op_If in a pre-order manner, so we can visit without
2280       // accidentally sharing the Cmp (the Bool and the If make 2 users).
2281       n->add_req( n->in(1)->in(1) ); // Add the Cmp next to the Bool
2282     }
2283     else if (nstate == Post_Visit) {
2284       mstack.pop(); // Remove node from stack
2285 




2028     if (m->Opcode() == Op_LoadI) {
2029       FusedPatternMatcher<TypeInt> bmii(n, m, Op_ConI);
2030       return bmii.match(Op_AndI, -1, Op_SubI,  1,  0)  ||
2031              bmii.match(Op_AndI, -1, Op_AddI, -1, -1)  ||
2032              bmii.match(Op_XorI, -1, Op_AddI, -1, -1);
2033     } else if (m->Opcode() == Op_LoadL) {
2034       FusedPatternMatcher<TypeLong> bmil(n, m, Op_ConL);
2035       return bmil.match(Op_AndL, -1, Op_SubL,  1,  0) ||
2036              bmil.match(Op_AndL, -1, Op_AddL, -1, -1) ||
2037              bmil.match(Op_XorL, -1, Op_AddL, -1, -1);
2038     }
2039   }
2040   return false;
2041 }
2042 #endif // X86
2043 
2044 // A method-klass-holder may be passed in the inline_cache_reg
2045 // and then expanded into the inline_cache_reg and a method_oop register
2046 //   defined in ad_<arch>.cpp
2047 
2048 // Check for shift by small constant as well
2049 static bool clone_shift(Node* shift, Matcher* matcher, MStack& mstack, VectorSet& address_visited) {
2050   if (shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() &&
2051       shift->in(2)->get_int() <= 3 &&
2052       // Are there other uses besides address expressions?
2053       !matcher->is_visited(shift)) {
2054     address_visited.set(shift->_idx); // Flag as address_visited
2055     mstack.push(shift->in(2), Visit);
2056     Node *conv = shift->in(1);
2057 #ifdef _LP64
2058     // Allow Matcher to match the rule which bypass
2059     // ConvI2L operation for an array index on LP64
2060     // if the index value is positive.
2061     if (conv->Opcode() == Op_ConvI2L &&
2062         conv->as_Type()->type()->is_long()->_lo >= 0 &&
2063         // Are there other uses besides address expressions?
2064         !matcher->is_visited(conv)) {
2065       address_visited.set(conv->_idx); // Flag as address_visited
2066       mstack.push(conv->in(1), Pre_Visit);
2067     } else
2068 #endif
2069       mstack.push(conv, Pre_Visit);
2070     return true;
2071   }
2072   return false;
2073 }
2074 
2075 
2076 //------------------------------find_shared------------------------------------
2077 // Set bits if Node is shared or otherwise a root
2078 void Matcher::find_shared( Node *n ) {
2079   // Allocate stack of size C->unique() * 2 to avoid frequent realloc
2080   MStack mstack(C->live_nodes() * 2);
2081   // Mark nodes as address_visited if they are inputs to an address expression
2082   VectorSet address_visited(Thread::current()->resource_area());
2083   mstack.push(n, Visit);     // Don't need to pre-visit root node
2084   while (mstack.is_nonempty()) {
2085     n = mstack.node();       // Leave node on stack
2086     Node_State nstate = mstack.state();
2087     uint nop = n->Opcode();
2088     if (nstate == Pre_Visit) {
2089       if (address_visited.test(n->_idx)) { // Visited in address already?
2090         // Flag as visited and shared now.
2091         set_visited(n);
2092       }
2093       if (is_visited(n)) {   // Visited already?
2094         // Node is shared and has no reason to clone.  Flag it as shared.


2215           mstack.push(m, Visit);
2216           continue; // for(int i = ...)
2217         }
2218 
2219         if( mop == Op_AddP && m->in(AddPNode::Base)->is_DecodeNarrowPtr()) {
2220           // Bases used in addresses must be shared but since
2221           // they are shared through a DecodeN they may appear
2222           // to have a single use so force sharing here.
2223           set_shared(m->in(AddPNode::Base)->in(1));
2224         }
2225 
2226         // if 'n' and 'm' are part of a graph for BMI instruction, clone this node.
2227 #ifdef X86
2228         if (UseBMI1Instructions && is_bmi_pattern(n, m)) {
2229           mstack.push(m, Visit);
2230           continue;
2231         }
2232 #endif
2233 
2234         // Clone addressing expressions as they are "free" in memory access instructions
2235         if (mem_op && i == MemNode::Address && mop == Op_AddP &&
2236             // When there are other uses besides address expressions
2237             // put it on stack and mark as shared.
2238             !is_visited(m)) {
2239           // Some inputs for address expression are not put on stack
2240           // to avoid marking them as shared and forcing them into register
2241           // if they are used only in address expressions.
2242           // But they should be marked as shared if there are other uses
2243           // besides address expressions.
2244 
2245           Node *off = m->in(AddPNode::Offset);
2246           if (off->is_Con()) {



2247             address_visited.test_set(m->_idx); // Flag as address_visited
2248             Node *adr = m->in(AddPNode::Address);
2249 
2250             // Intel, ARM and friends can handle 2 adds in addressing mode
2251             if( clone_shift_expressions && adr->is_AddP() &&
2252                 // AtomicAdd is not an addressing expression.
2253                 // Cheap to find it by looking for screwy base.
2254                 !adr->in(AddPNode::Base)->is_top() &&
2255                 // Are there other uses besides address expressions?
2256                 !is_visited(adr) ) {
2257               address_visited.set(adr->_idx); // Flag as address_visited
2258               Node *shift = adr->in(AddPNode::Offset);
2259               if (!clone_shift(shift, this, mstack, address_visited)) {





















2260                 mstack.push(shift, Pre_Visit);
2261               }
2262               mstack.push(adr->in(AddPNode::Address), Pre_Visit);
2263               mstack.push(adr->in(AddPNode::Base), Pre_Visit);
2264             } else {  // Sparc, Alpha, PPC and friends
2265               mstack.push(adr, Pre_Visit);
2266             }
2267 
2268             // Clone X+offset as it also folds into most addressing expressions
2269             mstack.push(off, Visit);
2270             mstack.push(m->in(AddPNode::Base), Pre_Visit);
2271             continue; // for(int i = ...)
2272           } else if (clone_shift_expressions &&
2273                      clone_shift(off, this, mstack, address_visited)) {
2274               address_visited.test_set(m->_idx); // Flag as address_visited
2275               mstack.push(m->in(AddPNode::Address), Pre_Visit);
2276               mstack.push(m->in(AddPNode::Base), Pre_Visit);
2277               continue;
2278           } // if( off->is_Con() )
2279         }   // if( mem_op &&
2280         mstack.push(m, Pre_Visit);
2281       }     // for(int i = ...)
2282     }
2283     else if (nstate == Alt_Post_Visit) {
2284       mstack.pop(); // Remove node from stack
2285       // We cannot remove the Cmp input from the Bool here, as the Bool may be
2286       // shared and all users of the Bool need to move the Cmp in parallel.
2287       // This leaves both the Bool and the If pointing at the Cmp.  To
2288       // prevent the Matcher from trying to Match the Cmp along both paths
2289       // BoolNode::match_edge always returns a zero.
2290 
2291       // We reorder the Op_If in a pre-order manner, so we can visit without
2292       // accidentally sharing the Cmp (the Bool and the If make 2 users).
2293       n->add_req( n->in(1)->in(1) ); // Add the Cmp next to the Bool
2294     }
2295     else if (nstate == Post_Visit) {
2296       mstack.pop(); // Remove node from stack
2297 


src/share/vm/opto/matcher.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File