// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_H_
#define RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_H_

#if defined(DART_PRECOMPILED_RUNTIME)
#error "AOT runtime should not use compiler sources (including header files)"
#endif  // defined(DART_PRECOMPILED_RUNTIME)

#include <utility>

#include "vm/bit_vector.h"
#include "vm/compiler/backend/dart_calling_conventions.h"
#include "vm/compiler/backend/il.h"
#include "vm/growable_array.h"
#include "vm/hash_map.h"
#include "vm/parser.h"
#include "vm/thread.h"

namespace dart {

class LoopHierarchy;
class VariableLivenessAnalysis;

namespace compiler {
class GraphIntrinsifier;
}

class BlockIterator : public ValueObject {
 public:
  explicit BlockIterator(const GrowableArray<BlockEntryInstr*>& block_order)
      : block_order_(block_order), current_(0) {}

  BlockIterator(const BlockIterator& other)
      : ValueObject(),
        block_order_(other.block_order_),
        current_(other.current_) {}

  void Advance() {
    ASSERT(!Done());
    current_++;
  }

  bool Done() const { return current_ >= block_order_.length(); }

  BlockEntryInstr* Current() const { return block_order_[current_]; }

 private:
  const GrowableArray<BlockEntryInstr*>& block_order_;
  intptr_t current_;
};

struct ConstantAndRepresentation {
  const Object& constant;
  Representation representation;
};

struct ConstantPoolTrait {
  typedef ConstantInstr* Value;
  typedef ConstantAndRepresentation Key;
  typedef ConstantInstr* Pair;

  static Key KeyOf(Pair kv) {
    return ConstantAndRepresentation{kv->value(), kv->representation()};
  }

  static Value ValueOf(Pair kv) { return kv; }

  static inline uword Hash(Key key) {
    if (key.constant.IsSmi()) {
      return Smi::Cast(key.constant).Value();
    }
    if (key.constant.IsDouble()) {
      return static_cast<intptr_t>(bit_cast<int32_t, float>(
          static_cast<float>(Double::Cast(key.constant).value())));
    }
    if (key.constant.IsMint()) {
      return static_cast<intptr_t>(Mint::Cast(key.constant).value());
    }
    if (key.constant.IsString()) {
      return String::Cast(key.constant).Hash();
    }
    return key.constant.GetClassId();
  }

  static inline bool IsKeyEqual(Pair kv, Key key) {
    return (kv->value().ptr() == key.constant.ptr()) &&
           (kv->representation() == key.representation);
  }
};

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.
  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.
  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:
  enum class CompilationMode {
    kUnoptimized,
    kOptimized,
    kIntrinsic,
  };

  FlowGraph(const ParsedFunction& parsed_function,
            GraphEntryInstr* graph_entry,
            intptr_t max_block_id,
            PrologueInfo prologue_info,
            CompilationMode compilation_mode);

  // Function properties.
  const ParsedFunction& parsed_function() const { return parsed_function_; }
  const Function& function() const { return parsed_function_.function(); }

  void Print(const char* phase = "unknown");

  // The number of directly accessable parameters (above the frame pointer).
  // All other parameters can only be indirectly loaded via metadata found in
  // the arguments descriptor.
  intptr_t num_direct_parameters() const { return num_direct_parameters_; }

  // The number of variables (or boxes) which code can load from / store to.
  // The SSA renaming will insert phi's for them (and only them - i.e. there
  // will be no phi insertion for [LocalVariable]s pointing to the expression
  // stack!).
  intptr_t variable_count() const {
    return num_direct_parameters_ + parsed_function_.num_stack_locals();
  }

  // The number of variables during OSR, which may include stack slots
  // that pass in initial contents for the expression stack.
  intptr_t osr_variable_count() const {
    ASSERT(IsCompiledForOsr());
    return variable_count() + graph_entry()->osr_entry()->stack_depth();
  }

  static Representation ParameterRepresentationAt(const Function& function,
                                                  intptr_t index);

  static Representation ReturnRepresentationOf(const Function& function);

  // The number of variables (or boxes) inside the functions frame - meaning
  // below the frame pointer.  This does not include the expression stack.
  intptr_t num_stack_locals() const {
    return parsed_function_.num_stack_locals();
  }

