mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-07 00:48:38 +00:00
8021898: Broken JIT compiler optimization for loop unswitching
Fix method clone_projs() to clone all related MachProj nodes. Reviewed-by: roland, adlertz
This commit is contained in:
parent
5ab8312aa5
commit
4ee53ef4e3
@ -287,21 +287,26 @@ void PhaseChaitin::new_lrg(const Node *x, uint lrg) {
|
||||
}
|
||||
|
||||
|
||||
bool PhaseChaitin::clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id) {
|
||||
Block* bcon = _cfg.get_block_for_node(con);
|
||||
uint cindex = bcon->find_node(con);
|
||||
Node *con_next = bcon->_nodes[cindex+1];
|
||||
if (con_next->in(0) != con || !con_next->is_MachProj()) {
|
||||
return false; // No MachProj's follow
|
||||
int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id) {
|
||||
assert(b->find_node(copy) == (idx - 1), "incorrect insert index for copy kill projections");
|
||||
DEBUG_ONLY( Block* borig = _cfg.get_block_for_node(orig); )
|
||||
int found_projs = 0;
|
||||
uint cnt = orig->outcnt();
|
||||
for (uint i = 0; i < cnt; i++) {
|
||||
Node* proj = orig->raw_out(i);
|
||||
if (proj->is_MachProj()) {
|
||||
assert(proj->outcnt() == 0, "only kill projections are expected here");
|
||||
assert(_cfg.get_block_for_node(proj) == borig, "incorrect block for kill projections");
|
||||
found_projs++;
|
||||
// Copy kill projections after the cloned node
|
||||
Node* kills = proj->clone();
|
||||
kills->set_req(0, copy);
|
||||
b->_nodes.insert(idx++, kills);
|
||||
_cfg.map_node_to_block(kills, b);
|
||||
new_lrg(kills, max_lrg_id++);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy kills after the cloned constant
|
||||
Node *kills = con_next->clone();
|
||||
kills->set_req(0, copy);
|
||||
b->_nodes.insert(idx, kills);
|
||||
_cfg.map_node_to_block(kills, b);
|
||||
new_lrg(kills, max_lrg_id);
|
||||
return true;
|
||||
return found_projs;
|
||||
}
|
||||
|
||||
// Renumber the live ranges to compact them. Makes the IFG smaller.
|
||||
|
||||
@ -412,33 +412,22 @@ class PhaseChaitin : public PhaseRegAlloc {
|
||||
uint split_DEF( Node *def, Block *b, int loc, uint max, Node **Reachblock, Node **debug_defs, GrowableArray<uint> splits, int slidx );
|
||||
uint split_USE( Node *def, Block *b, Node *use, uint useidx, uint max, bool def_down, bool cisc_sp, GrowableArray<uint> splits, int slidx );
|
||||
|
||||
bool clone_projs(Block *b, uint idx, Node *con, Node *copy, LiveRangeMap &lrg_map) {
|
||||
bool found_projs = clone_projs_shared(b, idx, con, copy, lrg_map.max_lrg_id());
|
||||
|
||||
if(found_projs) {
|
||||
uint max_lrg_id = lrg_map.max_lrg_id();
|
||||
lrg_map.set_max_lrg_id(max_lrg_id + 1);
|
||||
}
|
||||
|
||||
return found_projs;
|
||||
}
|
||||
|
||||
//------------------------------clone_projs------------------------------------
|
||||
// After cloning some rematerialized instruction, clone any MachProj's that
|
||||
// follow it. Example: Intel zero is XOR, kills flags. Sparc FP constants
|
||||
// use G3 as an address temp.
|
||||
bool clone_projs(Block *b, uint idx, Node *con, Node *copy, uint &max_lrg_id) {
|
||||
bool found_projs = clone_projs_shared(b, idx, con, copy, max_lrg_id);
|
||||
int clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& max_lrg_id);
|
||||
|
||||
if(found_projs) {
|
||||
max_lrg_id++;
|
||||
int clone_projs(Block* b, uint idx, Node* orig, Node* copy, LiveRangeMap& lrg_map) {
|
||||
uint max_lrg_id = lrg_map.max_lrg_id();
|
||||
int found_projs = clone_projs(b, idx, orig, copy, max_lrg_id);
|
||||
if (found_projs > 0) {
|
||||
// max_lrg_id is updated during call above
|
||||
lrg_map.set_max_lrg_id(max_lrg_id);
|
||||
}
|
||||
|
||||
return found_projs;
|
||||
}
|
||||
|
||||
bool clone_projs_shared(Block *b, uint idx, Node *con, Node *copy, uint max_lrg_id);
|
||||
|
||||
Node *split_Rematerialize(Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits,
|
||||
int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru);
|
||||
// True if lidx is used before any real register is def'd in the block
|
||||
|
||||
@ -322,9 +322,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
|
||||
copy = m->clone();
|
||||
// Insert the copy in the basic block, just before us
|
||||
b->_nodes.insert(l++, copy);
|
||||
if(_phc.clone_projs(b, l, m, copy, _phc._lrg_map)) {
|
||||
l++;
|
||||
}
|
||||
l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map);
|
||||
} else {
|
||||
const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()];
|
||||
copy = new (C) MachSpillCopyNode(m, *rm, *rm);
|
||||
|
||||
@ -397,10 +397,15 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
|
||||
#endif
|
||||
// See if the cloned def kills any flags, and copy those kills as well
|
||||
uint i = insidx+1;
|
||||
if( clone_projs( b, i, def, spill, maxlrg) ) {
|
||||
int found_projs = clone_projs( b, i, def, spill, maxlrg);
|
||||
if (found_projs > 0) {
|
||||
// Adjust the point where we go hi-pressure
|
||||
if( i <= b->_ihrp_index ) b->_ihrp_index++;
|
||||
if( i <= b->_fhrp_index ) b->_fhrp_index++;
|
||||
if (i <= b->_ihrp_index) {
|
||||
b->_ihrp_index += found_projs;
|
||||
}
|
||||
if (i <= b->_fhrp_index) {
|
||||
b->_fhrp_index += found_projs;
|
||||
}
|
||||
}
|
||||
|
||||
return spill;
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "gc_interface/collectedHeap.inline.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
@ -559,7 +560,7 @@ void frame::print_value_on(outputStream* st, JavaThread *thread) const {
|
||||
|
||||
st->print("%s frame (sp=" INTPTR_FORMAT " unextended sp=" INTPTR_FORMAT, print_name(), sp(), unextended_sp());
|
||||
if (sp() != NULL)
|
||||
st->print(", fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), pc());
|
||||
st->print(", fp=" INTPTR_FORMAT ", real_fp=" INTPTR_FORMAT ", pc=" INTPTR_FORMAT, fp(), real_fp(), pc());
|
||||
|
||||
if (StubRoutines::contains(pc())) {
|
||||
st->print_cr(")");
|
||||
@ -720,11 +721,14 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose
|
||||
} else if (_cb->is_buffer_blob()) {
|
||||
st->print("v ~BufferBlob::%s", ((BufferBlob *)_cb)->name());
|
||||
} else if (_cb->is_nmethod()) {
|
||||
Method* m = ((nmethod *)_cb)->method();
|
||||
nmethod* nm = (nmethod*)_cb;
|
||||
Method* m = nm->method();
|
||||
if (m != NULL) {
|
||||
m->name_and_sig_as_C_string(buf, buflen);
|
||||
st->print("J %s @ " PTR_FORMAT " [" PTR_FORMAT "+" SIZE_FORMAT "]",
|
||||
buf, _pc, _cb->code_begin(), _pc - _cb->code_begin());
|
||||
st->print("J %d%s %s %s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+0x%x]",
|
||||
nm->compile_id(), (nm->is_osr_method() ? "%" : ""),
|
||||
((nm->compiler() != NULL) ? nm->compiler()->name() : ""),
|
||||
buf, m->code_size(), _pc, _cb->code_begin(), _pc - _cb->code_begin());
|
||||
} else {
|
||||
st->print("J " PTR_FORMAT, pc());
|
||||
}
|
||||
|
||||
@ -586,6 +586,13 @@ void VMError::report(outputStream* st) {
|
||||
while (count++ < StackPrintLimit) {
|
||||
fr.print_on_error(st, buf, sizeof(buf));
|
||||
st->cr();
|
||||
// Compiled code may use EBP register on x86 so it looks like
|
||||
// non-walkable C frame. Use frame.sender() for java frames.
|
||||
if (_thread && _thread->is_Java_thread() && fr.is_java_frame()) {
|
||||
RegisterMap map((JavaThread*)_thread, false); // No update
|
||||
fr = fr.sender(&map);
|
||||
continue;
|
||||
}
|
||||
if (os::is_first_C_frame(&fr)) break;
|
||||
fr = os::get_sender_for_C_frame(&fr);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user