Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
flow_graph.h
Go to the documentation of this file.
1// Copyright (c) 2013, 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_FLOW_GRAPH_H_
6#define RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_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
12#include <utility>
13
14#include "vm/bit_vector.h"
17#include "vm/growable_array.h"
18#include "vm/hash_map.h"
19#include "vm/parser.h"
20#include "vm/thread.h"
21
22namespace dart {
23
24class LoopHierarchy;
25class VariableLivenessAnalysis;
26
27namespace compiler {
28class GraphIntrinsifier;
29}
30
31class BlockIterator : public ValueObject {
32 public:
34 : block_order_(block_order), current_(0) {}
35
37 : ValueObject(),
38 block_order_(other.block_order_),
39 current_(other.current_) {}
40
41 void Advance() {
42 ASSERT(!Done());
43 current_++;
44 }
45
46 bool Done() const { return current_ >= block_order_.length(); }
47
48 BlockEntryInstr* Current() const { return block_order_[current_]; }
49
50 private:
51 const GrowableArray<BlockEntryInstr*>& block_order_;
52 intptr_t current_;
53};
54
59
64
65 static Key KeyOf(Pair kv) {
66 return ConstantAndRepresentation{kv->value(), kv->representation()};
67 }
68
69 static Value ValueOf(Pair kv) { return kv; }
70
71 static inline uword Hash(Key key) {
72 if (key.constant.IsSmi()) {
73 return Smi::Cast(key.constant).Value();
74 }
75 if (key.constant.IsDouble()) {
76 return static_cast<intptr_t>(bit_cast<int32_t, float>(
77 static_cast<float>(Double::Cast(key.constant).value())));
78 }
79 if (key.constant.IsMint()) {
80 return static_cast<intptr_t>(Mint::Cast(key.constant).value());
81 }
82 if (key.constant.IsString()) {
83 return String::Cast(key.constant).Hash();
84 }
85 return key.constant.GetClassId();
86 }
87
88 static inline bool IsKeyEqual(Pair kv, Key key) {
89 return (kv->value().ptr() == key.constant.ptr()) &&
90 (kv->representation() == key.representation);
91 }
92};
93
95 // The first blockid used for prologue building. This information can be used
96 // by the inliner for budget calculations: The prologue code falls away when
97 // inlining, so we should not include it in the budget.
98 intptr_t min_block_id;
99
100 // The last blockid used for prologue building. This information can be used
101 // by the inliner for budget calculations: The prologue code falls away when
102 // inlining, so we should not include it in the budget.
103 intptr_t max_block_id;
104
105 PrologueInfo(intptr_t min, intptr_t max)
107
108 bool Contains(intptr_t block_id) const {
109 return min_block_id <= block_id && block_id <= max_block_id;
110 }
111};
112
113// Class to encapsulate the construction and manipulation of the flow graph.
114class FlowGraph : public ZoneAllocated {
115 public:
116 enum class CompilationMode {
120 };
121
124 intptr_t max_block_id,
126 CompilationMode compilation_mode);
127
128 // Function properties.
129 const ParsedFunction& parsed_function() const { return parsed_function_; }
130 const Function& function() const { return parsed_function_.function(); }
131
132 void Print(const char* phase = "unknown");
133
134 // The number of directly accessable parameters (above the frame pointer).
135 // All other parameters can only be indirectly loaded via metadata found in
136 // the arguments descriptor.
137 intptr_t num_direct_parameters() const { return num_direct_parameters_; }
138
139 // The number of variables (or boxes) which code can load from / store to.
140 // The SSA renaming will insert phi's for them (and only them - i.e. there
141 // will be no phi insertion for [LocalVariable]s pointing to the expression
142 // stack!).
143 intptr_t variable_count() const {
144 return num_direct_parameters_ + parsed_function_.num_stack_locals();
145 }
146
147 // The number of variables during OSR, which may include stack slots
148 // that pass in initial contents for the expression stack.
149 intptr_t osr_variable_count() const {
152 }
153
155 intptr_t index);
156
158
159 // The number of variables (or boxes) inside the functions frame - meaning
160 // below the frame pointer. This does not include the expression stack.
161 intptr_t num_stack_locals() const {
162 return parsed_function_.num_stack_locals();
163 }
164
165 bool IsIrregexpFunction() const { return function().IsIrregexpFunction(); }
166
170
171 intptr_t SuspendStateEnvIndex() const { return EnvIndex(SuspendStateVar()); }
172
176
177 intptr_t CurrentContextEnvIndex() const {
178 return EnvIndex(parsed_function().current_context_var());
179 }
180
181 intptr_t RawTypeArgumentEnvIndex() const {
182 return EnvIndex(parsed_function().RawTypeArgumentsVariable());
183 }
184
185 intptr_t ArgumentDescriptorEnvIndex() const {
186 return EnvIndex(parsed_function().arg_desc_var());
187 }
188
189 intptr_t EnvIndex(const LocalVariable* variable) const {
190 ASSERT(!variable->is_captured());
191 return num_direct_parameters_ - variable->index().value();
192 }
193
194 // Context and :suspend_state variables are never pruned and
195 // artificially kept alive.
196 bool IsImmortalVariable(intptr_t env_index) const {
197 return (env_index == CurrentContextEnvIndex()) ||
198 (SuspendStateVar() != nullptr &&
199 env_index == SuspendStateEnvIndex());
200 }
201
202 // Flow graph orders.
203 const GrowableArray<BlockEntryInstr*>& preorder() const { return preorder_; }
205 return postorder_;
206 }
208 return reverse_postorder_;
209 }
211 return optimized_block_order_;
212 }
213
214 // In AOT these are guaranteed to be topologically sorted, but not in JIT.
217
218 // Iterators.
225
226 void EnsureSSATempIndex(Definition* defn, Definition* replacement);
227
229 Instruction* current,
230 Instruction* replacement);
231
233 const Cids& cids,
234 intptr_t deopt_id,
236
238 Definition* index,
239 intptr_t deopt_id);
240
241 void AddExactnessGuard(InstanceCallInstr* call, intptr_t receiver_cid);
242
243 intptr_t current_ssa_temp_index() const { return current_ssa_temp_index_; }
244 void set_current_ssa_temp_index(intptr_t index) {
245 current_ssa_temp_index_ = index;
246 }
247
248 intptr_t max_vreg() const {
250 }
251
253
254 // Uses CHA to determine if the called method can be overridden.
255 // Return value indicates that the call needs no check at all,
256 // just a null check, or a full class check.
258 UntaggedFunction::Kind kind) const;
259
260 Thread* thread() const { return thread_; }
261 Zone* zone() const { return thread()->zone(); }
263
264 intptr_t max_block_id() const { return max_block_id_; }
265 void set_max_block_id(intptr_t id) { max_block_id_ = id; }
266 intptr_t allocate_block_id() { return ++max_block_id_; }
267
268 GraphEntryInstr* graph_entry() const { return graph_entry_; }
269
270 ConstantInstr* constant_null() const { return constant_null_; }
271
272 ConstantInstr* constant_dead() const { return constant_dead_; }
273
275 def->set_ssa_temp_index(current_ssa_temp_index_);
276 current_ssa_temp_index_++;
277 }
278
279 intptr_t InstructionCount() const;
280
281 // Returns the definition for the object from the constant pool if
282 // one exists, otherwise returns nullptr.
284 const Object& object,
285 Representation representation = kTagged) const;
286
287 // Always returns a definition for the object from the constant pool,
288 // allocating one if it doesn't already exist.
289 ConstantInstr* GetConstant(const Object& object,
290 Representation representation = kTagged);
291
294 Definition* defn);
295
296 // Tries to create a constant definition with the given value which can be
297 // used to replace the given operation. Ensures that the representation of
298 // the replacement matches the representation of the original definition.
299 // If the given value can't be represented using matching representation
300 // then returns op itself.
302 const Object& value);
303
304 // Returns true if the given constant value can be represented in the given
305 // representation.
306 static bool IsConstantRepresentable(const Object& value,
307 Representation target_rep,
308 bool tagged_value_must_be_smi);
309
311
313 Instruction* instr,
315 UseKind use_kind) {
316 InsertAfter(next->previous(), instr, env, use_kind);
317 }
319 Instruction* instr,
321 UseKind use_kind) {
322 InsertSpeculativeAfter(next->previous(), instr, env, use_kind);
323 }
325 Instruction* instr,
327 UseKind use_kind);
328
329 // Inserts a speculative [instr] after existing [prev] instruction.
330 //
331 // If the inserted [instr] deopts eagerly or lazily we will always continue in
332 // unoptimized code at before-call using the given [env].
333 //
334 // This is mainly used during inlining / call specializing when replacing
335 // calls with N specialized instructions where the inserted [1..N[
336 // instructions cannot continue in unoptimized code after-call since they
337 // would miss instructions following the one that lazy-deopted.
338 //
339 // For example specializing an instance call to an implicit field setter
340 //
341 // InstanceCall:<id>(v0, set:<name>, args = [v1])
342 //
343 // to
344 //
345 // v2 <- AssertAssignable:<id>(v1, ...)
346 // StoreField(v0, v2)
347 //
348 // If the [AssertAssignable] causes a lazy-deopt on return, we'll have to
349 // *re-try* the implicit setter call in unoptimized mode, i.e. lazy deopt to
350 // before-call (otherwise - if we continued after-call - the
351 // StoreField would not be performed).
353 Instruction* instr,
355 UseKind use_kind);
357 Instruction* instr,
359 UseKind use_kind);
361 Instruction* instr,
363 UseKind use_kind);
364
365 // Operations on the flow graph.
366 void ComputeSSA(ZoneGrowableArray<Definition*>* inlining_parameters);
367
368 // Verification method for debugging.
369 bool VerifyRedefinitions();
370
371 void DiscoverBlocks();
372
373 void MergeBlocks();
374
375 // Insert a redefinition of an original definition after prev and rename all
376 // dominated uses of the original. If an equivalent redefinition is already
377 // present, nothing is inserted.
378 // Returns the redefinition, if a redefinition was inserted, nullptr
379 // otherwise.
381 Definition* original,
382 CompileType compile_type);
383
384 // Remove the redefinition instructions inserted to inhibit code motion.
385 void RemoveRedefinitions(bool keep_checks = false);
386
387 // Insert MoveArgument instructions and remove explicit def-use
388 // relations between calls and their arguments.
389 //
390 // Compute the maximum number of arguments.
391 void InsertMoveArguments();
392
393 // Copy deoptimization target from one instruction to another if we still
394 // have to keep deoptimization environment at gotos for LICM purposes.
396 if (is_licm_allowed()) {
397 to->InheritDeoptTarget(zone(), from);
398 }
399 }
400
401 // Returns true if every Goto in the graph is expected to have a
402 // deoptimization environment and can be used as deoptimization target
403 // for hoisted instructions.
404 bool is_licm_allowed() const { return licm_allowed_; }
405
406 // Stop preserving environments on Goto instructions. LICM is not allowed
407 // after this point.
408 void disallow_licm() { licm_allowed_ = false; }
409
410 // Returns true if mismatch in input/output representations is allowed.
412 return unmatched_representations_allowed_;
413 }
414
415 // After the last SelectRepresentations pass all further transformations
416 // should maintain matching input/output representations.
418 unmatched_representations_allowed_ = false;
419 }
420
421 // Returns true if this flow graph was built for a huge method
422 // and certain optimizations should be disabled.
423 bool is_huge_method() const { return huge_method_; }
424 // Mark this flow graph as huge and disable certain optimizations.
425 void mark_huge_method() { huge_method_ = true; }
426
427 PrologueInfo prologue_info() const { return prologue_info_; }
428
429 // Computes the loop hierarchy of the flow graph on demand.
431 if (loop_hierarchy_ == nullptr) {
432 loop_hierarchy_ = ComputeLoops();
433 }
434 return loop_hierarchy();
435 }
436
437 const LoopHierarchy& loop_hierarchy() const { return *loop_hierarchy_; }
438
439 // Resets the loop hierarchy of the flow graph. Use this to
440 // force a recomputation of loop detection by the next call
441 // to GetLoopHierarchy() (note that this does not immediately
442 // reset the loop_info fields of block entries, although
443 // these will be overwritten by that next call).
445 loop_hierarchy_ = nullptr;
446 loop_invariant_loads_ = nullptr;
447 }
448
449 // Per loop header invariant loads sets. Each set contains load id for
450 // those loads that are not affected by anything in the loop and can be
451 // hoisted out. Sets are computed by LoadOptimizer.
453 return loop_invariant_loads_;
454 }
459
460 bool IsCompiledForOsr() const { return graph_entry()->IsCompiledForOsr(); }
461
462 BitVector* captured_parameters() const { return captured_parameters_; }
463
464 intptr_t inlining_id() const { return inlining_id_; }
465 void set_inlining_id(intptr_t value) { inlining_id_ = value; }
466
467 // Returns true if any instructions were canonicalized away.
468 bool Canonicalize();
469
470 // Attaches new ICData's to static/instance calls which don't already have
471 // them.
473
475
476 void WidenSmiToInt32();
477
478 // Remove environments from the instructions which do not deoptimize.
480
481 // Extract typed data payloads prior to any LoadIndexed, StoreIndexed, or
482 // MemoryCopy instruction where the incoming typed data array(s) are not
483 // proven to be internal typed data objects at compile time.
484 //
485 // Once this is done, no intra-block code motion should be performed.
487
488 bool IsReceiver(Definition* def) const;
489
490 // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
491 // shift can be a truncating Smi shift-left and result is always Smi.
492 // Merge instructions (only per basic-block).
493 void TryOptimizePatterns();
494
495 // Replaces uses that are dominated by dom of 'def' with 'other'.
496 // Note: uses that occur at instruction dom itself are not dominated by it.
497 static void RenameDominatedUses(Definition* def,
499 Definition* other);
500
501 // Renames uses of redefined values to make sure that uses of redefined
502 // values that are dominated by a redefinition are renamed.
504
505 bool should_print() const { return should_print_; }
506 const uint8_t* compiler_pass_filters() const {
507 return compiler_pass_filters_;
508 }
509
510 bool should_reorder_blocks() const { return should_reorder_blocks_; }
511
513 return should_remove_all_bounds_checks_;
514 }
515
516 //
517 // High-level utilities.
518 //
519
520 // Logical-AND (for use in short-circuit diamond).
526
527 // Constructs a diamond control flow at the instruction, inheriting
528 // properties from inherit and using the given compare. Returns the
529 // join (and true/false blocks in out parameters). Updates dominance
530 // relation, but not the succ/pred ordering on block.
532 Instruction* inherit,
534 TargetEntryInstr** block_true,
535 TargetEntryInstr** block_false);
536
537 // As above, but with a short-circuit on two comparisons.
539 Instruction* inherit,
540 const LogicalAnd& condition,
541 TargetEntryInstr** block_true,
542 TargetEntryInstr** block_false);
543
544 // Adds a 2-way phi.
546
547 // SSA transformation methods and fields.
548 void ComputeDominators(GrowableArray<BitVector*>* dominance_frontier);
549
551
552 const Array& coverage_array() const { return *coverage_array_; }
553 void set_coverage_array(const Array& array) { coverage_array_ = &array; }
554
555 // Renumbers SSA values and basic blocks to make numbering dense.
556 // Preserves order among block ids.
557 //
558 // Also collects definitions which are detached from the flow graph
559 // but still referenced (currently only MaterializeObject instructions
560 // can be detached).
561 void CompactSSA(ZoneGrowableArray<Definition*>* detached_defs = nullptr);
562
563 // Maximum number of word-sized slots needed for outgoing arguments.
564 intptr_t max_argument_slot_count() const {
565 RELEASE_ASSERT(max_argument_slot_count_ >= 0);
566 return max_argument_slot_count_;
567 }
569 RELEASE_ASSERT(max_argument_slot_count_ == -1);
570 max_argument_slot_count_ = count;
571 }
572
573 const std::pair<Location, Representation>& GetDirectParameterInfoAt(
574 intptr_t i) {
575 return direct_parameter_locations_[i];
576 }
577
578 static intptr_t ComputeLocationsOfFixedParameters(
579 Zone* zone,
580 const Function& function,
581 bool should_assign_stack_locations = false,
582 compiler::ParameterInfoArray* parameter_info = nullptr);
583
584 static intptr_t ComputeArgumentsSizeInWords(const Function& function,
585 intptr_t arguments_count);
586
587 static constexpr CompilationMode CompilationModeFrom(bool is_optimizing) {
588 return is_optimizing ? CompilationMode::kOptimized
590 }
591
592 // If either IsExternalPayloadClassId([cid]) or
593 // IsExternalPayloadClassId(array()->Type()->ToCid()) is true and
594 // [array] (an input of [instr]) is tagged, inserts a load of the array
595 // payload as an untagged pointer and rebinds [array] to the new load.
596 //
597 // Otherwise does not change the flow graph.
598 //
599 // Returns whether any changes were made to the flow graph.
601 Value* array,
602 classid_t cid);
603
604 private:
605 friend class FlowGraphCompiler; // TODO(ajcbik): restructure
606 friend class FlowGraphChecker;
607 friend class IfConverter;
608 friend class BranchSimplifier;
609 friend class ConstantPropagator;
612
613 void CompressPath(intptr_t start_index,
614 intptr_t current_index,
617
618 void AddSyntheticPhis(BlockEntryInstr* block);
619
620 void Rename(GrowableArray<PhiInstr*>* live_phis,
621 VariableLivenessAnalysis* variable_liveness,
622 ZoneGrowableArray<Definition*>* inlining_parameters);
623 void RenameRecursive(BlockEntryInstr* block_entry,
625 GrowableArray<PhiInstr*>* live_phis,
626 VariableLivenessAnalysis* variable_liveness,
627 ZoneGrowableArray<Definition*>* inlining_parameters);
628#if defined(DEBUG)
629 // Validates no phis are missing on join entry instructions.
630 void ValidatePhis();
631#endif // defined(DEBUG)
632
633 void PopulateEnvironmentFromFunctionEntry(
634 FunctionEntryInstr* function_entry,
636 GrowableArray<PhiInstr*>* live_phis,
637 VariableLivenessAnalysis* variable_liveness,
638 ZoneGrowableArray<Definition*>* inlining_parameters);
639
640 void PopulateEnvironmentFromOsrEntry(OsrEntryInstr* osr_entry,
642
643 void PopulateEnvironmentFromCatchEntry(CatchBlockEntryInstr* catch_entry,
645
646 void AttachEnvironment(Instruction* instr, GrowableArray<Definition*>* env);
647
648 void InsertPhis(const GrowableArray<BlockEntryInstr*>& preorder,
649 const GrowableArray<BitVector*>& assigned_vars,
650 const GrowableArray<BitVector*>& dom_frontier,
651 GrowableArray<PhiInstr*>* live_phis);
652
653 void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis);
654
655 void ReplacePredecessor(BlockEntryInstr* old_block,
656 BlockEntryInstr* new_block);
657
658 // Finds the blocks in the natural loop for the back edge m->n. The
659 // algorithm is described in "Advanced Compiler Design & Implementation"
660 // (Muchnick) p192. Returns a BitVector indexed by block pre-order
661 // number where each bit indicates membership in the loop.
662 BitVector* FindLoopBlocks(BlockEntryInstr* m, BlockEntryInstr* n) const;
663
664 // Finds the natural loops in the flow graph and attaches the loop
665 // information to each entry block. Returns the loop hierarchy.
666 LoopHierarchy* ComputeLoops() const;
667
668 void InsertConversionsFor(Definition* def);
669 void ConvertUse(Value* use, Representation from);
670 void InsertConversion(Representation from,
672 Value* use,
673 bool is_environment_use);
674
675 // Insert allocation of a record instance for [def]
676 // which returns an unboxed record.
677 void InsertRecordBoxing(Definition* def);
678
679 void ComputeIsReceiver(PhiInstr* phi) const;
680 void ComputeIsReceiverRecursive(PhiInstr* phi,
681 GrowableArray<PhiInstr*>* unmark) const;
682
683 void OptimizeLeftShiftBitAndSmiOp(
684 ForwardInstructionIterator* current_iterator,
685 Definition* bit_and_instr,
686 Definition* left_instr,
687 Definition* right_instr);
688
689 void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);
690
691 void AppendExtractNthOutputForMerged(Definition* instr,
692 intptr_t ix,
693 Representation rep,
694 intptr_t cid);
695
696 void ExtractUntaggedPayload(Instruction* instr,
697 Value* array,
698 const Slot& slot,
699 InnerPointerAccess access);
700
701 void ExtractNonInternalTypedDataPayload(Instruction* instr,
702 Value* array,
703 classid_t cid);
704
705 Thread* thread_;
706
707 // DiscoverBlocks computes parent_ and assigned_vars_ which are then used
708 // if/when computing SSA.
710
711 intptr_t current_ssa_temp_index_;
712 intptr_t max_block_id_;
713
714 // Flow graph fields.
715 const ParsedFunction& parsed_function_;
716 intptr_t num_direct_parameters_;
717 compiler::ParameterInfoArray direct_parameter_locations_;
718 GraphEntryInstr* graph_entry_;
721 GrowableArray<BlockEntryInstr*> reverse_postorder_;
722 GrowableArray<BlockEntryInstr*> optimized_block_order_;
723 ConstantInstr* constant_null_;
724 ConstantInstr* constant_dead_;
725
726 bool licm_allowed_;
727 bool unmatched_representations_allowed_ = true;
728 bool huge_method_ = false;
729 const bool should_reorder_blocks_;
730
731 const PrologueInfo prologue_info_;
732
733 // Loop related fields.
734 LoopHierarchy* loop_hierarchy_;
735 ZoneGrowableArray<BitVector*>* loop_invariant_loads_;
736
737 DirectChainedHashMap<ConstantPoolTrait> constant_instr_pool_;
738 BitVector* captured_parameters_;
739
740 intptr_t inlining_id_;
741 bool should_print_;
742 const bool should_remove_all_bounds_checks_;
743 uint8_t* compiler_pass_filters_ = nullptr;
744
745 intptr_t max_argument_slot_count_ = -1;
746
747 const Array* coverage_array_ = &Array::empty_array();
748};
749
751 public:
752 LivenessAnalysis(intptr_t variable_count,
753 const GrowableArray<BlockEntryInstr*>& postorder);
754
755 void Analyze();
756
757 virtual ~LivenessAnalysis() {}
758
759 BitVector* GetLiveInSetAt(intptr_t postorder_number) const {
760 return live_in_[postorder_number];
761 }
762
763 BitVector* GetLiveOutSetAt(intptr_t postorder_number) const {
764 return live_out_[postorder_number];
765 }
766
768 return GetLiveInSetAt(block->postorder_number());
769 }
770
772 return kill_[block->postorder_number()];
773 }
774
776 return GetLiveOutSetAt(block->postorder_number());
777 }
778
779 // Print results of liveness analysis.
780 void Dump();
781
782 protected:
783 // Compute initial values for live-out, kill and live-in sets.
784 virtual void ComputeInitialSets() = 0;
785
786 // Update live-out set for the given block: live-out should contain
787 // all values that are live-in for block's successors.
788 // Returns true if live-out set was changed.
789 bool UpdateLiveOut(const BlockEntryInstr& instr);
790
791 // Update live-in set for the given block: live-in should contain
792 // all values that are live-out from the block and are not defined
793 // by this block.
794 // Returns true if live-in set was changed.
795 bool UpdateLiveIn(const BlockEntryInstr& instr);
796
797 // Perform fix-point iteration updating live-out and live-in sets
798 // for blocks until they stop changing.
800
801 Zone* zone() const { return zone_; }
802
804
805 const intptr_t variable_count_;
806
808
809 // Live-out sets for each block. They contain indices of variables
810 // that are live out from this block. That is values that were (1) either
811 // defined in this block or live into it, and (2) that are used in some
812 // successor block.
814
815 // Kill sets for each block. They contain indices of variables that
816 // are defined by this block.
818
819 // Live-in sets for each block. They contain indices of variables
820 // that are used by this block or its successors.
822};
823
825 public:
826 DefinitionWorklist(FlowGraph* flow_graph, intptr_t initial_capacity)
827 : defs_(initial_capacity),
828 contains_vector_(new BitVector(flow_graph->zone(),
829 flow_graph->current_ssa_temp_index())) {}
830
831 void Add(Definition* defn) {
832 if (!Contains(defn)) {
833 defs_.Add(defn);
834 contains_vector_->Add(defn->ssa_temp_index());
835 }
836 }
837
838 bool Contains(Definition* defn) const {
839 return (defn->ssa_temp_index() >= 0) &&
840 contains_vector_->Contains(defn->ssa_temp_index());
841 }
842
843 bool IsEmpty() const { return defs_.is_empty(); }
844
846 Definition* defn = defs_.RemoveLast();
847 contains_vector_->Remove(defn->ssa_temp_index());
848 return defn;
849 }
850
851 const GrowableArray<Definition*>& definitions() const { return defs_; }
852 BitVector* contains_vector() const { return contains_vector_; }
853
854 void Clear() {
855 defs_.TruncateTo(0);
856 contains_vector_->Clear();
857 }
858
859 private:
861 BitVector* contains_vector_;
862};
863
864} // namespace dart
865
866#endif // RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_H_
static bool compare(const SkBitmap &ref, const SkIRect &iref, const SkBitmap &test, const SkIRect &itest)
Definition BlurTest.cpp:100
int count
static float next(float f)
static float prev(float f)
#define RELEASE_ASSERT(cond)
Definition assert.h:327
void Add(intptr_t i)
Definition bit_vector.h:63
bool Contains(intptr_t i) const
Definition bit_vector.h:91
void Remove(intptr_t i)
Definition bit_vector.h:68
intptr_t postorder_number() const
Definition il.h:1652
intptr_t stack_depth() const
Definition il.h:1750
BlockIterator(const GrowableArray< BlockEntryInstr * > &block_order)
Definition flow_graph.h:33
bool Done() const
Definition flow_graph.h:46
BlockEntryInstr * Current() const
Definition flow_graph.h:48
BlockIterator(const BlockIterator &other)
Definition flow_graph.h:36
const Object & value() const
Definition il.h:4212
BitVector * contains_vector() const
Definition flow_graph.h:852
bool Contains(Definition *defn) const
Definition flow_graph.h:838
void Add(Definition *defn)
Definition flow_graph.h:831
Definition * RemoveLast()
Definition flow_graph.h:845
const GrowableArray< Definition * > & definitions() const
Definition flow_graph.h:851
DefinitionWorklist(FlowGraph *flow_graph, intptr_t initial_capacity)
Definition flow_graph.h:826
void set_ssa_temp_index(intptr_t index)
Definition il.h:2486
intptr_t ssa_temp_index() const
Definition il.h:2485
const GrowableArray< BlockEntryInstr * > & reverse_postorder() const
Definition flow_graph.h:207
GraphEntryInstr * graph_entry() const
Definition flow_graph.h:268
ConstantInstr * GetConstant(const Object &object, Representation representation=kTagged)
IsolateGroup * isolate_group() const
Definition flow_graph.h:262
bool should_print() const
Definition flow_graph.h:505
PrologueInfo prologue_info() const
Definition flow_graph.h:427
bool VerifyRedefinitions()
void EnsureSSATempIndex(Definition *defn, Definition *replacement)
Definition flow_graph.cc:95
Instruction * AppendTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
static constexpr CompilationMode CompilationModeFrom(bool is_optimizing)
Definition flow_graph.h:587
void set_coverage_array(const Array &array)
Definition flow_graph.h:553
void CompactSSA(ZoneGrowableArray< Definition * > *detached_defs=nullptr)
intptr_t max_argument_slot_count() const
Definition flow_graph.h:564
bool IsCompiledForOsr() const
Definition flow_graph.h:460
ConstantInstr * constant_dead() const
Definition flow_graph.h:272
ConstantInstr * GetExistingConstant(const Object &object, Representation representation=kTagged) const
Zone * zone() const
Definition flow_graph.h:261
intptr_t current_ssa_temp_index() const
Definition flow_graph.h:243
bool IsReceiver(Definition *def) const
intptr_t ArgumentDescriptorEnvIndex() const
Definition flow_graph.h:185
static Representation ReturnRepresentationOf(const Function &function)
intptr_t inlining_id() const
Definition flow_graph.h:464
const uint8_t * compiler_pass_filters() const
Definition flow_graph.h:506
void ReplaceCurrentInstruction(ForwardInstructionIterator *iterator, Instruction *current, Instruction *replacement)
bool should_remove_all_bounds_checks() const
Definition flow_graph.h:512
JoinEntryInstr * NewDiamond(Instruction *instruction, Instruction *inherit, ComparisonInstr *compare, TargetEntryInstr **block_true, TargetEntryInstr **block_false)
Instruction * AppendSpeculativeTo(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
Thread * thread() const
Definition flow_graph.h:260
intptr_t InstructionCount() const
ToCheck CheckForInstanceCall(InstanceCallInstr *call, UntaggedFunction::Kind kind) const
void RemoveRedefinitions(bool keep_checks=false)
void mark_huge_method()
Definition flow_graph.h:425
bool IsIrregexpFunction() const
Definition flow_graph.h:165
intptr_t SuspendStateEnvIndex() const
Definition flow_graph.h:171
const GrowableArray< BlockEntryInstr * > & preorder() const
Definition flow_graph.h:203
void set_current_ssa_temp_index(intptr_t index)
Definition flow_graph.h:244
void CreateCommonConstants()
void AddExactnessGuard(InstanceCallInstr *call, intptr_t receiver_cid)
const std::pair< Location, Representation > & GetDirectParameterInfoAt(intptr_t i)
Definition flow_graph.h:573
void InsertSpeculativeAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
void set_max_argument_slot_count(intptr_t count)
Definition flow_graph.h:568
void set_loop_invariant_loads(ZoneGrowableArray< BitVector * > *loop_invariant_loads)
Definition flow_graph.h:455
BlockIterator postorder_iterator() const
Definition flow_graph.h:222
Definition * CreateCheckBound(Definition *length, Definition *index, intptr_t deopt_id)
intptr_t max_block_id() const
Definition flow_graph.h:264
const GrowableArray< BlockEntryInstr * > & optimized_block_order() const
Definition flow_graph.h:210
static intptr_t ComputeArgumentsSizeInWords(const Function &function, intptr_t arguments_count)
void InsertMoveArguments()
void Print(const char *phase="unknown")
void DiscoverBlocks()
const GrowableArray< BlockEntryInstr * > & postorder() const
Definition flow_graph.h:204
intptr_t num_stack_locals() const
Definition flow_graph.h:161
void ComputeDominators(GrowableArray< BitVector * > *dominance_frontier)
static Representation ParameterRepresentationAt(const Function &function, intptr_t index)
intptr_t max_vreg() const
Definition flow_graph.h:248
void set_inlining_id(intptr_t value)
Definition flow_graph.h:465
void EliminateEnvironments()
void disallow_unmatched_representations()
Definition flow_graph.h:417
const Array & coverage_array() const
Definition flow_graph.h:552
intptr_t CurrentContextEnvIndex() const
Definition flow_graph.h:177
static intptr_t ComputeLocationsOfFixedParameters(Zone *zone, const Function &function, bool should_assign_stack_locations=false, compiler::ParameterInfoArray *parameter_info=nullptr)
BitVector * captured_parameters() const
Definition flow_graph.h:462
void set_max_block_id(intptr_t id)
Definition flow_graph.h:265
ConstantInstr * constant_null() const
Definition flow_graph.h:270
Instruction * CreateCheckClass(Definition *to_check, const Cids &cids, intptr_t deopt_id, const InstructionSource &source)
const LoopHierarchy & GetLoopHierarchy()
Definition flow_graph.h:430
const Function & function() const
Definition flow_graph.h:130
const ParsedFunction & parsed_function() const
Definition flow_graph.h:129
bool is_huge_method() const
Definition flow_graph.h:423
bool is_licm_allowed() const
Definition flow_graph.h:404
void ResetLoopHierarchy()
Definition flow_graph.h:444
intptr_t num_direct_parameters() const
Definition flow_graph.h:137
ZoneGrowableArray< BitVector * > * loop_invariant_loads() const
Definition flow_graph.h:452
const LoopHierarchy & loop_hierarchy() const
Definition flow_graph.h:437
void RenameUsesDominatedByRedefinitions()
bool unmatched_representations_allowed() const
Definition flow_graph.h:411
Definition * TryCreateConstantReplacementFor(Definition *op, const Object &value)
intptr_t osr_variable_count() const
Definition flow_graph.h:149
void PopulateWithICData(const Function &function)
RedefinitionInstr * EnsureRedefinition(Instruction *prev, Definition *original, CompileType compile_type)
void TryOptimizePatterns()
PhiInstr * AddPhi(JoinEntryInstr *join, Definition *d1, Definition *d2)
void AddToGraphInitialDefinitions(Definition *defn)
bool ExtractExternalUntaggedPayload(Instruction *instr, Value *array, classid_t cid)
void CopyDeoptTarget(Instruction *to, Instruction *from)
Definition flow_graph.h:395
void AllocateSSAIndex(Definition *def)
Definition flow_graph.h:274
static bool IsConstantRepresentable(const Object &value, Representation target_rep, bool tagged_value_must_be_smi)
BlockIterator reverse_postorder_iterator() const
Definition flow_graph.h:219
void ComputeSSA(ZoneGrowableArray< Definition * > *inlining_parameters)
LocalVariable * CurrentContextVar() const
Definition flow_graph.h:173
intptr_t RawTypeArgumentEnvIndex() const
Definition flow_graph.h:181
void InsertBefore(Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
Definition flow_graph.h:312
static void RenameDominatedUses(Definition *def, Instruction *dom, Definition *other)
LocalVariable * SuspendStateVar() const
Definition flow_graph.h:167
friend class FlowGraphChecker
Definition flow_graph.h:606
void SelectRepresentations()
intptr_t variable_count() const
Definition flow_graph.h:143
void AddToInitialDefinitions(BlockEntryWithInitialDefs *entry, Definition *defn)
void ExtractNonInternalTypedDataPayloads()
GrowableArray< BlockEntryInstr * > * CodegenBlockOrder()
intptr_t allocate_block_id()
Definition flow_graph.h:266
void InsertAfter(Instruction *prev, Instruction *instr, Environment *env, UseKind use_kind)
void InsertSpeculativeBefore(Instruction *next, Instruction *instr, Environment *env, UseKind use_kind)
Definition flow_graph.h:318
bool should_reorder_blocks() const
Definition flow_graph.h:510
bool IsImmortalVariable(intptr_t env_index) const
Definition flow_graph.h:196
void disallow_licm()
Definition flow_graph.h:408
intptr_t EnvIndex(const LocalVariable *variable) const
Definition flow_graph.h:189
bool IsIrregexpFunction() const
Definition object.h:3878
bool IsCompiledForOsr() const
Definition il.cc:1255
OsrEntryInstr * osr_entry() const
Definition il.h:1992
void InheritDeoptTarget(Zone *zone, Instruction *other)
Definition il.cc:1560
const intptr_t variable_count_
Definition flow_graph.h:805
virtual ~LivenessAnalysis()
Definition flow_graph.h:757
virtual void ComputeInitialSets()=0
GrowableArray< BitVector * > kill_
Definition flow_graph.h:817
bool UpdateLiveOut(const BlockEntryInstr &instr)
BitVector * GetKillSet(BlockEntryInstr *block) const
Definition flow_graph.h:771
BitVector * GetLiveOutSetAt(intptr_t postorder_number) const
Definition flow_graph.h:763
GrowableArray< BitVector * > live_out_
Definition flow_graph.h:813
Zone * zone() const
Definition flow_graph.h:801
BitVector * GetLiveOutSet(BlockEntryInstr *block) const
Definition flow_graph.h:775
GrowableArray< BitVector * > live_in_
Definition flow_graph.h:821
BitVector * GetLiveInSet(BlockEntryInstr *block) const
Definition flow_graph.h:767
BitVector * GetLiveInSetAt(intptr_t postorder_number) const
Definition flow_graph.h:759
const GrowableArray< BlockEntryInstr * > & postorder_
Definition flow_graph.h:807
bool UpdateLiveIn(const BlockEntryInstr &instr)
VariableIndex index() const
Definition scopes.h:202
bool is_captured() const
Definition scopes.h:143
ObjectPtr ptr() const
Definition object.h:332
const Function & function() const
Definition parser.h:73
int num_stack_locals() const
Definition parser.h:194
LocalVariable * current_context_var() const
Definition parser.h:128
LocalVariable * suspend_state_var() const
Definition parser.h:103
Zone * zone() const
IsolateGroup * isolate_group() const
Definition thread.h:540
int value() const
Definition scopes.h:69
#define ASSERT(E)
SkBitmap source
Definition examples.cpp:28
uint8_t value
static float max(float r, float g, float b)
Definition hsl.cpp:49
static float min(float r, float g, float b)
Definition hsl.cpp:48
size_t length
double y
double x
InnerPointerAccess
Definition il.h:6246
static constexpr intptr_t kMaxLocationCount
Definition locations.h:73
int32_t classid_t
Definition globals.h:524
Representation
Definition locations.h:66
uintptr_t uword
Definition globals.h:501
const intptr_t cid
Definition dom.py:1
Definition __init__.py:1
static Key KeyOf(Pair kv)
Definition flow_graph.h:65
static uword Hash(Key key)
Definition flow_graph.h:71
ConstantInstr * Value
Definition flow_graph.h:61
static bool IsKeyEqual(Pair kv, Key key)
Definition flow_graph.h:88
ConstantAndRepresentation Key
Definition flow_graph.h:62
ConstantInstr * Pair
Definition flow_graph.h:63
static Value ValueOf(Pair kv)
Definition flow_graph.h:69
ComparisonInstr * oper1
Definition flow_graph.h:523
LogicalAnd(ComparisonInstr *x, ComparisonInstr *y)
Definition flow_graph.h:522
ComparisonInstr * oper2
Definition flow_graph.h:524
intptr_t max_block_id
Definition flow_graph.h:103
intptr_t min_block_id
Definition flow_graph.h:98
bool Contains(intptr_t block_id) const
Definition flow_graph.h:108
PrologueInfo(intptr_t min, intptr_t max)
Definition flow_graph.h:105
const uintptr_t id