  bool IsIrregexpFunction() const { return function().IsIrregexpFunction(); }

  LocalVariable* SuspendStateVar() const {
    return parsed_function().suspend_state_var();
  }

  intptr_t SuspendStateEnvIndex() const { return EnvIndex(SuspendStateVar()); }

  LocalVariable* CurrentContextVar() const {
    return parsed_function().current_context_var();
  }

  intptr_t CurrentContextEnvIndex() const {
    return EnvIndex(parsed_function().current_context_var());
  }

  intptr_t RawTypeArgumentEnvIndex() const {
    return EnvIndex(parsed_function().RawTypeArgumentsVariable());
  }

  intptr_t ArgumentDescriptorEnvIndex() const {
    return EnvIndex(parsed_function().arg_desc_var());
  }

  intptr_t EnvIndex(const LocalVariable* variable) const {
    ASSERT(!variable->is_captured());
    return num_direct_parameters_ - variable->index().value();
  }

  // Context and :suspend_state variables are never pruned and
  // artificially kept alive.
  bool IsImmortalVariable(intptr_t env_index) const {
    return (env_index == CurrentContextEnvIndex()) ||
           (SuspendStateVar() != nullptr &&
            env_index == SuspendStateEnvIndex());
  }

  // Flow graph orders.
  const GrowableArray<BlockEntryInstr*>& preorder() const { return preorder_; }
  const GrowableArray<BlockEntryInstr*>& postorder() const {
    return postorder_;
  }
  const GrowableArray<BlockEntryInstr*>& reverse_postorder() const {
    return reverse_postorder_;
  }
  const GrowableArray<BlockEntryInstr*>& optimized_block_order() const {
    return optimized_block_order_;
  }

  // In AOT these are guaranteed to be topologically sorted, but not in JIT.
  GrowableArray<BlockEntryInstr*>* CodegenBlockOrder();
  const GrowableArray<BlockEntryInstr*>* CodegenBlockOrder() const;

  // Iterators.
  BlockIterator reverse_postorder_iterator() const {
    return BlockIterator(reverse_postorder());
  }
  BlockIterator postorder_iterator() const {
    return BlockIterator(postorder());
  }

  void EnsureSSATempIndex(Definition* defn, Definition* replacement);

  void ReplaceCurrentInstruction(ForwardInstructionIterator* iterator,
                                 Instruction* current,
                                 Instruction* replacement);

  Instruction* CreateCheckClass(Definition* to_check,
                                const Cids& cids,
                                intptr_t deopt_id,
                                const InstructionSource& source);

  Definition* CreateCheckBound(Definition* length,
                               Definition* index,
                               intptr_t deopt_id);

  void AddExactnessGuard(InstanceCallInstr* call, intptr_t receiver_cid);

  intptr_t current_ssa_temp_index() const { return current_ssa_temp_index_; }
  void set_current_ssa_temp_index(intptr_t index) {
    current_ssa_temp_index_ = index;
  }

  intptr_t max_vreg() const {
    return current_ssa_temp_index() * kMaxLocationCount;
  }

  enum class ToCheck { kNoCheck, kCheckNull, kCheckCid };

  // Uses CHA to determine if the called method can be overridden.
  // Return value indicates that the call needs no check at all,
  // just a null check, or a full class check.
  ToCheck CheckForInstanceCall(InstanceCallInstr* call,
                               UntaggedFunction::Kind kind) const;

  Thread* thread() const { return thread_; }
  Zone* zone() const { return thread()->zone(); }
  IsolateGroup* isolate_group() const { return thread()->isolate_group(); }

  intptr_t max_block_id() const { return max_block_id_; }
  void set_max_block_id(intptr_t id) { max_block_id_ = id; }
  intptr_t allocate_block_id() { return ++max_block_id_; }

  GraphEntryInstr* graph_entry() const { return graph_entry_; }

  ConstantInstr* constant_null() const { return constant_null_; }

  ConstantInstr* constant_dead() const { return constant_dead_; }

  void AllocateSSAIndex(Definition* def) {
    def->set_ssa_temp_index(current_ssa_temp_index_);
    current_ssa_temp_index_++;
  }

