6732194: Data corruption dependent on -server/-client/-Xbatch
Summary: rematerializing nodes results in incorrect inputs
Reviewed-by: rasbold
--- a/hotspot/src/share/vm/opto/chaitin.cpp Thu Aug 14 10:15:29 2008 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Mon Aug 18 23:17:51 2008 -0700
@@ -43,7 +43,7 @@
if( _degree_valid ) tty->print( "%d ", _eff_degree );
else tty->print("? ");
- if( _def == NodeSentinel ) {
+ if( is_multidef() ) {
tty->print("MultiDef ");
if (_defs != NULL) {
tty->print("(");
@@ -765,7 +765,7 @@
// if the LRG is an unaligned pair, we will have to spill
// so clear the LRG's register mask if it is not already spilled
if ( !n->is_SpillCopy() &&
- (lrg._def == NULL || lrg._def == NodeSentinel || !lrg._def->is_SpillCopy()) &&
+ (lrg._def == NULL || lrg.is_multidef() || !lrg._def->is_SpillCopy()) &&
lrgmask.is_misaligned_Pair()) {
lrg.Clear();
}
@@ -1282,7 +1282,7 @@
// Live range is live and no colors available
else {
assert( lrg->alive(), "" );
- assert( !lrg->_fat_proj || lrg->_def == NodeSentinel ||
+ assert( !lrg->_fat_proj || lrg->is_multidef() ||
lrg->_def->outcnt() > 0, "fat_proj cannot spill");
assert( !orig_mask.is_AllStack(), "All Stack does not spill" );
--- a/hotspot/src/share/vm/opto/chaitin.hpp Thu Aug 14 10:15:29 2008 -0700
+++ b/hotspot/src/share/vm/opto/chaitin.hpp Mon Aug 18 23:17:51 2008 -0700
@@ -156,6 +156,8 @@
// Alive if non-zero, dead if zero
bool alive() const { return _def != NULL; }
+ bool is_multidef() const { return _def == NodeSentinel; }
+ bool is_singledef() const { return _def != NodeSentinel; }
#ifndef PRODUCT
void dump( ) const;
@@ -320,7 +322,8 @@
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 );
int clone_projs( Block *b, uint idx, Node *con, Node *copy, uint &maxlrg );
- Node *split_Rematerialize( Node *def, Block *b, uint insidx, uint &maxlrg, GrowableArray<uint> splits, int slidx, uint *lrg2reach, Node **Reachblock, bool walkThru );
+ 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
bool prompt_use( Block *b, uint lidx );
Node *get_spillcopy_wide( Node *def, Node *use, uint uidx );
--- a/hotspot/src/share/vm/opto/coalesce.cpp Thu Aug 14 10:15:29 2008 -0700
+++ b/hotspot/src/share/vm/opto/coalesce.cpp Mon Aug 18 23:17:51 2008 -0700
@@ -604,8 +604,8 @@
// If both are single def, then src_def powers one live range
// and def_copy powers the other. After merging, src_def powers
// the combined live range.
- lrgs(lr1)._def = (lrgs(lr1)._def == NodeSentinel ||
- lrgs(lr2)._def == NodeSentinel )
+ lrgs(lr1)._def = (lrgs(lr1).is_multidef() ||
+ lrgs(lr2).is_multidef() )
? NodeSentinel : src_def;
lrgs(lr2)._def = NULL; // No def for lrg 2
lrgs(lr2).Clear(); // Force empty mask for LRG 2
--- a/hotspot/src/share/vm/opto/ifg.cpp Thu Aug 14 10:15:29 2008 -0700
+++ b/hotspot/src/share/vm/opto/ifg.cpp Mon Aug 18 23:17:51 2008 -0700
@@ -594,7 +594,7 @@
// Insure high score for immediate-use spill copies so they get a color
if( n->is_SpillCopy()
- && lrgs(r)._def != NodeSentinel // MultiDef live range can still split
+ && lrgs(r).is_singledef() // MultiDef live range can still split
&& n->outcnt() == 1 // and use must be in this block
&& _cfg._bbs[n->unique_out()->_idx] == b ) {
// All single-use MachSpillCopy(s) that immediately precede their
--- a/hotspot/src/share/vm/opto/reg_split.cpp Thu Aug 14 10:15:29 2008 -0700
+++ b/hotspot/src/share/vm/opto/reg_split.cpp Mon Aug 18 23:17:51 2008 -0700
@@ -284,7 +284,7 @@
// Check for single-def (LRG cannot redefined)
uint lidx = n2lidx(in);
if( lidx >= _maxlrg ) continue; // Value is a recent spill-copy
- if( lrgs(lidx)._def != NodeSentinel ) continue;
+ if (lrgs(lidx).is_singledef()) continue;
Block *b_def = _cfg._bbs[def->_idx];
int idx_def = b_def->find_node(def);
@@ -311,12 +311,20 @@
uint lidx = Find_id(in);
// Walk backwards thru spill copy node intermediates
- if( walkThru )
+ if (walkThru) {
while ( in->is_SpillCopy() && lidx >= _maxlrg ) {
in = in->in(1);
lidx = Find_id(in);
}
+ if (lidx < _maxlrg && lrgs(lidx).is_multidef()) {
+ // walkThru found a multidef LRG, which is unsafe to use, so
+ // just keep the original def used in the clone.
+ in = spill->in(i);
+ lidx = Find_id(in);
+ }
+ }
+
if( lidx < _maxlrg && lrgs(lidx).reg() >= LRG::SPILL_REG ) {
Node *rdef = Reachblock[lrg2reach[lidx]];
if( rdef ) spill->set_req(i,rdef);
@@ -505,7 +513,7 @@
// Do not bother splitting or putting in Phis for single-def
// rematerialized live ranges. This happens alot to constants
// with long live ranges.
- if( lrgs(lidx)._def != NodeSentinel &&
+ if( lrgs(lidx).is_singledef() &&
lrgs(lidx)._def->rematerialize() ) {
// reset the Reaches & UP entries
Reachblock[slidx] = lrgs(lidx)._def;