Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(485)

Side by Side Diff: runtime/vm/constant_propagator.h

Issue 820883004: Move ConstantPropagator from flow_graph_optimizer.cc/.h into separate files. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/constant_propagator.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_FLOW_GRAPH_OPTIMIZER_H_ 5 #ifndef VM_CONSTANT_PROPAGATOR_H_
6 #define VM_FLOW_GRAPH_OPTIMIZER_H_ 6 #define VM_CONSTANT_PROPAGATOR_H_
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 #include "vm/flow_graph.h" 9 #include "vm/flow_graph.h"
10 10
11 namespace dart { 11 namespace dart {
12 12
13 class CSEInstructionMap;
14 template <typename T> class GrowableArray;
15 class ParsedFunction;
16
17 class FlowGraphOptimizer : public FlowGraphVisitor {
18 public:
19 explicit FlowGraphOptimizer(FlowGraph* flow_graph)
20 : FlowGraphVisitor(flow_graph->reverse_postorder()),
21 flow_graph_(flow_graph) { }
22 virtual ~FlowGraphOptimizer() {}
23
24 FlowGraph* flow_graph() const { return flow_graph_; }
25
26 // Use ICData to optimize, replace or eliminate instructions.
27 void ApplyICData();
28
29 // Use propagated class ids to optimize, replace or eliminate instructions.
30 void ApplyClassIds();
31
32 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
33 // shift can be a truncating Smi shift-left and result is always Smi.
34 // Merge instructions (only per basic-block).
35 void TryOptimizePatterns();
36
37 // Returns true if any instructions were canonicalized away.
38 bool Canonicalize();
39
40 void EliminateDeadPhis();
41
42 void SelectRepresentations();
43
44 void WidenSmiToInt32();
45
46 void InferIntRanges();
47
48 void SelectIntegerInstructions();
49
50 void AnalyzeTryCatch();
51
52 bool TryInlineRecognizedMethod(intptr_t receiver_cid,
53 const Function& target,
54 Instruction* call,
55 Definition* receiver,
56 intptr_t token_pos,
57 const ICData& ic_data,
58 TargetEntryInstr** entry,
59 Definition** last);
60
61 // Remove environments from the instructions which do not deoptimize.
62 void EliminateEnvironments();
63
64 virtual void VisitStaticCall(StaticCallInstr* instr);
65 virtual void VisitInstanceCall(InstanceCallInstr* instr);
66 virtual void VisitStoreInstanceField(StoreInstanceFieldInstr* instr);
67 virtual void VisitAllocateContext(AllocateContextInstr* instr);
68 virtual void VisitLoadCodeUnits(LoadCodeUnitsInstr* instr);
69
70 void InsertBefore(Instruction* next,
71 Instruction* instr,
72 Environment* env,
73 FlowGraph::UseKind use_kind) {
74 flow_graph_->InsertBefore(next, instr, env, use_kind);
75 }
76
77 private:
78 // Attempt to build ICData for call using propagated class-ids.
79 bool TryCreateICData(InstanceCallInstr* call);
80 const ICData& TrySpecializeICData(const ICData& ic_data, intptr_t cid);
81
82 void SpecializePolymorphicInstanceCall(PolymorphicInstanceCallInstr* call);
83
84 bool TryReplaceWithStoreIndexed(InstanceCallInstr* call);
85 bool InlineSetIndexed(MethodRecognizer::Kind kind,
86 const Function& target,
87 Instruction* call,
88 Definition* receiver,
89 intptr_t token_pos,
90 const ICData* ic_data,
91 const ICData& value_check,
92 TargetEntryInstr** entry,
93 Definition** last);
94 bool TryReplaceWithLoadIndexed(InstanceCallInstr* call);
95 bool InlineGetIndexed(MethodRecognizer::Kind kind,
96 Instruction* call,
97 Definition* receiver,
98 const ICData& ic_data,
99 TargetEntryInstr** entry,
100 Definition** last);
101 intptr_t PrepareInlineIndexedOp(Instruction* call,
102 intptr_t array_cid,
103 Definition** array,
104 Definition* index,
105 Instruction** cursor);
106
107
108 bool TryReplaceWithBinaryOp(InstanceCallInstr* call, Token::Kind op_kind);
109 bool TryReplaceWithUnaryOp(InstanceCallInstr* call, Token::Kind op_kind);
110
111 bool TryReplaceWithEqualityOp(InstanceCallInstr* call, Token::Kind op_kind);
112 bool TryReplaceWithRelationalOp(InstanceCallInstr* call, Token::Kind op_kind);
113
114 bool TryInlineInstanceGetter(InstanceCallInstr* call);
115 bool TryInlineInstanceSetter(InstanceCallInstr* call,
116 const ICData& unary_ic_data);
117
118 bool TryInlineInstanceMethod(InstanceCallInstr* call);
119 bool TryInlineFloat32x4Constructor(StaticCallInstr* call,
120 MethodRecognizer::Kind recognized_kind);
121 bool TryInlineFloat64x2Constructor(StaticCallInstr* call,
122 MethodRecognizer::Kind recognized_kind);
123 bool TryInlineInt32x4Constructor(StaticCallInstr* call,
124 MethodRecognizer::Kind recognized_kind);
125 bool TryInlineFloat32x4Method(InstanceCallInstr* call,
126 MethodRecognizer::Kind recognized_kind);
127 bool TryInlineFloat64x2Method(InstanceCallInstr* call,
128 MethodRecognizer::Kind recognized_kind);
129 bool TryInlineInt32x4Method(InstanceCallInstr* call,
130 MethodRecognizer::Kind recognized_kind);
131 void ReplaceWithInstanceOf(InstanceCallInstr* instr);
132 bool TypeCheckAsClassEquality(const AbstractType& type);
133 void ReplaceWithTypeCast(InstanceCallInstr* instr);
134
135 bool TryReplaceInstanceCallWithInline(InstanceCallInstr* call);
136
137 Definition* PrepareInlineStringIndexOp(Instruction* call,
138 intptr_t cid,
139 Definition* str,
140 Definition* index,
141 Instruction* cursor);
142
143 bool InlineStringCodeUnitAt(Instruction* call,
144 intptr_t cid,
145 TargetEntryInstr** entry,
146 Definition** last);
147
148 bool InlineStringBaseCharAt(Instruction* call,
149 intptr_t cid,
150 TargetEntryInstr** entry,
151 Definition** last);
152
153 bool InlineDoubleOp(Token::Kind op_kind,
154 Instruction* call,
155 TargetEntryInstr** entry,
156 Definition** last);
157
158 bool InlineByteArrayViewLoad(Instruction* call,
159 Definition* receiver,
160 intptr_t array_cid,
161 intptr_t view_cid,
162 const ICData& ic_data,
163 TargetEntryInstr** entry,
164 Definition** last);
165
166 bool InlineByteArrayViewStore(const Function& target,
167 Instruction* call,
168 Definition* receiver,
169 intptr_t array_cid,
170 intptr_t view_cid,
171 const ICData& ic_data,
172 TargetEntryInstr** entry,
173 Definition** last);
174
175 intptr_t PrepareInlineByteArrayViewOp(Instruction* call,
176 intptr_t array_cid,
177 intptr_t view_cid,
178 Definition** array,
179 Definition* index,
180 Instruction** cursor);
181
182 bool BuildByteArrayViewLoad(InstanceCallInstr* call,
183 intptr_t view_cid);
184 bool BuildByteArrayViewStore(InstanceCallInstr* call,
185 intptr_t view_cid);
186
187 // Insert a check of 'to_check' determined by 'unary_checks'. If the
188 // check fails it will deoptimize to 'deopt_id' using the deoptimization
189 // environment 'deopt_environment'. The check is inserted immediately
190 // before 'insert_before'.
191 void AddCheckClass(Definition* to_check,
192 const ICData& unary_checks,
193 intptr_t deopt_id,
194 Environment* deopt_environment,
195 Instruction* insert_before);
196 Instruction* GetCheckClass(Definition* to_check,
197 const ICData& unary_checks,
198 intptr_t deopt_id,
199 intptr_t token_pos);
200
201 // Insert a Smi check if needed.
202 void AddCheckSmi(Definition* to_check,
203 intptr_t deopt_id,
204 Environment* deopt_environment,
205 Instruction* insert_before);
206
207 // Add a class check for a call's first argument immediately before the
208 // call, using the call's IC data to determine the check, and the call's
209 // deopt ID and deoptimization environment if the check fails.
210 void AddReceiverCheck(InstanceCallInstr* call);
211
212 void ReplaceCall(Definition* call, Definition* replacement);
213
214 void InsertConversionsFor(Definition* def);
215
216 void ConvertUse(Value* use, Representation from);
217 void ConvertEnvironmentUse(Value* use, Representation from);
218
219 void InsertConversion(Representation from,
220 Representation to,
221 Value* use,
222 bool is_environment_use);
223
224 bool InstanceCallNeedsClassCheck(InstanceCallInstr* call,
225 RawFunction::Kind kind) const;
226
227 bool InlineFloat32x4Getter(InstanceCallInstr* call,
228 MethodRecognizer::Kind getter);
229 bool InlineFloat64x2Getter(InstanceCallInstr* call,
230 MethodRecognizer::Kind getter);
231 bool InlineInt32x4Getter(InstanceCallInstr* call,
232 MethodRecognizer::Kind getter);
233 bool InlineFloat32x4BinaryOp(InstanceCallInstr* call,
234 Token::Kind op_kind);
235 bool InlineInt32x4BinaryOp(InstanceCallInstr* call,
236 Token::Kind op_kind);
237 bool InlineFloat64x2BinaryOp(InstanceCallInstr* call,
238 Token::Kind op_kind);
239 void InlineImplicitInstanceGetter(InstanceCallInstr* call);
240
241 RawBool* InstanceOfAsBool(const ICData& ic_data,
242 const AbstractType& type,
243 ZoneGrowableArray<intptr_t>* results) const;
244
245 void ReplaceWithMathCFunction(InstanceCallInstr* call,
246 MethodRecognizer::Kind recognized_kind);
247
248 void OptimizeLeftShiftBitAndSmiOp(Definition* bit_and_instr,
249 Definition* left_instr,
250 Definition* right_instr);
251 void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);
252 void TryMergeMathUnary(GrowableArray<MathUnaryInstr*>* merge_candidates);
253
254 void AppendLoadIndexedForMerged(Definition* instr, intptr_t ix, intptr_t cid);
255 void AppendExtractNthOutputForMerged(Definition* instr, intptr_t ix,
256 Representation rep, intptr_t cid);
257 bool TryStringLengthOneEquality(InstanceCallInstr* call, Token::Kind op_kind);
258
259 Isolate* isolate() const { return flow_graph_->isolate(); }
260
261 FlowGraph* flow_graph_;
262
263 DISALLOW_COPY_AND_ASSIGN(FlowGraphOptimizer);
264 };
265
266
267 // Loop invariant code motion.
268 class LICM : public ValueObject {
269 public:
270 explicit LICM(FlowGraph* flow_graph);
271
272 void Optimize();
273
274 void OptimisticallySpecializeSmiPhis();
275
276 private:
277 FlowGraph* flow_graph() const { return flow_graph_; }
278
279 void Hoist(ForwardInstructionIterator* it,
280 BlockEntryInstr* pre_header,
281 Instruction* current);
282
283 void TrySpecializeSmiPhi(PhiInstr* phi,
284 BlockEntryInstr* header,
285 BlockEntryInstr* pre_header);
286
287 FlowGraph* const flow_graph_;
288 };
289
290
291 // A simple common subexpression elimination based
292 // on the dominator tree.
293 class DominatorBasedCSE : public AllStatic {
294 public:
295 // Return true, if the optimization changed the flow graph.
296 // False, if nothing changed.
297 static bool Optimize(FlowGraph* graph);
298
299 private:
300 static bool OptimizeRecursive(
301 FlowGraph* graph,
302 BlockEntryInstr* entry,
303 CSEInstructionMap* map);
304 };
305
306
307 class DeadStoreElimination : public AllStatic {
308 public:
309 static void Optimize(FlowGraph* graph);
310 };
311
312
313 class DeadCodeElimination : public AllStatic {
314 public:
315 static void EliminateDeadPhis(FlowGraph* graph);
316 };
317
318
319 // Sparse conditional constant propagation and unreachable code elimination. 13 // Sparse conditional constant propagation and unreachable code elimination.
320 // Assumes that use lists are computed and preserves them. 14 // Assumes that use lists are computed and preserves them.
321 class ConstantPropagator : public FlowGraphVisitor { 15 class ConstantPropagator : public FlowGraphVisitor {
322 public: 16 public:
323 ConstantPropagator(FlowGraph* graph, 17 ConstantPropagator(FlowGraph* graph,
324 const GrowableArray<BlockEntryInstr*>& ignored); 18 const GrowableArray<BlockEntryInstr*>& ignored);
325 19
326 static void Optimize(FlowGraph* graph); 20 static void Optimize(FlowGraph* graph);
327 21
328 // (1) Visit branches to optimize away unreachable blocks discovered by range 22 // (1) Visit branches to optimize away unreachable blocks discovered by range
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 BitVector* reachable_; 80 BitVector* reachable_;
387 81
388 BitVector* marked_phis_; 82 BitVector* marked_phis_;
389 83
390 // Worklists of blocks and definitions. 84 // Worklists of blocks and definitions.
391 GrowableArray<BlockEntryInstr*> block_worklist_; 85 GrowableArray<BlockEntryInstr*> block_worklist_;
392 DefinitionWorklist definition_worklist_; 86 DefinitionWorklist definition_worklist_;
393 }; 87 };
394 88
395 89
396 // Rewrite branches to eliminate materialization of boolean values after
397 // inlining, and to expose other optimizations (e.g., constant folding of
398 // branches, unreachable code elimination).
399 class BranchSimplifier : public AllStatic {
400 public:
401 static void Simplify(FlowGraph* flow_graph);
402
403 // Replace a target entry instruction with a join entry instruction. Does
404 // not update the original target's predecessors to point to the new block
405 // and does not replace the target in already computed block order lists.
406 static JoinEntryInstr* ToJoinEntry(Isolate* isolate,
407 TargetEntryInstr* target);
408
409 private:
410 // Match an instance of the pattern to rewrite. See the implementation
411 // for the patterns that are handled by this pass.
412 static bool Match(JoinEntryInstr* block);
413
414 // Duplicate a branch while replacing its comparison's left and right
415 // inputs.
416 static BranchInstr* CloneBranch(Isolate* isolate,
417 BranchInstr* branch,
418 Value* new_left,
419 Value* new_right);
420 };
421
422
423 // Rewrite diamond control flow patterns that materialize values to use more
424 // efficient branchless code patterns if such are supported on the current
425 // platform.
426 class IfConverter : public AllStatic {
427 public:
428 static void Simplify(FlowGraph* flow_graph);
429 };
430
431
432 class AllocationSinking : public ZoneAllocated {
433 public:
434 explicit AllocationSinking(FlowGraph* flow_graph)
435 : flow_graph_(flow_graph),
436 candidates_(5),
437 materializations_(5) { }
438
439 const GrowableArray<Definition*>& candidates() const {
440 return candidates_;
441 }
442
443 // Find the materialization insterted for the given allocation
444 // at the given exit.
445 MaterializeObjectInstr* MaterializationFor(Definition* alloc,
446 Instruction* exit);
447
448 void Optimize();
449
450 void DetachMaterializations();
451
452 private:
453 // Helper class to collect deoptimization exits that might need to
454 // rematerialize an object: that is either instructions that reference
455 // this object explicitly in their deoptimization environment or
456 // reference some other allocation sinking candidate that points to
457 // this object.
458 class ExitsCollector : public ValueObject {
459 public:
460 ExitsCollector() : exits_(10), worklist_(3) { }
461
462 const GrowableArray<Instruction*>& exits() const { return exits_; }
463
464 void CollectTransitively(Definition* alloc);
465
466 private:
467 // Collect immediate uses of this object in the environments.
468 // If this object is stored into other allocation sinking candidates
469 // put them onto worklist so that CollectTransitively will process them.
470 void Collect(Definition* alloc);
471
472 GrowableArray<Instruction*> exits_;
473 GrowableArray<Definition*> worklist_;
474 };
475
476 void CollectCandidates();
477
478 void NormalizeMaterializations();
479
480 void RemoveUnusedMaterializations();
481
482 void DiscoverFailedCandidates();
483
484 void InsertMaterializations(Definition* alloc);
485
486 void CreateMaterializationAt(
487 Instruction* exit,
488 Definition* alloc,
489 const ZoneGrowableArray<const Object*>& fields);
490
491 void EliminateAllocation(Definition* alloc);
492
493 Isolate* isolate() const { return flow_graph_->isolate(); }
494
495 FlowGraph* flow_graph_;
496
497 GrowableArray<Definition*> candidates_;
498 GrowableArray<MaterializeObjectInstr*> materializations_;
499
500 ExitsCollector exits_collector_;
501 };
502
503
504 // Optimize spill stores inside try-blocks by identifying values that always
505 // contain a single known constant at catch block entry.
506 class TryCatchAnalyzer : public AllStatic {
507 public:
508 static void Optimize(FlowGraph* flow_graph);
509 };
510
511 } // namespace dart 90 } // namespace dart
512 91
513 #endif // VM_FLOW_GRAPH_OPTIMIZER_H_ 92 #endif // VM_CONSTANT_PROPAGATOR_H_
OLDNEW
« no previous file with comments | « runtime/vm/compiler.cc ('k') | runtime/vm/constant_propagator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698