  intptr_t InstructionCount() const;

  // Returns the definition for the object from the constant pool if
  // one exists, otherwise returns nullptr.
  ConstantInstr* GetExistingConstant(
      const Object& object,
      Representation representation = kTagged) const;

  // Always returns a definition for the object from the constant pool,
  // allocating one if it doesn't already exist.
  ConstantInstr* GetConstant(const Object& object,
                             Representation representation = kTagged);

  void AddToGraphInitialDefinitions(Definition* defn);
  void AddToInitialDefinitions(BlockEntryWithInitialDefs* entry,
                               Definition* defn);

  // Tries to create a constant definition with the given value which can be
  // used to replace the given operation. Ensures that the representation of
  // the replacement matches the representation of the original definition.
  // If the given value can't be represented using matching representation
  // then returns op itself.
  Definition* TryCreateConstantReplacementFor(Definition* op,
                                              const Object& value);

  // Returns true if the given constant value can be represented in the given
  // representation.
  static bool IsConstantRepresentable(const Object& value,
                                      Representation target_rep,
                                      bool tagged_value_must_be_smi);

  enum UseKind { kEffect, kValue };

  void InsertBefore(Instruction* next,
                    Instruction* instr,
                    Environment* env,
                    UseKind use_kind) {
    InsertAfter(next->previous(), instr, env, use_kind);
  }
  void InsertSpeculativeBefore(Instruction* next,
                               Instruction* instr,
                               Environment* env,
                               UseKind use_kind) {
    InsertSpeculativeAfter(next->previous(), instr, env, use_kind);
  }
  void InsertAfter(Instruction* prev,
                   Instruction* instr,
                   Environment* env,
                   UseKind use_kind);

  // Inserts a speculative [instr] after existing [prev] instruction.
  //
  // If the inserted [instr] deopts eagerly or lazily we will always continue in
  // unoptimized code at before-call using the given [env].
  //
  // This is mainly used during inlining / call specializing when replacing
  // calls with N specialized instructions where the inserted [1..N[
  // instructions cannot continue in unoptimized code after-call since they
  // would miss instructions following the one that lazy-deopted.
  //
  // For example specializing an instance call to an implicit field setter
  //
  //     InstanceCall:<id>(v0, set:<name>, args = [v1])
  //
  // to
  //
  //     v2 <- AssertAssignable:<id>(v1, ...)
  //     StoreField(v0, v2)
  //
  // If the [AssertAssignable] causes a lazy-deopt on return, we'll have to
  // *re-try* the implicit setter call in unoptimized mode, i.e. lazy deopt to
  // before-call (otherwise - if we continued after-call - the
  // StoreField would not be performed).
  void InsertSpeculativeAfter(Instruction* prev,
                              Instruction* instr,
                              Environment* env,
                              UseKind use_kind);
  Instruction* AppendTo(Instruction* prev,
                        Instruction* instr,
                        Environment* env,
                        UseKind use_kind);
  Instruction* AppendSpeculativeTo(Instruction* prev,
                                   Instruction* instr,
                                   Environment* env,
                                   UseKind use_kind);

  // Operations on the flow graph.
  void ComputeSSA(ZoneGrowableArray<Definition*>* inlining_parameters);

  // Verification method for debugging.
  bool VerifyRedefinitions();

  void DiscoverBlocks();

  void MergeBlocks();

  // Insert a redefinition of an original definition after prev and rename all
  // dominated uses of the original.  If an equivalent redefinition is already
  // present, nothing is inserted.
  // Returns the redefinition, if a redefinition was inserted, nullptr
  // otherwise.
  RedefinitionInstr* EnsureRedefinition(Instruction* prev,
                                        Definition* original,
                                        CompileType compile_type);

  // Remove the redefinition instructions inserted to inhibit code motion.
  void RemoveRedefinitions(bool keep_checks = false);

  // Insert MoveArgument instructions and remove explicit def-use
  // relations between calls and their arguments.
  //
  // Compute the maximum number of arguments.
  void InsertMoveArguments();

  // Copy deoptimization target from one instruction to another if we still
  // have to keep deoptimization environment at gotos for LICM purposes.
  void CopyDeoptTarget(Instruction* to, Instruction* from) {
    if (is_licm_allowed()) {
      to->InheritDeoptTarget(zone(), from);
    }
  }

