• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
HInstructionList()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:
HGraph(ArenaAllocator * arena)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 
GetArena()83   ArenaAllocator* GetArena() const { return arena_; }
GetBlocks()84   const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
85 
GetEntryBlock()86   HBasicBlock* GetEntryBlock() const { return entry_block_; }
GetExitBlock()87   HBasicBlock* GetExitBlock() const { return exit_block_; }
88 
SetEntryBlock(HBasicBlock * block)89   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
SetExitBlock(HBasicBlock * 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 
GetNextInstructionId()106   int GetNextInstructionId() {
107     return current_instruction_id_++;
108   }
109 
GetMaximumNumberOfOutVRegs()110   uint16_t GetMaximumNumberOfOutVRegs() const {
111     return maximum_number_of_out_vregs_;
112   }
113 
UpdateMaximumNumberOfOutVRegs(uint16_t new_value)114   void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
115     maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
116   }
117 
UpdateNumberOfTemporaries(size_t count)118   void UpdateNumberOfTemporaries(size_t count) {
119     number_of_temporaries_ = std::max(count, number_of_temporaries_);
120   }
121 
GetNumberOfTemporaries()122   size_t GetNumberOfTemporaries() const {
123     return number_of_temporaries_;
124   }
125 
SetNumberOfVRegs(uint16_t number_of_vregs)126   void SetNumberOfVRegs(uint16_t number_of_vregs) {
127     number_of_vregs_ = number_of_vregs;
128   }
129 
GetNumberOfVRegs()130   uint16_t GetNumberOfVRegs() const {
131     return number_of_vregs_;
132   }
133 
SetNumberOfInVRegs(uint16_t value)134   void SetNumberOfInVRegs(uint16_t value) {
135     number_of_in_vregs_ = value;
136   }
137 
GetNumberOfInVRegs()138   uint16_t GetNumberOfInVRegs() const {
139     return number_of_in_vregs_;
140   }
141 
GetNumberOfLocalVRegs()142   uint16_t GetNumberOfLocalVRegs() const {
143     return number_of_vregs_ - number_of_in_vregs_;
144   }
145 
GetReversePostOrder()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:
HLoopInformation(HBasicBlock * header,HGraph * graph)192   HLoopInformation(HBasicBlock* header, HGraph* graph)
193       : header_(header),
194         back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
195         blocks_(graph->GetArena(), graph->GetBlocks().Size(), false) {}
196 
GetHeader()197   HBasicBlock* GetHeader() const {
198     return header_;
199   }
200 
AddBackEdge(HBasicBlock * back_edge)201   void AddBackEdge(HBasicBlock* back_edge) {
202     back_edges_.Add(back_edge);
203   }
204 
RemoveBackEdge(HBasicBlock * back_edge)205   void RemoveBackEdge(HBasicBlock* back_edge) {
206     back_edges_.Delete(back_edge);
207   }
208 
IsBackEdge(HBasicBlock * block)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 
NumberOfBackEdges()216   int NumberOfBackEdges() const {
217     return back_edges_.Size();
218   }
219 
220   HBasicBlock* GetPreHeader() const;
221 
GetBackEdges()222   const GrowableArray<HBasicBlock*>& GetBackEdges() const {
223     return back_edges_;
224   }
225 
ClearBackEdges()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 
GetBlocks()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:
HBasicBlock(HGraph * graph)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 
GetPredecessors()272   const GrowableArray<HBasicBlock*>& GetPredecessors() const {
273     return predecessors_;
274   }
275 
GetSuccessors()276   const GrowableArray<HBasicBlock*>& GetSuccessors() const {
277     return successors_;
278   }
279 
AddBackEdge(HBasicBlock * back_edge)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 
GetGraph()288   HGraph* GetGraph() const { return graph_; }
289 
GetBlockId()290   int GetBlockId() const { return block_id_; }
SetBlockId(int id)291   void SetBlockId(int id) { block_id_ = id; }
292 
GetDominator()293   HBasicBlock* GetDominator() const { return dominator_; }
SetDominator(HBasicBlock * dominator)294   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
295 
NumberOfBackEdges()296   int NumberOfBackEdges() const {
297     return loop_information_ == nullptr
298         ? 0
299         : loop_information_->NumberOfBackEdges();
300   }
301 
GetFirstInstruction()302   HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
GetLastInstruction()303   HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
GetInstructions()304   const HInstructionList& GetInstructions() const { return instructions_; }
GetPhis()305   const HInstructionList& GetPhis() const { return phis_; }
GetFirstPhi()306   HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
307 
AddSuccessor(HBasicBlock * block)308   void AddSuccessor(HBasicBlock* block) {
309     successors_.Add(block);
310     block->predecessors_.Add(this);
311   }
312 
ReplaceSuccessor(HBasicBlock * existing,HBasicBlock * new_block)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 
RemovePredecessor(HBasicBlock * block)321   void RemovePredecessor(HBasicBlock* block) {
322     predecessors_.Delete(block);
323   }
324 
ClearAllPredecessors()325   void ClearAllPredecessors() {
326     predecessors_.Reset();
327   }
328 
AddPredecessor(HBasicBlock * block)329   void AddPredecessor(HBasicBlock* block) {
330     predecessors_.Add(block);
331     block->successors_.Add(this);
332   }
333 
GetPredecessorIndexOf(HBasicBlock * predecessor)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 
GetSuccessorIndexOf(HBasicBlock * successor)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 
IsLoopHeader()358   bool IsLoopHeader() const {
359     return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
360   }
361 
GetLoopInformation()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.
SetInLoop(HLoopInformation * info)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 
IsInLoop()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 
GetLifetimeStart()390   size_t GetLifetimeStart() const { return lifetime_start_; }
GetLifetimeEnd()391   size_t GetLifetimeEnd() const { return lifetime_end_; }
392 
SetLifetimeStart(size_t start)393   void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
SetLifetimeEnd(size_t end)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;
FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)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:
HInstruction()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 
~HInstruction()495   virtual ~HInstruction() {}
496 
GetNext()497   HInstruction* GetNext() const { return next_; }
GetPrevious()498   HInstruction* GetPrevious() const { return previous_; }
499 
GetBlock()500   HBasicBlock* GetBlock() const { return block_; }
SetBlock(HBasicBlock * block)501   void SetBlock(HBasicBlock* block) { block_ = block; }
IsInBlock()502   bool IsInBlock() const { return block_ != nullptr; }
IsInLoop()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 
GetType()511   virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
512   virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
513 
NeedsEnvironment()514   virtual bool NeedsEnvironment() const { return false; }
IsControlFlow()515   virtual bool IsControlFlow() const { return false; }
516 
AddUseAt(HInstruction * user,size_t index)517   void AddUseAt(HInstruction* user, size_t index) {
518     uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
519   }
520 
AddEnvUseAt(HEnvironment * user,size_t index)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 
GetUses()528   HUseListNode<HInstruction>* GetUses() const { return uses_; }
GetEnvUses()529   HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
530 
HasUses()531   bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
HasEnvironmentUses()532   bool HasEnvironmentUses() const { return env_uses_ != nullptr; }
533 
NumberOfUses()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 
GetId()545   int GetId() const { return id_; }
SetId(int id)546   void SetId(int id) { id_ = id; }
547 
GetSsaIndex()548   int GetSsaIndex() const { return ssa_index_; }
SetSsaIndex(int ssa_index)549   void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
HasSsaIndex()550   bool HasSsaIndex() const { return ssa_index_ != -1; }
551 
HasEnvironment()552   bool HasEnvironment() const { return environment_ != nullptr; }
GetEnvironment()553   HEnvironment* GetEnvironment() const { return environment_; }
SetEnvironment(HEnvironment * environment)554   void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
555 
GetLocations()556   LocationSummary* GetLocations() const { return locations_; }
SetLocations(LocationSummary * locations)557   void SetLocations(LocationSummary* locations) { locations_ = locations; }
558 
559   void ReplaceWith(HInstruction* instruction);
560 
HasOnlyOneUse()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 
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)569   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
570 #undef INSTRUCTION_TYPE_CHECK
571 
572   size_t GetLifetimePosition() const { return lifetime_position_; }
SetLifetimePosition(size_t position)573   void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
GetLiveInterval()574   LiveInterval* GetLiveInterval() const { return live_interval_; }
SetLiveInterval(LiveInterval * interval)575   void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
HasLiveInterval()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:
HUseIterator(HUseListNode<T> * uses)618   explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
619 
Done()620   bool Done() const { return current_ == nullptr; }
621 
Advance()622   void Advance() {
623     DCHECK(!Done());
624     current_ = current_->GetTail();
625   }
626 
Current()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:
HEnvironment(ArenaAllocator * arena,size_t number_of_vregs)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 
Populate(const GrowableArray<HInstruction * > & env)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 
SetRawEnvAt(size_t index,HInstruction * instruction)658   void SetRawEnvAt(size_t index, HInstruction* instruction) {
659     vregs_.Put(index, instruction);
660   }
661 
GetVRegs()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:
HInputIterator(HInstruction * instruction)674   explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
675 
Done()676   bool Done() const { return index_ == instruction_->InputCount(); }
Current()677   HInstruction* Current() const { return instruction_->InputAt(index_); }
Advance()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:
HInstructionIterator(const HInstructionList & instructions)689   explicit HInstructionIterator(const HInstructionList& instructions)
690       : instruction_(instructions.first_instruction_) {
691     next_ = Done() ? nullptr : instruction_->GetNext();
692   }
693 
Done()694   bool Done() const { return instruction_ == nullptr; }
Current()695   HInstruction* Current() const { return instruction_; }
Advance()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:
HBackwardInstructionIterator(const HInstructionList & instructions)710   explicit HBackwardInstructionIterator(const HInstructionList& instructions)
711       : instruction_(instructions.last_instruction_) {
712     next_ = Done() ? nullptr : instruction_->GetPrevious();
713   }
714 
Done()715   bool Done() const { return instruction_ == nullptr; }
Current()716   HInstruction* Current() const { return instruction_; }
Advance()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:
EmbeddedArray()734   EmbeddedArray() : elements_() {}
735 
GetLength()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 
At(intptr_t i)748   const T& At(intptr_t i) const {
749     return (*this)[i];
750   }
751 
SetAt(intptr_t i,const T & val)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:
length()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:
inputs_()779   HTemplateInstruction<N>() : inputs_() {}
~HTemplateInstruction()780   virtual ~HTemplateInstruction() {}
781 
InputCount()782   virtual size_t InputCount() const { return N; }
InputAt(size_t i)783   virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
784 
785  protected:
SetRawInputAt(size_t i,HInstruction * instruction)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:
type_(type)799   explicit HExpression<N>(Primitive::Type type) : type_(type) {}
~HExpression()800   virtual ~HExpression() {}
801 
GetType()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:
HReturnVoid()812   HReturnVoid() {}
813 
IsControlFlow()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:
HReturn(HInstruction * value)826   explicit HReturn(HInstruction* value) {
827     SetRawInputAt(0, value);
828   }
829 
IsControlFlow()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:
HExit()843   HExit() {}
844 
IsControlFlow()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:
HGoto()856   HGoto() {}
857 
GetSuccessor()858   HBasicBlock* GetSuccessor() const {
859     return GetBlock()->GetSuccessors().Get(0);
860   }
861 
IsControlFlow()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:
HIf(HInstruction * input)875   explicit HIf(HInstruction* input) {
876     SetRawInputAt(0, input);
877   }
878 
IfTrueSuccessor()879   HBasicBlock* IfTrueSuccessor() const {
880     return GetBlock()->GetSuccessors().Get(0);
881   }
882 
IfFalseSuccessor()883   HBasicBlock* IfFalseSuccessor() const {
884     return GetBlock()->GetSuccessors().Get(1);
885   }
886 
IsControlFlow()887   virtual bool IsControlFlow() const { return true; }
888 
889   DECLARE_INSTRUCTION(If);
890 
IsIfInstruction()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:
HBinaryOperation(Primitive::Type result_type,HInstruction * left,HInstruction * right)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 
GetLeft()906   HInstruction* GetLeft() const { return InputAt(0); }
GetRight()907   HInstruction* GetRight() const { return InputAt(1); }
GetResultType()908   Primitive::Type GetResultType() const { return GetType(); }
909 
IsCommutative()910   virtual bool IsCommutative() { return false; }
911 
912  private:
913   DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
914 };
915 
916 class HCondition : public HBinaryOperation {
917  public:
HCondition(HInstruction * first,HInstruction * second)918   HCondition(HInstruction* first, HInstruction* second)
919       : HBinaryOperation(Primitive::kPrimBoolean, first, second) {}
920 
IsCommutative()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:
HEqual(HInstruction * first,HInstruction * second)935   HEqual(HInstruction* first, HInstruction* second)
936       : HCondition(first, second) {}
937 
938   DECLARE_INSTRUCTION(Equal);
939 
GetCondition()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:
HNotEqual(HInstruction * first,HInstruction * second)950   HNotEqual(HInstruction* first, HInstruction* second)
951       : HCondition(first, second) {}
952 
953   DECLARE_INSTRUCTION(NotEqual);
954 
GetCondition()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:
HLessThan(HInstruction * first,HInstruction * second)965   HLessThan(HInstruction* first, HInstruction* second)
966       : HCondition(first, second) {}
967 
968   DECLARE_INSTRUCTION(LessThan);
969 
GetCondition()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:
HLessThanOrEqual(HInstruction * first,HInstruction * second)980   HLessThanOrEqual(HInstruction* first, HInstruction* second)
981       : HCondition(first, second) {}
982 
983   DECLARE_INSTRUCTION(LessThanOrEqual);
984 
GetCondition()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:
HGreaterThan(HInstruction * first,HInstruction * second)995   HGreaterThan(HInstruction* first, HInstruction* second)
996       : HCondition(first, second) {}
997 
998   DECLARE_INSTRUCTION(GreaterThan);
999 
GetCondition()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:
HGreaterThanOrEqual(HInstruction * first,HInstruction * second)1010   HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
1011       : HCondition(first, second) {}
1012 
1013   DECLARE_INSTRUCTION(GreaterThanOrEqual);
1014 
GetCondition()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:
HCompare(Primitive::Type type,HInstruction * first,HInstruction * second)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:
HLocal(uint16_t reg_number)1043   explicit HLocal(uint16_t reg_number) : reg_number_(reg_number) {}
1044 
1045   DECLARE_INSTRUCTION(Local);
1046 
GetRegNumber()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:
HLoadLocal(HLocal * local,Primitive::Type type)1059   explicit HLoadLocal(HLocal* local, Primitive::Type type) : HExpression(type) {
1060     SetRawInputAt(0, local);
1061   }
1062 
GetLocal()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:
HStoreLocal(HLocal * local,HInstruction * value)1075   HStoreLocal(HLocal* local, HInstruction* value) {
1076     SetRawInputAt(0, local);
1077     SetRawInputAt(1, value);
1078   }
1079 
GetLocal()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:
HConstant(Primitive::Type type)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:
HIntConstant(int32_t value)1102   explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
1103 
GetValue()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:
HLongConstant(int64_t value)1116   explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
1117 
GetValue()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:
HInvoke(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc)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 
InputCount()1140   virtual size_t InputCount() const { return inputs_.Size(); }
InputAt(size_t i)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.
NeedsEnvironment()1145   virtual bool NeedsEnvironment() const { return true; }
1146 
SetArgumentAt(size_t index,HInstruction * argument)1147   void SetArgumentAt(size_t index, HInstruction* argument) {
1148     SetRawInputAt(index, argument);
1149   }
1150 
SetRawInputAt(size_t index,HInstruction * input)1151   virtual void SetRawInputAt(size_t index, HInstruction* input) {
1152     inputs_.Put(index, input);
1153   }
1154 
GetType()1155   virtual Primitive::Type GetType() const { return return_type_; }
1156 
GetDexPc()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:
HInvokeStatic(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t index_in_dex_cache)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 
GetIndexInDexCache()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:
HNewInstance(uint32_t dex_pc,uint16_t type_index)1190   HNewInstance(uint32_t dex_pc, uint16_t type_index) : HExpression(Primitive::kPrimNot),
1191     dex_pc_(dex_pc), type_index_(type_index) {}
1192 
GetDexPc()1193   uint32_t GetDexPc() const { return dex_pc_; }
GetTypeIndex()1194   uint16_t GetTypeIndex() const { return type_index_; }
1195 
1196   // Calls runtime so needs an environment.
NeedsEnvironment()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:
HAdd(Primitive::Type result_type,HInstruction * left,HInstruction * right)1210   HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1211       : HBinaryOperation(result_type, left, right) {}
1212 
IsCommutative()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:
HSub(Primitive::Type result_type,HInstruction * left,HInstruction * right)1223   HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1224       : HBinaryOperation(result_type, left, right) {}
1225 
IsCommutative()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:
HParameterValue(uint8_t index,Primitive::Type parameter_type)1238   HParameterValue(uint8_t index, Primitive::Type parameter_type)
1239       : HExpression(parameter_type), index_(index) {}
1240 
GetIndex()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:
HNot(HInstruction * input)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:
HPhi(ArenaAllocator * arena,uint32_t reg_number,size_t number_of_inputs,Primitive::Type type)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 
InputCount()1275   virtual size_t InputCount() const { return inputs_.Size(); }
InputAt(size_t i)1276   virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1277 
SetRawInputAt(size_t index,HInstruction * input)1278   virtual void SetRawInputAt(size_t index, HInstruction* input) {
1279     inputs_.Put(index, input);
1280   }
1281 
1282   void AddInput(HInstruction* input);
1283 
GetType()1284   virtual Primitive::Type GetType() const { return type_; }
SetType(Primitive::Type type)1285   void SetType(Primitive::Type type) { type_ = type; }
1286 
GetRegNumber()1287   uint32_t GetRegNumber() const { return reg_number_; }
1288 
SetDead()1289   void SetDead() { is_live_ = false; }
SetLive()1290   void SetLive() { is_live_ = true; }
IsDead()1291   bool IsDead() const { return !is_live_; }
IsLive()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:
HNullCheck(HInstruction * value,uint32_t dex_pc)1307   HNullCheck(HInstruction* value, uint32_t dex_pc)
1308       : HExpression(value->GetType()), dex_pc_(dex_pc) {
1309     SetRawInputAt(0, value);
1310   }
1311 
NeedsEnvironment()1312   virtual bool NeedsEnvironment() const { return true; }
1313 
GetDexPc()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:
FieldInfo(MemberOffset field_offset)1326   explicit FieldInfo(MemberOffset field_offset)
1327       : field_offset_(field_offset) {}
1328 
GetFieldOffset()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:
HInstanceFieldGet(HInstruction * value,Primitive::Type field_type,MemberOffset field_offset)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 
GetFieldOffset()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:
HInstanceFieldSet(HInstruction * object,HInstruction * value,MemberOffset field_offset)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 
GetFieldOffset()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:
HArrayGet(HInstruction * array,HInstruction * index,Primitive::Type type)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:
HArraySet(HInstruction * array,HInstruction * index,HInstruction * value,uint32_t dex_pc)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 
NeedsEnvironment()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 
GetDexPc()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:
HArrayLength(HInstruction * array)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:
HBoundsCheck(HInstruction * index,HInstruction * length,uint32_t dex_pc)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 
NeedsEnvironment()1436   virtual bool NeedsEnvironment() const { return true; }
1437 
GetDexPc()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:
HTemporary(size_t index)1457   explicit HTemporary(size_t index) : index_(index) {}
1458 
GetIndex()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:
MoveOperands(Location source,Location destination)1471   MoveOperands(Location source, Location destination)
1472       : source_(source), destination_(destination) {}
1473 
GetSource()1474   Location GetSource() const { return source_; }
GetDestination()1475   Location GetDestination() const { return destination_; }
1476 
SetSource(Location value)1477   void SetSource(Location value) { source_ = value; }
SetDestination(Location 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).
MarkPending()1482   Location MarkPending() {
1483     DCHECK(!IsPending());
1484     Location dest = destination_;
1485     destination_ = Location::NoLocation();
1486     return dest;
1487   }
1488 
ClearPending(Location dest)1489   void ClearPending(Location dest) {
1490     DCHECK(IsPending());
1491     destination_ = dest;
1492   }
1493 
IsPending()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.
Blocks(Location loc)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.
IsRedundant()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.
Eliminate()1511   void Eliminate() {
1512     source_ = destination_ = Location::NoLocation();
1513   }
1514 
IsEliminated()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:
HParallelMove(ArenaAllocator * arena)1531   explicit HParallelMove(ArenaAllocator* arena) : moves_(arena, kDefaultNumberOfMoves) {}
1532 
AddMove(MoveOperands * move)1533   void AddMove(MoveOperands* move) {
1534     moves_.Add(move);
1535   }
1536 
MoveOperandsAt(size_t index)1537   MoveOperands* MoveOperandsAt(size_t index) const {
1538     return moves_.Get(index);
1539   }
1540 
NumMoves()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:
HGraphVisitor(HGraph * graph)1553   explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
~HGraphVisitor()1554   virtual ~HGraphVisitor() {}
1555 
VisitInstruction(HInstruction * instruction)1556   virtual void VisitInstruction(HInstruction* instruction) {}
1557   virtual void VisitBasicBlock(HBasicBlock* block);
1558 
1559   void VisitInsertionOrder();
1560 
GetGraph()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:
HInsertionOrderIterator(const HGraph & graph)1579   explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1580 
Done()1581   bool Done() const { return index_ == graph_.GetBlocks().Size(); }
Current()1582   HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
Advance()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:
HReversePostOrderIterator(const HGraph & graph)1594   explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
1595 
Done()1596   bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
Current()1597   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Advance()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:
HPostOrderIterator(const HGraph & graph)1609   explicit HPostOrderIterator(const HGraph& graph)
1610       : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
1611 
Done()1612   bool Done() const { return index_ == 0; }
Current()1613   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Advance()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