Home | History | Annotate | Download | only in optimizing
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ART_COMPILER_OPTIMIZING_NODES_H_
     18 #define ART_COMPILER_OPTIMIZING_NODES_H_
     19 
     20 #include "locations.h"
     21 #include "offsets.h"
     22 #include "primitive.h"
     23 #include "utils/allocation.h"
     24 #include "utils/arena_bit_vector.h"
     25 #include "utils/growable_array.h"
     26 
     27 namespace art {
     28 
     29 class HBasicBlock;
     30 class HEnvironment;
     31 class HInstruction;
     32 class HIntConstant;
     33 class HGraphVisitor;
     34 class HPhi;
     35 class LiveInterval;
     36 class LocationSummary;
     37 
     38 static const int kDefaultNumberOfBlocks = 8;
     39 static const int kDefaultNumberOfSuccessors = 2;
     40 static const int kDefaultNumberOfPredecessors = 2;
     41 static const int kDefaultNumberOfBackEdges = 1;
     42 
     43 enum IfCondition {
     44   kCondEQ,
     45   kCondNE,
     46   kCondLT,
     47   kCondLE,
     48   kCondGT,
     49   kCondGE,
     50 };
     51 
     52 class HInstructionList {
     53  public:
     54   HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
     55 
     56   void AddInstruction(HInstruction* instruction);
     57   void RemoveInstruction(HInstruction* instruction);
     58 
     59  private:
     60   HInstruction* first_instruction_;
     61   HInstruction* last_instruction_;
     62 
     63   friend class HBasicBlock;
     64   friend class HInstructionIterator;
     65   friend class HBackwardInstructionIterator;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(HInstructionList);
     68 };
     69 
     70 // Control-flow graph of a method. Contains a list of basic blocks.
     71 class HGraph : public ArenaObject {
     72  public:
     73   explicit HGraph(ArenaAllocator* arena)
     74       : arena_(arena),
     75         blocks_(arena, kDefaultNumberOfBlocks),
     76         reverse_post_order_(arena, kDefaultNumberOfBlocks),
     77         maximum_number_of_out_vregs_(0),
     78         number_of_vregs_(0),
     79         number_of_in_vregs_(0),
     80         number_of_temporaries_(0),
     81         current_instruction_id_(0) {}
     82 
     83   ArenaAllocator* GetArena() const { return arena_; }
     84   const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
     85 
     86   HBasicBlock* GetEntryBlock() const { return entry_block_; }
     87   HBasicBlock* GetExitBlock() const { return exit_block_; }
     88 
     89   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
     90   void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
     91 
     92   void AddBlock(HBasicBlock* block);
     93 
     94   void BuildDominatorTree();
     95   void TransformToSSA();
     96   void SimplifyCFG();
     97 
     98   // Find all natural loops in this graph. Aborts computation and returns false
     99   // if one loop is not natural, that is the header does not dominate the back
    100   // edge.
    101   bool FindNaturalLoops() const;
    102 
    103   void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
    104   void SimplifyLoop(HBasicBlock* header);
    105 
    106   int GetNextInstructionId() {
    107     return current_instruction_id_++;
    108   }
    109 
    110   uint16_t GetMaximumNumberOfOutVRegs() const {
    111     return maximum_number_of_out_vregs_;
    112   }
    113 
    114   void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
    115     maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
    116   }
    117 
    118   void UpdateNumberOfTemporaries(size_t count) {
    119     number_of_temporaries_ = std::max(count, number_of_temporaries_);
    120   }
    121 
    122   size_t GetNumberOfTemporaries() const {
    123     return number_of_temporaries_;
    124   }
    125 
    126   void SetNumberOfVRegs(uint16_t number_of_vregs) {
    127     number_of_vregs_ = number_of_vregs;
    128   }
    129 
    130   uint16_t GetNumberOfVRegs() const {
    131     return number_of_vregs_;
    132   }
    133 
    134   void SetNumberOfInVRegs(uint16_t value) {
    135     number_of_in_vregs_ = value;
    136   }
    137 
    138   uint16_t GetNumberOfInVRegs() const {
    139     return number_of_in_vregs_;
    140   }
    141 
    142   uint16_t GetNumberOfLocalVRegs() const {
    143     return number_of_vregs_ - number_of_in_vregs_;
    144   }
    145 
    146   const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
    147     return reverse_post_order_;
    148   }
    149 
    150  private:
    151   HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
    152   void VisitBlockForDominatorTree(HBasicBlock* block,
    153                                   HBasicBlock* predecessor,
    154                                   GrowableArray<size_t>* visits);
    155   void FindBackEdges(ArenaBitVector* visited);
    156   void VisitBlockForBackEdges(HBasicBlock* block,
    157                               ArenaBitVector* visited,
    158                               ArenaBitVector* visiting);
    159   void RemoveDeadBlocks(const ArenaBitVector& visited) const;
    160 
    161   ArenaAllocator* const arena_;
    162 
    163   // List of blocks in insertion order.
    164   GrowableArray<HBasicBlock*> blocks_;
    165 
    166   // List of blocks to perform a reverse post order tree traversal.
    167   GrowableArray<HBasicBlock*> reverse_post_order_;
    168 
    169   HBasicBlock* entry_block_;
    170   HBasicBlock* exit_block_;
    171 
    172   // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
    173   uint16_t maximum_number_of_out_vregs_;
    174 
    175   // The number of virtual registers in this method. Contains the parameters.
    176   uint16_t number_of_vregs_;
    177 
    178   // The number of virtual registers used by parameters of this method.
    179   uint16_t number_of_in_vregs_;
    180 
    181   // The number of temporaries that will be needed for the baseline compiler.
    182   size_t number_of_temporaries_;
    183 
    184   // The current id to assign to a newly added instruction. See HInstruction.id_.
    185   int current_instruction_id_;
    186 
    187   DISALLOW_COPY_AND_ASSIGN(HGraph);
    188 };
    189 
    190 class HLoopInformation : public ArenaObject {
    191  public:
    192   HLoopInformation(HBasicBlock* header, HGraph* graph)
    193       : header_(header),
    194         back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
    195         blocks_(graph->GetArena(), graph->GetBlocks().Size(), false) {}
    196 
    197   HBasicBlock* GetHeader() const {
    198     return header_;
    199   }
    200 
    201   void AddBackEdge(HBasicBlock* back_edge) {
    202     back_edges_.Add(back_edge);
    203   }
    204 
    205   void RemoveBackEdge(HBasicBlock* back_edge) {
    206     back_edges_.Delete(back_edge);
    207   }
    208 
    209   bool IsBackEdge(HBasicBlock* block) {
    210     for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
    211       if (back_edges_.Get(i) == block) return true;
    212     }
    213     return false;
    214   }
    215 
    216   int NumberOfBackEdges() const {
    217     return back_edges_.Size();
    218   }
    219 
    220   HBasicBlock* GetPreHeader() const;
    221 
    222   const GrowableArray<HBasicBlock*>& GetBackEdges() const {
    223     return back_edges_;
    224   }
    225 
    226   void ClearBackEdges() {
    227     back_edges_.Reset();
    228   }
    229 
    230   // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
    231   // that is the header dominates the back edge.
    232   bool Populate();
    233 
    234   // Returns whether this loop information contains `block`.
    235   // Note that this loop information *must* be populated before entering this function.
    236   bool Contains(const HBasicBlock& block) const;
    237 
    238   // Returns whether this loop information is an inner loop of `other`.
    239   // Note that `other` *must* be populated before entering this function.
    240   bool IsIn(const HLoopInformation& other) const;
    241 
    242   const ArenaBitVector& GetBlocks() const { return blocks_; }
    243 
    244  private:
    245   // Internal recursive implementation of `Populate`.
    246   void PopulateRecursive(HBasicBlock* block);
    247 
    248   HBasicBlock* header_;
    249   GrowableArray<HBasicBlock*> back_edges_;
    250   ArenaBitVector blocks_;
    251 
    252   DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
    253 };
    254 
    255 static constexpr size_t kNoLifetime = -1;
    256 
    257 // A block in a method. Contains the list of instructions represented
    258 // as a double linked list. Each block knows its predecessors and
    259 // successors.
    260 class HBasicBlock : public ArenaObject {
    261  public:
    262   explicit HBasicBlock(HGraph* graph)
    263       : graph_(graph),
    264         predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
    265         successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
    266         loop_information_(nullptr),
    267         dominator_(nullptr),
    268         block_id_(-1),
    269         lifetime_start_(kNoLifetime),
    270         lifetime_end_(kNoLifetime) {}
    271 
    272   const GrowableArray<HBasicBlock*>& GetPredecessors() const {
    273     return predecessors_;
    274   }
    275 
    276   const GrowableArray<HBasicBlock*>& GetSuccessors() const {
    277     return successors_;
    278   }
    279 
    280   void AddBackEdge(HBasicBlock* back_edge) {
    281     if (loop_information_ == nullptr) {
    282       loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
    283     }
    284     DCHECK_EQ(loop_information_->GetHeader(), this);
    285     loop_information_->AddBackEdge(back_edge);
    286   }
    287 
    288   HGraph* GetGraph() const { return graph_; }
    289 
    290   int GetBlockId() const { return block_id_; }
    291   void SetBlockId(int id) { block_id_ = id; }
    292 
    293   HBasicBlock* GetDominator() const { return dominator_; }
    294   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
    295 
    296   int NumberOfBackEdges() const {
    297     return loop_information_ == nullptr
    298         ? 0
    299         : loop_information_->NumberOfBackEdges();
    300   }
    301 
    302   HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
    303   HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
    304   const HInstructionList& GetInstructions() const { return instructions_; }
    305   const HInstructionList& GetPhis() const { return phis_; }
    306   HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
    307 
    308   void AddSuccessor(HBasicBlock* block) {
    309     successors_.Add(block);
    310     block->predecessors_.Add(this);
    311   }
    312 
    313   void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
    314     size_t successor_index = GetSuccessorIndexOf(existing);
    315     DCHECK_NE(successor_index, static_cast<size_t>(-1));
    316     existing->RemovePredecessor(this);
    317     new_block->predecessors_.Add(this);
    318     successors_.Put(successor_index, new_block);
    319   }
    320 
    321   void RemovePredecessor(HBasicBlock* block) {
    322     predecessors_.Delete(block);
    323   }
    324 
    325   void ClearAllPredecessors() {
    326     predecessors_.Reset();
    327   }
    328 
    329   void AddPredecessor(HBasicBlock* block) {
    330     predecessors_.Add(block);
    331     block->successors_.Add(this);
    332   }
    333 
    334   size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
    335     for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
    336       if (predecessors_.Get(i) == predecessor) {
    337         return i;
    338       }
    339     }
    340     return -1;
    341   }
    342 
    343   size_t GetSuccessorIndexOf(HBasicBlock* successor) {
    344     for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
    345       if (successors_.Get(i) == successor) {
    346         return i;
    347       }
    348     }
    349     return -1;
    350   }
    351 
    352   void AddInstruction(HInstruction* instruction);
    353   void RemoveInstruction(HInstruction* instruction);
    354   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
    355   void AddPhi(HPhi* phi);
    356   void RemovePhi(HPhi* phi);
    357 
    358   bool IsLoopHeader() const {
    359     return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
    360   }
    361 
    362   HLoopInformation* GetLoopInformation() const {
    363     return loop_information_;
    364   }
    365 
    366   // Set the loop_information_ on this block. This method overrides the current
    367   // loop_information if it is an outer loop of the passed loop information.
    368   void SetInLoop(HLoopInformation* info) {
    369     if (IsLoopHeader()) {
    370       // Nothing to do. This just means `info` is an outer loop.
    371     } else if (loop_information_ == nullptr) {
    372       loop_information_ = info;
    373     } else if (loop_information_->Contains(*info->GetHeader())) {
    374       // Block is currently part of an outer loop. Make it part of this inner loop.
    375       // Note that a non loop header having a loop information means this loop information
    376       // has already been populated
    377       loop_information_ = info;
    378     } else {
    379       // Block is part of an inner loop. Do not update the loop information.
    380       // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
    381       // at this point, because this method is being called while populating `info`.
    382     }
    383   }
    384 
    385   bool IsInLoop() const { return loop_information_ != nullptr; }
    386 
    387   // Returns wheter this block dominates the blocked passed as parameter.
    388   bool Dominates(HBasicBlock* block) const;
    389 
    390   size_t GetLifetimeStart() const { return lifetime_start_; }
    391   size_t GetLifetimeEnd() const { return lifetime_end_; }
    392 
    393   void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
    394   void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
    395 
    396  private:
    397   HGraph* const graph_;
    398   GrowableArray<HBasicBlock*> predecessors_;
    399   GrowableArray<HBasicBlock*> successors_;
    400   HInstructionList instructions_;
    401   HInstructionList phis_;
    402   HLoopInformation* loop_information_;
    403   HBasicBlock* dominator_;
    404   int block_id_;
    405   size_t lifetime_start_;
    406   size_t lifetime_end_;
    407 
    408   DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
    409 };
    410 
    411 #define FOR_EACH_CONCRETE_INSTRUCTION(M)                   \
    412   M(Add)                                                   \
    413   M(Condition)                                             \
    414   M(Equal)                                                 \
    415   M(NotEqual)                                              \
    416   M(LessThan)                                              \
    417   M(LessThanOrEqual)                                       \
    418   M(GreaterThan)                                           \
    419   M(GreaterThanOrEqual)                                    \
    420   M(Exit)                                                  \
    421   M(Goto)                                                  \
    422   M(If)                                                    \
    423   M(IntConstant)                                           \
    424   M(InvokeStatic)                                          \
    425   M(LoadLocal)                                             \
    426   M(Local)                                                 \
    427   M(LongConstant)                                          \
    428   M(NewInstance)                                           \
    429   M(Not)                                                   \
    430   M(ParameterValue)                                        \
    431   M(ParallelMove)                                          \
    432   M(Phi)                                                   \
    433   M(Return)                                                \
    434   M(ReturnVoid)                                            \
    435   M(StoreLocal)                                            \
    436   M(Sub)                                                   \
    437   M(Compare)                                               \
    438   M(InstanceFieldGet)                                      \
    439   M(InstanceFieldSet)                                      \
    440   M(ArrayGet)                                              \
    441   M(ArraySet)                                              \
    442   M(ArrayLength)                                           \
    443   M(BoundsCheck)                                           \
    444   M(NullCheck)                                             \
    445   M(Temporary)                                             \
    446 
    447 #define FOR_EACH_INSTRUCTION(M)                            \
    448   FOR_EACH_CONCRETE_INSTRUCTION(M)                         \
    449   M(Constant)
    450 
    451 #define FORWARD_DECLARATION(type) class H##type;
    452 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
    453 #undef FORWARD_DECLARATION
    454 
    455 #define DECLARE_INSTRUCTION(type)                          \
    456   virtual const char* DebugName() const { return #type; }  \
    457   virtual H##type* As##type() { return this; }             \
    458   virtual void Accept(HGraphVisitor* visitor)              \
    459 
    460 template <typename T>
    461 class HUseListNode : public ArenaObject {
    462  public:
    463   HUseListNode(T* user, size_t index, HUseListNode* tail)
    464       : user_(user), index_(index), tail_(tail) {}
    465 
    466   HUseListNode* GetTail() const { return tail_; }
    467   T* GetUser() const { return user_; }
    468   size_t GetIndex() const { return index_; }
    469 
    470   void SetTail(HUseListNode<T>* node) { tail_ = node; }
    471 
    472  private:
    473   T* const user_;
    474   const size_t index_;
    475   HUseListNode<T>* tail_;
    476 
    477   DISALLOW_COPY_AND_ASSIGN(HUseListNode);
    478 };
    479 
    480 class HInstruction : public ArenaObject {
    481  public:
    482   HInstruction()
    483       : previous_(nullptr),
    484         next_(nullptr),
    485         block_(nullptr),
    486         id_(-1),
    487         ssa_index_(-1),
    488         uses_(nullptr),
    489         env_uses_(nullptr),
    490         environment_(nullptr),
    491         locations_(nullptr),
    492         live_interval_(nullptr),
    493         lifetime_position_(kNoLifetime) {}
    494 
    495   virtual ~HInstruction() {}
    496 
    497   HInstruction* GetNext() const { return next_; }
    498   HInstruction* GetPrevious() const { return previous_; }
    499 
    500   HBasicBlock* GetBlock() const { return block_; }
    501   void SetBlock(HBasicBlock* block) { block_ = block; }
    502   bool IsInBlock() const { return block_ != nullptr; }
    503   bool IsInLoop() const { return block_->IsInLoop(); }
    504 
    505   virtual size_t InputCount() const  = 0;
    506   virtual HInstruction* InputAt(size_t i) const = 0;
    507 
    508   virtual void Accept(HGraphVisitor* visitor) = 0;
    509   virtual const char* DebugName() const = 0;
    510 
    511   virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
    512   virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
    513 
    514   virtual bool NeedsEnvironment() const { return false; }
    515   virtual bool IsControlFlow() const { return false; }
    516 
    517   void AddUseAt(HInstruction* user, size_t index) {
    518     uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
    519   }
    520 
    521   void AddEnvUseAt(HEnvironment* user, size_t index) {
    522     env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
    523         user, index, env_uses_);
    524   }
    525 
    526   void RemoveUser(HInstruction* user, size_t index);
    527 
    528   HUseListNode<HInstruction>* GetUses() const { return uses_; }
    529   HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
    530 
    531   bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
    532   bool HasEnvironmentUses() const { return env_uses_ != nullptr; }
    533 
    534   size_t NumberOfUses() const {
    535     // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
    536     size_t result = 0;
    537     HUseListNode<HInstruction>* current = uses_;
    538     while (current != nullptr) {
    539       current = current->GetTail();
    540       ++result;
    541     }
    542     return result;
    543   }
    544 
    545   int GetId() const { return id_; }
    546   void SetId(int id) { id_ = id; }
    547 
    548   int GetSsaIndex() const { return ssa_index_; }
    549   void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
    550   bool HasSsaIndex() const { return ssa_index_ != -1; }
    551 
    552   bool HasEnvironment() const { return environment_ != nullptr; }
    553   HEnvironment* GetEnvironment() const { return environment_; }
    554   void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
    555 
    556   LocationSummary* GetLocations() const { return locations_; }
    557   void SetLocations(LocationSummary* locations) { locations_ = locations; }
    558 
    559   void ReplaceWith(HInstruction* instruction);
    560 
    561   bool HasOnlyOneUse() const {
    562     return uses_ != nullptr && uses_->GetTail() == nullptr;
    563   }
    564 
    565 #define INSTRUCTION_TYPE_CHECK(type)                                           \
    566   bool Is##type() { return (As##type() != nullptr); }                          \
    567   virtual H##type* As##type() { return nullptr; }
    568 
    569   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
    570 #undef INSTRUCTION_TYPE_CHECK
    571 
    572   size_t GetLifetimePosition() const { return lifetime_position_; }
    573   void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
    574   LiveInterval* GetLiveInterval() const { return live_interval_; }
    575   void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
    576   bool HasLiveInterval() const { return live_interval_ != nullptr; }
    577 
    578  private:
    579   HInstruction* previous_;
    580   HInstruction* next_;
    581   HBasicBlock* block_;
    582 
    583   // An instruction gets an id when it is added to the graph.
    584   // It reflects creation order. A negative id means the instruction
    585   // has not beed added to the graph.
    586   int id_;
    587 
    588   // When doing liveness analysis, instructions that have uses get an SSA index.
    589   int ssa_index_;
    590 
    591   // List of instructions that have this instruction as input.
    592   HUseListNode<HInstruction>* uses_;
    593 
    594   // List of environments that contain this instruction.
    595   HUseListNode<HEnvironment>* env_uses_;
    596 
    597   HEnvironment* environment_;
    598 
    599   // Set by the code generator.
    600   LocationSummary* locations_;
    601 
    602   // Set by the liveness analysis.
    603   LiveInterval* live_interval_;
    604 
    605   // Set by the liveness analysis, this is the position in a linear
    606   // order of blocks where this instruction's live interval start.
    607   size_t lifetime_position_;
    608 
    609   friend class HBasicBlock;
    610   friend class HInstructionList;
    611 
    612   DISALLOW_COPY_AND_ASSIGN(HInstruction);
    613 };
    614 
    615 template<typename T>
    616 class HUseIterator : public ValueObject {
    617  public:
    618   explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
    619 
    620   bool Done() const { return current_ == nullptr; }
    621 
    622   void Advance() {
    623     DCHECK(!Done());
    624     current_ = current_->GetTail();
    625   }
    626 
    627   HUseListNode<T>* Current() const {
    628     DCHECK(!Done());
    629     return current_;
    630   }
    631 
    632  private:
    633   HUseListNode<T>* current_;
    634 
    635   friend class HValue;
    636 };
    637 
    638 // A HEnvironment object contains the values of virtual registers at a given location.
    639 class HEnvironment : public ArenaObject {
    640  public:
    641   HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
    642     vregs_.SetSize(number_of_vregs);
    643     for (size_t i = 0; i < number_of_vregs; i++) {
    644       vregs_.Put(i, nullptr);
    645     }
    646   }
    647 
    648   void Populate(const GrowableArray<HInstruction*>& env) {
    649     for (size_t i = 0; i < env.Size(); i++) {
    650       HInstruction* instruction = env.Get(i);
    651       vregs_.Put(i, instruction);
    652       if (instruction != nullptr) {
    653         instruction->AddEnvUseAt(this, i);
    654       }
    655     }
    656   }
    657 
    658   void SetRawEnvAt(size_t index, HInstruction* instruction) {
    659     vregs_.Put(index, instruction);
    660   }
    661 
    662   GrowableArray<HInstruction*>* GetVRegs() {
    663     return &vregs_;
    664   }
    665 
    666  private:
    667   GrowableArray<HInstruction*> vregs_;
    668 
    669   DISALLOW_COPY_AND_ASSIGN(HEnvironment);
    670 };
    671 
    672 class HInputIterator : public ValueObject {
    673  public:
    674   explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
    675 
    676   bool Done() const { return index_ == instruction_->InputCount(); }
    677   HInstruction* Current() const { return instruction_->InputAt(index_); }
    678   void Advance() { index_++; }
    679 
    680  private:
    681   HInstruction* instruction_;
    682   size_t index_;
    683 
    684   DISALLOW_COPY_AND_ASSIGN(HInputIterator);
    685 };
    686 
    687 class HInstructionIterator : public ValueObject {
    688  public:
    689   explicit HInstructionIterator(const HInstructionList& instructions)
    690       : instruction_(instructions.first_instruction_) {
    691     next_ = Done() ? nullptr : instruction_->GetNext();
    692   }
    693 
    694   bool Done() const { return instruction_ == nullptr; }
    695   HInstruction* Current() const { return instruction_; }
    696   void Advance() {
    697     instruction_ = next_;
    698     next_ = Done() ? nullptr : instruction_->GetNext();
    699   }
    700 
    701  private:
    702   HInstruction* instruction_;
    703   HInstruction* next_;
    704 
    705   DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
    706 };
    707 
    708 class HBackwardInstructionIterator : public ValueObject {
    709  public:
    710   explicit HBackwardInstructionIterator(const HInstructionList& instructions)
    711       : instruction_(instructions.last_instruction_) {
    712     next_ = Done() ? nullptr : instruction_->GetPrevious();
    713   }
    714 
    715   bool Done() const { return instruction_ == nullptr; }
    716   HInstruction* Current() const { return instruction_; }
    717   void Advance() {
    718     instruction_ = next_;
    719     next_ = Done() ? nullptr : instruction_->GetPrevious();
    720   }
    721 
    722  private:
    723   HInstruction* instruction_;
    724   HInstruction* next_;
    725 
    726   DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
    727 };
    728 
    729 // An embedded container with N elements of type T.  Used (with partial
    730 // specialization for N=0) because embedded arrays cannot have size 0.
    731 template<typename T, intptr_t N>
    732 class EmbeddedArray {
    733  public:
    734   EmbeddedArray() : elements_() {}
    735 
    736   intptr_t GetLength() const { return N; }
    737 
    738   const T& operator[](intptr_t i) const {
    739     DCHECK_LT(i, GetLength());
    740     return elements_[i];
    741   }
    742 
    743   T& operator[](intptr_t i) {
    744     DCHECK_LT(i, GetLength());
    745     return elements_[i];
    746   }
    747 
    748   const T& At(intptr_t i) const {
    749     return (*this)[i];
    750   }
    751 
    752   void SetAt(intptr_t i, const T& val) {
    753     (*this)[i] = val;
    754   }
    755 
    756  private:
    757   T elements_[N];
    758 };
    759 
    760 template<typename T>
    761 class EmbeddedArray<T, 0> {
    762  public:
    763   intptr_t length() const { return 0; }
    764   const T& operator[](intptr_t i) const {
    765     LOG(FATAL) << "Unreachable";
    766     static T sentinel = 0;
    767     return sentinel;
    768   }
    769   T& operator[](intptr_t i) {
    770     LOG(FATAL) << "Unreachable";
    771     static T sentinel = 0;
    772     return sentinel;
    773   }
    774 };
    775 
    776 template<intptr_t N>
    777 class HTemplateInstruction: public HInstruction {
    778  public:
    779   HTemplateInstruction<N>() : inputs_() {}
    780   virtual ~HTemplateInstruction() {}
    781 
    782   virtual size_t InputCount() const { return N; }
    783   virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
    784 
    785  protected:
    786   virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
    787     inputs_[i] = instruction;
    788   }
    789 
    790  private:
    791   EmbeddedArray<HInstruction*, N> inputs_;
    792 
    793   friend class SsaBuilder;
    794 };
    795 
    796 template<intptr_t N>
    797 class HExpression: public HTemplateInstruction<N> {
    798  public:
    799   explicit HExpression<N>(Primitive::Type type) : type_(type) {}
    800   virtual ~HExpression() {}
    801 
    802   virtual Primitive::Type GetType() const { return type_; }
    803 
    804  private:
    805   const Primitive::Type type_;
    806 };
    807 
    808 // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
    809 // instruction that branches to the exit block.
    810 class HReturnVoid : public HTemplateInstruction<0> {
    811  public:
    812   HReturnVoid() {}
    813 
    814   virtual bool IsControlFlow() const { return true; }
    815 
    816   DECLARE_INSTRUCTION(ReturnVoid);
    817 
    818  private:
    819   DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
    820 };
    821 
    822 // Represents dex's RETURN opcodes. A HReturn is a control flow
    823 // instruction that branches to the exit block.
    824 class HReturn : public HTemplateInstruction<1> {
    825  public:
    826   explicit HReturn(HInstruction* value) {
    827     SetRawInputAt(0, value);
    828   }
    829 
    830   virtual bool IsControlFlow() const { return true; }
    831 
    832   DECLARE_INSTRUCTION(Return);
    833 
    834  private:
    835   DISALLOW_COPY_AND_ASSIGN(HReturn);
    836 };
    837 
    838 // The exit instruction is the only instruction of the exit block.
    839 // Instructions aborting the method (HTrow and HReturn) must branch to the
    840 // exit block.
    841 class HExit : public HTemplateInstruction<0> {
    842  public:
    843   HExit() {}
    844 
    845   virtual bool IsControlFlow() const { return true; }
    846 
    847   DECLARE_INSTRUCTION(Exit);
    848 
    849  private:
    850   DISALLOW_COPY_AND_ASSIGN(HExit);
    851 };
    852 
    853 // Jumps from one block to another.
    854 class HGoto : public HTemplateInstruction<0> {
    855  public:
    856   HGoto() {}
    857 
    858   HBasicBlock* GetSuccessor() const {
    859     return GetBlock()->GetSuccessors().Get(0);
    860   }
    861 
    862   virtual bool IsControlFlow() const { return true; }
    863 
    864   DECLARE_INSTRUCTION(Goto);
    865 
    866  private:
    867   DISALLOW_COPY_AND_ASSIGN(HGoto);
    868 };
    869 
    870 
    871 // Conditional branch. A block ending with an HIf instruction must have
    872 // two successors.
    873 class HIf : public HTemplateInstruction<1> {
    874  public:
    875   explicit HIf(HInstruction* input) {
    876     SetRawInputAt(0, input);
    877   }
    878 
    879   HBasicBlock* IfTrueSuccessor() const {
    880     return GetBlock()->GetSuccessors().Get(0);
    881   }
    882 
    883   HBasicBlock* IfFalseSuccessor() const {
    884     return GetBlock()->GetSuccessors().Get(1);
    885   }
    886 
    887   virtual bool IsControlFlow() const { return true; }
    888 
    889   DECLARE_INSTRUCTION(If);
    890 
    891   virtual bool IsIfInstruction() const { return true; }
    892 
    893  private:
    894   DISALLOW_COPY_AND_ASSIGN(HIf);
    895 };
    896 
    897 class HBinaryOperation : public HExpression<2> {
    898  public:
    899   HBinaryOperation(Primitive::Type result_type,
    900                    HInstruction* left,
    901                    HInstruction* right) : HExpression(result_type) {
    902     SetRawInputAt(0, left);
    903     SetRawInputAt(1, right);
    904   }
    905 
    906   HInstruction* GetLeft() const { return InputAt(0); }
    907   HInstruction* GetRight() const { return InputAt(1); }
    908   Primitive::Type GetResultType() const { return GetType(); }
    909 
    910   virtual bool IsCommutative() { return false; }
    911 
    912  private:
    913   DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
    914 };
    915 
    916 class HCondition : public HBinaryOperation {
    917  public:
    918   HCondition(HInstruction* first, HInstruction* second)
    919       : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
    920 
    921   virtual bool IsCommutative() { return true; }
    922   bool NeedsMaterialization() const;
    923 
    924   DECLARE_INSTRUCTION(Condition);
    925 
    926   virtual IfCondition GetCondition() const = 0;
    927 
    928  private:
    929   DISALLOW_COPY_AND_ASSIGN(HCondition);
    930 };
    931 
    932 // Instruction to check if two inputs are equal to each other.
    933 class HEqual : public HCondition {
    934  public:
    935   HEqual(HInstruction* first, HInstruction* second)
    936       : HCondition(first, second) {}
    937 
    938   DECLARE_INSTRUCTION(Equal);
    939 
    940   virtual IfCondition GetCondition() const {
    941     return kCondEQ;
    942   }
    943 
    944  private:
    945   DISALLOW_COPY_AND_ASSIGN(HEqual);
    946 };
    947 
    948 class HNotEqual : public HCondition {
    949  public:
    950   HNotEqual(HInstruction* first, HInstruction* second)
    951       : HCondition(first, second) {}
    952 
    953   DECLARE_INSTRUCTION(NotEqual);
    954 
    955   virtual IfCondition GetCondition() const {
    956     return kCondNE;
    957   }
    958 
    959  private:
    960   DISALLOW_COPY_AND_ASSIGN(HNotEqual);
    961 };
    962 
    963 class HLessThan : public HCondition {
    964  public:
    965   HLessThan(HInstruction* first, HInstruction* second)
    966       : HCondition(first, second) {}
    967 
    968   DECLARE_INSTRUCTION(LessThan);
    969 
    970   virtual IfCondition GetCondition() const {
    971     return kCondLT;
    972   }
    973 
    974  private:
    975   DISALLOW_COPY_AND_ASSIGN(HLessThan);
    976 };
    977 
    978 class HLessThanOrEqual : public HCondition {
    979  public:
    980   HLessThanOrEqual(HInstruction* first, HInstruction* second)
    981       : HCondition(first, second) {}
    982 
    983   DECLARE_INSTRUCTION(LessThanOrEqual);
    984 
    985   virtual IfCondition GetCondition() const {
    986     return kCondLE;
    987   }
    988 
    989  private:
    990   DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
    991 };
    992 
    993 class HGreaterThan : public HCondition {
    994  public:
    995   HGreaterThan(HInstruction* first, HInstruction* second)
    996       : HCondition(first, second) {}
    997 
    998   DECLARE_INSTRUCTION(GreaterThan);
    999 
   1000   virtual IfCondition GetCondition() const {
   1001     return kCondGT;
   1002   }
   1003 
   1004  private:
   1005   DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
   1006 };
   1007 
   1008 class HGreaterThanOrEqual : public HCondition {
   1009  public:
   1010   HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
   1011       : HCondition(first, second) {}
   1012 
   1013   DECLARE_INSTRUCTION(GreaterThanOrEqual);
   1014 
   1015   virtual IfCondition GetCondition() const {
   1016     return kCondGE;
   1017   }
   1018 
   1019  private:
   1020   DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
   1021 };
   1022 
   1023 
   1024 // Instruction to check how two inputs compare to each other.
   1025 // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
   1026 class HCompare : public HBinaryOperation {
   1027  public:
   1028   HCompare(Primitive::Type type, HInstruction* first, HInstruction* second)
   1029       : HBinaryOperation(Primitive::kPrimInt, first, second) {
   1030     DCHECK_EQ(type, first->GetType());
   1031     DCHECK_EQ(type, second->GetType());
   1032   }
   1033 
   1034   DECLARE_INSTRUCTION(Compare);
   1035 
   1036  private:
   1037   DISALLOW_COPY_AND_ASSIGN(HCompare);
   1038 };
   1039 
   1040 // A local in the graph. Corresponds to a Dex register.
   1041 class HLocal : public HTemplateInstruction<0> {
   1042  public:
   1043   explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) {}
   1044 
   1045   DECLARE_INSTRUCTION(Local);
   1046 
   1047   uint16_t GetRegNumber() const { return reg_number_; }
   1048 
   1049  private:
   1050   // The Dex register number.
   1051   const uint16_t reg_number_;
   1052 
   1053   DISALLOW_COPY_AND_ASSIGN(HLocal);
   1054 };
   1055 
   1056 // Load a given local. The local is an input of this instruction.
   1057 class HLoadLocal : public HExpression<1> {
   1058  public:
   1059   explicit HLoadLocal(HLocal* local, Primitive::Type type) : HExpression(type) {
   1060     SetRawInputAt(0, local);
   1061   }
   1062 
   1063   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
   1064 
   1065   DECLARE_INSTRUCTION(LoadLocal);
   1066 
   1067  private:
   1068   DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
   1069 };
   1070 
   1071 // Store a value in a given local. This instruction has two inputs: the value
   1072 // and the local.
   1073 class HStoreLocal : public HTemplateInstruction<2> {
   1074  public:
   1075   HStoreLocal(HLocal* local, HInstruction* value) {
   1076     SetRawInputAt(0, local);
   1077     SetRawInputAt(1, value);
   1078   }
   1079 
   1080   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
   1081 
   1082   DECLARE_INSTRUCTION(StoreLocal);
   1083 
   1084  private:
   1085   DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
   1086 };
   1087 
   1088 class HConstant : public HExpression<0> {
   1089  public:
   1090   explicit HConstant(Primitive::Type type) : HExpression(type) {}
   1091 
   1092   DECLARE_INSTRUCTION(Constant);
   1093 
   1094  private:
   1095   DISALLOW_COPY_AND_ASSIGN(HConstant);
   1096 };
   1097 
   1098 // Constants of the type int. Those can be from Dex instructions, or
   1099 // synthesized (for example with the if-eqz instruction).
   1100 class HIntConstant : public HConstant {
   1101  public:
   1102   explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
   1103 
   1104   int32_t GetValue() const { return value_; }
   1105 
   1106   DECLARE_INSTRUCTION(IntConstant);
   1107 
   1108  private:
   1109   const int32_t value_;
   1110 
   1111   DISALLOW_COPY_AND_ASSIGN(HIntConstant);
   1112 };
   1113 
   1114 class HLongConstant : public HConstant {
   1115  public:
   1116   explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
   1117 
   1118   int64_t GetValue() const { return value_; }
   1119 
   1120   DECLARE_INSTRUCTION(LongConstant);
   1121 
   1122  private:
   1123   const int64_t value_;
   1124 
   1125   DISALLOW_COPY_AND_ASSIGN(HLongConstant);
   1126 };
   1127 
   1128 class HInvoke : public HInstruction {
   1129  public:
   1130   HInvoke(ArenaAllocator* arena,
   1131           uint32_t number_of_arguments,
   1132           Primitive::Type return_type,
   1133           uint32_t dex_pc)
   1134     : inputs_(arena, number_of_arguments),
   1135       return_type_(return_type),
   1136       dex_pc_(dex_pc) {
   1137     inputs_.SetSize(number_of_arguments);
   1138   }
   1139 
   1140   virtual size_t InputCount() const { return inputs_.Size(); }
   1141   virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
   1142 
   1143   // Runtime needs to walk the stack, so Dex -> Dex calls need to
   1144   // know their environment.
   1145   virtual bool NeedsEnvironment() const { return true; }
   1146 
   1147   void SetArgumentAt(size_t index, HInstruction* argument) {
   1148     SetRawInputAt(index, argument);
   1149   }
   1150 
   1151   virtual void SetRawInputAt(size_t index, HInstruction* input) {
   1152     inputs_.Put(index, input);
   1153   }
   1154 
   1155   virtual Primitive::Type GetType() const { return return_type_; }
   1156 
   1157   uint32_t GetDexPc() const { return dex_pc_; }
   1158 
   1159  protected:
   1160   GrowableArray<HInstruction*> inputs_;
   1161   const Primitive::Type return_type_;
   1162   const uint32_t dex_pc_;
   1163 
   1164  private:
   1165   DISALLOW_COPY_AND_ASSIGN(HInvoke);
   1166 };
   1167 
   1168 class HInvokeStatic : public HInvoke {
   1169  public:
   1170   HInvokeStatic(ArenaAllocator* arena,
   1171                 uint32_t number_of_arguments,
   1172                 Primitive::Type return_type,
   1173                 uint32_t dex_pc,
   1174                 uint32_t index_in_dex_cache)
   1175       : HInvoke(arena, number_of_arguments, return_type, dex_pc),
   1176         index_in_dex_cache_(index_in_dex_cache) {}
   1177 
   1178   uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
   1179 
   1180   DECLARE_INSTRUCTION(InvokeStatic);
   1181 
   1182  private:
   1183   const uint32_t index_in_dex_cache_;
   1184 
   1185   DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
   1186 };
   1187 
   1188 class HNewInstance : public HExpression<0> {
   1189  public:
   1190   HNewInstance(uint32_t dex_pc, uint16_t type_index) : HExpression(Primitive::kPrimNot),
   1191     dex_pc_(dex_pc), type_index_(type_index) {}
   1192 
   1193   uint32_t GetDexPc() const { return dex_pc_; }
   1194   uint16_t GetTypeIndex() const { return type_index_; }
   1195 
   1196   // Calls runtime so needs an environment.
   1197   virtual bool NeedsEnvironment() const { return true; }
   1198 
   1199   DECLARE_INSTRUCTION(NewInstance);
   1200 
   1201  private:
   1202   const uint32_t dex_pc_;
   1203   const uint16_t type_index_;
   1204 
   1205   DISALLOW_COPY_AND_ASSIGN(HNewInstance);
   1206 };
   1207 
   1208 class HAdd : public HBinaryOperation {
   1209  public:
   1210   HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
   1211       : HBinaryOperation(result_type, left, right) {}
   1212 
   1213   virtual bool IsCommutative() { return true; }
   1214 
   1215   DECLARE_INSTRUCTION(Add);
   1216 
   1217  private:
   1218   DISALLOW_COPY_AND_ASSIGN(HAdd);
   1219 };
   1220 
   1221 class HSub : public HBinaryOperation {
   1222  public:
   1223   HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
   1224       : HBinaryOperation(result_type, left, right) {}
   1225 
   1226   virtual bool IsCommutative() { return false; }
   1227 
   1228   DECLARE_INSTRUCTION(Sub);
   1229 
   1230  private:
   1231   DISALLOW_COPY_AND_ASSIGN(HSub);
   1232 };
   1233 
   1234 // The value of a parameter in this method. Its location depends on
   1235 // the calling convention.
   1236 class HParameterValue : public HExpression<0> {
   1237  public:
   1238   HParameterValue(uint8_t index, Primitive::Type parameter_type)
   1239       : HExpression(parameter_type), index_(index) {}
   1240 
   1241   uint8_t GetIndex() const { return index_; }
   1242 
   1243   DECLARE_INSTRUCTION(ParameterValue);
   1244 
   1245  private:
   1246   // The index of this parameter in the parameters list. Must be less
   1247   // than HGraph::number_of_in_vregs_;
   1248   const uint8_t index_;
   1249 
   1250   DISALLOW_COPY_AND_ASSIGN(HParameterValue);
   1251 };
   1252 
   1253 class HNot : public HExpression<1> {
   1254  public:
   1255   explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean) {
   1256     SetRawInputAt(0, input);
   1257   }
   1258 
   1259   DECLARE_INSTRUCTION(Not);
   1260 
   1261  private:
   1262   DISALLOW_COPY_AND_ASSIGN(HNot);
   1263 };
   1264 
   1265 class HPhi : public HInstruction {
   1266  public:
   1267   HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
   1268       : inputs_(arena, number_of_inputs),
   1269         reg_number_(reg_number),
   1270         type_(type),
   1271         is_live_(false) {
   1272     inputs_.SetSize(number_of_inputs);
   1273   }
   1274 
   1275   virtual size_t InputCount() const { return inputs_.Size(); }
   1276   virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
   1277 
   1278   virtual void SetRawInputAt(size_t index, HInstruction* input) {
   1279     inputs_.Put(index, input);
   1280   }
   1281 
   1282   void AddInput(HInstruction* input);
   1283 
   1284   virtual Primitive::Type GetType() const { return type_; }
   1285   void SetType(Primitive::Type type) { type_ = type; }
   1286 
   1287   uint32_t GetRegNumber() const { return reg_number_; }
   1288 
   1289   void SetDead() { is_live_ = false; }
   1290   void SetLive() { is_live_ = true; }
   1291   bool IsDead() const { return !is_live_; }
   1292   bool IsLive() const { return is_live_; }
   1293 
   1294   DECLARE_INSTRUCTION(Phi);
   1295 
   1296  private:
   1297   GrowableArray<HInstruction*> inputs_;
   1298   const uint32_t reg_number_;
   1299   Primitive::Type type_;
   1300   bool is_live_;
   1301 
   1302   DISALLOW_COPY_AND_ASSIGN(HPhi);
   1303 };
   1304 
   1305 class HNullCheck : public HExpression<1> {
   1306  public:
   1307   HNullCheck(HInstruction* value, uint32_t dex_pc)
   1308       : HExpression(value->GetType()), dex_pc_(dex_pc) {
   1309     SetRawInputAt(0, value);
   1310   }
   1311 
   1312   virtual bool NeedsEnvironment() const { return true; }
   1313 
   1314   uint32_t GetDexPc() const { return dex_pc_; }
   1315 
   1316   DECLARE_INSTRUCTION(NullCheck);
   1317 
   1318  private:
   1319   const uint32_t dex_pc_;
   1320 
   1321   DISALLOW_COPY_AND_ASSIGN(HNullCheck);
   1322 };
   1323 
   1324 class FieldInfo : public ValueObject {
   1325  public:
   1326   explicit FieldInfo(MemberOffset field_offset)
   1327       : field_offset_(field_offset) {}
   1328 
   1329   MemberOffset GetFieldOffset() const { return field_offset_; }
   1330 
   1331  private:
   1332   const MemberOffset field_offset_;
   1333 };
   1334 
   1335 class HInstanceFieldGet : public HExpression<1> {
   1336  public:
   1337   HInstanceFieldGet(HInstruction* value,
   1338                     Primitive::Type field_type,
   1339                     MemberOffset field_offset)
   1340       : HExpression(field_type), field_info_(field_offset) {
   1341     SetRawInputAt(0, value);
   1342   }
   1343 
   1344   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   1345 
   1346   DECLARE_INSTRUCTION(InstanceFieldGet);
   1347 
   1348  private:
   1349   const FieldInfo field_info_;
   1350 
   1351   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
   1352 };
   1353 
   1354 class HInstanceFieldSet : public HTemplateInstruction<2> {
   1355  public:
   1356   HInstanceFieldSet(HInstruction* object,
   1357                     HInstruction* value,
   1358                     MemberOffset field_offset)
   1359       : field_info_(field_offset) {
   1360     SetRawInputAt(0, object);
   1361     SetRawInputAt(1, value);
   1362   }
   1363 
   1364   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
   1365 
   1366   DECLARE_INSTRUCTION(InstanceFieldSet);
   1367 
   1368  private:
   1369   const FieldInfo field_info_;
   1370 
   1371   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
   1372 };
   1373 
   1374 class HArrayGet : public HExpression<2> {
   1375  public:
   1376   HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
   1377       : HExpression(type) {
   1378     SetRawInputAt(0, array);
   1379     SetRawInputAt(1, index);
   1380   }
   1381 
   1382   DECLARE_INSTRUCTION(ArrayGet);
   1383 
   1384  private:
   1385   DISALLOW_COPY_AND_ASSIGN(HArrayGet);
   1386 };
   1387 
   1388 class HArraySet : public HTemplateInstruction<3> {
   1389  public:
   1390   HArraySet(HInstruction* array,
   1391             HInstruction* index,
   1392             HInstruction* value,
   1393             uint32_t dex_pc) : dex_pc_(dex_pc) {
   1394     SetRawInputAt(0, array);
   1395     SetRawInputAt(1, index);
   1396     SetRawInputAt(2, value);
   1397   }
   1398 
   1399   virtual bool NeedsEnvironment() const {
   1400     // We currently always call a runtime method to catch array store
   1401     // exceptions.
   1402     return InputAt(2)->GetType() == Primitive::kPrimNot;
   1403   }
   1404 
   1405   uint32_t GetDexPc() const { return dex_pc_; }
   1406 
   1407   DECLARE_INSTRUCTION(ArraySet);
   1408 
   1409  private:
   1410   const uint32_t dex_pc_;
   1411 
   1412   DISALLOW_COPY_AND_ASSIGN(HArraySet);
   1413 };
   1414 
   1415 class HArrayLength : public HExpression<1> {
   1416  public:
   1417   explicit HArrayLength(HInstruction* array) : HExpression(Primitive::kPrimInt) {
   1418     SetRawInputAt(0, array);
   1419   }
   1420 
   1421   DECLARE_INSTRUCTION(ArrayLength);
   1422 
   1423  private:
   1424   DISALLOW_COPY_AND_ASSIGN(HArrayLength);
   1425 };
   1426 
   1427 class HBoundsCheck : public HExpression<2> {
   1428  public:
   1429   HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
   1430       : HExpression(index->GetType()), dex_pc_(dex_pc) {
   1431     DCHECK(index->GetType() == Primitive::kPrimInt);
   1432     SetRawInputAt(0, index);
   1433     SetRawInputAt(1, length);
   1434   }
   1435 
   1436   virtual bool NeedsEnvironment() const { return true; }
   1437 
   1438   uint32_t GetDexPc() const { return dex_pc_; }
   1439 
   1440   DECLARE_INSTRUCTION(BoundsCheck);
   1441 
   1442  private:
   1443   const uint32_t dex_pc_;
   1444 
   1445   DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
   1446 };
   1447 
   1448 /**
   1449  * Some DEX instructions are folded into multiple HInstructions that need
   1450  * to stay live until the last HInstruction. This class
   1451  * is used as a marker for the baseline compiler to ensure its preceding
   1452  * HInstruction stays live. `index` is the temporary number that is used
   1453  * for knowing the stack offset where to store the instruction.
   1454  */
   1455 class HTemporary : public HTemplateInstruction<0> {
   1456  public:
   1457   explicit HTemporary(size_t index) : index_(index) {}
   1458 
   1459   size_t GetIndex() const { return index_; }
   1460 
   1461   DECLARE_INSTRUCTION(Temporary);
   1462 
   1463  private:
   1464   const size_t index_;
   1465 
   1466   DISALLOW_COPY_AND_ASSIGN(HTemporary);
   1467 };
   1468 
   1469 class MoveOperands : public ArenaObject {
   1470  public:
   1471   MoveOperands(Location source, Location destination)
   1472       : source_(source), destination_(destination) {}
   1473 
   1474   Location GetSource() const { return source_; }
   1475   Location GetDestination() const { return destination_; }
   1476 
   1477   void SetSource(Location value) { source_ = value; }
   1478   void SetDestination(Location value) { destination_ = value; }
   1479 
   1480   // The parallel move resolver marks moves as "in-progress" by clearing the
   1481   // destination (but not the source).
   1482   Location MarkPending() {
   1483     DCHECK(!IsPending());
   1484     Location dest = destination_;
   1485     destination_ = Location::NoLocation();
   1486     return dest;
   1487   }
   1488 
   1489   void ClearPending(Location dest) {
   1490     DCHECK(IsPending());
   1491     destination_ = dest;
   1492   }
   1493 
   1494   bool IsPending() const {
   1495     DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
   1496     return destination_.IsInvalid() && !source_.IsInvalid();
   1497   }
   1498 
   1499   // True if this blocks a move from the given location.
   1500   bool Blocks(Location loc) const {
   1501     return !IsEliminated() && source_.Equals(loc);
   1502   }
   1503 
   1504   // A move is redundant if it's been eliminated, if its source and
   1505   // destination are the same, or if its destination is unneeded.
   1506   bool IsRedundant() const {
   1507     return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
   1508   }
   1509 
   1510   // We clear both operands to indicate move that's been eliminated.
   1511   void Eliminate() {
   1512     source_ = destination_ = Location::NoLocation();
   1513   }
   1514 
   1515   bool IsEliminated() const {
   1516     DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
   1517     return source_.IsInvalid();
   1518   }
   1519 
   1520  private:
   1521   Location source_;
   1522   Location destination_;
   1523 
   1524   DISALLOW_COPY_AND_ASSIGN(MoveOperands);
   1525 };
   1526 
   1527 static constexpr size_t kDefaultNumberOfMoves = 4;
   1528 
   1529 class HParallelMove : public HTemplateInstruction<0> {
   1530  public:
   1531   explicit HParallelMove(ArenaAllocator* arena) : moves_(arena, kDefaultNumberOfMoves) {}
   1532 
   1533   void AddMove(MoveOperands* move) {
   1534     moves_.Add(move);
   1535   }
   1536 
   1537   MoveOperands* MoveOperandsAt(size_t index) const {
   1538     return moves_.Get(index);
   1539   }
   1540 
   1541   size_t NumMoves() const { return moves_.Size(); }
   1542 
   1543   DECLARE_INSTRUCTION(ParallelMove);
   1544 
   1545  private:
   1546   GrowableArray<MoveOperands*> moves_;
   1547 
   1548   DISALLOW_COPY_AND_ASSIGN(HParallelMove);
   1549 };
   1550 
   1551 class HGraphVisitor : public ValueObject {
   1552  public:
   1553   explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
   1554   virtual ~HGraphVisitor() {}
   1555 
   1556   virtual void VisitInstruction(HInstruction* instruction) {}
   1557   virtual void VisitBasicBlock(HBasicBlock* block);
   1558 
   1559   void VisitInsertionOrder();
   1560 
   1561   HGraph* GetGraph() const { return graph_; }
   1562 
   1563   // Visit functions for instruction classes.
   1564 #define DECLARE_VISIT_INSTRUCTION(name)                                        \
   1565   virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
   1566 
   1567   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
   1568 
   1569 #undef DECLARE_VISIT_INSTRUCTION
   1570 
   1571  private:
   1572   HGraph* graph_;
   1573 
   1574   DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
   1575 };
   1576 
   1577 class HInsertionOrderIterator : public ValueObject {
   1578  public:
   1579   explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
   1580 
   1581   bool Done() const { return index_ == graph_.GetBlocks().Size(); }
   1582   HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
   1583   void Advance() { ++index_; }
   1584 
   1585  private:
   1586   const HGraph& graph_;
   1587   size_t index_;
   1588 
   1589   DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
   1590 };
   1591 
   1592 class HReversePostOrderIterator : public ValueObject {
   1593  public:
   1594   explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
   1595 
   1596   bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
   1597   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
   1598   void Advance() { ++index_; }
   1599 
   1600  private:
   1601   const HGraph& graph_;
   1602   size_t index_;
   1603 
   1604   DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
   1605 };
   1606 
   1607 class HPostOrderIterator : public ValueObject {
   1608  public:
   1609   explicit HPostOrderIterator(const HGraph& graph)
   1610       : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
   1611 
   1612   bool Done() const { return index_ == 0; }
   1613   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
   1614   void Advance() { --index_; }
   1615 
   1616  private:
   1617   const HGraph& graph_;
   1618   size_t index_;
   1619 
   1620   DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
   1621 };
   1622 
   1623 }  // namespace art
   1624 
   1625 #endif  // ART_COMPILER_OPTIMIZING_NODES_H_
   1626