提交 4d97e042 编写于 作者: A adlertz

8023988: Move local scheduling of nodes to the CFG creation and code motion phase (PhaseCFG)

Summary: Moved local scheduling code from class Block to class PhaseCFG
Reviewed-by: kvn, roland
上级 83f5e055
......@@ -209,15 +209,15 @@ bool Block::has_uncommon_code() const {
// True if block is low enough frequency or guarded by a test which
// mostly does not go here.
bool Block::is_uncommon(PhaseCFG* cfg) const {
bool PhaseCFG::is_uncommon(const Block* block) {
// Initial blocks must never be moved, so are never uncommon.
if (head()->is_Root() || head()->is_Start()) return false;
if (block->head()->is_Root() || block->head()->is_Start()) return false;
// Check for way-low freq
if( _freq < BLOCK_FREQUENCY(0.00001f) ) return true;
if(block->_freq < BLOCK_FREQUENCY(0.00001f) ) return true;
// Look for code shape indicating uncommon_trap or slow path
if (has_uncommon_code()) return true;
if (block->has_uncommon_code()) return true;
const float epsilon = 0.05f;
const float guard_factor = PROB_UNLIKELY_MAG(4) / (1.f - epsilon);
......@@ -225,8 +225,8 @@ bool Block::is_uncommon(PhaseCFG* cfg) const {
uint freq_preds = 0;
uint uncommon_for_freq_preds = 0;
for( uint i=1; i<num_preds(); i++ ) {
Block* guard = cfg->get_block_for_node(pred(i));
for( uint i=1; i< block->num_preds(); i++ ) {
Block* guard = get_block_for_node(block->pred(i));
// Check to see if this block follows its guard 1 time out of 10000
// or less.
//
......@@ -244,14 +244,14 @@ bool Block::is_uncommon(PhaseCFG* cfg) const {
uncommon_preds++;
} else {
freq_preds++;
if( _freq < guard->_freq * guard_factor ) {
if(block->_freq < guard->_freq * guard_factor ) {
uncommon_for_freq_preds++;
}
}
}
if( num_preds() > 1 &&
if( block->num_preds() > 1 &&
// The block is uncommon if all preds are uncommon or
(uncommon_preds == (num_preds()-1) ||
(uncommon_preds == (block->num_preds()-1) ||
// it is uncommon for all frequent preds.
uncommon_for_freq_preds == freq_preds) ) {
return true;
......@@ -669,7 +669,7 @@ void PhaseCFG::remove_empty_blocks() {
// Look for uncommon blocks and move to end.
if (!C->do_freq_based_layout()) {
if (block->is_uncommon(this)) {
if (is_uncommon(block)) {
move_to_end(block, i);
last--; // No longer check for being uncommon!
if (no_flip_branch(block)) { // Fall-thru case must follow?
......
......@@ -318,23 +318,6 @@ public:
// Find and remove n from block list
void find_remove( const Node *n );
// helper function that adds caller save registers to MachProjNode
void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe);
// Schedule a call next in the block
uint sched_call(Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_List &worklist, GrowableArray<int> &ready_cnt, MachCallNode *mcall, VectorSet &next_call);
// Perform basic-block local scheduling
Node *select(PhaseCFG *cfg, Node_List &worklist, GrowableArray<int> &ready_cnt, VectorSet &next_call, uint sched_slot);
void set_next_call( Node *n, VectorSet &next_call, PhaseCFG* cfg);
void needed_for_next_call(Node *this_call, VectorSet &next_call, PhaseCFG* cfg);
bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray<int> &ready_cnt, VectorSet &next_call);
// Cleanup if any code lands between a Call and his Catch
void call_catch_cleanup(PhaseCFG* cfg, Compile *C);
// Detect implicit-null-check opportunities. Basically, find NULL checks
// with suitable memory ops nearby. Use the memory op to do the NULL check.
// I can generate a memory op if there is not one nearby.
void implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowed_reasons);
// Return the empty status of a block
enum { not_empty, empty_with_goto, completely_empty };
int is_Empty() const;
......@@ -366,10 +349,6 @@ public:
// Examine block's code shape to predict if it is not commonly executed.
bool has_uncommon_code() const;
// Use frequency calculations and code shape to predict if the block
// is uncommon.
bool is_uncommon(PhaseCFG* cfg) const;
#ifndef PRODUCT
// Debugging print of basic block
void dump_bidx(const Block* orig, outputStream* st = tty) const;
......@@ -452,6 +431,27 @@ class PhaseCFG : public Phase {
// to late. Helper for schedule_late.
Block* hoist_to_cheaper_block(Block* LCA, Block* early, Node* self);
bool schedule_local(Block* block, GrowableArray<int>& ready_cnt, VectorSet& next_call);
void set_next_call(Block* block, Node* n, VectorSet& next_call);
void needed_for_next_call(Block* block, Node* this_call, VectorSet& next_call);
// Perform basic-block local scheduling
Node* select(Block* block, Node_List& worklist, GrowableArray<int>& ready_cnt, VectorSet& next_call, uint sched_slot);
// Schedule a call next in the block
uint sched_call(Block* block, uint node_cnt, Node_List& worklist, GrowableArray<int>& ready_cnt, MachCallNode* mcall, VectorSet& next_call);
// Cleanup if any code lands between a Call and his Catch
void call_catch_cleanup(Block* block);
Node* catch_cleanup_find_cloned_def(Block* use_blk, Node* def, Block* def_blk, int n_clone_idx);
void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, int n_clone_idx);
// Detect implicit-null-check opportunities. Basically, find NULL checks
// with suitable memory ops nearby. Use the memory op to do the NULL check.
// I can generate a memory op if there is not one nearby.
void implicit_null_check(Block* block, Node *proj, Node *val, int allowed_reasons);
// Perform a Depth First Search (DFS).
// Setup 'vertex' as DFS to vertex mapping.
// Setup 'semi' as vertex to DFS mapping.
......@@ -568,6 +568,10 @@ class PhaseCFG : public Phase {
return (_node_to_block_mapping.lookup(node->_idx) != NULL);
}
// Use frequency calculations and code shape to predict if the block
// is uncommon.
bool is_uncommon(const Block* block);
#ifdef ASSERT
Unique_Node_List _raw_oops;
#endif
......
......@@ -339,7 +339,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) {
} // End of is two-adr
// Insert a copy at a debug use for a lrg which has high frequency
if (b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(&_phc._cfg)) {
if (b->_freq < OPTO_DEBUG_SPLIT_FREQ || _phc._cfg.is_uncommon(b)) {
// Walk the debug inputs to the node and check for lrg freq
JVMState* jvms = n->jvms();
uint debug_start = jvms ? jvms->debug_start() : 999999;
......@@ -769,7 +769,7 @@ bool PhaseConservativeCoalesce::copy_copy(Node *dst_copy, Node *src_copy, Block
// Conservative (but pessimistic) copy coalescing of a single block
void PhaseConservativeCoalesce::coalesce( Block *b ) {
// Bail out on infrequent blocks
if (b->is_uncommon(&_phc._cfg)) {
if (_phc._cfg.is_uncommon(b)) {
return;
}
// Check this block for copies.
......
......@@ -1342,7 +1342,7 @@ void PhaseCFG::global_code_motion() {
Node* proj = _matcher._null_check_tests[i];
Node* val = _matcher._null_check_tests[i + 1];
Block* block = get_block_for_node(proj);
block->implicit_null_check(this, proj, val, allowed_reasons);
implicit_null_check(block, proj, val, allowed_reasons);
// The implicit_null_check will only perform the transformation
// if the null branch is truly uncommon, *and* it leads to an
// uncommon trap. Combined with the too_many_traps guards
......@@ -1363,7 +1363,7 @@ void PhaseCFG::global_code_motion() {
visited.Clear();
for (uint i = 0; i < number_of_blocks(); i++) {
Block* block = get_block(i);
if (!block->schedule_local(this, _matcher, ready_cnt, visited)) {
if (!schedule_local(block, ready_cnt, visited)) {
if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) {
C->record_method_not_compilable("local schedule failed");
}
......@@ -1375,7 +1375,7 @@ void PhaseCFG::global_code_motion() {
// clone the instructions on all paths below the Catch.
for (uint i = 0; i < number_of_blocks(); i++) {
Block* block = get_block(i);
block->call_catch_cleanup(this, C);
call_catch_cleanup(block);
}
#ifndef PRODUCT
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册