8021898: Broken JIT compiler optimization for loop unswitching

Fri, 16 Aug 2013 14:11:40 -0700

author
kvn
date
Fri, 16 Aug 2013 14:11:40 -0700
changeset 5543
4b2838704fd5
parent 5542
d18b10b1fd09
child 5544
6725044c5725

8021898: Broken JIT compiler optimization for loop unswitching
Summary: fix method clone_projs() to clone all related MachProj nodes.
Reviewed-by: roland, adlertz

src/share/vm/opto/chaitin.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/chaitin.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/coalesce.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/reg_split.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/frame.cpp file | annotate | diff | comparison | revisions
src/share/vm/utilities/vmError.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/chaitin.cpp	Fri Aug 16 13:39:26 2013 -0400
     1.2 +++ b/src/share/vm/opto/chaitin.cpp	Fri Aug 16 14:11:40 2013 -0700
     1.3 @@ -287,21 +287,26 @@
     1.4  }
     1.5  
     1.6  
     1.7 -bool PhaseChaitin::clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id) {
     1.8 -  Block* bcon = _cfg.get_block_for_node(con);
     1.9 -  uint cindex = bcon->find_node(con);
    1.10 -  Node *con_next = bcon->_nodes[cindex+1];
    1.11 -  if (con_next->in(0) != con || !con_next->is_MachProj()) {
    1.12 -    return false;               // No MachProj's follow
    1.13 +int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id) {
    1.14 +  assert(b->find_node(copy) == (idx - 1), "incorrect insert index for copy kill projections");
    1.15 +  DEBUG_ONLY( Block* borig = _cfg.get_block_for_node(orig); )
    1.16 +  int found_projs = 0;
    1.17 +  uint cnt = orig->outcnt();
    1.18 +  for (uint i = 0; i < cnt; i++) {
    1.19 +    Node* proj = orig->raw_out(i);
    1.20 +    if (proj->is_MachProj()) {
    1.21 +      assert(proj->outcnt() == 0, "only kill projections are expected here");
    1.22 +      assert(_cfg.get_block_for_node(proj) == borig, "incorrect block for kill projections");
    1.23 +      found_projs++;
    1.24 +      // Copy kill projections after the cloned node
    1.25 +      Node* kills = proj->clone();
    1.26 +      kills->set_req(0, copy);
    1.27 +      b->_nodes.insert(idx++, kills);
    1.28 +      _cfg.map_node_to_block(kills, b);
    1.29 +      new_lrg(kills, max_lrg_id++);
    1.30 +    }
    1.31    }
    1.32 -
    1.33 -  // Copy kills after the cloned constant
    1.34 -  Node *kills = con_next->clone();
    1.35 -  kills->set_req(0, copy);
    1.36 -  b->_nodes.insert(idx, kills);
    1.37 -  _cfg.map_node_to_block(kills, b);
    1.38 -  new_lrg(kills, max_lrg_id);
    1.39 -  return true;
    1.40 +  return found_projs;
    1.41  }
    1.42  
    1.43  // Renumber the live ranges to compact them.  Makes the IFG smaller.
     2.1 --- a/src/share/vm/opto/chaitin.hpp	Fri Aug 16 13:39:26 2013 -0400
     2.2 +++ b/src/share/vm/opto/chaitin.hpp	Fri Aug 16 14:11:40 2013 -0700
     2.3 @@ -412,33 +412,22 @@
     2.4    uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray<uint> splits, int slidx );
     2.5    uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray<uint> splits, int slidx );
     2.6  
     2.7 -  bool clone_projs(Block *b, uint idx, Node *con, Node *copy, LiveRangeMap &lrg_map) {
     2.8 -    bool found_projs = clone_projs_shared(b, idx, con, copy, lrg_map.max_lrg_id());
     2.9 -
    2.10 -    if(found_projs) {
    2.11 -      uint max_lrg_id = lrg_map.max_lrg_id();
    2.12 -      lrg_map.set_max_lrg_id(max_lrg_id + 1);
    2.13 -    }
    2.14 -
    2.15 -    return found_projs;
    2.16 -  }
    2.17 -
    2.18    //------------------------------clone_projs------------------------------------
    2.19    // After cloning some rematerialized instruction, clone any MachProj's that
    2.20    // follow it.  Example: Intel zero is XOR, kills flags.  Sparc FP constants
    2.21    // use G3 as an address temp.
    2.22 -  bool clone_projs(Block *b, uint idx, Node *con, Node *copy, uint &max_lrg_id) {
    2.23 -    bool found_projs = clone_projs_shared(b, idx, con, copy, max_lrg_id);
    2.24 +  int clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id);
    2.25  
    2.26 -    if(found_projs) {
    2.27 -      max_lrg_id++;
    2.28 +  int clone_projs(Block* b, uint idx, Node* orig, Node* copy, LiveRangeMap& lrg_map) {
    2.29 +    uint max_lrg_id = lrg_map.max_lrg_id();
    2.30 +    int found_projs = clone_projs(b, idx, orig, copy, max_lrg_id);
    2.31 +    if (found_projs > 0) {
    2.32 +      // max_lrg_id is updated during call above
    2.33 +      lrg_map.set_max_lrg_id(max_lrg_id);
    2.34      }
    2.35 -
    2.36      return found_projs;
    2.37    }
    2.38  
    2.39 -  bool clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id);
    2.40 -
    2.41    Node *split_Rematerialize(Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits,
    2.42                              int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru);
    2.43    // True if lidx is used before any real register is def'd in the block
     3.1 --- a/src/share/vm/opto/coalesce.cpp	Fri Aug 16 13:39:26 2013 -0400
     3.2 +++ b/src/share/vm/opto/coalesce.cpp	Fri Aug 16 14:11:40 2013 -0700
     3.3 @@ -322,9 +322,7 @@
     3.4                copy = m->clone();
     3.5                // Insert the copy in the basic block, just before us
     3.6                b->_nodes.insert(l++, copy);
     3.7 -              if(_phc.clone_projs(b, l, m, copy, _phc._lrg_map)) {
     3.8 -                l++;
     3.9 -              }
    3.10 +              l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map);
    3.11              } else {
    3.12                const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
    3.13                copy = new (C) MachSpillCopyNode(m, *rm, *rm);
     4.1 --- a/src/share/vm/opto/reg_split.cpp	Fri Aug 16 13:39:26 2013 -0400
     4.2 +++ b/src/share/vm/opto/reg_split.cpp	Fri Aug 16 14:11:40 2013 -0700
     4.3 @@ -397,10 +397,15 @@
     4.4  #endif
     4.5    // See if the cloned def kills any flags, and copy those kills as well
     4.6    uint i = insidx+1;
     4.7 -  if( clone_projs( b, i, def, spill, maxlrg) ) {
     4.8 +  int found_projs = clone_projs( b, i, def, spill, maxlrg);
     4.9 +  if (found_projs > 0) {
    4.10      // Adjust the point where we go hi-pressure
    4.11 -    if( i <= b->_ihrp_index ) b->_ihrp_index++;
    4.12 -    if( i <= b->_fhrp_index ) b->_fhrp_index++;
    4.13 +    if (i <= b->_ihrp_index) {
    4.14 +      b->_ihrp_index += found_projs;
    4.15 +    }
    4.16 +    if (i <= b->_fhrp_index) {
    4.17 +      b->_fhrp_index += found_projs;
    4.18 +    }
    4.19    }
    4.20  
    4.21    return spill;
     5.1 --- a/src/share/vm/runtime/frame.cpp	Fri Aug 16 13:39:26 2013 -0400
     5.2 +++ b/src/share/vm/runtime/frame.cpp	Fri Aug 16 14:11:40 2013 -0700
     5.3 @@ -23,6 +23,7 @@
     5.4   */
     5.5  
     5.6  #include "precompiled.hpp"
     5.7 +#include "compiler/abstractCompiler.hpp"
     5.8  #include "compiler/disassembler.hpp"
     5.9  #include "gc_interface/collectedHeap.inline.hpp"
    5.10  #include "interpreter/interpreter.hpp"
    5.11 @@ -559,7 +560,7 @@
    5.12  
    5.13    st->print("%s frame (sp=" INTPTR_FORMAT " unextended sp=" INTPTR_FORMAT, print_name(), sp(), unextended_sp());
    5.14    if (sp() != NULL)
    5.15 -    st->print(", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), pc());
    5.16 +    st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), real_fp(), pc());
    5.17  
    5.18    if (StubRoutines::contains(pc())) {
    5.19      st->print_cr(")");
    5.20 @@ -720,11 +721,14 @@
    5.21      } else if (_cb->is_buffer_blob()) {
    5.22        st->print("v  ~BufferBlob::%s", ((BufferBlob *)_cb)->name());
    5.23      } else if (_cb->is_nmethod()) {
    5.24 -      Method* m = ((nmethod *)_cb)->method();
    5.25 +      nmethod* nm = (nmethod*)_cb;
    5.26 +      Method* m = nm->method();
    5.27        if (m != NULL) {
    5.28          m->name_and_sig_as_C_string(buf, buflen);
    5.29 -        st->print("J  %s @ " PTR_FORMAT " [" PTR_FORMAT "+" SIZE_FORMAT "]",
    5.30 -                  buf, _pc, _cb->code_begin(), _pc - _cb->code_begin());
    5.31 +        st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]",
    5.32 +                  nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
    5.33 +                  ((nm->compiler() != NULL) ? nm->compiler()->name() : ""),
    5.34 +                  buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin());
    5.35        } else {
    5.36          st->print("J  " PTR_FORMAT, pc());
    5.37        }
     6.1 --- a/src/share/vm/utilities/vmError.cpp	Fri Aug 16 13:39:26 2013 -0400
     6.2 +++ b/src/share/vm/utilities/vmError.cpp	Fri Aug 16 14:11:40 2013 -0700
     6.3 @@ -586,6 +586,13 @@
     6.4            while (count++ < StackPrintLimit) {
     6.5               fr.print_on_error(st, buf, sizeof(buf));
     6.6               st->cr();
     6.7 +             // Compiled code may use EBP register on x86 so it looks like
     6.8 +             // non-walkable C frame. Use frame.sender() for java frames.
     6.9 +             if (_thread && _thread->is_Java_thread() && fr.is_java_frame()) {
    6.10 +               RegisterMap map((JavaThread*)_thread, false); // No update
    6.11 +               fr = fr.sender(&map);
    6.12 +               continue;
    6.13 +             }
    6.14               if (os::is_first_C_frame(&fr)) break;
    6.15               fr = os::get_sender_for_C_frame(&fr);
    6.16            }

mercurial