Skip to content

Commit 12c461b

Browse files
aartbikcommit-bot@chromium.org
authored andcommitted
[vm/inliner] Inlining of typed_data polymorphic getters/setters
Rationale: Handles remaining polymorphic reason for typed_data setters and getters (internal vs. external) during inlining. Also introduces high level flow graph utilities that can be reused throughout the compiler to reduce future code duplication. Disables type speculation for 64-bit AOT Dart2 to make all work. Performance: About 4x speedup on micro benchmarks (AOT64). #33205 Change-Id: I678426719e49cd8aa1e5051523da12178120b3ba Reviewed-on: https://dart-review.googlesource.com/59000 Reviewed-by: Vyacheslav Egorov <[email protected]> Reviewed-by: Alexander Markov <[email protected]> Commit-Queue: Aart Bik <[email protected]>
1 parent 8e472ac commit 12c461b

File tree

5 files changed

+473
-132
lines changed

5 files changed

+473
-132
lines changed

runtime/vm/compiler/backend/flow_graph.cc

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,144 @@ void FlowGraph::AppendExtractNthOutputForMerged(Definition* instr,
22662266
InsertAfter(instr, extract, NULL, FlowGraph::kValue);
22672267
}
22682268

2269+
//
2270+
// Static helpers for the flow graph utilities.
2271+
//
2272+
2273+
static TargetEntryInstr* NewTarget(FlowGraph* graph, Instruction* inherit) {
2274+
TargetEntryInstr* target = new (graph->zone())
2275+
TargetEntryInstr(graph->allocate_block_id(),
2276+
inherit->GetBlock()->try_index(), Thread::kNoDeoptId);
2277+
target->InheritDeoptTarget(graph->zone(), inherit);
2278+
return target;
2279+
}
2280+
2281+
static JoinEntryInstr* NewJoin(FlowGraph* graph, Instruction* inherit) {
2282+
JoinEntryInstr* join = new (graph->zone())
2283+
JoinEntryInstr(graph->allocate_block_id(),
2284+
inherit->GetBlock()->try_index(), Thread::kNoDeoptId);
2285+
join->InheritDeoptTarget(graph->zone(), inherit);
2286+
return join;
2287+
}
2288+
2289+
static GotoInstr* NewGoto(FlowGraph* graph,
2290+
JoinEntryInstr* target,
2291+
Instruction* inherit) {
2292+
GotoInstr* got = new (graph->zone()) GotoInstr(target, Thread::kNoDeoptId);
2293+
got->InheritDeoptTarget(graph->zone(), inherit);
2294+
return got;
2295+
}
2296+
2297+
static BranchInstr* NewBranch(FlowGraph* graph,
2298+
ComparisonInstr* cmp,
2299+
Instruction* inherit) {
2300+
BranchInstr* bra = new (graph->zone()) BranchInstr(cmp, Thread::kNoDeoptId);
2301+
bra->InheritDeoptTarget(graph->zone(), inherit);
2302+
return bra;
2303+
}
2304+
2305+
//
2306+
// Flow graph utilities.
2307+
//
2308+
2309+
// Constructs new diamond decision at the given instruction.
2310+
//
2311+
// ENTRY
2312+
// instruction
2313+
// if (compare)
2314+
// / \
2315+
// B_TRUE B_FALSE
2316+
// \ /
2317+
// JOIN
2318+
//
2319+
JoinEntryInstr* FlowGraph::NewDiamond(Instruction* instruction,
2320+
Instruction* inherit,
2321+
ComparisonInstr* compare,
2322+
TargetEntryInstr** b_true,
2323+
TargetEntryInstr** b_false) {
2324+
BlockEntryInstr* entry = instruction->GetBlock();
2325+
2326+
TargetEntryInstr* bt = NewTarget(this, inherit);
2327+
TargetEntryInstr* bf = NewTarget(this, inherit);
2328+
JoinEntryInstr* join = NewJoin(this, inherit);
2329+
GotoInstr* gotot = NewGoto(this, join, inherit);
2330+
GotoInstr* gotof = NewGoto(this, join, inherit);
2331+
BranchInstr* bra = NewBranch(this, compare, inherit);
2332+
2333+
instruction->AppendInstruction(bra);
2334+
entry->set_last_instruction(bra);
2335+
2336+
*bra->true_successor_address() = bt;
2337+
*bra->false_successor_address() = bf;
2338+
2339+
bt->AppendInstruction(gotot);
2340+
bt->set_last_instruction(gotot);
2341+
2342+
bf->AppendInstruction(gotof);
2343+
bf->set_last_instruction(gotof);
2344+
2345+
// Update dominance relation incrementally.
2346+
for (intptr_t i = 0, n = entry->dominated_blocks().length(); i < n; ++i) {
2347+
join->AddDominatedBlock(entry->dominated_blocks()[i]);
2348+
}
2349+
entry->ClearDominatedBlocks();
2350+
entry->AddDominatedBlock(bt);
2351+
entry->AddDominatedBlock(bf);
2352+
entry->AddDominatedBlock(join);
2353+
2354+
// TODO(ajcbik): update pred/succ/ordering incrementally too.
2355+
2356+
// Return new blocks.
2357+
*b_true = bt;
2358+
*b_false = bf;
2359+
return join;
2360+
}
2361+
2362+
JoinEntryInstr* FlowGraph::NewDiamond(Instruction* instruction,
2363+
Instruction* inherit,
2364+
const LogicalAnd& condition,
2365+
TargetEntryInstr** b_true,
2366+
TargetEntryInstr** b_false) {
2367+
// First diamond for first comparison.
2368+
TargetEntryInstr* bt = nullptr;
2369+
TargetEntryInstr* bf = nullptr;
2370+
JoinEntryInstr* mid_point =
2371+
NewDiamond(instruction, inherit, condition.oper1, &bt, &bf);
2372+
2373+
// Short-circuit second comparison and connect through phi.
2374+
condition.oper2->InsertAfter(bt);
2375+
AllocateSSAIndexes(condition.oper2);
2376+
condition.oper2->InheritDeoptTarget(zone(), inherit); // must inherit
2377+
PhiInstr* phi =
2378+
AddPhi(mid_point, condition.oper2, GetConstant(Bool::False()));
2379+
StrictCompareInstr* circuit = new (zone()) StrictCompareInstr(
2380+
inherit->token_pos(), Token::kEQ_STRICT, new (zone()) Value(phi),
2381+
new (zone()) Value(GetConstant(Bool::True())), false,
2382+
Thread::kNoDeoptId); // don't inherit
2383+
2384+
// Return new blocks through the second diamond.
2385+
return NewDiamond(mid_point, inherit, circuit, b_true, b_false);
2386+
}
2387+
2388+
PhiInstr* FlowGraph::AddPhi(JoinEntryInstr* join,
2389+
Definition* d1,
2390+
Definition* d2) {
2391+
PhiInstr* phi = new (zone()) PhiInstr(join, 2);
2392+
Value* v1 = new (zone()) Value(d1);
2393+
Value* v2 = new (zone()) Value(d2);
2394+
2395+
AllocateSSAIndexes(phi);
2396+
2397+
phi->mark_alive();
2398+
phi->SetInputAt(0, v1);
2399+
phi->SetInputAt(1, v2);
2400+
d1->AddInputUse(v1);
2401+
d2->AddInputUse(v2);
2402+
join->InsertPhi(phi);
2403+
2404+
return phi;
2405+
}
2406+
22692407
} // namespace dart
22702408

