Merge

Tue, 02 Dec 2014 10:43:43 +0000

author
roland
date
Tue, 02 Dec 2014 10:43:43 +0000
changeset 7396
b12418b0d05c
parent 7393
ecccc23346fe
parent 7395
4c228230f1d6
child 7397
abb8b1de96ff
child 7398
c03d85ef5e6a

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 +}

mercurial