Flutter Engine
The Flutter Engine
redundancy_elimination.h
Go to the documentation of this file.
1// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#ifndef RUNTIME_VM_COMPILER_BACKEND_REDUNDANCY_ELIMINATION_H_
6#define RUNTIME_VM_COMPILER_BACKEND_REDUNDANCY_ELIMINATION_H_
7
8#if defined(DART_PRECOMPILED_RUNTIME)
9#error "AOT runtime should not use compiler sources (including header files)"
10#endif // defined(DART_PRECOMPILED_RUNTIME)
11
14
15namespace dart {
16
17class CSEInstructionSet;
18
20 public:
21 explicit AllocationSinking(FlowGraph* flow_graph)
22 : flow_graph_(flow_graph), candidates_(5), materializations_(5) {}
23
24 const GrowableArray<Definition*>& candidates() const { return candidates_; }
25
26 // Find the materialization inserted for the given allocation
27 // at the given exit.
30
31 void Optimize();
32
34
35 private:
36 // Helper class to collect deoptimization exits that might need to
37 // rematerialize an object: that is either instructions that reference
38 // this object explicitly in their deoptimization environment or
39 // reference some other allocation sinking candidate that points to
40 // this object.
41 class ExitsCollector : public ValueObject {
42 public:
43 ExitsCollector() : exits_(10), worklist_(3) {}
44
45 const GrowableArray<Instruction*>& exits() const { return exits_; }
46
47 void CollectTransitively(Definition* alloc);
48
49 private:
50 // Collect immediate uses of this object in the environments.
51 // If this object is stored into other allocation sinking candidates
52 // put them onto worklist so that CollectTransitively will process them.
53 void Collect(Definition* alloc);
54
55 GrowableArray<Instruction*> exits_;
56 GrowableArray<Definition*> worklist_;
57 };
58
59 void CollectCandidates();
60
61 void NormalizeMaterializations();
62
63 void RemoveUnusedMaterializations();
64
65 void DiscoverFailedCandidates();
66
67 void InsertMaterializations(Definition* alloc);
68
69 void CreateMaterializationAt(Instruction* exit,
70 Definition* alloc,
71 const ZoneGrowableArray<const Slot*>& fields);
72
73 void EliminateAllocation(Definition* alloc);
74
75 enum SafeUseCheck { kOptimisticCheck, kStrictCheck };
76
77 bool IsAllocationSinkingCandidate(Definition* alloc, SafeUseCheck check_type);
78
79 bool IsSafeUse(Value* use, SafeUseCheck check_type);
80
81 Zone* zone() const { return flow_graph_->zone(); }
82
83 FlowGraph* flow_graph_;
84
85 GrowableArray<Definition*> candidates_;
86 GrowableArray<MaterializeObjectInstr*> materializations_;
87
88 ExitsCollector exits_collector_;
89};
90
91// A simple common subexpression elimination based
92// on the dominator tree.
94 public:
95 // Return true, if the optimization changed the flow graph.
96 // False, if nothing changed.
97 static bool Optimize(FlowGraph* graph, bool run_load_optimization = true);
98
99 private:
100 static bool OptimizeRecursive(FlowGraph* graph,
101 BlockEntryInstr* entry,
103};
104
106 public:
107 static void Optimize(FlowGraph* graph);
108};
109
111 public:
112 // Discover phis that have no real (non-phi) uses and don't escape into
113 // deoptimization environments and eliminate them.
114 static void EliminateDeadPhis(FlowGraph* graph);
115
116 // Remove phis that are not marked alive from the graph.
118
119 // Remove instructions which do not have any effect.
120 static void EliminateDeadCode(FlowGraph* graph);
121};
122
123// Optimize spill stores inside try-blocks by identifying values that always
124// contain a single known constant at catch block entry.
125// If is_aot is passed then this optimization can assume that no deoptimization
126// can occur and environments assigned to instructions are only used to
127// compute try/catch sync moves.
128void OptimizeCatchEntryStates(FlowGraph* flow_graph, bool is_aot);
129
130// Loop invariant code motion.
131class LICM : public ValueObject {
132 public:
133 explicit LICM(FlowGraph* flow_graph);
134
135 void Optimize();
136
138
139 private:
140 FlowGraph* flow_graph() const { return flow_graph_; }
141
142 void Hoist(ForwardInstructionIterator* it,
143 BlockEntryInstr* pre_header,
144 Instruction* current);
145
146 void TrySpecializeSmiPhi(PhiInstr* phi,
148 BlockEntryInstr* pre_header);
149
150 FlowGraph* const flow_graph_;
151};
152
153// Move allocations down to their first use. Improves write barrier elimination.
155 public:
156 static void Optimize(FlowGraph* graph);
157
158 private:
159 static Instruction* DominantUse(Definition* def);
160 static bool IsOneTimeUse(Instruction* use, Definition* def);
161};
162
164 public:
165 // For leaf functions with only a single [StackOverflowInstr] we remove it.
166 static void EliminateStackOverflow(FlowGraph* graph);
167};
168
169} // namespace dart
170
171#endif // RUNTIME_VM_COMPILER_BACKEND_REDUNDANCY_ELIMINATION_H_
MaterializeObjectInstr * MaterializationFor(Definition *alloc, Instruction *exit)
const GrowableArray< Definition * > & candidates() const
AllocationSinking(FlowGraph *flow_graph)
static void EliminateStackOverflow(FlowGraph *graph)
static void EliminateDeadPhis(FlowGraph *graph)
static void RemoveDeadAndRedundantPhisFromTheGraph(FlowGraph *graph)
static void EliminateDeadCode(FlowGraph *graph)
static void Optimize(FlowGraph *graph)
static void Optimize(FlowGraph *graph)
static bool Optimize(FlowGraph *graph, bool run_load_optimization=true)
Zone * zone() const
Definition: flow_graph.h:261
void OptimisticallySpecializeSmiPhis()
LICM(FlowGraph *flow_graph)
exit(kErrorExitCode)
Definition: dart_vm.cc:33
void OptimizeCatchEntryStates(FlowGraph *flow_graph, bool is_aot)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
Definition: SkVx.h:680
static const char header[]
Definition: skpbench.cpp:88