mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:30:32 +00:00
[VM] Add support for skipping a prologue range of blocks (for inlining heuristics)
Issue https://github.com/dart-lang/sdk/issues/31495 Change-Id: I876f4e064cfd21f5c3e99b531ff69776eba99635 Reviewed-on: https://dart-review.googlesource.com/25060 Commit-Queue: Martin Kustermann <kustermann@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
9174a627f5
commit
3347b700df
|
@ -26,7 +26,8 @@ DECLARE_FLAG(bool, verify_compiler);
|
|||
|
||||
FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
|
||||
GraphEntryInstr* graph_entry,
|
||||
intptr_t max_block_id)
|
||||
intptr_t max_block_id,
|
||||
PrologueInfo prologue_info)
|
||||
: thread_(Thread::Current()),
|
||||
parent_(),
|
||||
current_ssa_temp_index_(0),
|
||||
|
@ -43,6 +44,7 @@ FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
|
|||
constant_dead_(NULL),
|
||||
constant_empty_context_(NULL),
|
||||
licm_allowed_(true),
|
||||
prologue_info_(prologue_info),
|
||||
loop_headers_(NULL),
|
||||
loop_invariant_loads_(NULL),
|
||||
deferred_prefixes_(parsed_function.deferred_prefixes()),
|
||||
|
@ -1410,8 +1412,16 @@ intptr_t FlowGraph::InstructionCount() const {
|
|||
intptr_t size = 0;
|
||||
// Iterate each block, skipping the graph entry.
|
||||
for (intptr_t i = 1; i < preorder_.length(); ++i) {
|
||||
for (ForwardInstructionIterator it(preorder_[i]); !it.Done();
|
||||
it.Advance()) {
|
||||
BlockEntryInstr* block = preorder_[i];
|
||||
|
||||
// Skip any blocks from the prologue to make them not count towards the
|
||||
// inlining instruction budget.
|
||||
const intptr_t block_id = block->block_id();
|
||||
if (prologue_info_.Contains(block_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
|
||||
++size;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,12 +73,32 @@ struct ConstantPoolTrait {
|
|||
}
|
||||
};
|
||||
|
||||
struct PrologueInfo {
|
||||
// The first blockid used for prologue building. This information can be used
|
||||
// by the inliner for budget calculations: The prologue code falls away when
|
||||
// inlining, so we should not include it in the budget.
|
||||
const intptr_t min_block_id;
|
||||
|
||||
// The last blockid used for prologue building. This information can be used
|
||||
// by the inliner for budget calculations: The prologue code falls away when
|
||||
// inlining, so we should not include it in the budget.
|
||||
const intptr_t max_block_id;
|
||||
|
||||
PrologueInfo(intptr_t min, intptr_t max)
|
||||
: min_block_id(min), max_block_id(max) {}
|
||||
|
||||
bool Contains(intptr_t block_id) const {
|
||||
return min_block_id <= block_id && block_id <= max_block_id;
|
||||
}
|
||||
};
|
||||
|
||||
// Class to encapsulate the construction and manipulation of the flow graph.
|
||||
class FlowGraph : public ZoneAllocated {
|
||||
public:
|
||||
FlowGraph(const ParsedFunction& parsed_function,
|
||||
GraphEntryInstr* graph_entry,
|
||||
intptr_t max_block_id);
|
||||
intptr_t max_block_id,
|
||||
PrologueInfo prologue_info);
|
||||
|
||||
// Function properties.
|
||||
const ParsedFunction& parsed_function() const { return parsed_function_; }
|
||||
|
@ -235,6 +255,8 @@ class FlowGraph : public ZoneAllocated {
|
|||
// after this point.
|
||||
void disallow_licm() { licm_allowed_ = false; }
|
||||
|
||||
PrologueInfo prologue_info() const { return prologue_info_; }
|
||||
|
||||
const ZoneGrowableArray<BlockEntryInstr*>& LoopHeaders() {
|
||||
if (loop_headers_ == NULL) {
|
||||
loop_headers_ = ComputeLoops();
|
||||
|
@ -401,6 +423,8 @@ class FlowGraph : public ZoneAllocated {
|
|||
|
||||
bool licm_allowed_;
|
||||
|
||||
const PrologueInfo prologue_info_;
|
||||
|
||||
ZoneGrowableArray<BlockEntryInstr*>* loop_headers_;
|
||||
ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
|
||||
ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes_;
|
||||
|
|
|
@ -2911,6 +2911,9 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
TokenPosition::kNoSource);
|
||||
}
|
||||
if (HasParallelMove()) {
|
||||
if (Assembler::EmittingComments()) {
|
||||
compiler->EmitComment(parallel_move());
|
||||
}
|
||||
compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,6 +152,13 @@ class GraphInfoCollector : public ValueObject {
|
|||
instruction_count_ = 0;
|
||||
for (BlockIterator block_it = graph.postorder_iterator(); !block_it.Done();
|
||||
block_it.Advance()) {
|
||||
// Skip any blocks from the prologue to make them not count towards the
|
||||
// inlining instruction budget.
|
||||
const intptr_t block_id = block_it.Current()->block_id();
|
||||
if (graph.prologue_info().Contains(block_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (ForwardInstructionIterator it(block_it.Current()); !it.Done();
|
||||
it.Advance()) {
|
||||
Instruction* current = it.Current();
|
||||
|
|
|
@ -4428,9 +4428,11 @@ FlowGraph* FlowGraphBuilder::BuildGraph() {
|
|||
graph_entry_->RelinkToOsrEntry(Z, last_used_block_id_);
|
||||
}
|
||||
|
||||
FlowGraph* graph =
|
||||
new (Z) FlowGraph(parsed_function(), graph_entry_, last_used_block_id_);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
FlowGraph* graph = new (Z) FlowGraph(parsed_function(), graph_entry_,
|
||||
last_used_block_id_, prologue_info);
|
||||
graph->set_await_token_positions(await_token_positions_);
|
||||
|
||||
return graph;
|
||||
}
|
||||
|
||||
|
|
|
@ -3484,9 +3484,10 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfStaticFieldInitializer() {
|
|||
}
|
||||
body += Return(TokenPosition::kNoSource);
|
||||
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
|
||||
flow_graph_builder_->last_used_block_id_);
|
||||
flow_graph_builder_->last_used_block_id_, prologue_info);
|
||||
}
|
||||
|
||||
FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
|
||||
|
@ -3542,9 +3543,10 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFieldAccessor(
|
|||
}
|
||||
body += Return(TokenPosition::kNoSource);
|
||||
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
|
||||
flow_graph_builder_->last_used_block_id_);
|
||||
flow_graph_builder_->last_used_block_id_, prologue_info);
|
||||
}
|
||||
|
||||
void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
|
||||
|
@ -3887,9 +3889,10 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfImplicitClosureFunction(
|
|||
// Return the result.
|
||||
body += Return(function_node_helper.end_position_);
|
||||
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function(), flow_graph_builder_->graph_entry_,
|
||||
flow_graph_builder_->last_used_block_id_);
|
||||
flow_graph_builder_->last_used_block_id_, prologue_info);
|
||||
}
|
||||
|
||||
LocalVariable* StreamingFlowGraphBuilder::LookupParameterDirect(
|
||||
|
@ -4245,8 +4248,10 @@ FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfFunction(bool constructor) {
|
|||
graph_entry->RelinkToOsrEntry(Z,
|
||||
flow_graph_builder_->last_used_block_id_ + 1);
|
||||
}
|
||||
return new (Z) FlowGraph(*parsed_function(), graph_entry,
|
||||
flow_graph_builder_->last_used_block_id_);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function(), graph_entry,
|
||||
flow_graph_builder_->last_used_block_id_, prologue_info);
|
||||
}
|
||||
|
||||
FlowGraph* StreamingFlowGraphBuilder::BuildGraph(intptr_t kernel_offset) {
|
||||
|
|
|
@ -2212,8 +2212,10 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfMethodExtractor(
|
|||
body += BuildImplicitClosureCreation(function);
|
||||
body += Return(TokenPosition::kNoSource);
|
||||
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_);
|
||||
// There is no prologue code for a method extractor.
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
|
||||
prologue_info);
|
||||
}
|
||||
|
||||
FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
|
||||
|
@ -2326,8 +2328,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfNoSuchMethodDispatcher(
|
|||
/* argument_count = */ 2, ICData::kNSMDispatch);
|
||||
body += Return(TokenPosition::kNoSource);
|
||||
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
|
||||
prologue_info);
|
||||
}
|
||||
|
||||
FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher(
|
||||
|
@ -2426,8 +2429,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher(
|
|||
|
||||
body += Return(TokenPosition::kNoSource);
|
||||
|
||||
return new (Z)
|
||||
FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
|
||||
prologue_info);
|
||||
}
|
||||
|
||||
TargetEntryInstr* BaseFlowGraphBuilder::BuildTargetEntry() {
|
||||
|
|
|
@ -165,6 +165,7 @@ static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) {
|
|||
bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
|
||||
FlowGraphCompiler* compiler) {
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
ASSERT(!parsed_function.function().HasOptionalParameters());
|
||||
ZoneGrowableArray<const ICData*>* ic_data_array =
|
||||
new ZoneGrowableArray<const ICData*>();
|
||||
FlowGraphBuilder builder(parsed_function, *ic_data_array,
|
||||
|
@ -177,7 +178,9 @@ bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
|
|||
Thread::Current()->GetNextDeoptId());
|
||||
GraphEntryInstr* graph_entry = new GraphEntryInstr(
|
||||
parsed_function, normal_entry, Compiler::kNoOSRDeoptId);
|
||||
FlowGraph* graph = new FlowGraph(parsed_function, graph_entry, block_id);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
FlowGraph* graph =
|
||||
new FlowGraph(parsed_function, graph_entry, block_id, prologue_info);
|
||||
const Function& function = parsed_function.function();
|
||||
switch (function.recognized_kind()) {
|
||||
#define EMIT_CASE(class_name, function_name, enum_name, type, fp) \
|
||||
|
|
|
@ -241,9 +241,9 @@ FlowGraph* IrregexpCompilationPipeline::BuildFlowGraph(
|
|||
if (osr_id != Compiler::kNoOSRDeoptId) {
|
||||
result.graph_entry->RelinkToOsrEntry(zone, result.num_blocks);
|
||||
}
|
||||
|
||||
return new (zone)
|
||||
FlowGraph(*parsed_function, result.graph_entry, result.num_blocks);
|
||||
PrologueInfo prologue_info(-1, -1);
|
||||
return new (zone) FlowGraph(*parsed_function, result.graph_entry,
|
||||
result.num_blocks, prologue_info);
|
||||
}
|
||||
|
||||
void IrregexpCompilationPipeline::FinalizeCompilation(FlowGraph* flow_graph) {
|
||||
|
|
Loading…
Reference in a new issue