提交 e5a807c0 编写于 作者: N neliasso

8011621: live_ranges_in_separate_class.patch

Reviewed-by: kvn, roland
Contributed-by: niclas.adlertz@oracle.com
上级 b5884a6f
......@@ -187,7 +187,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS)
Src_Dirs := $(Src_Dirs/$(TYPE))
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp chaitin\* c2_\* runtime_\*
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
COMPILER1_SPECIFIC_FILES := c1_\*
SHARK_SPECIFIC_FILES := shark
ZERO_SPECIFIC_FILES := zero
......
......@@ -189,7 +189,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK := $(CORE_PATHS) $(SHARK_PATHS)
Src_Dirs := $(Src_Dirs/$(TYPE))
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp chaitin\* c2_\* runtime_\*
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
COMPILER1_SPECIFIC_FILES := c1_\*
SHARK_SPECIFIC_FILES := shark
ZERO_SPECIFIC_FILES := zero
......
......@@ -202,7 +202,7 @@ Src_Dirs/ZERO := $(CORE_PATHS)
Src_Dirs/SHARK := $(CORE_PATHS)
Src_Dirs := $(Src_Dirs/$(TYPE))
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp chaitin\* c2_\* runtime_\*
COMPILER2_SPECIFIC_FILES := opto libadt bcEscapeAnalyzer.cpp c2_\* runtime_\*
COMPILER1_SPECIFIC_FILES := c1_\*
SHARK_SPECIFIC_FILES := shark
ZERO_SPECIFIC_FILES := zero
......
......@@ -114,7 +114,7 @@ case "${TYPE}" in
"shark") Src_Dirs="${CORE_PATHS}" ;;
esac
COMPILER2_SPECIFIC_FILES="opto libadt bcEscapeAnalyzer.cpp chaitin* c2_* runtime_*"
COMPILER2_SPECIFIC_FILES="opto libadt bcEscapeAnalyzer.cpp c2_* runtime_*"
COMPILER1_SPECIFIC_FILES="c1_*"
SHARK_SPECIFIC_FILES="shark"
ZERO_SPECIFIC_FILES="zero"
......
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void PhaseRegAlloc::pd_preallocate_hook() {
// no action
}
#ifdef ASSERT
void PhaseRegAlloc::pd_postallocate_verify_hook() {
// no action
}
#endif
// Reconciliation History
// chaitin_solaris.cpp 1.7 99/07/12 23:54:22
// End
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void PhaseRegAlloc::pd_preallocate_hook() {
// no action
}
#ifdef ASSERT
void PhaseRegAlloc::pd_postallocate_verify_hook() {
// no action
}
#endif
// Reconciliation History
// chaitin_solaris.cpp 1.7 99/07/12 23:54:22
// End
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
void PhaseRegAlloc::pd_preallocate_hook() {
// no action
}
#ifdef ASSERT
void PhaseRegAlloc::pd_postallocate_verify_hook() {
// no action
}
#endif
//Reconciliation History
// 1.1 99/02/12 15:35:26 chaitin_win32.cpp
// 1.2 99/02/18 15:38:56 chaitin_win32.cpp
// 1.4 99/03/09 10:37:48 chaitin_win32.cpp
// 1.6 99/03/25 11:07:44 chaitin_win32.cpp
// 1.8 99/06/22 16:38:58 chaitin_win32.cpp
//End
/*
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/chaitin.hpp"
#include "opto/machnode.hpp"
// Disallow the use of the frame pointer (EBP) for implicit null exceptions
// on win95/98. If we do not do this, the OS gets confused and gives a stack
// error.
void PhaseRegAlloc::pd_preallocate_hook() {
#ifndef _WIN64
if (ImplicitNullChecks && !os::win32::is_nt()) {
for (uint block_num=1; block_num<_cfg._num_blocks; block_num++) {
Block *block = _cfg._blocks[block_num];
Node *block_end = block->end();
if (block_end->is_MachNullCheck() &&
block_end->as_Mach()->ideal_Opcode() != Op_Con) {
// The last instruction in the block is an implicit null check.
// Fix its input so that it does not load into the frame pointer.
_matcher.pd_implicit_null_fixup(block_end->in(1)->as_Mach(),
block_end->as_MachNullCheck()->_vidx);
}
}
}
#else
// WIN64==itanium on XP
#endif
}
#ifdef ASSERT
// Verify that no implicit null check uses the frame pointer (EBP) as
// its register on win95/98. Use of the frame pointer in an implicit
// null check confuses the OS, yielding a stack error.
void PhaseRegAlloc::pd_postallocate_verify_hook() {
#ifndef _WIN64
if (ImplicitNullChecks && !os::win32::is_nt()) {
for (uint block_num=1; block_num<_cfg._num_blocks; block_num++) {
Block *block = _cfg._blocks[block_num];
Node *block_end = block->_nodes[block->_nodes.size()-1];
if (block_end->is_MachNullCheck() && block_end->as_Mach()->ideal_Opcode() != Op_Con) {
// The last instruction in the block is an implicit
// null check. Verify that this instruction does not
// use the frame pointer.
int reg = get_reg_first(block_end->in(1)->in(block_end->as_MachNullCheck()->_vidx));
assert(reg != EBP_num,
"implicit null check using frame pointer on win95/98");
}
}
}
#else
// WIN64==itanium on XP
#endif
}
#endif
此差异已折叠。
......@@ -265,18 +265,118 @@ public:
int effective_degree( uint lidx ) const;
};
// TEMPORARILY REPLACED WITH COMMAND LINE FLAG
//// !!!!! Magic Constants need to move into ad file
#ifdef SPARC
//#define FLOAT_PRESSURE 30 /* SFLT_REG_mask.Size() - 1 */
//#define INT_PRESSURE 23 /* NOTEMP_I_REG_mask.Size() - 1 */
#define FLOAT_INCREMENT(regs) regs
#else
//#define FLOAT_PRESSURE 6
//#define INT_PRESSURE 6
#define FLOAT_INCREMENT(regs) 1
#endif
// The LiveRangeMap class is responsible for storing node to live range id mapping.
// Each node is mapped to a live range id (a virtual register). Nodes that are
// not considered for register allocation are given live range id 0.
class LiveRangeMap VALUE_OBJ_CLASS_SPEC {
private:
uint _max_lrg_id;
// Union-find map. Declared as a short for speed.
// Indexed by live-range number, it returns the compacted live-range number
LRG_List _uf_map;
// Map from Nodes to live ranges
LRG_List _names;
// Straight out of Tarjan's union-find algorithm
uint find_compress(const Node *node) {
uint lrg_id = find_compress(_names[node->_idx]);
_names.map(node->_idx, lrg_id);
return lrg_id;
}
uint find_compress(uint lrg);
public:
const LRG_List& names() {
return _names;
}
uint max_lrg_id() const {
return _max_lrg_id;
}
void set_max_lrg_id(uint max_lrg_id) {
_max_lrg_id = max_lrg_id;
}
uint size() const {
return _names.Size();
}
uint live_range_id(uint idx) const {
return _names[idx];
}
uint live_range_id(const Node *node) const {
return _names[node->_idx];
}
uint uf_live_range_id(uint lrg_id) const {
return _uf_map[lrg_id];
}
void map(uint idx, uint lrg_id) {
_names.map(idx, lrg_id);
}
void uf_map(uint dst_lrg_id, uint src_lrg_id) {
_uf_map.map(dst_lrg_id, src_lrg_id);
}
void extend(uint idx, uint lrg_id) {
_names.extend(idx, lrg_id);
}
void uf_extend(uint dst_lrg_id, uint src_lrg_id) {
_uf_map.extend(dst_lrg_id, src_lrg_id);
}
LiveRangeMap(uint unique)
: _names(unique)
, _uf_map(unique)
, _max_lrg_id(0) {}
uint find_id( const Node *n ) {
uint retval = live_range_id(n);
assert(retval == find(n),"Invalid node to lidx mapping");
return retval;
}
// Reset the Union-Find map to identity
void reset_uf_map(uint max_lrg_id);
// Make all Nodes map directly to their final live range; no need for
// the Union-Find mapping after this call.
void compress_uf_map_for_nodes();
uint find(uint lidx) {
uint uf_lidx = _uf_map[lidx];
return (uf_lidx == lidx) ? uf_lidx : find_compress(lidx);
}
// Convert a Node into a Live Range Index - a lidx
uint find(const Node *node) {
uint lidx = live_range_id(node);
uint uf_lidx = _uf_map[lidx];
return (uf_lidx == lidx) ? uf_lidx : find_compress(node);
}
// Like Find above, but no path compress, so bad asymptotic behavior
uint find_const(uint lrg) const;
// Like Find above, but no path compress, so bad asymptotic behavior
uint find_const(const Node *node) const {
if(node->_idx >= _names.Size()) {
return 0; // not mapped, usual for debug dump
}
return find_const(_names[node->_idx]);
}
};
//------------------------------Chaitin----------------------------------------
// Briggs-Chaitin style allocation, mostly.
......@@ -286,7 +386,6 @@ class PhaseChaitin : public PhaseRegAlloc {
int _trip_cnt;
int _alternate;
uint _maxlrg; // Max live range number
LRG &lrgs(uint idx) const { return _ifg->lrgs(idx); }
PhaseLive *_live; // Liveness, used in the interference graph
PhaseIFG *_ifg; // Interference graph (for original chunk)
......@@ -294,16 +393,6 @@ class PhaseChaitin : public PhaseRegAlloc {
VectorSet _spilled_once; // Nodes that have been spilled
VectorSet _spilled_twice; // Nodes that have been spilled twice
LRG_List _names; // Map from Nodes to Live RanGes
// Union-find map. Declared as a short for speed.
// Indexed by live-range number, it returns the compacted live-range number
LRG_List _uf_map;
// Reset the Union-Find map to identity
void reset_uf_map( uint maxlrg );
// Remove the need for the Union-Find mapping
void compress_uf_map_for_nodes( );
// Combine the Live Range Indices for these 2 Nodes into a single live
// range. Future requests for any Node in either live range will
// return the live range index for the combined live range.
......@@ -322,7 +411,34 @@ class PhaseChaitin : public PhaseRegAlloc {
// Helper functions for Split()
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 );
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);
if(found_projs) {
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
......@@ -349,20 +465,11 @@ public:
PhaseChaitin( uint unique, PhaseCFG &cfg, Matcher &matcher );
~PhaseChaitin() {}
// Convert a Node into a Live Range Index - a lidx
uint Find( const Node *n ) {
uint lidx = n2lidx(n);
uint uf_lidx = _uf_map[lidx];
return (uf_lidx == lidx) ? uf_lidx : Find_compress(n);
}
uint Find_const( uint lrg ) const;
uint Find_const( const Node *n ) const;
LiveRangeMap _lrg_map;
// Do all the real work of allocate
void Register_Allocate();
uint n2lidx( const Node *n ) const { return _names[n->_idx]; }
float high_frequency_lrg() const { return _high_frequency_lrg; }
#ifndef PRODUCT
......@@ -374,18 +481,6 @@ private:
// all inputs to a PhiNode, effectively coalescing live ranges. Insert
// copies as needed.
void de_ssa();
uint Find_compress( const Node *n );
uint Find( uint lidx ) {
uint uf_lidx = _uf_map[lidx];
return (uf_lidx == lidx) ? uf_lidx : Find_compress(lidx);
}
uint Find_compress( uint lidx );
uint Find_id( const Node *n ) {
uint retval = n2lidx(n);
assert(retval == Find(n),"Invalid node to lidx mapping");
return retval;
}
// Add edge between reg and everything in the vector.
// Same as _ifg->add_vector(reg,live) EXCEPT use the RegMask
......
此差异已折叠。
......@@ -41,23 +41,25 @@ protected:
public:
// Coalesce copies
PhaseCoalesce( PhaseChaitin &chaitin ) : Phase(Coalesce), _phc(chaitin) { }
PhaseCoalesce(PhaseChaitin &phc)
: Phase(Coalesce)
, _phc(phc) {}
virtual void verify() = 0;
// Coalesce copies
void coalesce_driver( );
void coalesce_driver();
// Coalesce copies in this block
virtual void coalesce( Block *b ) = 0;
virtual void coalesce(Block *b) = 0;
// Attempt to coalesce live ranges defined by these 2
void combine_these_two( Node *n1, Node *n2 );
void combine_these_two(Node *n1, Node *n2);
LRG &lrgs( uint lidx ) { return _phc.lrgs(lidx); }
LRG &lrgs(uint lidx) { return _phc.lrgs(lidx); }
#ifndef PRODUCT
// Dump internally name
void dump( Node *n ) const;
void dump(Node *n) const;
// Dump whole shebang
void dump() const;
#endif
......
......@@ -2127,22 +2127,19 @@ void Compile::Code_Gen() {
}
NOT_PRODUCT( verify_graph_edges(); )
PhaseChaitin regalloc(unique(),cfg,m);
PhaseChaitin regalloc(unique(), cfg, m);
_regalloc = &regalloc;
{
TracePhase t2("regalloc", &_t_registerAllocation, true);
// Perform any platform dependent preallocation actions. This is used,
// for example, to avoid taking an implicit null pointer exception
// using the frame pointer on win95.
_regalloc->pd_preallocate_hook();
// Perform register allocation. After Chaitin, use-def chains are
// no longer accurate (at spill code) and so must be ignored.
// Node->LRG->reg mappings are still accurate.
_regalloc->Register_Allocate();
// Bail out if the allocator builds too many nodes
if (failing()) return;
if (failing()) {
return;
}
}
// Prior to register allocation we kept empty basic blocks in case the
......@@ -2160,9 +2157,6 @@ void Compile::Code_Gen() {
cfg.fixup_flow();
}
// Perform any platform dependent postallocation verifications.
debug_only( _regalloc->pd_postallocate_verify_hook(); )
// Apply peephole optimizations
if( OptoPeephole ) {
NOT_PRODUCT( TracePhase t2("peephole", &_t_peephole, TimeCompiler); )
......
......@@ -616,7 +616,7 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
buffer[0] = 0;
_chaitin->dump_register(node, buffer);
print_prop("reg", buffer);
print_prop("lrg", _chaitin->n2lidx(node));
print_prop("lrg", _chaitin->_lrg_map.live_range_id(node));
}
node->_in_dump_cnt--;
......
......@@ -286,15 +286,14 @@ void PhaseIFG::verify( const PhaseChaitin *pc ) const {
uint idx;
uint last = 0;
while ((idx = elements.next()) != 0) {
assert( idx != i, "Must have empty diagonal");
assert( pc->Find_const(idx) == idx, "Must not need Find" );
assert( _adjs[idx].member(i), "IFG not square" );
assert( !(*_yanked)[idx], "No yanked neighbors" );
assert( last < idx, "not sorted increasing");
assert(idx != i, "Must have empty diagonal");
assert(pc->_lrg_map.find_const(idx) == idx, "Must not need Find");
assert(_adjs[idx].member(i), "IFG not square");
assert(!(*_yanked)[idx], "No yanked neighbors");
assert(last < idx, "not sorted increasing");
last = idx;
}
assert( !lrgs(i)._degree_valid ||
effective_degree(i) == lrgs(i).degree(), "degree is valid but wrong" );
assert(!lrgs(i)._degree_valid || effective_degree(i) == lrgs(i).degree(), "degree is valid but wrong");
}
}
#endif
......@@ -342,10 +341,10 @@ void PhaseChaitin::build_ifg_virtual( ) {
Node *n = b->_nodes[j-1];
// Get value being defined
uint r = n2lidx(n);
uint r = _lrg_map.live_range_id(n);
// Some special values do not allocate
if( r ) {
if (r) {
// Remove from live-out set
liveout->remove(r);
......@@ -353,16 +352,19 @@ void PhaseChaitin::build_ifg_virtual( ) {
// Copies do not define a new value and so do not interfere.
// Remove the copies source from the liveout set before interfering.
uint idx = n->is_Copy();
if( idx ) liveout->remove( n2lidx(n->in(idx)) );
if (idx) {
liveout->remove(_lrg_map.live_range_id(n->in(idx)));
}
// Interfere with everything live
interfere_with_live( r, liveout );
interfere_with_live(r, liveout);
}
// Make all inputs live
if( !n->is_Phi() ) { // Phi function uses come from prior block
for( uint k = 1; k < n->req(); k++ )
liveout->insert( n2lidx(n->in(k)) );
if (!n->is_Phi()) { // Phi function uses come from prior block
for(uint k = 1; k < n->req(); k++) {
liveout->insert(_lrg_map.live_range_id(n->in(k)));
}
}
// 2-address instructions always have the defined value live
......@@ -394,11 +396,12 @@ void PhaseChaitin::build_ifg_virtual( ) {
n->set_req( 2, tmp );
}
// Defined value interferes with all inputs
uint lidx = n2lidx(n->in(idx));
for( uint k = 1; k < n->req(); k++ ) {
uint kidx = n2lidx(n->in(k));
if( kidx != lidx )
_ifg->add_edge( r, kidx );
uint lidx = _lrg_map.live_range_id(n->in(idx));
for (uint k = 1; k < n->req(); k++) {
uint kidx = _lrg_map.live_range_id(n->in(k));
if (kidx != lidx) {
_ifg->add_edge(r, kidx);
}
}
}
} // End of forall instructions in block
......@@ -542,10 +545,10 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
Node *n = b->_nodes[j - 1];
// Get value being defined
uint r = n2lidx(n);
uint r = _lrg_map.live_range_id(n);
// Some special values do not allocate
if( r ) {
if(r) {
// A DEF normally costs block frequency; rematerialized values are
// removed from the DEF sight, so LOWER costs here.
lrgs(r)._cost += n->rematerialize() ? 0 : b->_freq;
......@@ -556,9 +559,11 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
Node *def = n->in(0);
if( !n->is_Proj() ||
// Could also be a flags-projection of a dead ADD or such.
(n2lidx(def) && !liveout.member(n2lidx(def)) ) ) {
(_lrg_map.live_range_id(def) && !liveout.member(_lrg_map.live_range_id(def)))) {
b->_nodes.remove(j - 1);
if( lrgs(r)._def == n ) lrgs(r)._def = 0;
if (lrgs(r)._def == n) {
lrgs(r)._def = 0;
}
n->disconnect_inputs(NULL, C);
_cfg._bbs.map(n->_idx,NULL);
n->replace_by(C->top());
......@@ -570,7 +575,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// Fat-projections kill many registers which cannot be used to
// hold live ranges.
if( lrgs(r)._fat_proj ) {
if (lrgs(r)._fat_proj) {
// Count the int-only registers
RegMask itmp = lrgs(r).mask();
itmp.AND(*Matcher::idealreg2regmask[Op_RegI]);
......@@ -636,12 +641,12 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// Copies do not define a new value and so do not interfere.
// Remove the copies source from the liveout set before interfering.
uint idx = n->is_Copy();
if( idx ) {
uint x = n2lidx(n->in(idx));
if( liveout.remove( x ) ) {
if (idx) {
uint x = _lrg_map.live_range_id(n->in(idx));
if (liveout.remove(x)) {
lrgs(x)._area -= cost;
// Adjust register pressure.
lower_pressure( &lrgs(x), j-1, b, pressure, hrp_index );
lower_pressure(&lrgs(x), j-1, b, pressure, hrp_index);
assert( pressure[0] == count_int_pressure (&liveout), "" );
assert( pressure[1] == count_float_pressure(&liveout), "" );
}
......@@ -727,18 +732,21 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) {
// the flags and assumes it's dead. This keeps the (useless)
// flag-setting behavior alive while also keeping the (useful)
// memory update effect.
for( uint k = ((n->Opcode() == Op_SCMemProj) ? 0:1); k < n->req(); k++ ) {
for (uint k = ((n->Opcode() == Op_SCMemProj) ? 0:1); k < n->req(); k++) {
Node *def = n->in(k);
uint x = n2lidx(def);
if( !x ) continue;
uint x = _lrg_map.live_range_id(def);
if (!x) {
continue;
}
LRG &lrg = lrgs(x);
// No use-side cost for spilling debug info
if( k < debug_start )
if (k < debug_start) {
// A USE costs twice block frequency (once for the Load, once
// for a Load-delay). Rematerialized uses only cost once.
lrg._cost += (def->rematerialize() ? b->_freq : (b->_freq + b->_freq));
}
// It is live now
if( liveout.insert( x ) ) {
if (liveout.insert(x)) {
// Newly live things assumed live from here to top of block
lrg._area += cost;
// Adjust register pressure
......
......@@ -44,7 +44,7 @@
// block is put on the worklist.
// The locally live-in stuff is computed once and added to predecessor
// live-out sets. This separate compilation is done in the outer loop below.
PhaseLive::PhaseLive( const PhaseCFG &cfg, LRG_List &names, Arena *arena ) : Phase(LIVE), _cfg(cfg), _names(names), _arena(arena), _live(0) {
PhaseLive::PhaseLive( const PhaseCFG &cfg, const LRG_List &names, Arena *arena ) : Phase(LIVE), _cfg(cfg), _names(names), _arena(arena), _live(0) {
}
void PhaseLive::compute(uint maxlrg) {
......
......@@ -80,7 +80,7 @@ class PhaseLive : public Phase {
Block_List *_worklist; // Worklist for iterative solution
const PhaseCFG &_cfg; // Basic blocks
LRG_List &_names; // Mapping from Nodes to live ranges
const LRG_List &_names; // Mapping from Nodes to live ranges
uint _maxlrg; // Largest live-range number
Arena *_arena;
......@@ -91,7 +91,7 @@ class PhaseLive : public Phase {
void add_liveout( Block *p, IndexSet *lo, VectorSet &first_pass );
public:
PhaseLive( const PhaseCFG &cfg, LRG_List &names, Arena *arena );
PhaseLive(const PhaseCFG &cfg, const LRG_List &names, Arena *arena);
~PhaseLive() {}
// Compute liveness info
void compute(uint maxlrg);
......
......@@ -56,7 +56,7 @@ bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const {
int i;
for( i=0; i < limit; i++ ) {
if( def->is_Proj() && def->in(0)->is_Start() &&
_matcher.is_save_on_entry(lrgs(n2lidx(def)).reg()) )
_matcher.is_save_on_entry(lrgs(_lrg_map.live_range_id(def)).reg()))
return true; // Direct use of callee-save proj
if( def->is_Copy() ) // Copies carry value through
def = def->in(def->is_Copy());
......@@ -83,7 +83,7 @@ int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_
// Count 1 if deleting an instruction from the current block
if( oldb == current_block ) blk_adjust++;
_cfg._bbs.map(old->_idx,NULL);
OptoReg::Name old_reg = lrgs(n2lidx(old)).reg();
OptoReg::Name old_reg = lrgs(_lrg_map.live_range_id(old)).reg();
if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently available?
value->map(old_reg,NULL); // Yank from value/regnd maps
regnd->map(old_reg,NULL); // This register's value is now unknown
......@@ -164,7 +164,7 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre
// Not every pair of physical registers are assignment compatible,
// e.g. on sparc floating point registers are not assignable to integer
// registers.
const LRG &def_lrg = lrgs(n2lidx(def));
const LRG &def_lrg = lrgs(_lrg_map.live_range_id(def));
OptoReg::Name def_reg = def_lrg.reg();
const RegMask &use_mask = n->in_RegMask(idx);
bool can_use = ( RegMask::can_represent(def_reg) ? (use_mask.Member(def_reg) != 0)
......@@ -209,11 +209,12 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre
// Skip through any number of copies (that don't mod oop-i-ness)
Node *PhaseChaitin::skip_copies( Node *c ) {
int idx = c->is_Copy();
uint is_oop = lrgs(n2lidx(c))._is_oop;
uint is_oop = lrgs(_lrg_map.live_range_id(c))._is_oop;
while (idx != 0) {
guarantee(c->in(idx) != NULL, "must not resurrect dead copy");
if (lrgs(n2lidx(c->in(idx)))._is_oop != is_oop)
if (lrgs(_lrg_map.live_range_id(c->in(idx)))._is_oop != is_oop) {
break; // casting copy, not the same value
}
c = c->in(idx);
idx = c->is_Copy();
}
......@@ -225,8 +226,8 @@ Node *PhaseChaitin::skip_copies( Node *c ) {
int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List &regnd, bool can_change_regs ) {
int blk_adjust = 0;
uint nk_idx = n2lidx(n->in(k));
OptoReg::Name nk_reg = lrgs(nk_idx ).reg();
uint nk_idx = _lrg_map.live_range_id(n->in(k));
OptoReg::Name nk_reg = lrgs(nk_idx).reg();
// Remove obvious same-register copies
Node *x = n->in(k);
......@@ -234,9 +235,13 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
while( (idx=x->is_Copy()) != 0 ) {
Node *copy = x->in(idx);
guarantee(copy != NULL, "must not resurrect dead copy");
if( lrgs(n2lidx(copy)).reg() != nk_reg ) break;
if(lrgs(_lrg_map.live_range_id(copy)).reg() != nk_reg) {
break;
}
blk_adjust += use_prior_register(n,k,copy,current_block,value,regnd);
if( n->in(k) != copy ) break; // Failed for some cutout?
if (n->in(k) != copy) {
break; // Failed for some cutout?
}
x = copy; // Progress, try again
}
......@@ -256,7 +261,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
if (val == x && nk_idx != 0 &&
regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
n2lidx(x) == n2lidx(regnd[nk_reg])) {
_lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
// When rematerialzing nodes and stretching lifetimes, the
// allocator will reuse the original def for multidef LRG instead
// of the current reaching def because it can't know it's safe to
......@@ -270,7 +275,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v
if (val == x) return blk_adjust; // No progress?
int n_regs = RegMask::num_registers(val->ideal_reg());
uint val_idx = n2lidx(val);
uint val_idx = _lrg_map.live_range_id(val);
OptoReg::Name val_reg = lrgs(val_idx).reg();
// See if it happens to already be in the correct register!
......@@ -499,12 +504,12 @@ void PhaseChaitin::post_allocate_copy_removal() {
for( j = 1; j < phi_dex; j++ ) {
uint k;
Node *phi = b->_nodes[j];
uint pidx = n2lidx(phi);
OptoReg::Name preg = lrgs(n2lidx(phi)).reg();
uint pidx = _lrg_map.live_range_id(phi);
OptoReg::Name preg = lrgs(_lrg_map.live_range_id(phi)).reg();
// Remove copies remaining on edges. Check for junk phi.
Node *u = NULL;
for( k=1; k<phi->req(); k++ ) {
for (k = 1; k < phi->req(); k++) {
Node *x = phi->in(k);
if( phi != x && u != x ) // Found a different input
u = u ? NodeSentinel : x; // Capture unique input, or NodeSentinel for 2nd input
......@@ -555,10 +560,10 @@ void PhaseChaitin::post_allocate_copy_removal() {
// alive and well at the use (or else the allocator fubar'd). Take
// advantage of this info to set a reaching def for the use-reg.
uint k;
for( k = 1; k < n->req(); k++ ) {
for (k = 1; k < n->req(); k++) {
Node *def = n->in(k); // n->in(k) is a USE; def is the DEF for this USE
guarantee(def != NULL, "no disconnected nodes at this point");
uint useidx = n2lidx(def); // useidx is the live range index for this USE
uint useidx = _lrg_map.live_range_id(def); // useidx is the live range index for this USE
if( useidx ) {
OptoReg::Name ureg = lrgs(useidx).reg();
......@@ -566,7 +571,7 @@ void PhaseChaitin::post_allocate_copy_removal() {
int idx; // Skip occasional useless copy
while( (idx=def->is_Copy()) != 0 &&
def->in(idx) != NULL && // NULL should not happen
ureg == lrgs(n2lidx(def->in(idx))).reg() )
ureg == lrgs(_lrg_map.live_range_id(def->in(idx))).reg())
def = def->in(idx);
Node *valdef = skip_copies(def); // tighten up val through non-useless copies
value.map(ureg,valdef); // record improved reaching-def info
......@@ -594,8 +599,10 @@ void PhaseChaitin::post_allocate_copy_removal() {
j -= elide_copy( n, k, b, value, regnd, two_adr!=k );
// Unallocated Nodes define no registers
uint lidx = n2lidx(n);
if( !lidx ) continue;
uint lidx = _lrg_map.live_range_id(n);
if (!lidx) {
continue;
}
// Update the register defined by this instruction
OptoReg::Name nreg = lrgs(lidx).reg();
......
......@@ -318,9 +318,13 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
for( uint i = 1; i < def->req(); i++ ) {
Node *in = def->in(i);
// Check for single-def (LRG cannot redefined)
uint lidx = n2lidx(in);
if( lidx >= _maxlrg ) continue; // Value is a recent spill-copy
if (lrgs(lidx).is_singledef()) continue;
uint lidx = _lrg_map.live_range_id(in);
if (lidx >= _lrg_map.max_lrg_id()) {
continue; // Value is a recent spill-copy
}
if (lrgs(lidx).is_singledef()) {
continue;
}
Block *b_def = _cfg._bbs[def->_idx];
int idx_def = b_def->find_node(def);
......@@ -344,26 +348,28 @@ Node *PhaseChaitin::split_Rematerialize( Node *def, Block *b, uint insidx, uint
if( spill->req() > 1 ) {
for( uint i = 1; i < spill->req(); i++ ) {
Node *in = spill->in(i);
uint lidx = Find_id(in);
uint lidx = _lrg_map.find_id(in);
// Walk backwards thru spill copy node intermediates
if (walkThru) {
while ( in->is_SpillCopy() && lidx >= _maxlrg ) {
while (in->is_SpillCopy() && lidx >= _lrg_map.max_lrg_id()) {
in = in->in(1);
lidx = Find_id(in);
lidx = _lrg_map.find_id(in);
}
if (lidx < _maxlrg && lrgs(lidx).is_multidef()) {
if (lidx < _lrg_map.max_lrg_id() && 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);
lidx = _lrg_map.find_id(in);
}
}
if( lidx < _maxlrg && lrgs(lidx).reg() >= LRG::SPILL_REG ) {
if (lidx < _lrg_map.max_lrg_id() && lrgs(lidx).reg() >= LRG::SPILL_REG) {
Node *rdef = Reachblock[lrg2reach[lidx]];
if( rdef ) spill->set_req(i,rdef);
if (rdef) {
spill->set_req(i, rdef);
}
}
}
}
......@@ -382,7 +388,7 @@ 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 ) ) {
if( clone_projs( b, i, def, spill, maxlrg) ) {
// Adjust the point where we go hi-pressure
if( i <= b->_ihrp_index ) b->_ihrp_index++;
if( i <= b->_fhrp_index ) b->_fhrp_index++;
......@@ -424,17 +430,25 @@ bool PhaseChaitin::is_high_pressure( Block *b, LRG *lrg, uint insidx ) {
//------------------------------prompt_use---------------------------------
// True if lidx is used before any real register is def'd in the block
bool PhaseChaitin::prompt_use( Block *b, uint lidx ) {
if( lrgs(lidx)._was_spilled2 ) return false;
if (lrgs(lidx)._was_spilled2) {
return false;
}
// Scan block for 1st use.
for( uint i = 1; i <= b->end_idx(); i++ ) {
Node *n = b->_nodes[i];
// Ignore PHI use, these can be up or down
if( n->is_Phi() ) continue;
for( uint j = 1; j < n->req(); j++ )
if( Find_id(n->in(j)) == lidx )
if (n->is_Phi()) {
continue;
}
for (uint j = 1; j < n->req(); j++) {
if (_lrg_map.find_id(n->in(j)) == lidx) {
return true; // Found 1st use!
if( n->out_RegMask().is_NotEmpty() ) return false;
}
}
if (n->out_RegMask().is_NotEmpty()) {
return false;
}
}
return false;
}
......@@ -464,23 +478,23 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
bool u1, u2, u3;
Block *b, *pred;
PhiNode *phi;
GrowableArray<uint> lidxs(split_arena, _maxlrg, 0, 0);
GrowableArray<uint> lidxs(split_arena, maxlrg, 0, 0);
// Array of counters to count splits per live range
GrowableArray<uint> splits(split_arena, _maxlrg, 0, 0);
GrowableArray<uint> splits(split_arena, maxlrg, 0, 0);
#define NEW_SPLIT_ARRAY(type, size)\
(type*) split_arena->allocate_bytes((size) * sizeof(type))
//----------Setup Code----------
// Create a convenient mapping from lrg numbers to reaches/leaves indices
uint *lrg2reach = NEW_SPLIT_ARRAY( uint, _maxlrg );
uint *lrg2reach = NEW_SPLIT_ARRAY(uint, maxlrg);
// Keep track of DEFS & Phis for later passes
defs = new Node_List();
phis = new Node_List();
// Gather info on which LRG's are spilling, and build maps
for( bidx = 1; bidx < _maxlrg; bidx++ ) {
if( lrgs(bidx).alive() && lrgs(bidx).reg() >= LRG::SPILL_REG ) {
for (bidx = 1; bidx < maxlrg; bidx++) {
if (lrgs(bidx).alive() && lrgs(bidx).reg() >= LRG::SPILL_REG) {
assert(!lrgs(bidx).mask().is_AllStack(),"AllStack should color");
lrg2reach[bidx] = spill_cnt;
spill_cnt++;
......@@ -629,7 +643,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
break;
}
// must be looking at a phi
if( Find_id(n1) == lidxs.at(slidx) ) {
if (_lrg_map.find_id(n1) == lidxs.at(slidx)) {
// found the necessary phi
needs_phi = false;
has_phi = true;
......@@ -651,11 +665,11 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
Reachblock[slidx] = phi;
// add node to block & node_to_block mapping
insert_proj( b, insidx++, phi, maxlrg++ );
insert_proj(b, insidx++, phi, maxlrg++);
non_phi++;
// Reset new phi's mapping to be the spilling live range
_names.map(phi->_idx, lidx);
assert(Find_id(phi) == lidx,"Bad update on Union-Find mapping");
_lrg_map.map(phi->_idx, lidx);
assert(_lrg_map.find_id(phi) == lidx, "Bad update on Union-Find mapping");
} // end if not found correct phi
// Here you have either found or created the Phi, so record it
assert(phi != NULL,"Must have a Phi Node here");
......@@ -721,12 +735,12 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
for( insidx = 1; insidx <= b->end_idx(); insidx++ ) {
Node *n = b->_nodes[insidx];
// Find the defining Node's live range index
uint defidx = Find_id(n);
uint defidx = _lrg_map.find_id(n);
uint cnt = n->req();
if( n->is_Phi() ) {
if (n->is_Phi()) {
// Skip phi nodes after removing dead copies.
if( defidx < _maxlrg ) {
if (defidx < _lrg_map.max_lrg_id()) {
// Check for useless Phis. These appear if we spill, then
// coalesce away copies. Dont touch Phis in spilling live
// ranges; they are busy getting modifed in this pass.
......@@ -744,8 +758,8 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
}
}
assert( u, "at least 1 valid input expected" );
if( i >= cnt ) { // Found one unique input
assert(Find_id(n) == Find_id(u), "should be the same lrg");
if (i >= cnt) { // Found one unique input
assert(_lrg_map.find_id(n) == _lrg_map.find_id(u), "should be the same lrg");
n->replace_by(u); // Then replace with unique input
n->disconnect_inputs(NULL, C);
b->_nodes.remove(insidx);
......@@ -793,16 +807,24 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
while( insert_point > 0 ) {
Node *n = b->_nodes[insert_point];
// Hit top of block? Quit going backwards
if( n->is_Phi() ) break;
if (n->is_Phi()) {
break;
}
// Found a def? Better split after it.
if( n2lidx(n) == lidx ) break;
if (_lrg_map.live_range_id(n) == lidx) {
break;
}
// Look for a use
uint i;
for( i = 1; i < n->req(); i++ )
if( n2lidx(n->in(i)) == lidx )
for( i = 1; i < n->req(); i++ ) {
if (_lrg_map.live_range_id(n->in(i)) == lidx) {
break;
}
}
// Found a use? Better split after it.
if( i < n->req() ) break;
if (i < n->req()) {
break;
}
insert_point--;
}
uint orig_eidx = b->end_idx();
......@@ -812,8 +834,9 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
return 0;
}
// Spill of NULL check mem op goes into the following block.
if (b->end_idx() > orig_eidx)
if (b->end_idx() > orig_eidx) {
insidx++;
}
}
// This is a new DEF, so update UP
UPblock[slidx] = false;
......@@ -832,13 +855,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
} // end if crossing HRP Boundry
// If the LRG index is oob, then this is a new spillcopy, skip it.
if( defidx >= _maxlrg ) {
if (defidx >= _lrg_map.max_lrg_id()) {
continue;
}
LRG &deflrg = lrgs(defidx);
uint copyidx = n->is_Copy();
// Remove coalesced copy from CFG
if( copyidx && defidx == n2lidx(n->in(copyidx)) ) {
if (copyidx && defidx == _lrg_map.live_range_id(n->in(copyidx))) {
n->replace_by( n->in(copyidx) );
n->set_req( copyidx, NULL );
b->_nodes.remove(insidx--);
......@@ -864,13 +887,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
// If inpidx > old_last, then one of these new inputs is being
// handled. Skip the derived part of the pair, but process
// the base like any other input.
if( inpidx > old_last && ((inpidx - oopoff) & 1) == DERIVED ) {
if (inpidx > old_last && ((inpidx - oopoff) & 1) == DERIVED) {
continue; // skip derived_debug added below
}
// Get lidx of input
uint useidx = Find_id(n->in(inpidx));
uint useidx = _lrg_map.find_id(n->in(inpidx));
// Not a brand-new split, and it is a spill use
if( useidx < _maxlrg && lrgs(useidx).reg() >= LRG::SPILL_REG ) {
if (useidx < _lrg_map.max_lrg_id() && lrgs(useidx).reg() >= LRG::SPILL_REG) {
// Check for valid reaching DEF
slidx = lrg2reach[useidx];
Node *def = Reachblock[slidx];
......@@ -886,7 +909,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
if (def == NULL || C->check_node_count(NodeLimitFudgeFactor, out_of_nodes)) {
return 0;
}
_names.extend(def->_idx,0);
_lrg_map.extend(def->_idx, 0);
_cfg._bbs.map(def->_idx,b);
n->set_req(inpidx, def);
continue;
......@@ -1186,10 +1209,10 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
// ********** Split Left Over Mem-Mem Moves **********
// Check for mem-mem copies and split them now. Do not do this
// to copies about to be spilled; they will be Split shortly.
if( copyidx ) {
if (copyidx) {
Node *use = n->in(copyidx);
uint useidx = Find_id(use);
if( useidx < _maxlrg && // This is not a new split
uint useidx = _lrg_map.find_id(use);
if (useidx < _lrg_map.max_lrg_id() && // This is not a new split
OptoReg::is_stack(deflrg.reg()) &&
deflrg.reg() < LRG::SPILL_REG ) { // And DEF is from stack
LRG &uselrg = lrgs(useidx);
......@@ -1228,7 +1251,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
uint member;
IndexSetIterator isi(liveout);
while ((member = isi.next()) != 0) {
assert(defidx != Find_const(member), "Live out member has not been compressed");
assert(defidx != _lrg_map.find_const(member), "Live out member has not been compressed");
}
#endif
Reachblock[slidx] = NULL;
......@@ -1261,7 +1284,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
assert(phi->is_Phi(),"This list must only contain Phi Nodes");
Block *b = _cfg._bbs[phi->_idx];
// Grab the live range number
uint lidx = Find_id(phi);
uint lidx = _lrg_map.find_id(phi);
uint slidx = lrg2reach[lidx];
// Update node to lidx map
new_lrg(phi, maxlrg++);
......@@ -1296,11 +1319,13 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
int insert = pred->end_idx();
while (insert >= 1 &&
pred->_nodes[insert - 1]->is_SpillCopy() &&
Find(pred->_nodes[insert - 1]) >= lrgs_before_phi_split) {
_lrg_map.find(pred->_nodes[insert - 1]) >= lrgs_before_phi_split) {
insert--;
}
def = split_Rematerialize( def, pred, insert, maxlrg, splits, slidx, lrg2reach, Reachblock, false );
if( !def ) return 0; // Bail out
def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, Reachblock, false);
if (!def) {
return 0; // Bail out
}
}
// Update the Phi's input edge array
phi->set_req(i,def);
......@@ -1316,7 +1341,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
} // End for all inputs to the Phi
} // End for all Phi Nodes
// Update _maxlrg to save Union asserts
_maxlrg = maxlrg;
_lrg_map.set_max_lrg_id(maxlrg);
//----------PASS 3----------
......@@ -1328,47 +1353,51 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) {
for( uint i = 1; i < phi->req(); i++ ) {
// Grab the input node
Node *n = phi->in(i);
assert( n, "" );
uint lidx = Find(n);
uint pidx = Find(phi);
if( lidx < pidx )
assert(n, "node should exist");
uint lidx = _lrg_map.find(n);
uint pidx = _lrg_map.find(phi);
if (lidx < pidx) {
Union(n, phi);
else if( lidx > pidx )
}
else if(lidx > pidx) {
Union(phi, n);
}
} // End for all inputs to the Phi Node
} // End for all Phi Nodes
// Now union all two address instructions
for( insidx = 0; insidx < defs->size(); insidx++ ) {
for (insidx = 0; insidx < defs->size(); insidx++) {
// Grab the def
n1 = defs->at(insidx);
// Set new lidx for DEF & handle 2-addr instructions
if( n1->is_Mach() && ((twoidx = n1->as_Mach()->two_adr()) != 0) ) {
assert( Find(n1->in(twoidx)) < maxlrg,"Assigning bad live range index");
if (n1->is_Mach() && ((twoidx = n1->as_Mach()->two_adr()) != 0)) {
assert(_lrg_map.find(n1->in(twoidx)) < maxlrg,"Assigning bad live range index");
// Union the input and output live ranges
uint lr1 = Find(n1);
uint lr2 = Find(n1->in(twoidx));
if( lr1 < lr2 )
uint lr1 = _lrg_map.find(n1);
uint lr2 = _lrg_map.find(n1->in(twoidx));
if (lr1 < lr2) {
Union(n1, n1->in(twoidx));
else if( lr1 > lr2 )
}
else if (lr1 > lr2) {
Union(n1->in(twoidx), n1);
}
} // End if two address
} // End for all defs
// DEBUG
#ifdef ASSERT
// Validate all live range index assignments
for( bidx = 0; bidx < _cfg._num_blocks; bidx++ ) {
for (bidx = 0; bidx < _cfg._num_blocks; bidx++) {
b = _cfg._blocks[bidx];
for( insidx = 0; insidx <= b->end_idx(); insidx++ ) {
for (insidx = 0; insidx <= b->end_idx(); insidx++) {
Node *n = b->_nodes[insidx];
uint defidx = Find(n);
assert(defidx < _maxlrg,"Bad live range index in Split");
uint defidx = _lrg_map.find(n);
assert(defidx < _lrg_map.max_lrg_id(), "Bad live range index in Split");
assert(defidx < maxlrg,"Bad live range index in Split");
}
}
// Issue a warning if splitting made no progress
int noprogress = 0;
for( slidx = 0; slidx < spill_cnt; slidx++ ) {
if( PrintOpto && WizardMode && splits.at(slidx) == 0 ) {
for (slidx = 0; slidx < spill_cnt; slidx++) {
if (PrintOpto && WizardMode && splits.at(slidx) == 0) {
tty->print_cr("Failed to split live range %d", lidxs.at(slidx));
//BREAKPOINT;
}
......
......@@ -113,7 +113,7 @@ public:
OptoReg::Name offset2reg( int stk_offset ) const;
// Get the register encoding associated with the Node
int get_encode( const Node *n ) const {
int get_encode(const Node *n) const {
assert( n->_idx < _node_regs_max_index, "Exceeded _node_regs array");
OptoReg::Name first = _node_regs[n->_idx].first();
OptoReg::Name second = _node_regs[n->_idx].second();
......@@ -122,15 +122,6 @@ public:
return Matcher::_regEncode[first];
}
// Platform dependent hook for actions prior to allocation
void pd_preallocate_hook();
#ifdef ASSERT
// Platform dependent hook for verification after allocation. Will
// only get called when compiling with asserts.
void pd_postallocate_verify_hook();
#endif
#ifndef PRODUCT
static int _total_framesize;
static int _max_framesize;
......
......@@ -1115,7 +1115,6 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
c2_nonstatic_field(PhaseChaitin, _lo_stk_degree, uint) \
c2_nonstatic_field(PhaseChaitin, _hi_degree, uint) \
c2_nonstatic_field(PhaseChaitin, _simplified, uint) \
c2_nonstatic_field(PhaseChaitin, _maxlrg, uint) \
\
c2_nonstatic_field(Block, _nodes, Node_List) \
c2_nonstatic_field(Block, _succs, Block_Array) \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册