  // Returns true if every Goto in the graph is expected to have a
  // deoptimization environment and can be used as deoptimization target
  // for hoisted instructions.
  bool is_licm_allowed() const { return licm_allowed_; }

  // Stop preserving environments on Goto instructions. LICM is not allowed
  // after this point.
  void disallow_licm() { licm_allowed_ = false; }

  // Returns true if mismatch in input/output representations is allowed.
  bool unmatched_representations_allowed() const {
    return unmatched_representations_allowed_;
  }

  // After the last SelectRepresentations pass all further transformations
  // should maintain matching input/output representations.
  void disallow_unmatched_representations() {
    unmatched_representations_allowed_ = false;
  }

  // Returns true if this flow graph was built for a huge method
  // and certain optimizations should be disabled.
  bool is_huge_method() const { return huge_method_; }
  // Mark this flow graph as huge and disable certain optimizations.
  void mark_huge_method() { huge_method_ = true; }

  PrologueInfo prologue_info() const { return prologue_info_; }

  // Computes the loop hierarchy of the flow graph on demand.
  const LoopHierarchy& GetLoopHierarchy() {
    if (loop_hierarchy_ == nullptr) {
      loop_hierarchy_ = ComputeLoops();
    }
    return loop_hierarchy();
  }

  const LoopHierarchy& loop_hierarchy() const { return *loop_hierarchy_; }

  // Resets the loop hierarchy of the flow graph. Use this to
  // force a recomputation of loop detection by the next call
  // to GetLoopHierarchy() (note that this does not immediately
  // reset the loop_info fields of block entries, although
  // these will be overwritten by that next call).
  void ResetLoopHierarchy() {
    loop_hierarchy_ = nullptr;
    loop_invariant_loads_ = nullptr;
  }

  // Per loop header invariant loads sets. Each set contains load id for
  // those loads that are not affected by anything in the loop and can be
  // hoisted out. Sets are computed by LoadOptimizer.
  ZoneGrowableArray<BitVector*>* loop_invariant_loads() const {
    return loop_invariant_loads_;
  }
  void set_loop_invariant_loads(
      ZoneGrowableArray<BitVector*>* loop_invariant_loads) {
    loop_invariant_loads_ = loop_invariant_loads;
  }

  bool IsCompiledForOsr() const { return graph_entry()->IsCompiledForOsr(); }

  BitVector* captured_parameters() const { return captured_parameters_; }

  intptr_t inlining_id() const { return inlining_id_; }
  void set_inlining_id(intptr_t value) { inlining_id_ = value; }

  // Returns true if any instructions were canonicalized away.
  bool Canonicalize();

  // Attaches new ICData's to static/instance calls which don't already have
  // them.
  void PopulateWithICData(const Function& function);

  void SelectRepresentations();

  void WidenSmiToInt32();

  // Remove environments from the instructions which do not deoptimize.
  void EliminateEnvironments();

  // Extract typed data payloads prior to any LoadIndexed, StoreIndexed, or
  // MemoryCopy instruction where the incoming typed data array(s) are not
  // proven to be internal typed data objects at compile time.
  //
  // Once this is done, no intra-block code motion should be performed.
  void ExtractNonInternalTypedDataPayloads();

  bool IsReceiver(Definition* def) const;

  // Optimize (a << b) & c pattern: if c is a positive Smi or zero, then the
  // shift can be a truncating Smi shift-left and result is always Smi.
  // Merge instructions (only per basic-block).
  void TryOptimizePatterns();

  // Replaces uses that are dominated by dom of 'def' with 'other'.
  // Note: uses that occur at instruction dom itself are not dominated by it.
  static void RenameDominatedUses(Definition* def,
                                  Instruction* dom,
                                  Definition* other);

  // Renames uses of redefined values to make sure that uses of redefined
  // values that are dominated by a redefinition are renamed.
  void RenameUsesDominatedByRedefinitions();

  bool should_print() const { return should_print_; }
  const uint8_t* compiler_pass_filters() const {
    return compiler_pass_filters_;
  }

  bool should_reorder_blocks() const { return should_reorder_blocks_; }