22712409
#endif // !defined(DART_PRECOMPILED_RUNTIME)

runtime/vm/compiler/backend/flow_graph.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,37 @@ class FlowGraph : public ZoneAllocated {
351351

352352
bool should_print() const { return should_print_; }
353353

354+
//
355+
// High-level utilities.
356+
//
357+
358+
// Logical-AND (for use in short-circuit diamond).
359+
struct LogicalAnd {
360+
LogicalAnd(ComparisonInstr* x, ComparisonInstr* y) : oper1(x), oper2(y) {}
361+
ComparisonInstr* oper1;
362+
ComparisonInstr* oper2;
363+
};
364+
365+
// Constructs a diamond control flow at the instruction, inheriting
366+
// properties from inherit and using the given compare. Returns the
367+
// join (and true/false blocks in out parameters). Updates dominance
368+
// relation, but not the succ/pred ordering on block.
369+
JoinEntryInstr* NewDiamond(Instruction* instruction,
370+
Instruction* inherit,
371+
ComparisonInstr* compare,
372+
TargetEntryInstr** block_true,
373+
TargetEntryInstr** block_false);
374+
375+
// As above, but with a short-circuit on two comparisons.
376+
JoinEntryInstr* NewDiamond(Instruction* instruction,
377+
Instruction* inherit,
378+
const LogicalAnd& condition,
379+
TargetEntryInstr** block_true,
380+
TargetEntryInstr** block_false);
381+
382+
// Adds a 2-way phi.
383+
PhiInstr* AddPhi(JoinEntryInstr* join, Definition* d1, Definition* d2);
384+
354385
private:
355386
friend class IfConverter;
356387
friend class BranchSimplifier;

0 commit comments

Comments
 (0)