提交 3296e1f2 编写于 作者: R rasbold

6743900: frequency based block layout

Summary: post-register allocation pass that drives block layout by edge frequencies
Reviewed-by: never, kvn
上级 fa4624c4
此差异已折叠。
......@@ -75,6 +75,7 @@ public:
void insert( uint i, Block *n );
uint size() const { return _cnt; }
void reset() { _cnt = 0; }
void print();
};
......@@ -129,7 +130,11 @@ class Block : public CFGElement {
uint _rpo; // Number in reverse post order walk
virtual bool is_block() { return true; }
float succ_prob(uint i); // return probability of i'th successor
float succ_prob(uint i); // return probability of i'th successor
int num_fall_throughs(); // How many fall-through candidate this block has
void update_uncommon_branch(Block* un); // Lower branch prob to uncommon code
bool succ_fall_through(uint i); // Is successor "i" is a fall-through candidate
Block* lone_fall_through(); // Return lone fall-through Block or null
Block* dom_lca(Block* that); // Compute LCA in dominator tree.
#ifdef ASSERT
......@@ -144,6 +149,7 @@ class Block : public CFGElement {
// Report the alignment required by this block. Must be a power of 2.
// The previous block will insert nops to get this alignment.
uint code_alignment();
uint compute_loop_alignment();
// BLOCK_FREQUENCY is a sentinel to mark uses of constant block frequencies.
// It is currently also used to scale such frequencies relative to
......@@ -184,11 +190,12 @@ class Block : public CFGElement {
int current_alignment = current_offset & max_pad;
if( current_alignment != 0 ) {
uint padding = (block_alignment-current_alignment) & max_pad;
if( !head()->is_Loop() ||
padding <= (uint)MaxLoopPad ||
first_inst_size() > padding ) {
return padding;
if( has_loop_alignment() &&
padding > (uint)MaxLoopPad &&
first_inst_size() <= padding ) {
return 0;
}
return padding;
}
}
return 0;
......@@ -202,6 +209,21 @@ class Block : public CFGElement {
void set_connector() { _connector = true; }
bool is_connector() const { return _connector; };
// Loop_alignment will be set for blocks which are at the top of loops.
// The block layout pass may rotate loops such that the loop head may not
// be the sequentially first block of the loop encountered in the linear
// list of blocks. If the layout pass is not run, loop alignment is set
// for each block which is the head of a loop.
uint _loop_alignment;
void set_loop_alignment(Block *loop_top) {
uint new_alignment = loop_top->compute_loop_alignment();
if (new_alignment > _loop_alignment) {
_loop_alignment = new_alignment;
}
}
uint loop_alignment() const { return _loop_alignment; }
bool has_loop_alignment() const { return loop_alignment() > 0; }
// Create a new Block with given head Node.
// Creates the (empty) predecessor arrays.
Block( Arena *a, Node *headnode )
......@@ -219,7 +241,8 @@ class Block : public CFGElement {
_raise_LCA_mark(0),
_raise_LCA_visited(0),
_first_inst_size(999999),
_connector(false) {
_connector(false),
_loop_alignment(0) {
_nodes.push(headnode);
}
......@@ -275,6 +298,16 @@ class Block : public CFGElement {
return s;
}
// Return true if b is a successor of this block
bool has_successor(Block* b) const {
for (uint i = 0; i < _num_succs; i++ ) {
if (non_connector_successor(i) == b) {
return true;
}
}
return false;
}
// Successor block, after forwarding through connectors
Block* non_connector_successor(int i) const {
return _succs[i]->non_connector();
......@@ -319,7 +352,6 @@ class PhaseCFG : public Phase {
// I'll need a few machine-specific GotoNodes. Clone from this one.
MachNode *_goto;
void insert_goto_at(uint block_no, uint succ_no);
Block* insert_anti_dependences(Block* LCA, Node* load, bool verify = false);
void verify_anti_dependences(Block* LCA, Node* load) {
......@@ -379,10 +411,15 @@ class PhaseCFG : public Phase {
// Compute the instruction global latency with a backwards walk
void ComputeLatenciesBackwards(VectorSet &visited, Node_List &stack);
// Set loop alignment
void set_loop_alignment();
// Remove empty basic blocks
void RemoveEmpty();
bool MoveToNext(Block* bx, uint b_index);
void MoveToEnd(Block* bx, uint b_index);
void remove_empty();
void fixup_flow();
bool move_to_next(Block* bx, uint b_index);
void move_to_end(Block* bx, uint b_index);
void insert_goto_at(uint block_no, uint succ_no);
// Check for NeverBranch at block end. This needs to become a GOTO to the
// true target. NeverBranch are treated as a conditional branch that always
......@@ -413,7 +450,7 @@ class PhaseCFG : public Phase {
};
//------------------------------UnionFindInfo----------------------------------
//------------------------------UnionFind--------------------------------------
// Map Block indices to a block-index for a cfg-cover.
// Array lookup in the optimized case.
class UnionFind : public ResourceObj {
......@@ -508,3 +545,166 @@ class CFGLoop : public CFGElement {
void dump_tree() const;
#endif
};
//----------------------------------CFGEdge------------------------------------
// A edge between two basic blocks that will be embodied by a branch or a
// fall-through.
class CFGEdge : public ResourceObj {
private:
Block * _from; // Source basic block
Block * _to; // Destination basic block
float _freq; // Execution frequency (estimate)
int _state;
bool _infrequent;
int _from_pct;
int _to_pct;
// Private accessors
int from_pct() const { return _from_pct; }
int to_pct() const { return _to_pct; }
int from_infrequent() const { return from_pct() < BlockLayoutMinDiamondPercentage; }
int to_infrequent() const { return to_pct() < BlockLayoutMinDiamondPercentage; }
public:
enum {
open, // initial edge state; unprocessed
connected, // edge used to connect two traces together
interior // edge is interior to trace (could be backedge)
};
CFGEdge(Block *from, Block *to, float freq, int from_pct, int to_pct) :
_from(from), _to(to), _freq(freq),
_from_pct(from_pct), _to_pct(to_pct), _state(open) {
_infrequent = from_infrequent() || to_infrequent();
}
float freq() const { return _freq; }
Block* from() const { return _from; }
Block* to () const { return _to; }
int infrequent() const { return _infrequent; }
int state() const { return _state; }
void set_state(int state) { _state = state; }
#ifndef PRODUCT
void dump( ) const;
#endif
};
//-----------------------------------Trace-------------------------------------
// An ordered list of basic blocks.
class Trace : public ResourceObj {
private:
uint _id; // Unique Trace id (derived from initial block)
Block ** _next_list; // Array mapping index to next block
Block ** _prev_list; // Array mapping index to previous block
Block * _first; // First block in the trace
Block * _last; // Last block in the trace
// Return the block that follows "b" in the trace.
Block * next(Block *b) const { return _next_list[b->_pre_order]; }
void set_next(Block *b, Block *n) const { _next_list[b->_pre_order] = n; }
// Return the block that preceeds "b" in the trace.
Block * prev(Block *b) const { return _prev_list[b->_pre_order]; }
void set_prev(Block *b, Block *p) const { _prev_list[b->_pre_order] = p; }
// We've discovered a loop in this trace. Reset last to be "b", and first as
// the block following "b
void break_loop_after(Block *b) {
_last = b;
_first = next(b);
set_prev(_first, NULL);
set_next(_last, NULL);
}
public:
Trace(Block *b, Block **next_list, Block **prev_list) :
_first(b),
_last(b),
_next_list(next_list),
_prev_list(prev_list),
_id(b->_pre_order) {
set_next(b, NULL);
set_prev(b, NULL);
};
// Return the id number
uint id() const { return _id; }
void set_id(uint id) { _id = id; }
// Return the first block in the trace
Block * first_block() const { return _first; }
// Return the last block in the trace
Block * last_block() const { return _last; }
// Insert a trace in the middle of this one after b
void insert_after(Block *b, Trace *tr) {
set_next(tr->last_block(), next(b));
if (next(b) != NULL) {
set_prev(next(b), tr->last_block());
}
set_next(b, tr->first_block());
set_prev(tr->first_block(), b);
if (b == _last) {
_last = tr->last_block();
}
}
void insert_before(Block *b, Trace *tr) {
Block *p = prev(b);
assert(p != NULL, "use append instead");
insert_after(p, tr);
}
// Append another trace to this one.
void append(Trace *tr) {
insert_after(_last, tr);
}
// Append a block at the end of this trace
void append(Block *b) {
set_next(_last, b);
set_prev(b, _last);
_last = b;
}
// Adjust the the blocks in this trace
void fixup_blocks(PhaseCFG &cfg);
bool backedge(CFGEdge *e);
#ifndef PRODUCT
void dump( ) const;
#endif
};
//------------------------------PhaseBlockLayout-------------------------------
// Rearrange blocks into some canonical order, based on edges and their frequencies
class PhaseBlockLayout : public Phase {
PhaseCFG &_cfg; // Control flow graph
GrowableArray<CFGEdge *> *edges;
Trace **traces;
Block **next;
Block **prev;
UnionFind *uf;
// Given a block, find its encompassing Trace
Trace * trace(Block *b) {
return traces[uf->Find_compress(b->_pre_order)];
}
public:
PhaseBlockLayout(PhaseCFG &cfg);
void find_edges();
void grow_traces();
void merge_traces(bool loose_connections);
void reorder_traces(int count);
void union_traces(Trace* from, Trace* to);
};
......@@ -396,5 +396,15 @@
\
diagnostic(intx, DominatorSearchLimit, 1000, \
"Iterations limit in Node::dominates") \
\
product(bool, BlockLayoutByFrequency, true, \
"Use edge frequencies to drive block ordering") \
\
product(intx, BlockLayoutMinDiamondPercentage, 20, \
"Miniumum %% of a successor (predecessor) for which block layout "\
"a will allow a fork (join) in a single chain") \
\
product(bool, BlockLayoutRotateLoops, false, \
"Allow back branches to be fall throughs in the block layour") \
C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG)
......@@ -822,6 +822,7 @@ void Compile::Init(int aliaslevel) {
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
set_decompile_count(0);
set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
// Compilation level related initialization
if (env()->comp_level() == CompLevel_fast_compile) {
set_num_loop_opts(Tier1LoopOptsCount);
......@@ -1701,8 +1702,14 @@ void Compile::Code_Gen() {
// are not adding any new instructions. If any basic block is empty, we
// can now safely remove it.
{
NOT_PRODUCT( TracePhase t2("removeEmpty", &_t_removeEmptyBlocks, TimeCompiler); )
cfg.RemoveEmpty();
NOT_PRODUCT( TracePhase t2("blockOrdering", &_t_blockOrdering, TimeCompiler); )
cfg.remove_empty();
if (do_freq_based_layout()) {
PhaseBlockLayout layout(cfg);
} else {
cfg.set_loop_alignment();
}
cfg.fixup_flow();
}
// Perform any platform dependent postallocation verifications.
......
......@@ -154,6 +154,7 @@ class Compile : public Phase {
uint _decompile_count; // Cumulative decompilation counts.
bool _do_inlining; // True if we intend to do inlining
bool _do_scheduling; // True if we intend to do scheduling
bool _do_freq_based_layout; // True if we intend to do frequency based block layout
bool _do_count_invocations; // True if we generate code to count invocations
bool _do_method_data_update; // True if we generate code to update methodDataOops
int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
......@@ -307,6 +308,8 @@ class Compile : public Phase {
void set_do_inlining(bool z) { _do_inlining = z; }
bool do_scheduling() const { return _do_scheduling; }
void set_do_scheduling(bool z) { _do_scheduling = z; }
bool do_freq_based_layout() const{ return _do_freq_based_layout; }
void set_do_freq_based_layout(bool z){ _do_freq_based_layout = z; }
bool do_count_invocations() const{ return _do_count_invocations; }
void set_do_count_invocations(bool z){ _do_count_invocations = z; }
bool do_method_data_update() const { return _do_method_data_update; }
......
......@@ -1319,11 +1319,33 @@ void PhaseCFG::GlobalCodeMotion( Matcher &matcher, uint unique, Node_List &proj_
//------------------------------Estimate_Block_Frequency-----------------------
// Estimate block frequencies based on IfNode probabilities.
void PhaseCFG::Estimate_Block_Frequency() {
int cnts = C->method() ? C->method()->interpreter_invocation_count() : 1;
// Most of our algorithms will die horribly if frequency can become
// negative so make sure cnts is a sane value.
if( cnts <= 0 ) cnts = 1;
float f = (float)cnts/(float)FreqCountInvocations;
// Force conditional branches leading to uncommon traps to be unlikely,
// not because we get to the uncommon_trap with less relative frequency,
// but because an uncommon_trap typically causes a deopt, so we only get
// there once.
if (C->do_freq_based_layout()) {
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 1; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
if (uct == _broot) continue;
for (uint i = 1; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1) {
worklist.push(pb);
} else if (pb->num_fall_throughs() == 2) {
pb->update_uncommon_branch(uct);
}
}
}
}
// Create the loop tree and calculate loop depth.
_root_loop = create_loop_tree();
......@@ -1333,27 +1355,29 @@ void PhaseCFG::Estimate_Block_Frequency() {
_root_loop->compute_freq();
// Adjust all frequencies to be relative to a single method entry
_root_loop->_freq = f * 1.0;
_root_loop->_freq = 1.0;
_root_loop->scale_freq();
// force paths ending at uncommon traps to be infrequent
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 0; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
uct->_freq = PROB_MIN;
for (uint i = 0; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) {
if (!C->do_freq_based_layout()) {
Block_List worklist;
Block* root_blk = _blocks[0];
for (uint i = 1; i < root_blk->num_preds(); i++) {
Block *pb = _bbs[root_blk->pred(i)->_idx];
if (pb->has_uncommon_code()) {
worklist.push(pb);
}
}
while (worklist.size() > 0) {
Block* uct = worklist.pop();
uct->_freq = PROB_MIN;
for (uint i = 1; i < uct->num_preds(); i++) {
Block *pb = _bbs[uct->pred(i)->_idx];
if (pb->_num_succs == 1 && pb->_freq > PROB_MIN) {
worklist.push(pb);
}
}
}
}
#ifndef PRODUCT
......@@ -1556,22 +1580,6 @@ void CFGLoop::compute_freq() {
}
}
#if 0
// Raise frequency of the loop backedge block, in an effort
// to keep it empty. Skip the method level "loop".
if (_parent != NULL) {
CFGElement* s = _members.at(_members.length() - 1);
if (s->is_block()) {
Block* bk = s->as_Block();
if (bk->_num_succs == 1 && bk->_succs[0] == hd) {
// almost any value >= 1.0f works
// FIXME: raw constant
bk->_freq = 1.05f;
}
}
}
#endif
// For all loops other than the outer, "method" loop,
// sum and normalize the exit probability. The "method" loop
// should keep the initial exit probability of 1, so that
......@@ -1589,12 +1597,15 @@ void CFGLoop::compute_freq() {
// the probability of exit per loop entry.
for (int i = 0; i < _exits.length(); i++) {
Block* et = _exits.at(i).get_target();
float new_prob = _exits.at(i).get_prob() / exits_sum;
float new_prob = 0.0f;
if (_exits.at(i).get_prob() > 0.0f) {
new_prob = _exits.at(i).get_prob() / exits_sum;
}
BlockProbPair bpp(et, new_prob);
_exits.at_put(i, bpp);
}
// Save the total, but guard against unreasoable probability,
// Save the total, but guard against unreasonable probability,
// as the value is used to estimate the loop trip count.
// An infinite trip count would blur relative block
// frequencies.
......@@ -1688,6 +1699,137 @@ float Block::succ_prob(uint i) {
return 0.0f;
}
//------------------------------num_fall_throughs-----------------------------
// Return the number of fall-through candidates for a block
int Block::num_fall_throughs() {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->Opcode();
if (n->is_Mach()) {
if (n->is_MachNullCheck()) {
// In theory, either side can fall-thru, for simplicity sake,
// let's say only the false branch can now.
return 1;
}
op = n->as_Mach()->ideal_Opcode();
}
// Switch on branch type
switch( op ) {
case Op_CountedLoopEnd:
case Op_If:
return 2;
case Op_Root:
case Op_Goto:
return 1;
case Op_Catch: {
for (uint i = 0; i < _num_succs; i++) {
const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj();
if (ci->_con == CatchProjNode::fall_through_index) {
return 1;
}
}
return 0;
}
case Op_Jump:
case Op_NeverBranch:
case Op_TailCall:
case Op_TailJump:
case Op_Return:
case Op_Halt:
case Op_Rethrow:
return 0;
default:
ShouldNotReachHere();
}
return 0;
}
//------------------------------succ_fall_through-----------------------------
// Return true if a specific successor could be fall-through target.
bool Block::succ_fall_through(uint i) {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->Opcode();
if (n->is_Mach()) {
if (n->is_MachNullCheck()) {
// In theory, either side can fall-thru, for simplicity sake,
// let's say only the false branch can now.
return _nodes[i + eidx + 1]->Opcode() == Op_IfFalse;
}
op = n->as_Mach()->ideal_Opcode();
}
// Switch on branch type
switch( op ) {
case Op_CountedLoopEnd:
case Op_If:
case Op_Root:
case Op_Goto:
return true;
case Op_Catch: {
const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj();
return ci->_con == CatchProjNode::fall_through_index;
}
case Op_Jump:
case Op_NeverBranch:
case Op_TailCall:
case Op_TailJump:
case Op_Return:
case Op_Halt:
case Op_Rethrow:
return false;
default:
ShouldNotReachHere();
}
return false;
}
//------------------------------update_uncommon_branch------------------------
// Update the probability of a two-branch to be uncommon
void Block::update_uncommon_branch(Block* ub) {
int eidx = end_idx();
Node *n = _nodes[eidx]; // Get ending Node
int op = n->as_Mach()->ideal_Opcode();
assert(op == Op_CountedLoopEnd || op == Op_If, "must be a If");
assert(num_fall_throughs() == 2, "must be a two way branch block");
// Which successor is ub?
uint s;
for (s = 0; s <_num_succs; s++) {
if (_succs[s] == ub) break;
}
assert(s < 2, "uncommon successor must be found");
// If ub is the true path, make the proability small, else
// ub is the false path, and make the probability large
bool invert = (_nodes[s + eidx + 1]->Opcode() == Op_IfFalse);
// Get existing probability
float p = n->as_MachIf()->_prob;
if (invert) p = 1.0 - p;
if (p > PROB_MIN) {
p = PROB_MIN;
}
if (invert) p = 1.0 - p;
n->as_MachIf()->_prob = p;
}
//------------------------------update_succ_freq-------------------------------
// Update the appropriate frequency associated with block 'b', a succesor of
// a block in this loop.
......
......@@ -263,7 +263,7 @@ bool Compile::is_node_getting_a_safepoint( Node* n) {
# endif // ENABLE_ZAP_DEAD_LOCALS
//------------------------------compute_loop_first_inst_sizes------------------
// Compute the size of first NumberOfLoopInstrToAlign instructions at head
// Compute the size of first NumberOfLoopInstrToAlign instructions at the top
// of a loop. When aligning a loop we need to provide enough instructions
// in cpu's fetch buffer to feed decoders. The loop alignment could be
// avoided if we have enough instructions in fetch buffer at the head of a loop.
......@@ -284,34 +284,23 @@ void Compile::compute_loop_first_inst_sizes() {
for( uint i=1; i <= last_block; i++ ) {
Block *b = _cfg->_blocks[i];
// Check the first loop's block which requires an alignment.
if( b->head()->is_Loop() &&
b->code_alignment() > (uint)relocInfo::addr_unit() ) {
if( b->loop_alignment() > (uint)relocInfo::addr_unit() ) {
uint sum_size = 0;
uint inst_cnt = NumberOfLoopInstrToAlign;
inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt,
_regalloc);
// Check the next fallthrough block if first loop's block does not have
// enough instructions.
if( inst_cnt > 0 && i < last_block ) {
// First, check if the first loop's block contains whole loop.
// LoopNode::LoopBackControl == 2.
Block *bx = _cfg->_bbs[b->pred(2)->_idx];
// Skip connector blocks (with limit in case of irreducible loops).
int search_limit = 16;
while( bx->is_connector() && search_limit-- > 0) {
bx = _cfg->_bbs[bx->pred(1)->_idx];
}
if( bx != b ) { // loop body is in several blocks.
Block *nb = NULL;
while( inst_cnt > 0 && i < last_block && nb != bx &&
!_cfg->_blocks[i+1]->head()->is_Loop() ) {
i++;
nb = _cfg->_blocks[i];
inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt,
_regalloc);
} // while( inst_cnt > 0 && i < last_block )
} // if( bx != b )
} // if( inst_cnt > 0 && i < last_block )
inst_cnt = b->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
// Check subsequent fallthrough blocks if the loop's first
// block(s) does not have enough instructions.
Block *nb = b;
while( inst_cnt > 0 &&
i < last_block &&
!_cfg->_blocks[i+1]->has_loop_alignment() &&
!nb->has_successor(b) ) {
i++;
nb = _cfg->_blocks[i];
inst_cnt = nb->compute_first_inst_size(sum_size, inst_cnt, _regalloc);
} // while( inst_cnt > 0 && i < last_block )
b->set_first_inst_size(sum_size);
} // f( b->head()->is_Loop() )
} // for( i <= last_block )
......@@ -512,7 +501,7 @@ void Compile::Shorten_branches(Label *labels, int& code_size, int& reloc_size, i
// Get the size of the block
uint blk_size = adr - blk_starts[i];
// When the next block starts a loop, we may insert pad NOP
// When the next block is the top of a loop, we may insert pad NOP
// instructions.
Block *nb = _cfg->_blocks[i+1];
int current_offset = blk_starts[i] + blk_size;
......@@ -1382,8 +1371,8 @@ void Compile::Fill_buffer() {
} // End for all instructions in block
// If the next block _starts_ a loop, pad this block out to align
// the loop start a little. Helps prevent pipe stalls at loop starts
// If the next block is the top of a loop, pad this block out to align
// the loop top a little. Helps prevent pipe stalls at loop back branches.
int nop_size = (new (this) MachNopNode())->size(_regalloc);
if( i<_cfg->_num_blocks-1 ) {
Block *nb = _cfg->_blocks[i+1];
......
......@@ -46,7 +46,7 @@ elapsedTimer Phase::_t_output;
#ifndef PRODUCT
elapsedTimer Phase::_t_graphReshaping;
elapsedTimer Phase::_t_scheduler;
elapsedTimer Phase::_t_removeEmptyBlocks;
elapsedTimer Phase::_t_blockOrdering;
elapsedTimer Phase::_t_macroExpand;
elapsedTimer Phase::_t_peephole;
elapsedTimer Phase::_t_codeGeneration;
......@@ -128,7 +128,7 @@ void Phase::print_timers() {
tty->print_cr (" subtotal : %3.3f sec, %3.2f %%", regalloc_subtotal, percent_of_regalloc);
}
tty->print_cr (" macroExpand : %3.3f sec", Phase::_t_macroExpand.seconds());
tty->print_cr (" removeEmpty : %3.3f sec", Phase::_t_removeEmptyBlocks.seconds());
tty->print_cr (" blockOrdering: %3.3f sec", Phase::_t_blockOrdering.seconds());
tty->print_cr (" peephole : %3.3f sec", Phase::_t_peephole.seconds());
tty->print_cr (" codeGen : %3.3f sec", Phase::_t_codeGeneration.seconds());
tty->print_cr (" install_code : %3.3f sec", Phase::_t_registerMethod.seconds());
......@@ -137,7 +137,7 @@ void Phase::print_timers() {
(DoEscapeAnalysis ? Phase::_t_escapeAnalysis.seconds() : 0.0) +
Phase::_t_optimizer.seconds() + Phase::_t_graphReshaping.seconds() +
Phase::_t_matcher.seconds() + Phase::_t_scheduler.seconds() +
Phase::_t_registerAllocation.seconds() + Phase::_t_removeEmptyBlocks.seconds() +
Phase::_t_registerAllocation.seconds() + Phase::_t_blockOrdering.seconds() +
Phase::_t_macroExpand.seconds() + Phase::_t_peephole.seconds() +
Phase::_t_codeGeneration.seconds() + Phase::_t_registerMethod.seconds();
double percent_of_method_compile = ((phase_subtotal == 0.0) ? 0.0 : phase_subtotal / Phase::_t_methodCompilation.seconds()) * 100.0;
......
......@@ -40,16 +40,12 @@ public:
Optimistic, // Optimistic analysis phase
GVN, // Pessimistic global value numbering phase
Ins_Select, // Instruction selection phase
Copy_Elimination, // Copy Elimination
Dead_Code_Elimination, // DCE and compress Nodes
Conditional_Constant, // Conditional Constant Propagation
CFG, // Build a CFG
DefUse, // Build Def->Use chains
BlockLayout, // Linear ordering of blocks
Register_Allocation, // Register allocation, duh
LIVE, // Dragon-book LIVE range problem
Interference_Graph, // Building the IFG
Coalesce, // Coalescing copies
Conditional_CProp, // Conditional Constant Propagation
Ideal_Loop, // Find idealized trip-counted loops
Macro_Expand, // Expand macro nodes
Peephole, // Apply peephole optimizations
......@@ -80,7 +76,7 @@ protected:
#ifndef PRODUCT
static elapsedTimer _t_graphReshaping;
static elapsedTimer _t_scheduler;
static elapsedTimer _t_removeEmptyBlocks;
static elapsedTimer _t_blockOrdering;
static elapsedTimer _t_macroExpand;
static elapsedTimer _t_peephole;
static elapsedTimer _t_codeGeneration;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册