Tue, 02 Dec 2014 10:43:43 +0000
Merge
1.1 --- a/src/share/vm/opto/connode.cpp Wed Nov 26 08:06:58 2014 +0100 1.2 +++ b/src/share/vm/opto/connode.cpp Tue Dec 02 10:43:43 2014 +0000 1.3 @@ -441,6 +441,101 @@ 1.4 return this; 1.5 } 1.6 1.7 +uint CastIINode::size_of() const { 1.8 + return sizeof(*this); 1.9 +} 1.10 + 1.11 +uint CastIINode::cmp(const Node &n) const { 1.12 + return TypeNode::cmp(n) && ((CastIINode&)n)._carry_dependency == _carry_dependency; 1.13 +} 1.14 + 1.15 +Node *CastIINode::Identity(PhaseTransform *phase) { 1.16 + if (_carry_dependency) { 1.17 + return this; 1.18 + } 1.19 + return ConstraintCastNode::Identity(phase); 1.20 +} 1.21 + 1.22 +const Type *CastIINode::Value(PhaseTransform *phase) const { 1.23 + const Type *res = ConstraintCastNode::Value(phase); 1.24 + 1.25 + // Try to improve the type of the CastII if we recognize a CmpI/If 1.26 + // pattern. 1.27 + if (_carry_dependency) { 1.28 + if (in(0) != NULL && (in(0)->is_IfFalse() || in(0)->is_IfTrue())) { 1.29 + Node* proj = in(0); 1.30 + if (proj->in(0)->in(1)->is_Bool()) { 1.31 + Node* b = proj->in(0)->in(1); 1.32 + if (b->in(1)->Opcode() == Op_CmpI) { 1.33 + Node* cmp = b->in(1); 1.34 + if (cmp->in(1) == in(1) && phase->type(cmp->in(2))->isa_int()) { 1.35 + const TypeInt* in2_t = phase->type(cmp->in(2))->is_int(); 1.36 + const Type* t = TypeInt::INT; 1.37 + BoolTest test = b->as_Bool()->_test; 1.38 + if (proj->is_IfFalse()) { 1.39 + test = test.negate(); 1.40 + } 1.41 + BoolTest::mask m = test._test; 1.42 + jlong lo_long = min_jint; 1.43 + jlong hi_long = max_jint; 1.44 + if (m == BoolTest::le || m == BoolTest::lt) { 1.45 + hi_long = in2_t->_hi; 1.46 + if (m == BoolTest::lt) { 1.47 + hi_long -= 1; 1.48 + } 1.49 + } else if (m == BoolTest::ge || m == BoolTest::gt) { 1.50 + lo_long = in2_t->_lo; 1.51 + if (m == BoolTest::gt) { 1.52 + lo_long += 1; 1.53 + } 1.54 + } else if (m == BoolTest::eq) { 1.55 + lo_long = in2_t->_lo; 1.56 + hi_long = in2_t->_hi; 1.57 + } else if (m == BoolTest::ne) { 1.58 + // can't do any better 1.59 + } else { 1.60 + stringStream ss; 1.61 + test.dump_on(&ss); 1.62 + fatal(err_msg_res("unexpected comparison %s", ss.as_string())); 1.63 + } 1.64 + int lo_int = (int)lo_long; 1.65 + int hi_int = (int)hi_long; 1.66 + 1.67 + if (lo_long != (jlong)lo_int) { 1.68 + lo_int = min_jint; 1.69 + } 1.70 + if (hi_long != (jlong)hi_int) { 1.71 + hi_int = max_jint; 1.72 + } 1.73 + 1.74 + t = TypeInt::make(lo_int, hi_int, Type::WidenMax); 1.75 + 1.76 + res = res->filter_speculative(t); 1.77 + 1.78 + return res; 1.79 + } 1.80 + } 1.81 + } 1.82 + } 1.83 + } 1.84 + return res; 1.85 +} 1.86 + 1.87 +Node *CastIINode::Ideal_DU_postCCP(PhaseCCP *ccp) { 1.88 + if (_carry_dependency) { 1.89 + return NULL; 1.90 + } 1.91 + return ConstraintCastNode::Ideal_DU_postCCP(ccp); 1.92 +} 1.93 + 1.94 +#ifndef PRODUCT 1.95 +void CastIINode::dump_spec(outputStream *st) const { 1.96 + TypeNode::dump_spec(st); 1.97 + if (_carry_dependency) { 1.98 + st->print(" carry dependency"); 1.99 + } 1.100 +} 1.101 +#endif 1.102 1.103 //============================================================================= 1.104
2.1 --- a/src/share/vm/opto/connode.hpp Wed Nov 26 08:06:58 2014 +0100 2.2 +++ b/src/share/vm/opto/connode.hpp Tue Dec 02 10:43:43 2014 +0000 2.3 @@ -241,10 +241,25 @@ 2.4 //------------------------------CastIINode------------------------------------- 2.5 // cast integer to integer (different range) 2.6 class CastIINode: public ConstraintCastNode { 2.7 + private: 2.8 + // Can this node be removed post CCP or does it carry a required dependency? 2.9 + const bool _carry_dependency; 2.10 + 2.11 + protected: 2.12 + virtual uint cmp( const Node &n ) const; 2.13 + virtual uint size_of() const; 2.14 + 2.15 public: 2.16 - CastIINode (Node *n, const Type *t ): ConstraintCastNode(n,t) {} 2.17 + CastIINode(Node *n, const Type *t, bool carry_dependency = false) 2.18 + : ConstraintCastNode(n,t), _carry_dependency(carry_dependency) {} 2.19 virtual int Opcode() const; 2.20 virtual uint ideal_reg() const { return Op_RegI; } 2.21 + virtual Node *Identity( PhaseTransform *phase ); 2.22 + virtual const Type *Value( PhaseTransform *phase ) const; 2.23 + virtual Node *Ideal_DU_postCCP( PhaseCCP * ); 2.24 +#ifndef PRODUCT 2.25 + virtual void dump_spec(outputStream *st) const; 2.26 +#endif 2.27 }; 2.28 2.29 //------------------------------CastPPNode-------------------------------------
3.1 --- a/src/share/vm/opto/loopTransform.cpp Wed Nov 26 08:06:58 2014 +0100 3.2 +++ b/src/share/vm/opto/loopTransform.cpp Tue Dec 02 10:43:43 2014 +0000 3.3 @@ -881,6 +881,20 @@ 3.4 return n; 3.5 } 3.6 3.7 +bool PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { 3.8 + Node* castii = new (C) CastIINode(incr, TypeInt::INT, true); 3.9 + castii->set_req(0, ctrl); 3.10 + register_new_node(castii, ctrl); 3.11 + for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { 3.12 + Node* n = incr->fast_out(i); 3.13 + if (n->is_Phi() && n->in(0) == loop) { 3.14 + int nrep = n->replace_edge(incr, castii); 3.15 + return true; 3.16 + } 3.17 + } 3.18 + return false; 3.19 +} 3.20 + 3.21 //------------------------------insert_pre_post_loops-------------------------- 3.22 // Insert pre and post loops. If peel_only is set, the pre-loop can not have 3.23 // more iterations added. It acts as a 'peel' only, no lower-bound RCE, no 3.24 @@ -1079,6 +1093,24 @@ 3.25 } 3.26 } 3.27 3.28 + // Nodes inside the loop may be control dependent on a predicate 3.29 + // that was moved before the preloop. If the back branch of the main 3.30 + // or post loops becomes dead, those nodes won't be dependent on the 3.31 + // test that guards that loop nest anymore which could lead to an 3.32 + // incorrect array access because it executes independently of the 3.33 + // test that was guarding the loop nest. We add a special CastII on 3.34 + // the if branch that enters the loop, between the input induction 3.35 + // variable value and the induction variable Phi to preserve correct 3.36 + // dependencies. 3.37 + 3.38 + // CastII for the post loop: 3.39 + bool inserted = cast_incr_before_loop(zer_opaq->in(1), zer_taken, post_head); 3.40 + assert(inserted, "no castII inserted"); 3.41 + 3.42 + // CastII for the main loop: 3.43 + inserted = cast_incr_before_loop(pre_incr, min_taken, main_head); 3.44 + assert(inserted, "no castII inserted"); 3.45 + 3.46 // Step B4: Shorten the pre-loop to run only 1 iteration (for now). 3.47 // RCE and alignment may change this later. 3.48 Node *cmp_end = pre_end->cmp_node();
4.1 --- a/src/share/vm/opto/loopnode.hpp Wed Nov 26 08:06:58 2014 +0100 4.2 +++ b/src/share/vm/opto/loopnode.hpp Tue Dec 02 10:43:43 2014 +0000 4.3 @@ -602,6 +602,8 @@ 4.4 return ctrl; 4.5 } 4.6 4.7 + bool cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop); 4.8 + 4.9 public: 4.10 bool has_node( Node* n ) const { 4.11 guarantee(n != NULL, "No Node.");
5.1 --- a/src/share/vm/opto/phaseX.cpp Wed Nov 26 08:06:58 2014 +0100 5.2 +++ b/src/share/vm/opto/phaseX.cpp Tue Dec 02 10:43:43 2014 +0000 5.3 @@ -1340,15 +1340,27 @@ 5.4 } 5.5 } 5.6 5.7 - if( use->is_Cmp() ) { // Enable CMP/BOOL optimization 5.8 + uint use_op = use->Opcode(); 5.9 + if(use->is_Cmp()) { // Enable CMP/BOOL optimization 5.10 add_users_to_worklist(use); // Put Bool on worklist 5.11 - // Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the 5.12 - // phi merging either 0 or 1 onto the worklist 5.13 if (use->outcnt() > 0) { 5.14 Node* bol = use->raw_out(0); 5.15 if (bol->outcnt() > 0) { 5.16 Node* iff = bol->raw_out(0); 5.17 - if (iff->outcnt() == 2) { 5.18 + if (use_op == Op_CmpI && 5.19 + iff->is_CountedLoopEnd()) { 5.20 + CountedLoopEndNode* cle = iff->as_CountedLoopEnd(); 5.21 + if (cle->limit() == n && cle->phi() != NULL) { 5.22 + // If an opaque node feeds into the limit condition of a 5.23 + // CountedLoop, we need to process the Phi node for the 5.24 + // induction variable when the opaque node is removed: 5.25 + // the range of values taken by the Phi is now known and 5.26 + // so its type is also known. 5.27 + _worklist.push(cle->phi()); 5.28 + } 5.29 + } else if (iff->outcnt() == 2) { 5.30 + // Look for the 'is_x2logic' pattern: "x ? : 0 : 1" and put the 5.31 + // phi merging either 0 or 1 onto the worklist 5.32 Node* ifproj0 = iff->raw_out(0); 5.33 Node* ifproj1 = iff->raw_out(1); 5.34 if (ifproj0->outcnt() > 0 && ifproj1->outcnt() > 0) { 5.35 @@ -1360,9 +1372,26 @@ 5.36 } 5.37 } 5.38 } 5.39 + if (use_op == Op_CmpI) { 5.40 + Node* in1 = use->in(1); 5.41 + for (uint i = 0; i < in1->outcnt(); i++) { 5.42 + if (in1->raw_out(i)->Opcode() == Op_CastII) { 5.43 + Node* castii = in1->raw_out(i); 5.44 + if (castii->in(0) != NULL && castii->in(0)->in(0) != NULL && castii->in(0)->in(0)->is_If()) { 5.45 + Node* ifnode = castii->in(0)->in(0); 5.46 + if (ifnode->in(1) != NULL && ifnode->in(1)->is_Bool() && ifnode->in(1)->in(1) == use) { 5.47 + // Reprocess a CastII node that may depend on an 5.48 + // opaque node value when the opaque node is 5.49 + // removed. In case it carries a dependency we can do 5.50 + // a better job of computing its type. 5.51 + _worklist.push(castii); 5.52 + } 5.53 + } 5.54 + } 5.55 + } 5.56 + } 5.57 } 5.58 5.59 - uint use_op = use->Opcode(); 5.60 // If changed Cast input, check Phi users for simple cycles 5.61 if( use->is_ConstraintCast() || use->is_CheckCastPP() ) { 5.62 for (DUIterator_Fast i2max, i2 = use->fast_outs(i2max); i2 < i2max; i2++) {
6.1 --- a/src/share/vm/opto/subnode.cpp Wed Nov 26 08:06:58 2014 +0100 6.2 +++ b/src/share/vm/opto/subnode.cpp Tue Dec 02 10:43:43 2014 +0000 6.3 @@ -1147,12 +1147,10 @@ 6.4 6.5 //------------------------------dump_spec------------------------------------- 6.6 // Print special per-node info 6.7 -#ifndef PRODUCT 6.8 void BoolTest::dump_on(outputStream *st) const { 6.9 const char *msg[] = {"eq","gt","of","lt","ne","le","nof","ge"}; 6.10 st->print("%s", msg[_test]); 6.11 } 6.12 -#endif 6.13 6.14 //============================================================================= 6.15 uint BoolNode::hash() const { return (Node::hash() << 3)|(_test._test+1); }
7.1 --- a/src/share/vm/opto/subnode.hpp Wed Nov 26 08:06:58 2014 +0100 7.2 +++ b/src/share/vm/opto/subnode.hpp Tue Dec 02 10:43:43 2014 +0000 7.3 @@ -275,9 +275,7 @@ 7.4 mask commute( ) const { return mask("032147658"[_test]-'0'); } 7.5 mask negate( ) const { return mask(_test^4); } 7.6 bool is_canonical( ) const { return (_test == BoolTest::ne || _test == BoolTest::lt || _test == BoolTest::le || _test == BoolTest::overflow); } 7.7 -#ifndef PRODUCT 7.8 void dump_on(outputStream *st) const; 7.9 -#endif 7.10 }; 7.11 7.12 //------------------------------BoolNode---------------------------------------
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/test/compiler/loopopts/TestDeadBackbranchArrayAccess.java Tue Dec 02 10:43:43 2014 +0000 8.3 @@ -0,0 +1,58 @@ 8.4 +/* 8.5 + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 8.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 8.7 + * 8.8 + * This code is free software; you can redistribute it and/or modify it 8.9 + * under the terms of the GNU General Public License version 2 only, as 8.10 + * published by the Free Software Foundation. 8.11 + * 8.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 8.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 8.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 8.15 + * version 2 for more details (a copy is included in the LICENSE file that 8.16 + * accompanied this code). 8.17 + * 8.18 + * You should have received a copy of the GNU General Public License version 8.19 + * 2 along with this work; if not, write to the Free Software Foundation, 8.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 8.21 + * 8.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 8.23 + * or visit www.oracle.com if you need additional information or have any 8.24 + * questions. 8.25 + * 8.26 + */ 8.27 + 8.28 +/** 8.29 + * @test 8.30 + * @bug 8054478 8.31 + * @summary dead backbranch in main loop results in erroneous array access 8.32 + * @run main/othervm -XX:CompileOnly=TestDeadBackbranchArrayAccess -Xcomp TestDeadBackbranchArrayAccess 8.33 + * 8.34 + */ 8.35 + 8.36 +public class TestDeadBackbranchArrayAccess { 8.37 + static char[] pattern0 = {0}; 8.38 + static char[] pattern1 = {1}; 8.39 + 8.40 + static void test(char[] array) { 8.41 + if (pattern1 == null) return; 8.42 + 8.43 + int i = 0; 8.44 + int pos = 0; 8.45 + char c = array[pos]; 8.46 + 8.47 + while (i >= 0 && (c == pattern0[i] || c == pattern1[i])) { 8.48 + i--; 8.49 + pos--; 8.50 + if (pos != -1) { 8.51 + c = array[pos]; 8.52 + } 8.53 + } 8.54 + } 8.55 + 8.56 + public static void main(String[] args) { 8.57 + for (int i = 0; i < 1000000; i++) { 8.58 + test(new char[1]); 8.59 + } 8.60 + } 8.61 +}