  //
  // High-level utilities.
  //

  // Logical-AND (for use in short-circuit diamond).
  struct LogicalAnd {
    LogicalAnd(ComparisonInstr* x, ComparisonInstr* y) : oper1(x), oper2(y) {}
    ComparisonInstr* oper1;
    ComparisonInstr* oper2;
  };

  // Constructs a diamond control flow at the instruction, inheriting
  // properties from inherit and using the given compare. Returns the
  // join (and true/false blocks in out parameters). Updates dominance
  // relation, but not the succ/pred ordering on block.
  JoinEntryInstr* NewDiamond(Instruction* instruction,
                             Instruction* inherit,
                             ComparisonInstr* compare,
                             TargetEntryInstr** block_true,
                             TargetEntryInstr** block_false);

  // As above, but with a short-circuit on two comparisons.
  JoinEntryInstr* NewDiamond(Instruction* instruction,
                             Instruction* inherit,
                             const LogicalAnd& condition,
                             TargetEntryInstr** block_true,
                             TargetEntryInstr** block_false);

  // Adds a 2-way phi.
  PhiInstr* AddPhi(JoinEntryInstr* join, Definition* d1, Definition* d2);

  // SSA transformation methods and fields.
  void ComputeDominators(GrowableArray<BitVector*>* dominance_frontier);

  void CreateCommonConstants();

  const Array& coverage_array() const { return *coverage_array_; }
  void set_coverage_array(const Array& array) { coverage_array_ = &array; }

  // Renumbers SSA values and basic blocks to make numbering dense.
  // Preserves order among block ids.
  //
  // Also collects definitions which are detached from the flow graph
  // but still referenced (currently only MaterializeObject instructions
  // can be detached).
  void CompactSSA(ZoneGrowableArray<Definition*>* detached_defs = nullptr);

  // Maximum number of word-sized slots needed for outgoing arguments.
  intptr_t max_argument_slot_count() const {
    RELEASE_ASSERT(max_argument_slot_count_ >= 0);
    return max_argument_slot_count_;
  }
  void set_max_argument_slot_count(intptr_t count) {
    RELEASE_ASSERT(max_argument_slot_count_ == -1);
    max_argument_slot_count_ = count;
  }

  const std::pair<Location, Representation>& GetDirectParameterInfoAt(
      intptr_t i) {
    return direct_parameter_locations_[i];
  }

  static intptr_t ComputeLocationsOfFixedParameters(
      Zone* zone,
      const Function& function,
      bool should_assign_stack_locations = false,
      compiler::ParameterInfoArray* parameter_info = nullptr);

  static intptr_t ComputeArgumentsSizeInWords(const Function& function,
                                              intptr_t arguments_count);

  static constexpr CompilationMode CompilationModeFrom(bool is_optimizing) {
    return is_optimizing ? CompilationMode::kOptimized
                         : CompilationMode::kUnoptimized;
  }

  // If either IsExternalPayloadClassId([cid]) or
  // IsExternalPayloadClassId(array()->Type()->ToCid()) is true and
  // [array] (an input of [instr]) is tagged, inserts a load of the array
  // payload as an untagged pointer and rebinds [array] to the new load.
  //
  // Otherwise does not change the flow graph.
  //
  // Returns whether any changes were made to the flow graph.
  bool ExtractExternalUntaggedPayload(Instruction* instr,
                                      Value* array,
                                      classid_t cid);

 private:
  friend class FlowGraphCompiler;  // TODO(ajcbik): restructure
  friend class FlowGraphChecker;
  friend class IfConverter;
  friend class BranchSimplifier;
  friend class ConstantPropagator;
  friend class DeadCodeElimination;
  friend class compiler::GraphIntrinsifier;

  void CompressPath(intptr_t start_index,
                    intptr_t current_index,
                    GrowableArray<intptr_t>* parent,
                    GrowableArray<intptr_t>* label);

  void AddSyntheticPhis(BlockEntryInstr* block);

