# HG changeset patch # User roland # Date 1442501622 -7200 # Node ID c3e302e8e429c3a075b882550b87b0fa9645282d # Parent 71794b149055eff9978e5e5c166688e3034dcce9 8136820: Generate better code for some Unsafe addressing patterns Summary: reshape address computation to move invariant part out of loops Reviewed-by: kvn diff -r 71794b149055 -r c3e302e8e429 hotspot/src/cpu/x86/vm/x86_64.ad --- a/hotspot/src/cpu/x86/vm/x86_64.ad Thu Sep 24 20:13:04 2015 +0300 +++ b/hotspot/src/cpu/x86/vm/x86_64.ad Thu Sep 17 16:53:42 2015 +0200 @@ -3767,6 +3767,22 @@ %} %} +operand indPosIndexScale(any_RegP reg, rRegI idx, immI2 scale) +%{ + constraint(ALLOC_IN_RC(ptr_reg)); + predicate(n->in(3)->in(1)->as_Type()->type()->is_long()->_lo >= 0); + match(AddP reg (LShiftL (ConvI2L idx) scale)); + + op_cost(10); + format %{"[$reg + pos $idx << $scale]" %} + interface(MEMORY_INTER) %{ + base($reg); + index($idx); + scale($scale); + disp(0x0); + %} +%} + // Indirect Memory Times Scale Plus Index Register Plus Offset Operand operand indIndexScaleOffset(any_RegP reg, immL32 off, rRegL lreg, immI2 scale) %{ @@ -4159,7 +4175,7 @@ // case of this is memory operands. opclass memory(indirect, indOffset8, indOffset32, indIndexOffset, indIndex, - indIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset, + indIndexScale, indPosIndexScale, indIndexScaleOffset, indPosIndexOffset, indPosIndexScaleOffset, indCompressedOopOffset, indirectNarrow, indOffset8Narrow, indOffset32Narrow, indIndexOffsetNarrow, indIndexNarrow, indIndexScaleNarrow, @@ -5186,6 +5202,17 @@ ins_pipe(ialu_reg_reg_fat); %} +instruct leaPPosIdxScale(rRegP dst, indPosIndexScale mem) +%{ + match(Set dst mem); + + ins_cost(110); + format %{ "leaq $dst, $mem\t# ptr idxscale" %} + opcode(0x8D); + ins_encode(REX_reg_mem_wide(dst, mem), OpcP, reg_mem(dst, mem)); + ins_pipe(ialu_reg_reg_fat); +%} + instruct leaPIdxScaleOff(rRegP dst, indIndexScaleOffset mem) %{ match(Set dst mem); diff -r 71794b149055 -r c3e302e8e429 hotspot/src/share/vm/opto/loopopts.cpp --- a/hotspot/src/share/vm/opto/loopopts.cpp Thu Sep 24 20:13:04 2015 +0300 +++ b/hotspot/src/share/vm/opto/loopopts.cpp Thu Sep 17 16:53:42 2015 +0200 @@ -447,21 +447,21 @@ } // Replace (I1 +p (I2 + V)) with ((I1 +p I2) +p V) - if( n2_loop != n_loop && n3_loop == n_loop ) { - if( n->in(3)->Opcode() == Op_AddI ) { + if (n2_loop != n_loop && n3_loop == n_loop) { + if (n->in(3)->Opcode() == Op_AddX) { Node *V = n->in(3)->in(1); Node *I = n->in(3)->in(2); - if( is_member(n_loop,get_ctrl(V)) ) { + if (is_member(n_loop,get_ctrl(V))) { } else { Node *tmp = V; V = I; I = tmp; } - if( !is_member(n_loop,get_ctrl(I)) ) { - Node *add1 = new AddPNode( n->in(1), n->in(2), I ); + if (!is_member(n_loop,get_ctrl(I))) { + Node *add1 = new AddPNode(n->in(1), n->in(2), I); // Stuff new AddP in the loop preheader - register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) ); - Node *add2 = new AddPNode( n->in(1), add1, V ); - register_new_node( add2, n_ctrl ); - _igvn.replace_node( n, add2 ); + register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl)); + Node *add2 = new AddPNode(n->in(1), add1, V); + register_new_node(add2, n_ctrl); + _igvn.replace_node(n, add2); return add2; } } diff -r 71794b149055 -r c3e302e8e429 hotspot/src/share/vm/opto/matcher.cpp --- a/hotspot/src/share/vm/opto/matcher.cpp Thu Sep 24 20:13:04 2015 +0300 +++ b/hotspot/src/share/vm/opto/matcher.cpp Thu Sep 17 16:53:42 2015 +0200 @@ -2045,6 +2045,33 @@ // and then expanded into the inline_cache_reg and a method_oop register // defined in ad_.cpp +// Check for shift by small constant as well +static bool clone_shift(Node* shift, Matcher* matcher, MStack& mstack, VectorSet& address_visited) { + if (shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() && + shift->in(2)->get_int() <= 3 && + // Are there other uses besides address expressions? + !matcher->is_visited(shift)) { + address_visited.set(shift->_idx); // Flag as address_visited + mstack.push(shift->in(2), Visit); + Node *conv = shift->in(1); +#ifdef _LP64 + // Allow Matcher to match the rule which bypass + // ConvI2L operation for an array index on LP64 + // if the index value is positive. + if (conv->Opcode() == Op_ConvI2L && + conv->as_Type()->type()->is_long()->_lo >= 0 && + // Are there other uses besides address expressions? + !matcher->is_visited(conv)) { + address_visited.set(conv->_idx); // Flag as address_visited + mstack.push(conv->in(1), Pre_Visit); + } else +#endif + mstack.push(conv, Pre_Visit); + return true; + } + return false; +} + //------------------------------find_shared------------------------------------ // Set bits if Node is shared or otherwise a root @@ -2205,7 +2232,10 @@ #endif // Clone addressing expressions as they are "free" in memory access instructions - if( mem_op && i == MemNode::Address && mop == Op_AddP ) { + if (mem_op && i == MemNode::Address && mop == Op_AddP && + // When there are other uses besides address expressions + // put it on stack and mark as shared. + !is_visited(m)) { // Some inputs for address expression are not put on stack // to avoid marking them as shared and forcing them into register // if they are used only in address expressions. @@ -2213,10 +2243,7 @@ // besides address expressions. Node *off = m->in(AddPNode::Offset); - if( off->is_Con() && - // When there are other uses besides address expressions - // put it on stack and mark as shared. - !is_visited(m) ) { + if (off->is_Con()) { address_visited.test_set(m->_idx); // Flag as address_visited Node *adr = m->in(AddPNode::Address); @@ -2229,28 +2256,7 @@ !is_visited(adr) ) { address_visited.set(adr->_idx); // Flag as address_visited Node *shift = adr->in(AddPNode::Offset); - // Check for shift by small constant as well - if( shift->Opcode() == Op_LShiftX && shift->in(2)->is_Con() && - shift->in(2)->get_int() <= 3 && - // Are there other uses besides address expressions? - !is_visited(shift) ) { - address_visited.set(shift->_idx); // Flag as address_visited - mstack.push(shift->in(2), Visit); - Node *conv = shift->in(1); -#ifdef _LP64 - // Allow Matcher to match the rule which bypass - // ConvI2L operation for an array index on LP64 - // if the index value is positive. - if( conv->Opcode() == Op_ConvI2L && - conv->as_Type()->type()->is_long()->_lo >= 0 && - // Are there other uses besides address expressions? - !is_visited(conv) ) { - address_visited.set(conv->_idx); // Flag as address_visited - mstack.push(conv->in(1), Pre_Visit); - } else -#endif - mstack.push(conv, Pre_Visit); - } else { + if (!clone_shift(shift, this, mstack, address_visited)) { mstack.push(shift, Pre_Visit); } mstack.push(adr->in(AddPNode::Address), Pre_Visit); @@ -2263,6 +2269,12 @@ mstack.push(off, Visit); mstack.push(m->in(AddPNode::Base), Pre_Visit); continue; // for(int i = ...) + } else if (clone_shift_expressions && + clone_shift(off, this, mstack, address_visited)) { + address_visited.test_set(m->_idx); // Flag as address_visited + mstack.push(m->in(AddPNode::Address), Pre_Visit); + mstack.push(m->in(AddPNode::Base), Pre_Visit); + continue; } // if( off->is_Con() ) } // if( mem_op && mstack.push(m, Pre_Visit); diff -r 71794b149055 -r c3e302e8e429 hotspot/src/share/vm/opto/superword.cpp --- a/hotspot/src/share/vm/opto/superword.cpp Thu Sep 24 20:13:04 2015 +0300 +++ b/hotspot/src/share/vm/opto/superword.cpp Thu Sep 17 16:53:42 2015 +0200 @@ -3055,6 +3055,9 @@ } } if (invariant(n)) { + if (opc == Op_ConvI2L) { + n = n->in(1); + } _negate_invar = negate; _invar = n; NOT_PRODUCT(_tracer.offset_plus_k_10(n, _invar, _negate_invar, _offset);)