  void Rename(GrowableArray<PhiInstr*>* live_phis,
              VariableLivenessAnalysis* variable_liveness,
              ZoneGrowableArray<Definition*>* inlining_parameters);
  void RenameRecursive(BlockEntryInstr* block_entry,
                       GrowableArray<Definition*>* env,
                       GrowableArray<PhiInstr*>* live_phis,
                       VariableLivenessAnalysis* variable_liveness,
                       ZoneGrowableArray<Definition*>* inlining_parameters);
#if defined(DEBUG)
  // Validates no phis are missing on join entry instructions.
  void ValidatePhis();
#endif  // defined(DEBUG)

  void PopulateEnvironmentFromFunctionEntry(
      FunctionEntryInstr* function_entry,
      GrowableArray<Definition*>* env,
      GrowableArray<PhiInstr*>* live_phis,
      VariableLivenessAnalysis* variable_liveness,
      ZoneGrowableArray<Definition*>* inlining_parameters);

  void PopulateEnvironmentFromOsrEntry(OsrEntryInstr* osr_entry,
                                       GrowableArray<Definition*>* env);

  void PopulateEnvironmentFromCatchEntry(CatchBlockEntryInstr* catch_entry,
                                         GrowableArray<Definition*>* env);

  void AttachEnvironment(Instruction* instr, GrowableArray<Definition*>* env);

  void InsertPhis(const GrowableArray<BlockEntryInstr*>& preorder,
                  const GrowableArray<BitVector*>& assigned_vars,
                  const GrowableArray<BitVector*>& dom_frontier,
                  GrowableArray<PhiInstr*>* live_phis);

  void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis);

  void ReplacePredecessor(BlockEntryInstr* old_block,
                          BlockEntryInstr* new_block);

  // Finds the blocks in the natural loop for the back edge m->n. The
  // algorithm is described in "Advanced Compiler Design & Implementation"
  // (Muchnick) p192. Returns a BitVector indexed by block pre-order
  // number where each bit indicates membership in the loop.
  BitVector* FindLoopBlocks(BlockEntryInstr* m, BlockEntryInstr* n) const;

  // Finds the natural loops in the flow graph and attaches the loop
  // information to each entry block. Returns the loop hierarchy.
  LoopHierarchy* ComputeLoops() const;

  void InsertConversionsFor(Definition* def);
  void ConvertUse(Value* use, Representation from);
  void InsertConversion(Representation from,
                        Representation to,
                        Value* use,
                        bool is_environment_use);

  // Insert allocation of a record instance for [def]
  // which returns an unboxed record.
  void InsertRecordBoxing(Definition* def);

  void ComputeIsReceiver(PhiInstr* phi) const;
  void ComputeIsReceiverRecursive(PhiInstr* phi,
                                  GrowableArray<PhiInstr*>* unmark) const;

  void OptimizeLeftShiftBitAndSmiOp(
      ForwardInstructionIterator* current_iterator,
      Definition* bit_and_instr,
      Definition* left_instr,
      Definition* right_instr);

  void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates);

  void AppendExtractNthOutputForMerged(Definition* instr,
                                       intptr_t ix,
                                       Representation rep,
                                       intptr_t cid);

  void ExtractUntaggedPayload(Instruction* instr,
                              Value* array,
                              const Slot& slot,
                              InnerPointerAccess access);

  void ExtractNonInternalTypedDataPayload(Instruction* instr,
                                          Value* array,
                                          classid_t cid);

  Thread* thread_;

  // DiscoverBlocks computes parent_ and assigned_vars_ which are then used
  // if/when computing SSA.
  GrowableArray<intptr_t> parent_;

  intptr_t current_ssa_temp_index_;
  intptr_t max_block_id_;

  // Flow graph fields.
  const ParsedFunction& parsed_function_;
  intptr_t num_direct_parameters_;
  compiler::ParameterInfoArray direct_parameter_locations_;
  GraphEntryInstr* graph_entry_;
  GrowableArray<BlockEntryInstr*> preorder_;
  GrowableArray<BlockEntryInstr*> postorder_;
  GrowableArray<BlockEntryInstr*> reverse_postorder_;
  GrowableArray<BlockEntryInstr*> optimized_block_order_;
  ConstantInstr* constant_null_;
  ConstantInstr* constant_dead_;

  bool licm_allowed_;
  bool unmatched_representations_allowed_ = true;
  bool huge_method_ = false;
  const bool should_reorder_blocks_;

  const PrologueInfo prologue_info_;

  // Loop related fields.
  LoopHierarchy* loop_hierarchy_;
  ZoneGrowableArray<BitVector*>* loop_invariant_loads_;

  DirectChainedHashMap<ConstantPoolTrait> constant_instr_pool_;
  BitVector* captured_parameters_;

  intptr_t inlining_id_;
  bool should_print_;
  uint8_t* compiler_pass_filters_ = nullptr;

  intptr_t max_argument_slot_count_ = -1;

  const Array* coverage_array_ = &Array::empty_array();
};

class LivenessAnalysis : public ValueObject {
 public:
  LivenessAnalysis(intptr_t variable_count,
                   const GrowableArray<BlockEntryInstr*>& postorder);

  void Analyze();

  virtual ~LivenessAnalysis() {}

  BitVector* GetLiveInSetAt(intptr_t postorder_number) const {
    return live_in_[postorder_number];
  }

  BitVector* GetLiveOutSetAt(intptr_t postorder_number) const {
    return live_out_[postorder_number];
  }

  BitVector* GetLiveInSet(BlockEntryInstr* block) const {
    return GetLiveInSetAt(block->postorder_number());
  }

  BitVector* GetKillSet(BlockEntryInstr* block) const {
    return kill_[block->postorder_number()];
  }

  BitVector* GetLiveOutSet(BlockEntryInstr* block) const {
    return GetLiveOutSetAt(block->postorder_number());
  }

  // Print results of liveness analysis.
  void Dump();

 protected:
  // Compute initial values for live-out, kill and live-in sets.
  virtual void ComputeInitialSets() = 0;

  // Update live-out set for the given block: live-out should contain
  // all values that are live-in for block's successors.
  // Returns true if live-out set was changed.
  bool UpdateLiveOut(const BlockEntryInstr& instr);

  // Update live-in set for the given block: live-in should contain
  // all values that are live-out from the block and are not defined
  // by this block.
  // Returns true if live-in set was changed.
  bool UpdateLiveIn(const BlockEntryInstr& instr);

  // Perform fix-point iteration updating live-out and live-in sets
  // for blocks until they stop changing.
  void ComputeLiveInAndLiveOutSets();

  Zone* zone() const { return zone_; }

  Zone* zone_;

  const intptr_t variable_count_;

  const GrowableArray<BlockEntryInstr*>& postorder_;

  // Live-out sets for each block.  They contain indices of variables
  // that are live out from this block. That is values that were (1) either
  // defined in this block or live into it, and (2) that are used in some
  // successor block.
  GrowableArray<BitVector*> live_out_;

  // Kill sets for each block.  They contain indices of variables that
  // are defined by this block.
  GrowableArray<BitVector*> kill_;

  // Live-in sets for each block.  They contain indices of variables
  // that are used by this block or its successors.
  GrowableArray<BitVector*> live_in_;
};

class DefinitionWorklist : public ValueObject {
 public:
  DefinitionWorklist(FlowGraph* flow_graph, intptr_t initial_capacity)
      : defs_(initial_capacity),
        contains_vector_(new BitVector(flow_graph->zone(),
                                       flow_graph->current_ssa_temp_index())) {}

  void Add(Definition* defn) {
    if (!Contains(defn)) {
      defs_.Add(defn);
      contains_vector_->Add(defn->ssa_temp_index());
    }
  }

  bool Contains(Definition* defn) const {
    return (defn->ssa_temp_index() >= 0) &&
           contains_vector_->Contains(defn->ssa_temp_index());
  }

  bool IsEmpty() const { return defs_.is_empty(); }

  Definition* RemoveLast() {
    Definition* defn = defs_.RemoveLast();
    contains_vector_->Remove(defn->ssa_temp_index());
    return defn;
  }

  const GrowableArray<Definition*>& definitions() const { return defs_; }
  BitVector* contains_vector() const { return contains_vector_; }

  void Clear() {
    defs_.TruncateTo(0);
    contains_vector_->Clear();
  }

 private:
  GrowableArray<Definition*> defs_;
  BitVector* contains_vector_;
};

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_BACKEND_FLOW_GRAPH_H_
