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 "base/arena_containers.h"
21 #include "base/arena_object.h"
22 #include "dex/compiler_enums.h"
23 #include "entrypoints/quick/quick_entrypoints_enum.h"
24 #include "handle.h"
25 #include "handle_scope.h"
26 #include "invoke_type.h"
27 #include "locations.h"
28 #include "mirror/class.h"
29 #include "offsets.h"
30 #include "primitive.h"
31 #include "utils/arena_bit_vector.h"
32 #include "utils/growable_array.h"
33 
34 namespace art {
35 
36 class GraphChecker;
37 class HBasicBlock;
38 class HDoubleConstant;
39 class HEnvironment;
40 class HFloatConstant;
41 class HGraphVisitor;
42 class HInstruction;
43 class HIntConstant;
44 class HInvoke;
45 class HLongConstant;
46 class HNullConstant;
47 class HPhi;
48 class HSuspendCheck;
49 class LiveInterval;
50 class LocationSummary;
51 class SlowPathCode;
52 class SsaBuilder;
53 
54 static const int kDefaultNumberOfBlocks = 8;
55 static const int kDefaultNumberOfSuccessors = 2;
56 static const int kDefaultNumberOfPredecessors = 2;
57 static const int kDefaultNumberOfDominatedBlocks = 1;
58 static const int kDefaultNumberOfBackEdges = 1;
59 
60 static constexpr uint32_t kMaxIntShiftValue = 0x1f;
61 static constexpr uint64_t kMaxLongShiftValue = 0x3f;
62 
63 enum IfCondition {
64   kCondEQ,
65   kCondNE,
66   kCondLT,
67   kCondLE,
68   kCondGT,
69   kCondGE,
70 };
71 
72 class HInstructionList {
73  public:
HInstructionList()74   HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
75 
76   void AddInstruction(HInstruction* instruction);
77   void RemoveInstruction(HInstruction* instruction);
78 
79   // Insert `instruction` before/after an existing instruction `cursor`.
80   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
81   void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
82 
83   // Return true if this list contains `instruction`.
84   bool Contains(HInstruction* instruction) const;
85 
86   // Return true if `instruction1` is found before `instruction2` in
87   // this instruction list and false otherwise.  Abort if none
88   // of these instructions is found.
89   bool FoundBefore(const HInstruction* instruction1,
90                    const HInstruction* instruction2) const;
91 
IsEmpty()92   bool IsEmpty() const { return first_instruction_ == nullptr; }
Clear()93   void Clear() { first_instruction_ = last_instruction_ = nullptr; }
94 
95   // Update the block of all instructions to be `block`.
96   void SetBlockOfInstructions(HBasicBlock* block) const;
97 
98   void AddAfter(HInstruction* cursor, const HInstructionList& instruction_list);
99   void Add(const HInstructionList& instruction_list);
100 
101   // Return the number of instructions in the list. This is an expensive operation.
102   size_t CountSize() const;
103 
104  private:
105   HInstruction* first_instruction_;
106   HInstruction* last_instruction_;
107 
108   friend class HBasicBlock;
109   friend class HGraph;
110   friend class HInstruction;
111   friend class HInstructionIterator;
112   friend class HBackwardInstructionIterator;
113 
114   DISALLOW_COPY_AND_ASSIGN(HInstructionList);
115 };
116 
117 // Control-flow graph of a method. Contains a list of basic blocks.
118 class HGraph : public ArenaObject<kArenaAllocMisc> {
119  public:
120   HGraph(ArenaAllocator* arena,
121          const DexFile& dex_file,
122          uint32_t method_idx,
123          InstructionSet instruction_set,
124          bool debuggable = false,
125          int start_instruction_id = 0)
arena_(arena)126       : arena_(arena),
127         blocks_(arena, kDefaultNumberOfBlocks),
128         reverse_post_order_(arena, kDefaultNumberOfBlocks),
129         linear_order_(arena, kDefaultNumberOfBlocks),
130         entry_block_(nullptr),
131         exit_block_(nullptr),
132         maximum_number_of_out_vregs_(0),
133         number_of_vregs_(0),
134         number_of_in_vregs_(0),
135         temporaries_vreg_slots_(0),
136         has_bounds_checks_(false),
137         debuggable_(debuggable),
138         current_instruction_id_(start_instruction_id),
139         dex_file_(dex_file),
140         method_idx_(method_idx),
141         instruction_set_(instruction_set),
142         cached_null_constant_(nullptr),
143         cached_int_constants_(std::less<int32_t>(), arena->Adapter()),
144         cached_float_constants_(std::less<int32_t>(), arena->Adapter()),
145         cached_long_constants_(std::less<int64_t>(), arena->Adapter()),
146         cached_double_constants_(std::less<int64_t>(), arena->Adapter()) {}
147 
GetArena()148   ArenaAllocator* GetArena() const { return arena_; }
GetBlocks()149   const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
GetBlock(size_t id)150   HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
151 
GetEntryBlock()152   HBasicBlock* GetEntryBlock() const { return entry_block_; }
GetExitBlock()153   HBasicBlock* GetExitBlock() const { return exit_block_; }
154 
SetEntryBlock(HBasicBlock * block)155   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
SetExitBlock(HBasicBlock * block)156   void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
157 
158   void AddBlock(HBasicBlock* block);
159 
160   // Try building the SSA form of this graph, with dominance computation and loop
161   // recognition. Returns whether it was successful in doing all these steps.
TryBuildingSsa()162   bool TryBuildingSsa() {
163     BuildDominatorTree();
164     // The SSA builder requires loops to all be natural. Specifically, the dead phi
165     // elimination phase checks the consistency of the graph when doing a post-order
166     // visit for eliminating dead phis: a dead phi can only have loop header phi
167     // users remaining when being visited.
168     if (!AnalyzeNaturalLoops()) return false;
169     TransformToSsa();
170     return true;
171   }
172 
173   void ComputeDominanceInformation();
174   void ClearDominanceInformation();
175 
176   void BuildDominatorTree();
177   void TransformToSsa();
178   void SimplifyCFG();
179 
180   // Analyze all natural loops in this graph. Returns false if one
181   // loop is not natural, that is the header does not dominate the
182   // back edge.
183   bool AnalyzeNaturalLoops() const;
184 
185   // Inline this graph in `outer_graph`, replacing the given `invoke` instruction.
186   void InlineInto(HGraph* outer_graph, HInvoke* invoke);
187 
188   // Need to add a couple of blocks to test if the loop body is entered and
189   // put deoptimization instructions, etc.
190   void TransformLoopHeaderForBCE(HBasicBlock* header);
191 
192   // Removes `block` from the graph.
193   void DeleteDeadBlock(HBasicBlock* block);
194 
195   void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
196   void SimplifyLoop(HBasicBlock* header);
197 
GetNextInstructionId()198   int32_t GetNextInstructionId() {
199     DCHECK_NE(current_instruction_id_, INT32_MAX);
200     return current_instruction_id_++;
201   }
202 
GetCurrentInstructionId()203   int32_t GetCurrentInstructionId() const {
204     return current_instruction_id_;
205   }
206 
SetCurrentInstructionId(int32_t id)207   void SetCurrentInstructionId(int32_t id) {
208     current_instruction_id_ = id;
209   }
210 
GetMaximumNumberOfOutVRegs()211   uint16_t GetMaximumNumberOfOutVRegs() const {
212     return maximum_number_of_out_vregs_;
213   }
214 
SetMaximumNumberOfOutVRegs(uint16_t new_value)215   void SetMaximumNumberOfOutVRegs(uint16_t new_value) {
216     maximum_number_of_out_vregs_ = new_value;
217   }
218 
UpdateTemporariesVRegSlots(size_t slots)219   void UpdateTemporariesVRegSlots(size_t slots) {
220     temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
221   }
222 
GetTemporariesVRegSlots()223   size_t GetTemporariesVRegSlots() const {
224     return temporaries_vreg_slots_;
225   }
226 
SetNumberOfVRegs(uint16_t number_of_vregs)227   void SetNumberOfVRegs(uint16_t number_of_vregs) {
228     number_of_vregs_ = number_of_vregs;
229   }
230 
GetNumberOfVRegs()231   uint16_t GetNumberOfVRegs() const {
232     return number_of_vregs_;
233   }
234 
SetNumberOfInVRegs(uint16_t value)235   void SetNumberOfInVRegs(uint16_t value) {
236     number_of_in_vregs_ = value;
237   }
238 
GetNumberOfLocalVRegs()239   uint16_t GetNumberOfLocalVRegs() const {
240     return number_of_vregs_ - number_of_in_vregs_;
241   }
242 
GetReversePostOrder()243   const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
244     return reverse_post_order_;
245   }
246 
GetLinearOrder()247   const GrowableArray<HBasicBlock*>& GetLinearOrder() const {
248     return linear_order_;
249   }
250 
HasBoundsChecks()251   bool HasBoundsChecks() const {
252     return has_bounds_checks_;
253   }
254 
SetHasBoundsChecks(bool value)255   void SetHasBoundsChecks(bool value) {
256     has_bounds_checks_ = value;
257   }
258 
IsDebuggable()259   bool IsDebuggable() const { return debuggable_; }
260 
261   // Returns a constant of the given type and value. If it does not exist
262   // already, it is created and inserted into the graph. This method is only for
263   // integral types.
264   HConstant* GetConstant(Primitive::Type type, int64_t value);
265   HNullConstant* GetNullConstant();
GetIntConstant(int32_t value)266   HIntConstant* GetIntConstant(int32_t value) {
267     return CreateConstant(value, &cached_int_constants_);
268   }
GetLongConstant(int64_t value)269   HLongConstant* GetLongConstant(int64_t value) {
270     return CreateConstant(value, &cached_long_constants_);
271   }
GetFloatConstant(float value)272   HFloatConstant* GetFloatConstant(float value) {
273     return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_);
274   }
GetDoubleConstant(double value)275   HDoubleConstant* GetDoubleConstant(double value) {
276     return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
277   }
278 
279   HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
280 
GetDexFile()281   const DexFile& GetDexFile() const {
282     return dex_file_;
283   }
284 
GetMethodIdx()285   uint32_t GetMethodIdx() const {
286     return method_idx_;
287   }
288 
289  private:
290   void VisitBlockForDominatorTree(HBasicBlock* block,
291                                   HBasicBlock* predecessor,
292                                   GrowableArray<size_t>* visits);
293   void FindBackEdges(ArenaBitVector* visited);
294   void VisitBlockForBackEdges(HBasicBlock* block,
295                               ArenaBitVector* visited,
296                               ArenaBitVector* visiting);
297   void RemoveInstructionsAsUsersFromDeadBlocks(const ArenaBitVector& visited) const;
298   void RemoveDeadBlocks(const ArenaBitVector& visited);
299 
300   template <class InstructionType, typename ValueType>
CreateConstant(ValueType value,ArenaSafeMap<ValueType,InstructionType * > * cache)301   InstructionType* CreateConstant(ValueType value,
302                                   ArenaSafeMap<ValueType, InstructionType*>* cache) {
303     // Try to find an existing constant of the given value.
304     InstructionType* constant = nullptr;
305     auto cached_constant = cache->find(value);
306     if (cached_constant != cache->end()) {
307       constant = cached_constant->second;
308     }
309 
310     // If not found or previously deleted, create and cache a new instruction.
311     if (constant == nullptr || constant->GetBlock() == nullptr) {
312       constant = new (arena_) InstructionType(value);
313       cache->Overwrite(value, constant);
314       InsertConstant(constant);
315     }
316     return constant;
317   }
318 
319   void InsertConstant(HConstant* instruction);
320 
321   // Cache a float constant into the graph. This method should only be
322   // called by the SsaBuilder when creating "equivalent" instructions.
323   void CacheFloatConstant(HFloatConstant* constant);
324 
325   // See CacheFloatConstant comment.
326   void CacheDoubleConstant(HDoubleConstant* constant);
327 
328   ArenaAllocator* const arena_;
329 
330   // List of blocks in insertion order.
331   GrowableArray<HBasicBlock*> blocks_;
332 
333   // List of blocks to perform a reverse post order tree traversal.
334   GrowableArray<HBasicBlock*> reverse_post_order_;
335 
336   // List of blocks to perform a linear order tree traversal.
337   GrowableArray<HBasicBlock*> linear_order_;
338 
339   HBasicBlock* entry_block_;
340   HBasicBlock* exit_block_;
341 
342   // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
343   uint16_t maximum_number_of_out_vregs_;
344 
345   // The number of virtual registers in this method. Contains the parameters.
346   uint16_t number_of_vregs_;
347 
348   // The number of virtual registers used by parameters of this method.
349   uint16_t number_of_in_vregs_;
350 
351   // Number of vreg size slots that the temporaries use (used in baseline compiler).
352   size_t temporaries_vreg_slots_;
353 
354   // Has bounds checks. We can totally skip BCE if it's false.
355   bool has_bounds_checks_;
356 
357   // Indicates whether the graph should be compiled in a way that
358   // ensures full debuggability. If false, we can apply more
359   // aggressive optimizations that may limit the level of debugging.
360   const bool debuggable_;
361 
362   // The current id to assign to a newly added instruction. See HInstruction.id_.
363   int32_t current_instruction_id_;
364 
365   // The dex file from which the method is from.
366   const DexFile& dex_file_;
367 
368   // The method index in the dex file.
369   const uint32_t method_idx_;
370 
371   const InstructionSet instruction_set_;
372 
373   // Cached constants.
374   HNullConstant* cached_null_constant_;
375   ArenaSafeMap<int32_t, HIntConstant*> cached_int_constants_;
376   ArenaSafeMap<int32_t, HFloatConstant*> cached_float_constants_;
377   ArenaSafeMap<int64_t, HLongConstant*> cached_long_constants_;
378   ArenaSafeMap<int64_t, HDoubleConstant*> cached_double_constants_;
379 
380   friend class SsaBuilder;           // For caching constants.
381   friend class SsaLivenessAnalysis;  // For the linear order.
382   ART_FRIEND_TEST(GraphTest, IfSuccessorSimpleJoinBlock1);
383   DISALLOW_COPY_AND_ASSIGN(HGraph);
384 };
385 
386 class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
387  public:
HLoopInformation(HBasicBlock * header,HGraph * graph)388   HLoopInformation(HBasicBlock* header, HGraph* graph)
389       : header_(header),
390         suspend_check_(nullptr),
391         back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
392         // Make bit vector growable, as the number of blocks may change.
393         blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
394 
GetHeader()395   HBasicBlock* GetHeader() const {
396     return header_;
397   }
398 
SetHeader(HBasicBlock * block)399   void SetHeader(HBasicBlock* block) {
400     header_ = block;
401   }
402 
GetSuspendCheck()403   HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
SetSuspendCheck(HSuspendCheck * check)404   void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
HasSuspendCheck()405   bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
406 
AddBackEdge(HBasicBlock * back_edge)407   void AddBackEdge(HBasicBlock* back_edge) {
408     back_edges_.Add(back_edge);
409   }
410 
RemoveBackEdge(HBasicBlock * back_edge)411   void RemoveBackEdge(HBasicBlock* back_edge) {
412     back_edges_.Delete(back_edge);
413   }
414 
IsBackEdge(const HBasicBlock & block)415   bool IsBackEdge(const HBasicBlock& block) const {
416     for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
417       if (back_edges_.Get(i) == &block) return true;
418     }
419     return false;
420   }
421 
NumberOfBackEdges()422   size_t NumberOfBackEdges() const {
423     return back_edges_.Size();
424   }
425 
426   HBasicBlock* GetPreHeader() const;
427 
GetBackEdges()428   const GrowableArray<HBasicBlock*>& GetBackEdges() const {
429     return back_edges_;
430   }
431 
432   // Returns the lifetime position of the back edge that has the
433   // greatest lifetime position.
434   size_t GetLifetimeEnd() const;
435 
ReplaceBackEdge(HBasicBlock * existing,HBasicBlock * new_back_edge)436   void ReplaceBackEdge(HBasicBlock* existing, HBasicBlock* new_back_edge) {
437     for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
438       if (back_edges_.Get(i) == existing) {
439         back_edges_.Put(i, new_back_edge);
440         return;
441       }
442     }
443     UNREACHABLE();
444   }
445 
446   // Finds blocks that are part of this loop. Returns whether the loop is a natural loop,
447   // that is the header dominates the back edge.
448   bool Populate();
449 
450   // Reanalyzes the loop by removing loop info from its blocks and re-running
451   // Populate(). If there are no back edges left, the loop info is completely
452   // removed as well as its SuspendCheck instruction. It must be run on nested
453   // inner loops first.
454   void Update();
455 
456   // Returns whether this loop information contains `block`.
457   // Note that this loop information *must* be populated before entering this function.
458   bool Contains(const HBasicBlock& block) const;
459 
460   // Returns whether this loop information is an inner loop of `other`.
461   // Note that `other` *must* be populated before entering this function.
462   bool IsIn(const HLoopInformation& other) const;
463 
GetBlocks()464   const ArenaBitVector& GetBlocks() const { return blocks_; }
465 
466   void Add(HBasicBlock* block);
467   void Remove(HBasicBlock* block);
468 
469  private:
470   // Internal recursive implementation of `Populate`.
471   void PopulateRecursive(HBasicBlock* block);
472 
473   HBasicBlock* header_;
474   HSuspendCheck* suspend_check_;
475   GrowableArray<HBasicBlock*> back_edges_;
476   ArenaBitVector blocks_;
477 
478   DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
479 };
480 
481 static constexpr size_t kNoLifetime = -1;
482 static constexpr uint32_t kNoDexPc = -1;
483 
484 // A block in a method. Contains the list of instructions represented
485 // as a double linked list. Each block knows its predecessors and
486 // successors.
487 
488 class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
489  public:
490   explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
graph_(graph)491       : graph_(graph),
492         predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
493         successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
494         loop_information_(nullptr),
495         dominator_(nullptr),
496         dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
497         block_id_(-1),
498         dex_pc_(dex_pc),
499         lifetime_start_(kNoLifetime),
500         lifetime_end_(kNoLifetime),
501         is_catch_block_(false) {}
502 
GetPredecessors()503   const GrowableArray<HBasicBlock*>& GetPredecessors() const {
504     return predecessors_;
505   }
506 
GetSuccessors()507   const GrowableArray<HBasicBlock*>& GetSuccessors() const {
508     return successors_;
509   }
510 
GetDominatedBlocks()511   const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
512     return dominated_blocks_;
513   }
514 
IsEntryBlock()515   bool IsEntryBlock() const {
516     return graph_->GetEntryBlock() == this;
517   }
518 
IsExitBlock()519   bool IsExitBlock() const {
520     return graph_->GetExitBlock() == this;
521   }
522 
523   bool IsSingleGoto() const;
524 
AddBackEdge(HBasicBlock * back_edge)525   void AddBackEdge(HBasicBlock* back_edge) {
526     if (loop_information_ == nullptr) {
527       loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
528     }
529     DCHECK_EQ(loop_information_->GetHeader(), this);
530     loop_information_->AddBackEdge(back_edge);
531   }
532 
GetGraph()533   HGraph* GetGraph() const { return graph_; }
SetGraph(HGraph * graph)534   void SetGraph(HGraph* graph) { graph_ = graph; }
535 
GetBlockId()536   int GetBlockId() const { return block_id_; }
SetBlockId(int id)537   void SetBlockId(int id) { block_id_ = id; }
538 
GetDominator()539   HBasicBlock* GetDominator() const { return dominator_; }
SetDominator(HBasicBlock * dominator)540   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
AddDominatedBlock(HBasicBlock * block)541   void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
RemoveDominatedBlock(HBasicBlock * block)542   void RemoveDominatedBlock(HBasicBlock* block) { dominated_blocks_.Delete(block); }
ReplaceDominatedBlock(HBasicBlock * existing,HBasicBlock * new_block)543   void ReplaceDominatedBlock(HBasicBlock* existing, HBasicBlock* new_block) {
544     for (size_t i = 0, e = dominated_blocks_.Size(); i < e; ++i) {
545       if (dominated_blocks_.Get(i) == existing) {
546         dominated_blocks_.Put(i, new_block);
547         return;
548       }
549     }
550     LOG(FATAL) << "Unreachable";
551     UNREACHABLE();
552   }
553   void ClearDominanceInformation();
554 
NumberOfBackEdges()555   int NumberOfBackEdges() const {
556     return IsLoopHeader() ? loop_information_->NumberOfBackEdges() : 0;
557   }
558 
GetFirstInstruction()559   HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
GetLastInstruction()560   HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
GetInstructions()561   const HInstructionList& GetInstructions() const { return instructions_; }
GetFirstPhi()562   HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
GetLastPhi()563   HInstruction* GetLastPhi() const { return phis_.last_instruction_; }
GetPhis()564   const HInstructionList& GetPhis() const { return phis_; }
565 
AddSuccessor(HBasicBlock * block)566   void AddSuccessor(HBasicBlock* block) {
567     successors_.Add(block);
568     block->predecessors_.Add(this);
569   }
570 
ReplaceSuccessor(HBasicBlock * existing,HBasicBlock * new_block)571   void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
572     size_t successor_index = GetSuccessorIndexOf(existing);
573     DCHECK_NE(successor_index, static_cast<size_t>(-1));
574     existing->RemovePredecessor(this);
575     new_block->predecessors_.Add(this);
576     successors_.Put(successor_index, new_block);
577   }
578 
ReplacePredecessor(HBasicBlock * existing,HBasicBlock * new_block)579   void ReplacePredecessor(HBasicBlock* existing, HBasicBlock* new_block) {
580     size_t predecessor_index = GetPredecessorIndexOf(existing);
581     DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
582     existing->RemoveSuccessor(this);
583     new_block->successors_.Add(this);
584     predecessors_.Put(predecessor_index, new_block);
585   }
586 
587   // Insert `this` between `predecessor` and `successor. This method
588   // preserves the indicies, and will update the first edge found between
589   // `predecessor` and `successor`.
InsertBetween(HBasicBlock * predecessor,HBasicBlock * successor)590   void InsertBetween(HBasicBlock* predecessor, HBasicBlock* successor) {
591     size_t predecessor_index = successor->GetPredecessorIndexOf(predecessor);
592     DCHECK_NE(predecessor_index, static_cast<size_t>(-1));
593     size_t successor_index = predecessor->GetSuccessorIndexOf(successor);
594     DCHECK_NE(successor_index, static_cast<size_t>(-1));
595     successor->predecessors_.Put(predecessor_index, this);
596     predecessor->successors_.Put(successor_index, this);
597     successors_.Add(successor);
598     predecessors_.Add(predecessor);
599   }
600 
RemovePredecessor(HBasicBlock * block)601   void RemovePredecessor(HBasicBlock* block) {
602     predecessors_.Delete(block);
603   }
604 
RemoveSuccessor(HBasicBlock * block)605   void RemoveSuccessor(HBasicBlock* block) {
606     successors_.Delete(block);
607   }
608 
ClearAllPredecessors()609   void ClearAllPredecessors() {
610     predecessors_.Reset();
611   }
612 
AddPredecessor(HBasicBlock * block)613   void AddPredecessor(HBasicBlock* block) {
614     predecessors_.Add(block);
615     block->successors_.Add(this);
616   }
617 
SwapPredecessors()618   void SwapPredecessors() {
619     DCHECK_EQ(predecessors_.Size(), 2u);
620     HBasicBlock* temp = predecessors_.Get(0);
621     predecessors_.Put(0, predecessors_.Get(1));
622     predecessors_.Put(1, temp);
623   }
624 
SwapSuccessors()625   void SwapSuccessors() {
626     DCHECK_EQ(successors_.Size(), 2u);
627     HBasicBlock* temp = successors_.Get(0);
628     successors_.Put(0, successors_.Get(1));
629     successors_.Put(1, temp);
630   }
631 
GetPredecessorIndexOf(HBasicBlock * predecessor)632   size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
633     for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
634       if (predecessors_.Get(i) == predecessor) {
635         return i;
636       }
637     }
638     return -1;
639   }
640 
GetSuccessorIndexOf(HBasicBlock * successor)641   size_t GetSuccessorIndexOf(HBasicBlock* successor) {
642     for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
643       if (successors_.Get(i) == successor) {
644         return i;
645       }
646     }
647     return -1;
648   }
649 
650   // Split the block into two blocks just after `cursor`. Returns the newly
651   // created block. Note that this method just updates raw block information,
652   // like predecessors, successors, dominators, and instruction list. It does not
653   // update the graph, reverse post order, loop information, nor make sure the
654   // blocks are consistent (for example ending with a control flow instruction).
655   HBasicBlock* SplitAfter(HInstruction* cursor);
656 
657   // Merge `other` at the end of `this`. Successors and dominated blocks of
658   // `other` are changed to be successors and dominated blocks of `this`. Note
659   // that this method does not update the graph, reverse post order, loop
660   // information, nor make sure the blocks are consistent (for example ending
661   // with a control flow instruction).
662   void MergeWithInlined(HBasicBlock* other);
663 
664   // Replace `this` with `other`. Predecessors, successors, and dominated blocks
665   // of `this` are moved to `other`.
666   // Note that this method does not update the graph, reverse post order, loop
667   // information, nor make sure the blocks are consistent (for example ending
668   // with a control flow instruction).
669   void ReplaceWith(HBasicBlock* other);
670 
671   // Merge `other` at the end of `this`. This method updates loops, reverse post
672   // order, links to predecessors, successors, dominators and deletes the block
673   // from the graph. The two blocks must be successive, i.e. `this` the only
674   // predecessor of `other` and vice versa.
675   void MergeWith(HBasicBlock* other);
676 
677   // Disconnects `this` from all its predecessors, successors and dominator,
678   // removes it from all loops it is included in and eventually from the graph.
679   // The block must not dominate any other block. Predecessors and successors
680   // are safely updated.
681   void DisconnectAndDelete();
682 
683   void AddInstruction(HInstruction* instruction);
684   // Insert `instruction` before/after an existing instruction `cursor`.
685   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
686   void InsertInstructionAfter(HInstruction* instruction, HInstruction* cursor);
687   // Replace instruction `initial` with `replacement` within this block.
688   void ReplaceAndRemoveInstructionWith(HInstruction* initial,
689                                        HInstruction* replacement);
690   void AddPhi(HPhi* phi);
691   void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
692   // RemoveInstruction and RemovePhi delete a given instruction from the respective
693   // instruction list. With 'ensure_safety' set to true, it verifies that the
694   // instruction is not in use and removes it from the use lists of its inputs.
695   void RemoveInstruction(HInstruction* instruction, bool ensure_safety = true);
696   void RemovePhi(HPhi* phi, bool ensure_safety = true);
697   void RemoveInstructionOrPhi(HInstruction* instruction, bool ensure_safety = true);
698 
IsLoopHeader()699   bool IsLoopHeader() const {
700     return IsInLoop() && (loop_information_->GetHeader() == this);
701   }
702 
IsLoopPreHeaderFirstPredecessor()703   bool IsLoopPreHeaderFirstPredecessor() const {
704     DCHECK(IsLoopHeader());
705     DCHECK(!GetPredecessors().IsEmpty());
706     return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
707   }
708 
GetLoopInformation()709   HLoopInformation* GetLoopInformation() const {
710     return loop_information_;
711   }
712 
713   // Set the loop_information_ on this block. Overrides the current
714   // loop_information if it is an outer loop of the passed loop information.
715   // Note that this method is called while creating the loop information.
SetInLoop(HLoopInformation * info)716   void SetInLoop(HLoopInformation* info) {
717     if (IsLoopHeader()) {
718       // Nothing to do. This just means `info` is an outer loop.
719     } else if (!IsInLoop()) {
720       loop_information_ = info;
721     } else if (loop_information_->Contains(*info->GetHeader())) {
722       // Block is currently part of an outer loop. Make it part of this inner loop.
723       // Note that a non loop header having a loop information means this loop information
724       // has already been populated
725       loop_information_ = info;
726     } else {
727       // Block is part of an inner loop. Do not update the loop information.
728       // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
729       // at this point, because this method is being called while populating `info`.
730     }
731   }
732 
733   // Raw update of the loop information.
SetLoopInformation(HLoopInformation * info)734   void SetLoopInformation(HLoopInformation* info) {
735     loop_information_ = info;
736   }
737 
IsInLoop()738   bool IsInLoop() const { return loop_information_ != nullptr; }
739 
740   // Returns whether this block dominates the blocked passed as parameter.
741   bool Dominates(HBasicBlock* block) const;
742 
GetLifetimeStart()743   size_t GetLifetimeStart() const { return lifetime_start_; }
GetLifetimeEnd()744   size_t GetLifetimeEnd() const { return lifetime_end_; }
745 
SetLifetimeStart(size_t start)746   void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
SetLifetimeEnd(size_t end)747   void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
748 
GetDexPc()749   uint32_t GetDexPc() const { return dex_pc_; }
750 
IsCatchBlock()751   bool IsCatchBlock() const { return is_catch_block_; }
SetIsCatchBlock()752   void SetIsCatchBlock() { is_catch_block_ = true; }
753 
754   bool EndsWithControlFlowInstruction() const;
755   bool EndsWithIf() const;
756   bool HasSinglePhi() const;
757 
758  private:
759   HGraph* graph_;
760   GrowableArray<HBasicBlock*> predecessors_;
761   GrowableArray<HBasicBlock*> successors_;
762   HInstructionList instructions_;
763   HInstructionList phis_;
764   HLoopInformation* loop_information_;
765   HBasicBlock* dominator_;
766   GrowableArray<HBasicBlock*> dominated_blocks_;
767   int block_id_;
768   // The dex program counter of the first instruction of this block.
769   const uint32_t dex_pc_;
770   size_t lifetime_start_;
771   size_t lifetime_end_;
772   bool is_catch_block_;
773 
774   friend class HGraph;
775   friend class HInstruction;
776 
777   DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
778 };
779 
780 // Iterates over the LoopInformation of all loops which contain 'block'
781 // from the innermost to the outermost.
782 class HLoopInformationOutwardIterator : public ValueObject {
783  public:
HLoopInformationOutwardIterator(const HBasicBlock & block)784   explicit HLoopInformationOutwardIterator(const HBasicBlock& block)
785       : current_(block.GetLoopInformation()) {}
786 
Done()787   bool Done() const { return current_ == nullptr; }
788 
Advance()789   void Advance() {
790     DCHECK(!Done());
791     current_ = current_->GetPreHeader()->GetLoopInformation();
792   }
793 
Current()794   HLoopInformation* Current() const {
795     DCHECK(!Done());
796     return current_;
797   }
798 
799  private:
800   HLoopInformation* current_;
801 
802   DISALLOW_COPY_AND_ASSIGN(HLoopInformationOutwardIterator);
803 };
804 
805 #define FOR_EACH_CONCRETE_INSTRUCTION(M)                                \
806   M(Add, BinaryOperation)                                               \
807   M(And, BinaryOperation)                                               \
808   M(ArrayGet, Instruction)                                              \
809   M(ArrayLength, Instruction)                                           \
810   M(ArraySet, Instruction)                                              \
811   M(BooleanNot, UnaryOperation)                                         \
812   M(BoundsCheck, Instruction)                                           \
813   M(BoundType, Instruction)                                             \
814   M(CheckCast, Instruction)                                             \
815   M(ClinitCheck, Instruction)                                           \
816   M(Compare, BinaryOperation)                                           \
817   M(Condition, BinaryOperation)                                         \
818   M(Deoptimize, Instruction)                                            \
819   M(Div, BinaryOperation)                                               \
820   M(DivZeroCheck, Instruction)                                          \
821   M(DoubleConstant, Constant)                                           \
822   M(Equal, Condition)                                                   \
823   M(Exit, Instruction)                                                  \
824   M(FloatConstant, Constant)                                            \
825   M(Goto, Instruction)                                                  \
826   M(GreaterThan, Condition)                                             \
827   M(GreaterThanOrEqual, Condition)                                      \
828   M(If, Instruction)                                                    \
829   M(InstanceFieldGet, Instruction)                                      \
830   M(InstanceFieldSet, Instruction)                                      \
831   M(InstanceOf, Instruction)                                            \
832   M(IntConstant, Constant)                                              \
833   M(InvokeInterface, Invoke)                                            \
834   M(InvokeStaticOrDirect, Invoke)                                       \
835   M(InvokeVirtual, Invoke)                                              \
836   M(LessThan, Condition)                                                \
837   M(LessThanOrEqual, Condition)                                         \
838   M(LoadClass, Instruction)                                             \
839   M(LoadException, Instruction)                                         \
840   M(LoadLocal, Instruction)                                             \
841   M(LoadString, Instruction)                                            \
842   M(Local, Instruction)                                                 \
843   M(LongConstant, Constant)                                             \
844   M(MemoryBarrier, Instruction)                                         \
845   M(MonitorOperation, Instruction)                                      \
846   M(Mul, BinaryOperation)                                               \
847   M(Neg, UnaryOperation)                                                \
848   M(NewArray, Instruction)                                              \
849   M(NewInstance, Instruction)                                           \
850   M(Not, UnaryOperation)                                                \
851   M(NotEqual, Condition)                                                \
852   M(NullConstant, Instruction)                                          \
853   M(NullCheck, Instruction)                                             \
854   M(Or, BinaryOperation)                                                \
855   M(ParallelMove, Instruction)                                          \
856   M(ParameterValue, Instruction)                                        \
857   M(Phi, Instruction)                                                   \
858   M(Rem, BinaryOperation)                                               \
859   M(Return, Instruction)                                                \
860   M(ReturnVoid, Instruction)                                            \
861   M(Shl, BinaryOperation)                                               \
862   M(Shr, BinaryOperation)                                               \
863   M(StaticFieldGet, Instruction)                                        \
864   M(StaticFieldSet, Instruction)                                        \
865   M(StoreLocal, Instruction)                                            \
866   M(Sub, BinaryOperation)                                               \
867   M(SuspendCheck, Instruction)                                          \
868   M(Temporary, Instruction)                                             \
869   M(Throw, Instruction)                                                 \
870   M(TypeConversion, Instruction)                                        \
871   M(UShr, BinaryOperation)                                              \
872   M(Xor, BinaryOperation)                                               \
873 
874 #define FOR_EACH_INSTRUCTION(M)                                         \
875   FOR_EACH_CONCRETE_INSTRUCTION(M)                                      \
876   M(Constant, Instruction)                                              \
877   M(UnaryOperation, Instruction)                                        \
878   M(BinaryOperation, Instruction)                                       \
879   M(Invoke, Instruction)
880 
881 #define FORWARD_DECLARATION(type, super) class H##type;
882 FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
883 #undef FORWARD_DECLARATION
884 
885 #define DECLARE_INSTRUCTION(type)                                       \
886   InstructionKind GetKind() const OVERRIDE { return k##type; }          \
887   const char* DebugName() const OVERRIDE { return #type; }              \
888   const H##type* As##type() const OVERRIDE { return this; }             \
889   H##type* As##type() OVERRIDE { return this; }                         \
890   bool InstructionTypeEquals(HInstruction* other) const OVERRIDE {      \
891     return other->Is##type();                                           \
892   }                                                                     \
893   void Accept(HGraphVisitor* visitor) OVERRIDE
894 
895 template <typename T> class HUseList;
896 
897 template <typename T>
898 class HUseListNode : public ArenaObject<kArenaAllocMisc> {
899  public:
GetPrevious()900   HUseListNode* GetPrevious() const { return prev_; }
GetNext()901   HUseListNode* GetNext() const { return next_; }
GetUser()902   T GetUser() const { return user_; }
GetIndex()903   size_t GetIndex() const { return index_; }
SetIndex(size_t index)904   void SetIndex(size_t index) { index_ = index; }
905 
906  private:
HUseListNode(T user,size_t index)907   HUseListNode(T user, size_t index)
908       : user_(user), index_(index), prev_(nullptr), next_(nullptr) {}
909 
910   T const user_;
911   size_t index_;
912   HUseListNode<T>* prev_;
913   HUseListNode<T>* next_;
914 
915   friend class HUseList<T>;
916 
917   DISALLOW_COPY_AND_ASSIGN(HUseListNode);
918 };
919 
920 template <typename T>
921 class HUseList : public ValueObject {
922  public:
HUseList()923   HUseList() : first_(nullptr) {}
924 
Clear()925   void Clear() {
926     first_ = nullptr;
927   }
928 
929   // Adds a new entry at the beginning of the use list and returns
930   // the newly created node.
AddUse(T user,size_t index,ArenaAllocator * arena)931   HUseListNode<T>* AddUse(T user, size_t index, ArenaAllocator* arena) {
932     HUseListNode<T>* new_node = new (arena) HUseListNode<T>(user, index);
933     if (IsEmpty()) {
934       first_ = new_node;
935     } else {
936       first_->prev_ = new_node;
937       new_node->next_ = first_;
938       first_ = new_node;
939     }
940     return new_node;
941   }
942 
GetFirst()943   HUseListNode<T>* GetFirst() const {
944     return first_;
945   }
946 
Remove(HUseListNode<T> * node)947   void Remove(HUseListNode<T>* node) {
948     DCHECK(node != nullptr);
949     DCHECK(Contains(node));
950 
951     if (node->prev_ != nullptr) {
952       node->prev_->next_ = node->next_;
953     }
954     if (node->next_ != nullptr) {
955       node->next_->prev_ = node->prev_;
956     }
957     if (node == first_) {
958       first_ = node->next_;
959     }
960   }
961 
Contains(const HUseListNode<T> * node)962   bool Contains(const HUseListNode<T>* node) const {
963     if (node == nullptr) {
964       return false;
965     }
966     for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
967       if (current == node) {
968         return true;
969       }
970     }
971     return false;
972   }
973 
IsEmpty()974   bool IsEmpty() const {
975     return first_ == nullptr;
976   }
977 
HasOnlyOneUse()978   bool HasOnlyOneUse() const {
979     return first_ != nullptr && first_->next_ == nullptr;
980   }
981 
SizeSlow()982   size_t SizeSlow() const {
983     size_t count = 0;
984     for (HUseListNode<T>* current = first_; current != nullptr; current = current->GetNext()) {
985       ++count;
986     }
987     return count;
988   }
989 
990  private:
991   HUseListNode<T>* first_;
992 };
993 
994 template<typename T>
995 class HUseIterator : public ValueObject {
996  public:
HUseIterator(const HUseList<T> & uses)997   explicit HUseIterator(const HUseList<T>& uses) : current_(uses.GetFirst()) {}
998 
Done()999   bool Done() const { return current_ == nullptr; }
1000 
Advance()1001   void Advance() {
1002     DCHECK(!Done());
1003     current_ = current_->GetNext();
1004   }
1005 
Current()1006   HUseListNode<T>* Current() const {
1007     DCHECK(!Done());
1008     return current_;
1009   }
1010 
1011  private:
1012   HUseListNode<T>* current_;
1013 
1014   friend class HValue;
1015 };
1016 
1017 // This class is used by HEnvironment and HInstruction classes to record the
1018 // instructions they use and pointers to the corresponding HUseListNodes kept
1019 // by the used instructions.
1020 template <typename T>
1021 class HUserRecord : public ValueObject {
1022  public:
HUserRecord()1023   HUserRecord() : instruction_(nullptr), use_node_(nullptr) {}
HUserRecord(HInstruction * instruction)1024   explicit HUserRecord(HInstruction* instruction) : instruction_(instruction), use_node_(nullptr) {}
1025 
HUserRecord(const HUserRecord<T> & old_record,HUseListNode<T> * use_node)1026   HUserRecord(const HUserRecord<T>& old_record, HUseListNode<T>* use_node)
1027     : instruction_(old_record.instruction_), use_node_(use_node) {
1028     DCHECK(instruction_ != nullptr);
1029     DCHECK(use_node_ != nullptr);
1030     DCHECK(old_record.use_node_ == nullptr);
1031   }
1032 
GetInstruction()1033   HInstruction* GetInstruction() const { return instruction_; }
GetUseNode()1034   HUseListNode<T>* GetUseNode() const { return use_node_; }
1035 
1036  private:
1037   // Instruction used by the user.
1038   HInstruction* instruction_;
1039 
1040   // Corresponding entry in the use list kept by 'instruction_'.
1041   HUseListNode<T>* use_node_;
1042 };
1043 
1044 // TODO: Add better documentation to this class and maybe refactor with more suggestive names.
1045 // - Has(All)SideEffects suggests that all the side effects are present but only ChangesSomething
1046 //   flag is consider.
1047 // - DependsOn suggests that there is a real dependency between side effects but it only
1048 //   checks DependendsOnSomething flag.
1049 //
1050 // Represents the side effects an instruction may have.
1051 class SideEffects : public ValueObject {
1052  public:
SideEffects()1053   SideEffects() : flags_(0) {}
1054 
None()1055   static SideEffects None() {
1056     return SideEffects(0);
1057   }
1058 
All()1059   static SideEffects All() {
1060     return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
1061   }
1062 
ChangesSomething()1063   static SideEffects ChangesSomething() {
1064     return SideEffects((1 << kFlagChangesCount) - 1);
1065   }
1066 
DependsOnSomething()1067   static SideEffects DependsOnSomething() {
1068     int count = kFlagDependsOnCount - kFlagChangesCount;
1069     return SideEffects(((1 << count) - 1) << kFlagChangesCount);
1070   }
1071 
Union(SideEffects other)1072   SideEffects Union(SideEffects other) const {
1073     return SideEffects(flags_ | other.flags_);
1074   }
1075 
HasSideEffects()1076   bool HasSideEffects() const {
1077     size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1078     return (flags_ & all_bits_set) != 0;
1079   }
1080 
HasAllSideEffects()1081   bool HasAllSideEffects() const {
1082     size_t all_bits_set = (1 << kFlagChangesCount) - 1;
1083     return all_bits_set == (flags_ & all_bits_set);
1084   }
1085 
DependsOn(SideEffects other)1086   bool DependsOn(SideEffects other) const {
1087     size_t depends_flags = other.ComputeDependsFlags();
1088     return (flags_ & depends_flags) != 0;
1089   }
1090 
HasDependencies()1091   bool HasDependencies() const {
1092     int count = kFlagDependsOnCount - kFlagChangesCount;
1093     size_t all_bits_set = (1 << count) - 1;
1094     return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
1095   }
1096 
1097  private:
1098   static constexpr int kFlagChangesSomething = 0;
1099   static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
1100 
1101   static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
1102   static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
1103 
SideEffects(size_t flags)1104   explicit SideEffects(size_t flags) : flags_(flags) {}
1105 
ComputeDependsFlags()1106   size_t ComputeDependsFlags() const {
1107     return flags_ << kFlagChangesCount;
1108   }
1109 
1110   size_t flags_;
1111 };
1112 
1113 // A HEnvironment object contains the values of virtual registers at a given location.
1114 class HEnvironment : public ArenaObject<kArenaAllocMisc> {
1115  public:
HEnvironment(ArenaAllocator * arena,size_t number_of_vregs,const DexFile & dex_file,uint32_t method_idx,uint32_t dex_pc)1116   HEnvironment(ArenaAllocator* arena,
1117                size_t number_of_vregs,
1118                const DexFile& dex_file,
1119                uint32_t method_idx,
1120                uint32_t dex_pc)
1121      : vregs_(arena, number_of_vregs),
1122        locations_(arena, number_of_vregs),
1123        parent_(nullptr),
1124        dex_file_(dex_file),
1125        method_idx_(method_idx),
1126        dex_pc_(dex_pc) {
1127     vregs_.SetSize(number_of_vregs);
1128     for (size_t i = 0; i < number_of_vregs; i++) {
1129       vregs_.Put(i, HUserRecord<HEnvironment*>());
1130     }
1131 
1132     locations_.SetSize(number_of_vregs);
1133     for (size_t i = 0; i < number_of_vregs; ++i) {
1134       locations_.Put(i, Location());
1135     }
1136   }
1137 
SetAndCopyParentChain(ArenaAllocator * allocator,HEnvironment * parent)1138   void SetAndCopyParentChain(ArenaAllocator* allocator, HEnvironment* parent) {
1139     parent_ = new (allocator) HEnvironment(allocator,
1140                                            parent->Size(),
1141                                            parent->GetDexFile(),
1142                                            parent->GetMethodIdx(),
1143                                            parent->GetDexPc());
1144     if (parent->GetParent() != nullptr) {
1145       parent_->SetAndCopyParentChain(allocator, parent->GetParent());
1146     }
1147     parent_->CopyFrom(parent);
1148   }
1149 
1150   void CopyFrom(const GrowableArray<HInstruction*>& locals);
1151   void CopyFrom(HEnvironment* environment);
1152 
1153   // Copy from `env`. If it's a loop phi for `loop_header`, copy the first
1154   // input to the loop phi instead. This is for inserting instructions that
1155   // require an environment (like HDeoptimization) in the loop pre-header.
1156   void CopyFromWithLoopPhiAdjustment(HEnvironment* env, HBasicBlock* loop_header);
1157 
SetRawEnvAt(size_t index,HInstruction * instruction)1158   void SetRawEnvAt(size_t index, HInstruction* instruction) {
1159     vregs_.Put(index, HUserRecord<HEnvironment*>(instruction));
1160   }
1161 
GetInstructionAt(size_t index)1162   HInstruction* GetInstructionAt(size_t index) const {
1163     return vregs_.Get(index).GetInstruction();
1164   }
1165 
1166   void RemoveAsUserOfInput(size_t index) const;
1167 
Size()1168   size_t Size() const { return vregs_.Size(); }
1169 
GetParent()1170   HEnvironment* GetParent() const { return parent_; }
1171 
SetLocationAt(size_t index,Location location)1172   void SetLocationAt(size_t index, Location location) {
1173     locations_.Put(index, location);
1174   }
1175 
GetLocationAt(size_t index)1176   Location GetLocationAt(size_t index) const {
1177     return locations_.Get(index);
1178   }
1179 
GetDexPc()1180   uint32_t GetDexPc() const {
1181     return dex_pc_;
1182   }
1183 
GetMethodIdx()1184   uint32_t GetMethodIdx() const {
1185     return method_idx_;
1186   }
1187 
GetDexFile()1188   const DexFile& GetDexFile() const {
1189     return dex_file_;
1190   }
1191 
1192  private:
1193   // Record instructions' use entries of this environment for constant-time removal.
1194   // It should only be called by HInstruction when a new environment use is added.
RecordEnvUse(HUseListNode<HEnvironment * > * env_use)1195   void RecordEnvUse(HUseListNode<HEnvironment*>* env_use) {
1196     DCHECK(env_use->GetUser() == this);
1197     size_t index = env_use->GetIndex();
1198     vregs_.Put(index, HUserRecord<HEnvironment*>(vregs_.Get(index), env_use));
1199   }
1200 
1201   GrowableArray<HUserRecord<HEnvironment*> > vregs_;
1202   GrowableArray<Location> locations_;
1203   HEnvironment* parent_;
1204   const DexFile& dex_file_;
1205   const uint32_t method_idx_;
1206   const uint32_t dex_pc_;
1207 
1208   friend class HInstruction;
1209 
1210   DISALLOW_COPY_AND_ASSIGN(HEnvironment);
1211 };
1212 
1213 class ReferenceTypeInfo : ValueObject {
1214  public:
1215   typedef Handle<mirror::Class> TypeHandle;
1216 
Create(TypeHandle type_handle,bool is_exact)1217   static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
1218       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1219     if (type_handle->IsObjectClass()) {
1220       // Override the type handle to be consistent with the case when we get to
1221       // Top but don't have the Object class available. It avoids having to guess
1222       // what value the type_handle has when it's Top.
1223       return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1224     } else {
1225       return ReferenceTypeInfo(type_handle, is_exact, false);
1226     }
1227   }
1228 
CreateTop(bool is_exact)1229   static ReferenceTypeInfo CreateTop(bool is_exact) {
1230     return ReferenceTypeInfo(TypeHandle(), is_exact, true);
1231   }
1232 
IsExact()1233   bool IsExact() const { return is_exact_; }
IsTop()1234   bool IsTop() const { return is_top_; }
1235 
GetTypeHandle()1236   Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
1237 
IsSupertypeOf(ReferenceTypeInfo rti)1238   bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1239     if (IsTop()) {
1240       // Top (equivalent for java.lang.Object) is supertype of anything.
1241       return true;
1242     }
1243     if (rti.IsTop()) {
1244       // If we get here `this` is not Top() so it can't be a supertype.
1245       return false;
1246     }
1247     return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
1248   }
1249 
1250   // Returns true if the type information provide the same amount of details.
1251   // Note that it does not mean that the instructions have the same actual type
1252   // (e.g. tops are equal but they can be the result of a merge).
IsEqual(ReferenceTypeInfo rti)1253   bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1254     if (IsExact() != rti.IsExact()) {
1255       return false;
1256     }
1257     if (IsTop() && rti.IsTop()) {
1258       // `Top` means java.lang.Object, so the types are equivalent.
1259       return true;
1260     }
1261     if (IsTop() || rti.IsTop()) {
1262       // If only one is top or object than they are not equivalent.
1263       // NB: We need this extra check because the type_handle of `Top` is invalid
1264       // and we cannot inspect its reference.
1265       return false;
1266     }
1267 
1268     // Finally check the types.
1269     return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
1270   }
1271 
1272  private:
ReferenceTypeInfo()1273   ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
ReferenceTypeInfo(TypeHandle type_handle,bool is_exact,bool is_top)1274   ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
1275       : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
1276 
1277   // The class of the object.
1278   TypeHandle type_handle_;
1279   // Whether or not the type is exact or a superclass of the actual type.
1280   // Whether or not we have any information about this type.
1281   bool is_exact_;
1282   // A true value here means that the object type should be java.lang.Object.
1283   // We don't have access to the corresponding mirror object every time so this
1284   // flag acts as a substitute. When true, the TypeHandle refers to a null
1285   // pointer and should not be used.
1286   bool is_top_;
1287 };
1288 
1289 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
1290 
1291 class HInstruction : public ArenaObject<kArenaAllocMisc> {
1292  public:
HInstruction(SideEffects side_effects)1293   explicit HInstruction(SideEffects side_effects)
1294       : previous_(nullptr),
1295         next_(nullptr),
1296         block_(nullptr),
1297         id_(-1),
1298         ssa_index_(-1),
1299         environment_(nullptr),
1300         locations_(nullptr),
1301         live_interval_(nullptr),
1302         lifetime_position_(kNoLifetime),
1303         side_effects_(side_effects),
1304         reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
1305 
~HInstruction()1306   virtual ~HInstruction() {}
1307 
1308 #define DECLARE_KIND(type, super) k##type,
1309   enum InstructionKind {
1310     FOR_EACH_INSTRUCTION(DECLARE_KIND)
1311   };
1312 #undef DECLARE_KIND
1313 
GetNext()1314   HInstruction* GetNext() const { return next_; }
GetPrevious()1315   HInstruction* GetPrevious() const { return previous_; }
1316 
1317   HInstruction* GetNextDisregardingMoves() const;
1318   HInstruction* GetPreviousDisregardingMoves() const;
1319 
GetBlock()1320   HBasicBlock* GetBlock() const { return block_; }
SetBlock(HBasicBlock * block)1321   void SetBlock(HBasicBlock* block) { block_ = block; }
IsInBlock()1322   bool IsInBlock() const { return block_ != nullptr; }
IsInLoop()1323   bool IsInLoop() const { return block_->IsInLoop(); }
IsLoopHeaderPhi()1324   bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
1325 
1326   virtual size_t InputCount() const = 0;
InputAt(size_t i)1327   HInstruction* InputAt(size_t i) const { return InputRecordAt(i).GetInstruction(); }
1328 
1329   virtual void Accept(HGraphVisitor* visitor) = 0;
1330   virtual const char* DebugName() const = 0;
1331 
GetType()1332   virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
SetRawInputAt(size_t index,HInstruction * input)1333   void SetRawInputAt(size_t index, HInstruction* input) {
1334     SetRawInputRecordAt(index, HUserRecord<HInstruction*>(input));
1335   }
1336 
NeedsEnvironment()1337   virtual bool NeedsEnvironment() const { return false; }
GetDexPc()1338   virtual uint32_t GetDexPc() const {
1339     LOG(FATAL) << "GetDexPc() cannot be called on an instruction that"
1340                   " does not need an environment";
1341     UNREACHABLE();
1342   }
IsControlFlow()1343   virtual bool IsControlFlow() const { return false; }
CanThrow()1344   virtual bool CanThrow() const { return false; }
HasSideEffects()1345   bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
1346 
1347   // Does not apply for all instructions, but having this at top level greatly
1348   // simplifies the null check elimination.
CanBeNull()1349   virtual bool CanBeNull() const {
1350     DCHECK_EQ(GetType(), Primitive::kPrimNot) << "CanBeNull only applies to reference types";
1351     return true;
1352   }
1353 
CanDoImplicitNullCheckOn(HInstruction * obj)1354   virtual bool CanDoImplicitNullCheckOn(HInstruction* obj) const {
1355     UNUSED(obj);
1356     return false;
1357   }
1358 
SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info)1359   void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
1360     DCHECK_EQ(GetType(), Primitive::kPrimNot);
1361     reference_type_info_ = reference_type_info;
1362   }
1363 
GetReferenceTypeInfo()1364   ReferenceTypeInfo GetReferenceTypeInfo() const {
1365     DCHECK_EQ(GetType(), Primitive::kPrimNot);
1366     return reference_type_info_;
1367   }
1368 
AddUseAt(HInstruction * user,size_t index)1369   void AddUseAt(HInstruction* user, size_t index) {
1370     DCHECK(user != nullptr);
1371     HUseListNode<HInstruction*>* use =
1372         uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1373     user->SetRawInputRecordAt(index, HUserRecord<HInstruction*>(user->InputRecordAt(index), use));
1374   }
1375 
AddEnvUseAt(HEnvironment * user,size_t index)1376   void AddEnvUseAt(HEnvironment* user, size_t index) {
1377     DCHECK(user != nullptr);
1378     HUseListNode<HEnvironment*>* env_use =
1379         env_uses_.AddUse(user, index, GetBlock()->GetGraph()->GetArena());
1380     user->RecordEnvUse(env_use);
1381   }
1382 
RemoveAsUserOfInput(size_t input)1383   void RemoveAsUserOfInput(size_t input) {
1384     HUserRecord<HInstruction*> input_use = InputRecordAt(input);
1385     input_use.GetInstruction()->uses_.Remove(input_use.GetUseNode());
1386   }
1387 
GetUses()1388   const HUseList<HInstruction*>& GetUses() const { return uses_; }
GetEnvUses()1389   const HUseList<HEnvironment*>& GetEnvUses() const { return env_uses_; }
1390 
HasUses()1391   bool HasUses() const { return !uses_.IsEmpty() || !env_uses_.IsEmpty(); }
HasEnvironmentUses()1392   bool HasEnvironmentUses() const { return !env_uses_.IsEmpty(); }
HasNonEnvironmentUses()1393   bool HasNonEnvironmentUses() const { return !uses_.IsEmpty(); }
HasOnlyOneNonEnvironmentUse()1394   bool HasOnlyOneNonEnvironmentUse() const {
1395     return !HasEnvironmentUses() && GetUses().HasOnlyOneUse();
1396   }
1397 
1398   // Does this instruction strictly dominate `other_instruction`?
1399   // Returns false if this instruction and `other_instruction` are the same.
1400   // Aborts if this instruction and `other_instruction` are both phis.
1401   bool StrictlyDominates(HInstruction* other_instruction) const;
1402 
GetId()1403   int GetId() const { return id_; }
SetId(int id)1404   void SetId(int id) { id_ = id; }
1405 
GetSsaIndex()1406   int GetSsaIndex() const { return ssa_index_; }
SetSsaIndex(int ssa_index)1407   void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
HasSsaIndex()1408   bool HasSsaIndex() const { return ssa_index_ != -1; }
1409 
HasEnvironment()1410   bool HasEnvironment() const { return environment_ != nullptr; }
GetEnvironment()1411   HEnvironment* GetEnvironment() const { return environment_; }
1412   // Set the `environment_` field. Raw because this method does not
1413   // update the uses lists.
SetRawEnvironment(HEnvironment * environment)1414   void SetRawEnvironment(HEnvironment* environment) { environment_ = environment; }
1415 
1416   // Set the environment of this instruction, copying it from `environment`. While
1417   // copying, the uses lists are being updated.
CopyEnvironmentFrom(HEnvironment * environment)1418   void CopyEnvironmentFrom(HEnvironment* environment) {
1419     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
1420     environment_ = new (allocator) HEnvironment(
1421         allocator,
1422         environment->Size(),
1423         environment->GetDexFile(),
1424         environment->GetMethodIdx(),
1425         environment->GetDexPc());
1426     environment_->CopyFrom(environment);
1427     if (environment->GetParent() != nullptr) {
1428       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1429     }
1430   }
1431 
CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment * environment,HBasicBlock * block)1432   void CopyEnvironmentFromWithLoopPhiAdjustment(HEnvironment* environment,
1433                                                 HBasicBlock* block) {
1434     ArenaAllocator* allocator = GetBlock()->GetGraph()->GetArena();
1435     environment_ = new (allocator) HEnvironment(
1436         allocator,
1437         environment->Size(),
1438         environment->GetDexFile(),
1439         environment->GetMethodIdx(),
1440         environment->GetDexPc());
1441     if (environment->GetParent() != nullptr) {
1442       environment_->SetAndCopyParentChain(allocator, environment->GetParent());
1443     }
1444     environment_->CopyFromWithLoopPhiAdjustment(environment, block);
1445   }
1446 
1447   // Returns the number of entries in the environment. Typically, that is the
1448   // number of dex registers in a method. It could be more in case of inlining.
1449   size_t EnvironmentSize() const;
1450 
GetLocations()1451   LocationSummary* GetLocations() const { return locations_; }
SetLocations(LocationSummary * locations)1452   void SetLocations(LocationSummary* locations) { locations_ = locations; }
1453 
1454   void ReplaceWith(HInstruction* instruction);
1455   void ReplaceInput(HInstruction* replacement, size_t index);
1456 
1457   // This is almost the same as doing `ReplaceWith()`. But in this helper, the
1458   // uses of this instruction by `other` are *not* updated.
ReplaceWithExceptInReplacementAtIndex(HInstruction * other,size_t use_index)1459   void ReplaceWithExceptInReplacementAtIndex(HInstruction* other, size_t use_index) {
1460     ReplaceWith(other);
1461     other->ReplaceInput(this, use_index);
1462   }
1463 
1464   // Move `this` instruction before `cursor`.
1465   void MoveBefore(HInstruction* cursor);
1466 
1467 #define INSTRUCTION_TYPE_CHECK(type, super)                                    \
1468   bool Is##type() const { return (As##type() != nullptr); }                    \
1469   virtual const H##type* As##type() const { return nullptr; }                  \
1470   virtual H##type* As##type() { return nullptr; }
1471 
FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)1472   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
1473 #undef INSTRUCTION_TYPE_CHECK
1474 
1475   // Returns whether the instruction can be moved within the graph.
1476   virtual bool CanBeMoved() const { return false; }
1477 
1478   // Returns whether the two instructions are of the same kind.
InstructionTypeEquals(HInstruction * other)1479   virtual bool InstructionTypeEquals(HInstruction* other) const {
1480     UNUSED(other);
1481     return false;
1482   }
1483 
1484   // Returns whether any data encoded in the two instructions is equal.
1485   // This method does not look at the inputs. Both instructions must be
1486   // of the same type, otherwise the method has undefined behavior.
InstructionDataEquals(HInstruction * other)1487   virtual bool InstructionDataEquals(HInstruction* other) const {
1488     UNUSED(other);
1489     return false;
1490   }
1491 
1492   // Returns whether two instructions are equal, that is:
1493   // 1) They have the same type and contain the same data (InstructionDataEquals).
1494   // 2) Their inputs are identical.
1495   bool Equals(HInstruction* other) const;
1496 
1497   virtual InstructionKind GetKind() const = 0;
1498 
ComputeHashCode()1499   virtual size_t ComputeHashCode() const {
1500     size_t result = GetKind();
1501     for (size_t i = 0, e = InputCount(); i < e; ++i) {
1502       result = (result * 31) + InputAt(i)->GetId();
1503     }
1504     return result;
1505   }
1506 
GetSideEffects()1507   SideEffects GetSideEffects() const { return side_effects_; }
1508 
GetLifetimePosition()1509   size_t GetLifetimePosition() const { return lifetime_position_; }
SetLifetimePosition(size_t position)1510   void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
GetLiveInterval()1511   LiveInterval* GetLiveInterval() const { return live_interval_; }
SetLiveInterval(LiveInterval * interval)1512   void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
HasLiveInterval()1513   bool HasLiveInterval() const { return live_interval_ != nullptr; }
1514 
IsSuspendCheckEntry()1515   bool IsSuspendCheckEntry() const { return IsSuspendCheck() && GetBlock()->IsEntryBlock(); }
1516 
1517   // Returns whether the code generation of the instruction will require to have access
1518   // to the current method. Such instructions are:
1519   // (1): Instructions that require an environment, as calling the runtime requires
1520   //      to walk the stack and have the current method stored at a specific stack address.
1521   // (2): Object literals like classes and strings, that are loaded from the dex cache
1522   //      fields of the current method.
NeedsCurrentMethod()1523   bool NeedsCurrentMethod() const {
1524     return NeedsEnvironment() || IsLoadClass() || IsLoadString();
1525   }
1526 
NeedsDexCache()1527   virtual bool NeedsDexCache() const { return false; }
1528 
1529  protected:
1530   virtual const HUserRecord<HInstruction*> InputRecordAt(size_t i) const = 0;
1531   virtual void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) = 0;
1532 
1533  private:
RemoveEnvironmentUser(HUseListNode<HEnvironment * > * use_node)1534   void RemoveEnvironmentUser(HUseListNode<HEnvironment*>* use_node) { env_uses_.Remove(use_node); }
1535 
1536   HInstruction* previous_;
1537   HInstruction* next_;
1538   HBasicBlock* block_;
1539 
1540   // An instruction gets an id when it is added to the graph.
1541   // It reflects creation order. A negative id means the instruction
1542   // has not been added to the graph.
1543   int id_;
1544 
1545   // When doing liveness analysis, instructions that have uses get an SSA index.
1546   int ssa_index_;
1547 
1548   // List of instructions that have this instruction as input.
1549   HUseList<HInstruction*> uses_;
1550 
1551   // List of environments that contain this instruction.
1552   HUseList<HEnvironment*> env_uses_;
1553 
1554   // The environment associated with this instruction. Not null if the instruction
1555   // might jump out of the method.
1556   HEnvironment* environment_;
1557 
1558   // Set by the code generator.
1559   LocationSummary* locations_;
1560 
1561   // Set by the liveness analysis.
1562   LiveInterval* live_interval_;
1563 
1564   // Set by the liveness analysis, this is the position in a linear
1565   // order of blocks where this instruction's live interval start.
1566   size_t lifetime_position_;
1567 
1568   const SideEffects side_effects_;
1569 
1570   // TODO: for primitive types this should be marked as invalid.
1571   ReferenceTypeInfo reference_type_info_;
1572 
1573   friend class GraphChecker;
1574   friend class HBasicBlock;
1575   friend class HEnvironment;
1576   friend class HGraph;
1577   friend class HInstructionList;
1578 
1579   DISALLOW_COPY_AND_ASSIGN(HInstruction);
1580 };
1581 std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
1582 
1583 class HInputIterator : public ValueObject {
1584  public:
HInputIterator(HInstruction * instruction)1585   explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
1586 
Done()1587   bool Done() const { return index_ == instruction_->InputCount(); }
Current()1588   HInstruction* Current() const { return instruction_->InputAt(index_); }
Advance()1589   void Advance() { index_++; }
1590 
1591  private:
1592   HInstruction* instruction_;
1593   size_t index_;
1594 
1595   DISALLOW_COPY_AND_ASSIGN(HInputIterator);
1596 };
1597 
1598 class HInstructionIterator : public ValueObject {
1599  public:
HInstructionIterator(const HInstructionList & instructions)1600   explicit HInstructionIterator(const HInstructionList& instructions)
1601       : instruction_(instructions.first_instruction_) {
1602     next_ = Done() ? nullptr : instruction_->GetNext();
1603   }
1604 
Done()1605   bool Done() const { return instruction_ == nullptr; }
Current()1606   HInstruction* Current() const { return instruction_; }
Advance()1607   void Advance() {
1608     instruction_ = next_;
1609     next_ = Done() ? nullptr : instruction_->GetNext();
1610   }
1611 
1612  private:
1613   HInstruction* instruction_;
1614   HInstruction* next_;
1615 
1616   DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
1617 };
1618 
1619 class HBackwardInstructionIterator : public ValueObject {
1620  public:
HBackwardInstructionIterator(const HInstructionList & instructions)1621   explicit HBackwardInstructionIterator(const HInstructionList& instructions)
1622       : instruction_(instructions.last_instruction_) {
1623     next_ = Done() ? nullptr : instruction_->GetPrevious();
1624   }
1625 
Done()1626   bool Done() const { return instruction_ == nullptr; }
Current()1627   HInstruction* Current() const { return instruction_; }
Advance()1628   void Advance() {
1629     instruction_ = next_;
1630     next_ = Done() ? nullptr : instruction_->GetPrevious();
1631   }
1632 
1633  private:
1634   HInstruction* instruction_;
1635   HInstruction* next_;
1636 
1637   DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
1638 };
1639 
1640 // An embedded container with N elements of type T.  Used (with partial
1641 // specialization for N=0) because embedded arrays cannot have size 0.
1642 template<typename T, intptr_t N>
1643 class EmbeddedArray {
1644  public:
EmbeddedArray()1645   EmbeddedArray() : elements_() {}
1646 
GetLength()1647   intptr_t GetLength() const { return N; }
1648 
1649   const T& operator[](intptr_t i) const {
1650     DCHECK_LT(i, GetLength());
1651     return elements_[i];
1652   }
1653 
1654   T& operator[](intptr_t i) {
1655     DCHECK_LT(i, GetLength());
1656     return elements_[i];
1657   }
1658 
At(intptr_t i)1659   const T& At(intptr_t i) const {
1660     return (*this)[i];
1661   }
1662 
SetAt(intptr_t i,const T & val)1663   void SetAt(intptr_t i, const T& val) {
1664     (*this)[i] = val;
1665   }
1666 
1667  private:
1668   T elements_[N];
1669 };
1670 
1671 template<typename T>
1672 class EmbeddedArray<T, 0> {
1673  public:
length()1674   intptr_t length() const { return 0; }
1675   const T& operator[](intptr_t i) const {
1676     UNUSED(i);
1677     LOG(FATAL) << "Unreachable";
1678     UNREACHABLE();
1679   }
1680   T& operator[](intptr_t i) {
1681     UNUSED(i);
1682     LOG(FATAL) << "Unreachable";
1683     UNREACHABLE();
1684   }
1685 };
1686 
1687 template<intptr_t N>
1688 class HTemplateInstruction: public HInstruction {
1689  public:
1690   HTemplateInstruction<N>(SideEffects side_effects)
HInstruction(side_effects)1691       : HInstruction(side_effects), inputs_() {}
~HTemplateInstruction()1692   virtual ~HTemplateInstruction() {}
1693 
InputCount()1694   size_t InputCount() const OVERRIDE { return N; }
1695 
1696  protected:
InputRecordAt(size_t i)1697   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_[i]; }
1698 
SetRawInputRecordAt(size_t i,const HUserRecord<HInstruction * > & input)1699   void SetRawInputRecordAt(size_t i, const HUserRecord<HInstruction*>& input) OVERRIDE {
1700     inputs_[i] = input;
1701   }
1702 
1703  private:
1704   EmbeddedArray<HUserRecord<HInstruction*>, N> inputs_;
1705 
1706   friend class SsaBuilder;
1707 };
1708 
1709 template<intptr_t N>
1710 class HExpression : public HTemplateInstruction<N> {
1711  public:
1712   HExpression<N>(Primitive::Type type, SideEffects side_effects)
1713       : HTemplateInstruction<N>(side_effects), type_(type) {}
~HExpression()1714   virtual ~HExpression() {}
1715 
GetType()1716   Primitive::Type GetType() const OVERRIDE { return type_; }
1717 
1718  protected:
1719   Primitive::Type type_;
1720 };
1721 
1722 // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1723 // instruction that branches to the exit block.
1724 class HReturnVoid : public HTemplateInstruction<0> {
1725  public:
HReturnVoid()1726   HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
1727 
IsControlFlow()1728   bool IsControlFlow() const OVERRIDE { return true; }
1729 
1730   DECLARE_INSTRUCTION(ReturnVoid);
1731 
1732  private:
1733   DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1734 };
1735 
1736 // Represents dex's RETURN opcodes. A HReturn is a control flow
1737 // instruction that branches to the exit block.
1738 class HReturn : public HTemplateInstruction<1> {
1739  public:
HReturn(HInstruction * value)1740   explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
1741     SetRawInputAt(0, value);
1742   }
1743 
IsControlFlow()1744   bool IsControlFlow() const OVERRIDE { return true; }
1745 
1746   DECLARE_INSTRUCTION(Return);
1747 
1748  private:
1749   DISALLOW_COPY_AND_ASSIGN(HReturn);
1750 };
1751 
1752 // The exit instruction is the only instruction of the exit block.
1753 // Instructions aborting the method (HThrow and HReturn) must branch to the
1754 // exit block.
1755 class HExit : public HTemplateInstruction<0> {
1756  public:
HExit()1757   HExit() : HTemplateInstruction(SideEffects::None()) {}
1758 
IsControlFlow()1759   bool IsControlFlow() const OVERRIDE { return true; }
1760 
1761   DECLARE_INSTRUCTION(Exit);
1762 
1763  private:
1764   DISALLOW_COPY_AND_ASSIGN(HExit);
1765 };
1766 
1767 // Jumps from one block to another.
1768 class HGoto : public HTemplateInstruction<0> {
1769  public:
HGoto()1770   HGoto() : HTemplateInstruction(SideEffects::None()) {}
1771 
IsControlFlow()1772   bool IsControlFlow() const OVERRIDE { return true; }
1773 
GetSuccessor()1774   HBasicBlock* GetSuccessor() const {
1775     return GetBlock()->GetSuccessors().Get(0);
1776   }
1777 
1778   DECLARE_INSTRUCTION(Goto);
1779 
1780  private:
1781   DISALLOW_COPY_AND_ASSIGN(HGoto);
1782 };
1783 
1784 
1785 // Conditional branch. A block ending with an HIf instruction must have
1786 // two successors.
1787 class HIf : public HTemplateInstruction<1> {
1788  public:
HIf(HInstruction * input)1789   explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
1790     SetRawInputAt(0, input);
1791   }
1792 
IsControlFlow()1793   bool IsControlFlow() const OVERRIDE { return true; }
1794 
IfTrueSuccessor()1795   HBasicBlock* IfTrueSuccessor() const {
1796     return GetBlock()->GetSuccessors().Get(0);
1797   }
1798 
IfFalseSuccessor()1799   HBasicBlock* IfFalseSuccessor() const {
1800     return GetBlock()->GetSuccessors().Get(1);
1801   }
1802 
1803   DECLARE_INSTRUCTION(If);
1804 
1805  private:
1806   DISALLOW_COPY_AND_ASSIGN(HIf);
1807 };
1808 
1809 // Deoptimize to interpreter, upon checking a condition.
1810 class HDeoptimize : public HTemplateInstruction<1> {
1811  public:
HDeoptimize(HInstruction * cond,uint32_t dex_pc)1812   HDeoptimize(HInstruction* cond, uint32_t dex_pc)
1813       : HTemplateInstruction(SideEffects::None()),
1814         dex_pc_(dex_pc) {
1815     SetRawInputAt(0, cond);
1816   }
1817 
NeedsEnvironment()1818   bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()1819   bool CanThrow() const OVERRIDE { return true; }
GetDexPc()1820   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
1821 
1822   DECLARE_INSTRUCTION(Deoptimize);
1823 
1824  private:
1825   uint32_t dex_pc_;
1826 
1827   DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
1828 };
1829 
1830 class HUnaryOperation : public HExpression<1> {
1831  public:
HUnaryOperation(Primitive::Type result_type,HInstruction * input)1832   HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1833       : HExpression(result_type, SideEffects::None()) {
1834     SetRawInputAt(0, input);
1835   }
1836 
GetInput()1837   HInstruction* GetInput() const { return InputAt(0); }
GetResultType()1838   Primitive::Type GetResultType() const { return GetType(); }
1839 
CanBeMoved()1840   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)1841   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
1842     UNUSED(other);
1843     return true;
1844   }
1845 
1846   // Try to statically evaluate `operation` and return a HConstant
1847   // containing the result of this evaluation.  If `operation` cannot
1848   // be evaluated as a constant, return null.
1849   HConstant* TryStaticEvaluation() const;
1850 
1851   // Apply this operation to `x`.
1852   virtual int32_t Evaluate(int32_t x) const = 0;
1853   virtual int64_t Evaluate(int64_t x) const = 0;
1854 
1855   DECLARE_INSTRUCTION(UnaryOperation);
1856 
1857  private:
1858   DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1859 };
1860 
1861 class HBinaryOperation : public HExpression<2> {
1862  public:
HBinaryOperation(Primitive::Type result_type,HInstruction * left,HInstruction * right)1863   HBinaryOperation(Primitive::Type result_type,
1864                    HInstruction* left,
1865                    HInstruction* right) : HExpression(result_type, SideEffects::None()) {
1866     SetRawInputAt(0, left);
1867     SetRawInputAt(1, right);
1868   }
1869 
GetLeft()1870   HInstruction* GetLeft() const { return InputAt(0); }
GetRight()1871   HInstruction* GetRight() const { return InputAt(1); }
GetResultType()1872   Primitive::Type GetResultType() const { return GetType(); }
1873 
IsCommutative()1874   virtual bool IsCommutative() const { return false; }
1875 
1876   // Put constant on the right.
1877   // Returns whether order is changed.
OrderInputsWithConstantOnTheRight()1878   bool OrderInputsWithConstantOnTheRight() {
1879     HInstruction* left = InputAt(0);
1880     HInstruction* right = InputAt(1);
1881     if (left->IsConstant() && !right->IsConstant()) {
1882       ReplaceInput(right, 0);
1883       ReplaceInput(left, 1);
1884       return true;
1885     }
1886     return false;
1887   }
1888 
1889   // Order inputs by instruction id, but favor constant on the right side.
1890   // This helps GVN for commutative ops.
OrderInputs()1891   void OrderInputs() {
1892     DCHECK(IsCommutative());
1893     HInstruction* left = InputAt(0);
1894     HInstruction* right = InputAt(1);
1895     if (left == right || (!left->IsConstant() && right->IsConstant())) {
1896       return;
1897     }
1898     if (OrderInputsWithConstantOnTheRight()) {
1899       return;
1900     }
1901     // Order according to instruction id.
1902     if (left->GetId() > right->GetId()) {
1903       ReplaceInput(right, 0);
1904       ReplaceInput(left, 1);
1905     }
1906   }
1907 
CanBeMoved()1908   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)1909   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
1910     UNUSED(other);
1911     return true;
1912   }
1913 
1914   // Try to statically evaluate `operation` and return a HConstant
1915   // containing the result of this evaluation.  If `operation` cannot
1916   // be evaluated as a constant, return null.
1917   HConstant* TryStaticEvaluation() const;
1918 
1919   // Apply this operation to `x` and `y`.
1920   virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1921   virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1922 
1923   // Returns an input that can legally be used as the right input and is
1924   // constant, or null.
1925   HConstant* GetConstantRight() const;
1926 
1927   // If `GetConstantRight()` returns one of the input, this returns the other
1928   // one. Otherwise it returns null.
1929   HInstruction* GetLeastConstantLeft() const;
1930 
1931   DECLARE_INSTRUCTION(BinaryOperation);
1932 
1933  private:
1934   DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1935 };
1936 
1937 class HCondition : public HBinaryOperation {
1938  public:
HCondition(HInstruction * first,HInstruction * second)1939   HCondition(HInstruction* first, HInstruction* second)
1940       : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1941         needs_materialization_(true) {}
1942 
NeedsMaterialization()1943   bool NeedsMaterialization() const { return needs_materialization_; }
ClearNeedsMaterialization()1944   void ClearNeedsMaterialization() { needs_materialization_ = false; }
1945 
1946   // For code generation purposes, returns whether this instruction is just before
1947   // `instruction`, and disregard moves in between.
1948   bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const;
1949 
1950   DECLARE_INSTRUCTION(Condition);
1951 
1952   virtual IfCondition GetCondition() const = 0;
1953 
1954  private:
1955   // For register allocation purposes, returns whether this instruction needs to be
1956   // materialized (that is, not just be in the processor flags).
1957   bool needs_materialization_;
1958 
1959   DISALLOW_COPY_AND_ASSIGN(HCondition);
1960 };
1961 
1962 // Instruction to check if two inputs are equal to each other.
1963 class HEqual : public HCondition {
1964  public:
HEqual(HInstruction * first,HInstruction * second)1965   HEqual(HInstruction* first, HInstruction* second)
1966       : HCondition(first, second) {}
1967 
IsCommutative()1968   bool IsCommutative() const OVERRIDE { return true; }
1969 
Evaluate(int32_t x,int32_t y)1970   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1971     return x == y ? 1 : 0;
1972   }
Evaluate(int64_t x,int64_t y)1973   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1974     return x == y ? 1 : 0;
1975   }
1976 
1977   DECLARE_INSTRUCTION(Equal);
1978 
GetCondition()1979   IfCondition GetCondition() const OVERRIDE {
1980     return kCondEQ;
1981   }
1982 
1983  private:
1984   DISALLOW_COPY_AND_ASSIGN(HEqual);
1985 };
1986 
1987 class HNotEqual : public HCondition {
1988  public:
HNotEqual(HInstruction * first,HInstruction * second)1989   HNotEqual(HInstruction* first, HInstruction* second)
1990       : HCondition(first, second) {}
1991 
IsCommutative()1992   bool IsCommutative() const OVERRIDE { return true; }
1993 
Evaluate(int32_t x,int32_t y)1994   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1995     return x != y ? 1 : 0;
1996   }
Evaluate(int64_t x,int64_t y)1997   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1998     return x != y ? 1 : 0;
1999   }
2000 
2001   DECLARE_INSTRUCTION(NotEqual);
2002 
GetCondition()2003   IfCondition GetCondition() const OVERRIDE {
2004     return kCondNE;
2005   }
2006 
2007  private:
2008   DISALLOW_COPY_AND_ASSIGN(HNotEqual);
2009 };
2010 
2011 class HLessThan : public HCondition {
2012  public:
HLessThan(HInstruction * first,HInstruction * second)2013   HLessThan(HInstruction* first, HInstruction* second)
2014       : HCondition(first, second) {}
2015 
Evaluate(int32_t x,int32_t y)2016   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2017     return x < y ? 1 : 0;
2018   }
Evaluate(int64_t x,int64_t y)2019   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2020     return x < y ? 1 : 0;
2021   }
2022 
2023   DECLARE_INSTRUCTION(LessThan);
2024 
GetCondition()2025   IfCondition GetCondition() const OVERRIDE {
2026     return kCondLT;
2027   }
2028 
2029  private:
2030   DISALLOW_COPY_AND_ASSIGN(HLessThan);
2031 };
2032 
2033 class HLessThanOrEqual : public HCondition {
2034  public:
HLessThanOrEqual(HInstruction * first,HInstruction * second)2035   HLessThanOrEqual(HInstruction* first, HInstruction* second)
2036       : HCondition(first, second) {}
2037 
Evaluate(int32_t x,int32_t y)2038   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2039     return x <= y ? 1 : 0;
2040   }
Evaluate(int64_t x,int64_t y)2041   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2042     return x <= y ? 1 : 0;
2043   }
2044 
2045   DECLARE_INSTRUCTION(LessThanOrEqual);
2046 
GetCondition()2047   IfCondition GetCondition() const OVERRIDE {
2048     return kCondLE;
2049   }
2050 
2051  private:
2052   DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
2053 };
2054 
2055 class HGreaterThan : public HCondition {
2056  public:
HGreaterThan(HInstruction * first,HInstruction * second)2057   HGreaterThan(HInstruction* first, HInstruction* second)
2058       : HCondition(first, second) {}
2059 
Evaluate(int32_t x,int32_t y)2060   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2061     return x > y ? 1 : 0;
2062   }
Evaluate(int64_t x,int64_t y)2063   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2064     return x > y ? 1 : 0;
2065   }
2066 
2067   DECLARE_INSTRUCTION(GreaterThan);
2068 
GetCondition()2069   IfCondition GetCondition() const OVERRIDE {
2070     return kCondGT;
2071   }
2072 
2073  private:
2074   DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
2075 };
2076 
2077 class HGreaterThanOrEqual : public HCondition {
2078  public:
HGreaterThanOrEqual(HInstruction * first,HInstruction * second)2079   HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
2080       : HCondition(first, second) {}
2081 
Evaluate(int32_t x,int32_t y)2082   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2083     return x >= y ? 1 : 0;
2084   }
Evaluate(int64_t x,int64_t y)2085   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2086     return x >= y ? 1 : 0;
2087   }
2088 
2089   DECLARE_INSTRUCTION(GreaterThanOrEqual);
2090 
GetCondition()2091   IfCondition GetCondition() const OVERRIDE {
2092     return kCondGE;
2093   }
2094 
2095  private:
2096   DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
2097 };
2098 
2099 
2100 // Instruction to check how two inputs compare to each other.
2101 // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
2102 class HCompare : public HBinaryOperation {
2103  public:
2104   // The bias applies for floating point operations and indicates how NaN
2105   // comparisons are treated:
2106   enum Bias {
2107     kNoBias,  // bias is not applicable (i.e. for long operation)
2108     kGtBias,  // return 1 for NaN comparisons
2109     kLtBias,  // return -1 for NaN comparisons
2110   };
2111 
HCompare(Primitive::Type type,HInstruction * first,HInstruction * second,Bias bias,uint32_t dex_pc)2112   HCompare(Primitive::Type type,
2113            HInstruction* first,
2114            HInstruction* second,
2115            Bias bias,
2116            uint32_t dex_pc)
2117       : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias), dex_pc_(dex_pc) {
2118     DCHECK_EQ(type, first->GetType());
2119     DCHECK_EQ(type, second->GetType());
2120   }
2121 
Evaluate(int32_t x,int32_t y)2122   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2123     return
2124       x == y ? 0 :
2125       x > y ? 1 :
2126       -1;
2127   }
2128 
Evaluate(int64_t x,int64_t y)2129   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2130     return
2131       x == y ? 0 :
2132       x > y ? 1 :
2133       -1;
2134   }
2135 
InstructionDataEquals(HInstruction * other)2136   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2137     return bias_ == other->AsCompare()->bias_;
2138   }
2139 
IsGtBias()2140   bool IsGtBias() { return bias_ == kGtBias; }
2141 
GetDexPc()2142   uint32_t GetDexPc() const { return dex_pc_; }
2143 
2144   DECLARE_INSTRUCTION(Compare);
2145 
2146  private:
2147   const Bias bias_;
2148   const uint32_t dex_pc_;
2149 
2150   DISALLOW_COPY_AND_ASSIGN(HCompare);
2151 };
2152 
2153 // A local in the graph. Corresponds to a Dex register.
2154 class HLocal : public HTemplateInstruction<0> {
2155  public:
HLocal(uint16_t reg_number)2156   explicit HLocal(uint16_t reg_number)
2157       : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
2158 
2159   DECLARE_INSTRUCTION(Local);
2160 
GetRegNumber()2161   uint16_t GetRegNumber() const { return reg_number_; }
2162 
2163  private:
2164   // The Dex register number.
2165   const uint16_t reg_number_;
2166 
2167   DISALLOW_COPY_AND_ASSIGN(HLocal);
2168 };
2169 
2170 // Load a given local. The local is an input of this instruction.
2171 class HLoadLocal : public HExpression<1> {
2172  public:
HLoadLocal(HLocal * local,Primitive::Type type)2173   HLoadLocal(HLocal* local, Primitive::Type type)
2174       : HExpression(type, SideEffects::None()) {
2175     SetRawInputAt(0, local);
2176   }
2177 
GetLocal()2178   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2179 
2180   DECLARE_INSTRUCTION(LoadLocal);
2181 
2182  private:
2183   DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
2184 };
2185 
2186 // Store a value in a given local. This instruction has two inputs: the value
2187 // and the local.
2188 class HStoreLocal : public HTemplateInstruction<2> {
2189  public:
HStoreLocal(HLocal * local,HInstruction * value)2190   HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
2191     SetRawInputAt(0, local);
2192     SetRawInputAt(1, value);
2193   }
2194 
GetLocal()2195   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
2196 
2197   DECLARE_INSTRUCTION(StoreLocal);
2198 
2199  private:
2200   DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
2201 };
2202 
2203 class HConstant : public HExpression<0> {
2204  public:
HConstant(Primitive::Type type)2205   explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
2206 
CanBeMoved()2207   bool CanBeMoved() const OVERRIDE { return true; }
2208 
IsMinusOne()2209   virtual bool IsMinusOne() const { return false; }
IsZero()2210   virtual bool IsZero() const { return false; }
IsOne()2211   virtual bool IsOne() const { return false; }
2212 
2213   DECLARE_INSTRUCTION(Constant);
2214 
2215  private:
2216   DISALLOW_COPY_AND_ASSIGN(HConstant);
2217 };
2218 
2219 class HFloatConstant : public HConstant {
2220  public:
GetValue()2221   float GetValue() const { return value_; }
2222 
InstructionDataEquals(HInstruction * other)2223   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2224     return bit_cast<uint32_t, float>(other->AsFloatConstant()->value_) ==
2225         bit_cast<uint32_t, float>(value_);
2226   }
2227 
ComputeHashCode()2228   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2229 
IsMinusOne()2230   bool IsMinusOne() const OVERRIDE {
2231     return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
2232         bit_cast<uint32_t, float>((-1.0f));
2233   }
IsZero()2234   bool IsZero() const OVERRIDE {
2235     return AsFloatConstant()->GetValue() == 0.0f;
2236   }
IsOne()2237   bool IsOne() const OVERRIDE {
2238     return bit_cast<uint32_t, float>(AsFloatConstant()->GetValue()) ==
2239         bit_cast<uint32_t, float>(1.0f);
2240   }
2241 
2242   DECLARE_INSTRUCTION(FloatConstant);
2243 
2244  private:
HFloatConstant(float value)2245   explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
HFloatConstant(int32_t value)2246   explicit HFloatConstant(int32_t value)
2247       : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {}
2248 
2249   const float value_;
2250 
2251   // Only the SsaBuilder and HGraph can create floating-point constants.
2252   friend class SsaBuilder;
2253   friend class HGraph;
2254   DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
2255 };
2256 
2257 class HDoubleConstant : public HConstant {
2258  public:
GetValue()2259   double GetValue() const { return value_; }
2260 
InstructionDataEquals(HInstruction * other)2261   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2262     return bit_cast<uint64_t, double>(other->AsDoubleConstant()->value_) ==
2263         bit_cast<uint64_t, double>(value_);
2264   }
2265 
ComputeHashCode()2266   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2267 
IsMinusOne()2268   bool IsMinusOne() const OVERRIDE {
2269     return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
2270         bit_cast<uint64_t, double>((-1.0));
2271   }
IsZero()2272   bool IsZero() const OVERRIDE {
2273     return AsDoubleConstant()->GetValue() == 0.0;
2274   }
IsOne()2275   bool IsOne() const OVERRIDE {
2276     return bit_cast<uint64_t, double>(AsDoubleConstant()->GetValue()) ==
2277         bit_cast<uint64_t, double>(1.0);
2278   }
2279 
2280   DECLARE_INSTRUCTION(DoubleConstant);
2281 
2282  private:
HDoubleConstant(double value)2283   explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
HDoubleConstant(int64_t value)2284   explicit HDoubleConstant(int64_t value)
2285       : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {}
2286 
2287   const double value_;
2288 
2289   // Only the SsaBuilder and HGraph can create floating-point constants.
2290   friend class SsaBuilder;
2291   friend class HGraph;
2292   DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
2293 };
2294 
2295 class HNullConstant : public HConstant {
2296  public:
InstructionDataEquals(HInstruction * other ATTRIBUTE_UNUSED)2297   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2298     return true;
2299   }
2300 
ComputeHashCode()2301   size_t ComputeHashCode() const OVERRIDE { return 0; }
2302 
2303   DECLARE_INSTRUCTION(NullConstant);
2304 
2305  private:
HNullConstant()2306   HNullConstant() : HConstant(Primitive::kPrimNot) {}
2307 
2308   friend class HGraph;
2309   DISALLOW_COPY_AND_ASSIGN(HNullConstant);
2310 };
2311 
2312 // Constants of the type int. Those can be from Dex instructions, or
2313 // synthesized (for example with the if-eqz instruction).
2314 class HIntConstant : public HConstant {
2315  public:
GetValue()2316   int32_t GetValue() const { return value_; }
2317 
InstructionDataEquals(HInstruction * other)2318   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2319     return other->AsIntConstant()->value_ == value_;
2320   }
2321 
ComputeHashCode()2322   size_t ComputeHashCode() const OVERRIDE { return GetValue(); }
2323 
IsMinusOne()2324   bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
IsZero()2325   bool IsZero() const OVERRIDE { return GetValue() == 0; }
IsOne()2326   bool IsOne() const OVERRIDE { return GetValue() == 1; }
2327 
2328   DECLARE_INSTRUCTION(IntConstant);
2329 
2330  private:
HIntConstant(int32_t value)2331   explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
2332 
2333   const int32_t value_;
2334 
2335   friend class HGraph;
2336   ART_FRIEND_TEST(GraphTest, InsertInstructionBefore);
2337   ART_FRIEND_TYPED_TEST(ParallelMoveTest, ConstantLast);
2338   DISALLOW_COPY_AND_ASSIGN(HIntConstant);
2339 };
2340 
2341 class HLongConstant : public HConstant {
2342  public:
GetValue()2343   int64_t GetValue() const { return value_; }
2344 
InstructionDataEquals(HInstruction * other)2345   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2346     return other->AsLongConstant()->value_ == value_;
2347   }
2348 
ComputeHashCode()2349   size_t ComputeHashCode() const OVERRIDE { return static_cast<size_t>(GetValue()); }
2350 
IsMinusOne()2351   bool IsMinusOne() const OVERRIDE { return GetValue() == -1; }
IsZero()2352   bool IsZero() const OVERRIDE { return GetValue() == 0; }
IsOne()2353   bool IsOne() const OVERRIDE { return GetValue() == 1; }
2354 
2355   DECLARE_INSTRUCTION(LongConstant);
2356 
2357  private:
HLongConstant(int64_t value)2358   explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
2359 
2360   const int64_t value_;
2361 
2362   friend class HGraph;
2363   DISALLOW_COPY_AND_ASSIGN(HLongConstant);
2364 };
2365 
2366 enum class Intrinsics {
2367 #define OPTIMIZING_INTRINSICS(Name, IsStatic) k ## Name,
2368 #include "intrinsics_list.h"
2369   kNone,
2370   INTRINSICS_LIST(OPTIMIZING_INTRINSICS)
2371 #undef INTRINSICS_LIST
2372 #undef OPTIMIZING_INTRINSICS
2373 };
2374 std::ostream& operator<<(std::ostream& os, const Intrinsics& intrinsic);
2375 
2376 class HInvoke : public HInstruction {
2377  public:
InputCount()2378   size_t InputCount() const OVERRIDE { return inputs_.Size(); }
2379 
2380   // Runtime needs to walk the stack, so Dex -> Dex calls need to
2381   // know their environment.
NeedsEnvironment()2382   bool NeedsEnvironment() const OVERRIDE { return true; }
2383 
SetArgumentAt(size_t index,HInstruction * argument)2384   void SetArgumentAt(size_t index, HInstruction* argument) {
2385     SetRawInputAt(index, argument);
2386   }
2387 
2388   // Return the number of arguments.  This number can be lower than
2389   // the number of inputs returned by InputCount(), as some invoke
2390   // instructions (e.g. HInvokeStaticOrDirect) can have non-argument
2391   // inputs at the end of their list of inputs.
GetNumberOfArguments()2392   uint32_t GetNumberOfArguments() const { return number_of_arguments_; }
2393 
GetType()2394   Primitive::Type GetType() const OVERRIDE { return return_type_; }
2395 
GetDexPc()2396   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
2397 
GetDexMethodIndex()2398   uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2399 
GetIntrinsic()2400   Intrinsics GetIntrinsic() const {
2401     return intrinsic_;
2402   }
2403 
SetIntrinsic(Intrinsics intrinsic)2404   void SetIntrinsic(Intrinsics intrinsic) {
2405     intrinsic_ = intrinsic;
2406   }
2407 
2408   DECLARE_INSTRUCTION(Invoke);
2409 
2410  protected:
HInvoke(ArenaAllocator * arena,uint32_t number_of_arguments,uint32_t number_of_other_inputs,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index)2411   HInvoke(ArenaAllocator* arena,
2412           uint32_t number_of_arguments,
2413           uint32_t number_of_other_inputs,
2414           Primitive::Type return_type,
2415           uint32_t dex_pc,
2416           uint32_t dex_method_index)
2417     : HInstruction(SideEffects::All()),
2418       number_of_arguments_(number_of_arguments),
2419       inputs_(arena, number_of_arguments),
2420       return_type_(return_type),
2421       dex_pc_(dex_pc),
2422       dex_method_index_(dex_method_index),
2423       intrinsic_(Intrinsics::kNone) {
2424     uint32_t number_of_inputs = number_of_arguments + number_of_other_inputs;
2425     inputs_.SetSize(number_of_inputs);
2426   }
2427 
InputRecordAt(size_t i)2428   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
SetRawInputRecordAt(size_t index,const HUserRecord<HInstruction * > & input)2429   void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
2430     inputs_.Put(index, input);
2431   }
2432 
2433   uint32_t number_of_arguments_;
2434   GrowableArray<HUserRecord<HInstruction*> > inputs_;
2435   const Primitive::Type return_type_;
2436   const uint32_t dex_pc_;
2437   const uint32_t dex_method_index_;
2438   Intrinsics intrinsic_;
2439 
2440  private:
2441   DISALLOW_COPY_AND_ASSIGN(HInvoke);
2442 };
2443 
2444 class HInvokeStaticOrDirect : public HInvoke {
2445  public:
2446   // Requirements of this method call regarding the class
2447   // initialization (clinit) check of its declaring class.
2448   enum class ClinitCheckRequirement {
2449     kNone,      // Class already initialized.
2450     kExplicit,  // Static call having explicit clinit check as last input.
2451     kImplicit,  // Static call implicitly requiring a clinit check.
2452   };
2453 
HInvokeStaticOrDirect(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,bool is_recursive,int32_t string_init_offset,InvokeType original_invoke_type,InvokeType invoke_type,ClinitCheckRequirement clinit_check_requirement)2454   HInvokeStaticOrDirect(ArenaAllocator* arena,
2455                         uint32_t number_of_arguments,
2456                         Primitive::Type return_type,
2457                         uint32_t dex_pc,
2458                         uint32_t dex_method_index,
2459                         bool is_recursive,
2460                         int32_t string_init_offset,
2461                         InvokeType original_invoke_type,
2462                         InvokeType invoke_type,
2463                         ClinitCheckRequirement clinit_check_requirement)
2464       : HInvoke(arena,
2465                 number_of_arguments,
2466                 clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
2467                 return_type,
2468                 dex_pc,
2469                 dex_method_index),
2470         original_invoke_type_(original_invoke_type),
2471         invoke_type_(invoke_type),
2472         is_recursive_(is_recursive),
2473         clinit_check_requirement_(clinit_check_requirement),
2474         string_init_offset_(string_init_offset) {}
2475 
CanDoImplicitNullCheckOn(HInstruction * obj)2476   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2477     UNUSED(obj);
2478     // We access the method via the dex cache so we can't do an implicit null check.
2479     // TODO: for intrinsics we can generate implicit null checks.
2480     return false;
2481   }
2482 
GetOriginalInvokeType()2483   InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
GetInvokeType()2484   InvokeType GetInvokeType() const { return invoke_type_; }
IsRecursive()2485   bool IsRecursive() const { return is_recursive_; }
NeedsDexCache()2486   bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
IsStringInit()2487   bool IsStringInit() const { return string_init_offset_ != 0; }
GetStringInitOffset()2488   int32_t GetStringInitOffset() const { return string_init_offset_; }
2489 
2490   // Is this instruction a call to a static method?
IsStatic()2491   bool IsStatic() const {
2492     return GetInvokeType() == kStatic;
2493   }
2494 
2495   // Remove the art::HLoadClass instruction set as last input by
2496   // art::PrepareForRegisterAllocation::VisitClinitCheck in lieu of
2497   // the initial art::HClinitCheck instruction (only relevant for
2498   // static calls with explicit clinit check).
RemoveLoadClassAsLastInput()2499   void RemoveLoadClassAsLastInput() {
2500     DCHECK(IsStaticWithExplicitClinitCheck());
2501     size_t last_input_index = InputCount() - 1;
2502     HInstruction* last_input = InputAt(last_input_index);
2503     DCHECK(last_input != nullptr);
2504     DCHECK(last_input->IsLoadClass()) << last_input->DebugName();
2505     RemoveAsUserOfInput(last_input_index);
2506     inputs_.DeleteAt(last_input_index);
2507     clinit_check_requirement_ = ClinitCheckRequirement::kImplicit;
2508     DCHECK(IsStaticWithImplicitClinitCheck());
2509   }
2510 
2511   // Is this a call to a static method whose declaring class has an
2512   // explicit intialization check in the graph?
IsStaticWithExplicitClinitCheck()2513   bool IsStaticWithExplicitClinitCheck() const {
2514     return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kExplicit);
2515   }
2516 
2517   // Is this a call to a static method whose declaring class has an
2518   // implicit intialization check requirement?
IsStaticWithImplicitClinitCheck()2519   bool IsStaticWithImplicitClinitCheck() const {
2520     return IsStatic() && (clinit_check_requirement_ == ClinitCheckRequirement::kImplicit);
2521   }
2522 
2523   DECLARE_INSTRUCTION(InvokeStaticOrDirect);
2524 
2525  protected:
InputRecordAt(size_t i)2526   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE {
2527     const HUserRecord<HInstruction*> input_record = HInvoke::InputRecordAt(i);
2528     if (kIsDebugBuild && IsStaticWithExplicitClinitCheck() && (i == InputCount() - 1)) {
2529       HInstruction* input = input_record.GetInstruction();
2530       // `input` is the last input of a static invoke marked as having
2531       // an explicit clinit check. It must either be:
2532       // - an art::HClinitCheck instruction, set by art::HGraphBuilder; or
2533       // - an art::HLoadClass instruction, set by art::PrepareForRegisterAllocation.
2534       DCHECK(input != nullptr);
2535       DCHECK(input->IsClinitCheck() || input->IsLoadClass()) << input->DebugName();
2536     }
2537     return input_record;
2538   }
2539 
2540  private:
2541   const InvokeType original_invoke_type_;
2542   const InvokeType invoke_type_;
2543   const bool is_recursive_;
2544   ClinitCheckRequirement clinit_check_requirement_;
2545   // Thread entrypoint offset for string init method if this is a string init invoke.
2546   // Note that there are multiple string init methods, each having its own offset.
2547   int32_t string_init_offset_;
2548 
2549   DISALLOW_COPY_AND_ASSIGN(HInvokeStaticOrDirect);
2550 };
2551 
2552 class HInvokeVirtual : public HInvoke {
2553  public:
HInvokeVirtual(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,uint32_t vtable_index)2554   HInvokeVirtual(ArenaAllocator* arena,
2555                  uint32_t number_of_arguments,
2556                  Primitive::Type return_type,
2557                  uint32_t dex_pc,
2558                  uint32_t dex_method_index,
2559                  uint32_t vtable_index)
2560       : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index),
2561         vtable_index_(vtable_index) {}
2562 
CanDoImplicitNullCheckOn(HInstruction * obj)2563   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2564     // TODO: Add implicit null checks in intrinsics.
2565     return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
2566   }
2567 
GetVTableIndex()2568   uint32_t GetVTableIndex() const { return vtable_index_; }
2569 
2570   DECLARE_INSTRUCTION(InvokeVirtual);
2571 
2572  private:
2573   const uint32_t vtable_index_;
2574 
2575   DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
2576 };
2577 
2578 class HInvokeInterface : public HInvoke {
2579  public:
HInvokeInterface(ArenaAllocator * arena,uint32_t number_of_arguments,Primitive::Type return_type,uint32_t dex_pc,uint32_t dex_method_index,uint32_t imt_index)2580   HInvokeInterface(ArenaAllocator* arena,
2581                    uint32_t number_of_arguments,
2582                    Primitive::Type return_type,
2583                    uint32_t dex_pc,
2584                    uint32_t dex_method_index,
2585                    uint32_t imt_index)
2586       : HInvoke(arena, number_of_arguments, 0u, return_type, dex_pc, dex_method_index),
2587         imt_index_(imt_index) {}
2588 
CanDoImplicitNullCheckOn(HInstruction * obj)2589   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
2590     // TODO: Add implicit null checks in intrinsics.
2591     return (obj == InputAt(0)) && !GetLocations()->Intrinsified();
2592   }
2593 
GetImtIndex()2594   uint32_t GetImtIndex() const { return imt_index_; }
GetDexMethodIndex()2595   uint32_t GetDexMethodIndex() const { return dex_method_index_; }
2596 
2597   DECLARE_INSTRUCTION(InvokeInterface);
2598 
2599  private:
2600   const uint32_t imt_index_;
2601 
2602   DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
2603 };
2604 
2605 class HNewInstance : public HExpression<0> {
2606  public:
HNewInstance(uint32_t dex_pc,uint16_t type_index,QuickEntrypointEnum entrypoint)2607   HNewInstance(uint32_t dex_pc, uint16_t type_index, QuickEntrypointEnum entrypoint)
2608       : HExpression(Primitive::kPrimNot, SideEffects::None()),
2609         dex_pc_(dex_pc),
2610         type_index_(type_index),
2611         entrypoint_(entrypoint) {}
2612 
GetDexPc()2613   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
GetTypeIndex()2614   uint16_t GetTypeIndex() const { return type_index_; }
2615 
2616   // Calls runtime so needs an environment.
NeedsEnvironment()2617   bool NeedsEnvironment() const OVERRIDE { return true; }
2618   // It may throw when called on:
2619   //   - interfaces
2620   //   - abstract/innaccessible/unknown classes
2621   // TODO: optimize when possible.
CanThrow()2622   bool CanThrow() const OVERRIDE { return true; }
2623 
CanBeNull()2624   bool CanBeNull() const OVERRIDE { return false; }
2625 
GetEntrypoint()2626   QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2627 
2628   DECLARE_INSTRUCTION(NewInstance);
2629 
2630  private:
2631   const uint32_t dex_pc_;
2632   const uint16_t type_index_;
2633   const QuickEntrypointEnum entrypoint_;
2634 
2635   DISALLOW_COPY_AND_ASSIGN(HNewInstance);
2636 };
2637 
2638 class HNeg : public HUnaryOperation {
2639  public:
HNeg(Primitive::Type result_type,HInstruction * input)2640   explicit HNeg(Primitive::Type result_type, HInstruction* input)
2641       : HUnaryOperation(result_type, input) {}
2642 
Evaluate(int32_t x)2643   int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
Evaluate(int64_t x)2644   int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
2645 
2646   DECLARE_INSTRUCTION(Neg);
2647 
2648  private:
2649   DISALLOW_COPY_AND_ASSIGN(HNeg);
2650 };
2651 
2652 class HNewArray : public HExpression<1> {
2653  public:
HNewArray(HInstruction * length,uint32_t dex_pc,uint16_t type_index,QuickEntrypointEnum entrypoint)2654   HNewArray(HInstruction* length,
2655             uint32_t dex_pc,
2656             uint16_t type_index,
2657             QuickEntrypointEnum entrypoint)
2658       : HExpression(Primitive::kPrimNot, SideEffects::None()),
2659         dex_pc_(dex_pc),
2660         type_index_(type_index),
2661         entrypoint_(entrypoint) {
2662     SetRawInputAt(0, length);
2663   }
2664 
GetDexPc()2665   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
GetTypeIndex()2666   uint16_t GetTypeIndex() const { return type_index_; }
2667 
2668   // Calls runtime so needs an environment.
NeedsEnvironment()2669   bool NeedsEnvironment() const OVERRIDE { return true; }
2670 
2671   // May throw NegativeArraySizeException, OutOfMemoryError, etc.
CanThrow()2672   bool CanThrow() const OVERRIDE { return true; }
2673 
CanBeNull()2674   bool CanBeNull() const OVERRIDE { return false; }
2675 
GetEntrypoint()2676   QuickEntrypointEnum GetEntrypoint() const { return entrypoint_; }
2677 
2678   DECLARE_INSTRUCTION(NewArray);
2679 
2680  private:
2681   const uint32_t dex_pc_;
2682   const uint16_t type_index_;
2683   const QuickEntrypointEnum entrypoint_;
2684 
2685   DISALLOW_COPY_AND_ASSIGN(HNewArray);
2686 };
2687 
2688 class HAdd : public HBinaryOperation {
2689  public:
HAdd(Primitive::Type result_type,HInstruction * left,HInstruction * right)2690   HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2691       : HBinaryOperation(result_type, left, right) {}
2692 
IsCommutative()2693   bool IsCommutative() const OVERRIDE { return true; }
2694 
Evaluate(int32_t x,int32_t y)2695   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2696     return x + y;
2697   }
Evaluate(int64_t x,int64_t y)2698   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2699     return x + y;
2700   }
2701 
2702   DECLARE_INSTRUCTION(Add);
2703 
2704  private:
2705   DISALLOW_COPY_AND_ASSIGN(HAdd);
2706 };
2707 
2708 class HSub : public HBinaryOperation {
2709  public:
HSub(Primitive::Type result_type,HInstruction * left,HInstruction * right)2710   HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2711       : HBinaryOperation(result_type, left, right) {}
2712 
Evaluate(int32_t x,int32_t y)2713   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2714     return x - y;
2715   }
Evaluate(int64_t x,int64_t y)2716   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2717     return x - y;
2718   }
2719 
2720   DECLARE_INSTRUCTION(Sub);
2721 
2722  private:
2723   DISALLOW_COPY_AND_ASSIGN(HSub);
2724 };
2725 
2726 class HMul : public HBinaryOperation {
2727  public:
HMul(Primitive::Type result_type,HInstruction * left,HInstruction * right)2728   HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2729       : HBinaryOperation(result_type, left, right) {}
2730 
IsCommutative()2731   bool IsCommutative() const OVERRIDE { return true; }
2732 
Evaluate(int32_t x,int32_t y)2733   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x * y; }
Evaluate(int64_t x,int64_t y)2734   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x * y; }
2735 
2736   DECLARE_INSTRUCTION(Mul);
2737 
2738  private:
2739   DISALLOW_COPY_AND_ASSIGN(HMul);
2740 };
2741 
2742 class HDiv : public HBinaryOperation {
2743  public:
HDiv(Primitive::Type result_type,HInstruction * left,HInstruction * right,uint32_t dex_pc)2744   HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2745       : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2746 
Evaluate(int32_t x,int32_t y)2747   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2748     // Our graph structure ensures we never have 0 for `y` during constant folding.
2749     DCHECK_NE(y, 0);
2750     // Special case -1 to avoid getting a SIGFPE on x86(_64).
2751     return (y == -1) ? -x : x / y;
2752   }
2753 
Evaluate(int64_t x,int64_t y)2754   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2755     DCHECK_NE(y, 0);
2756     // Special case -1 to avoid getting a SIGFPE on x86(_64).
2757     return (y == -1) ? -x : x / y;
2758   }
2759 
GetDexPc()2760   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
2761 
2762   DECLARE_INSTRUCTION(Div);
2763 
2764  private:
2765   const uint32_t dex_pc_;
2766 
2767   DISALLOW_COPY_AND_ASSIGN(HDiv);
2768 };
2769 
2770 class HRem : public HBinaryOperation {
2771  public:
HRem(Primitive::Type result_type,HInstruction * left,HInstruction * right,uint32_t dex_pc)2772   HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
2773       : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
2774 
Evaluate(int32_t x,int32_t y)2775   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2776     DCHECK_NE(y, 0);
2777     // Special case -1 to avoid getting a SIGFPE on x86(_64).
2778     return (y == -1) ? 0 : x % y;
2779   }
2780 
Evaluate(int64_t x,int64_t y)2781   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2782     DCHECK_NE(y, 0);
2783     // Special case -1 to avoid getting a SIGFPE on x86(_64).
2784     return (y == -1) ? 0 : x % y;
2785   }
2786 
GetDexPc()2787   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
2788 
2789   DECLARE_INSTRUCTION(Rem);
2790 
2791  private:
2792   const uint32_t dex_pc_;
2793 
2794   DISALLOW_COPY_AND_ASSIGN(HRem);
2795 };
2796 
2797 class HDivZeroCheck : public HExpression<1> {
2798  public:
HDivZeroCheck(HInstruction * value,uint32_t dex_pc)2799   HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
2800       : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2801     SetRawInputAt(0, value);
2802   }
2803 
CanBeMoved()2804   bool CanBeMoved() const OVERRIDE { return true; }
2805 
InstructionDataEquals(HInstruction * other)2806   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2807     UNUSED(other);
2808     return true;
2809   }
2810 
NeedsEnvironment()2811   bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()2812   bool CanThrow() const OVERRIDE { return true; }
2813 
GetDexPc()2814   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
2815 
2816   DECLARE_INSTRUCTION(DivZeroCheck);
2817 
2818  private:
2819   const uint32_t dex_pc_;
2820 
2821   DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
2822 };
2823 
2824 class HShl : public HBinaryOperation {
2825  public:
HShl(Primitive::Type result_type,HInstruction * left,HInstruction * right)2826   HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2827       : HBinaryOperation(result_type, left, right) {}
2828 
Evaluate(int32_t x,int32_t y)2829   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
Evaluate(int64_t x,int64_t y)2830   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
2831 
2832   DECLARE_INSTRUCTION(Shl);
2833 
2834  private:
2835   DISALLOW_COPY_AND_ASSIGN(HShl);
2836 };
2837 
2838 class HShr : public HBinaryOperation {
2839  public:
HShr(Primitive::Type result_type,HInstruction * left,HInstruction * right)2840   HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2841       : HBinaryOperation(result_type, left, right) {}
2842 
Evaluate(int32_t x,int32_t y)2843   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
Evaluate(int64_t x,int64_t y)2844   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
2845 
2846   DECLARE_INSTRUCTION(Shr);
2847 
2848  private:
2849   DISALLOW_COPY_AND_ASSIGN(HShr);
2850 };
2851 
2852 class HUShr : public HBinaryOperation {
2853  public:
HUShr(Primitive::Type result_type,HInstruction * left,HInstruction * right)2854   HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2855       : HBinaryOperation(result_type, left, right) {}
2856 
Evaluate(int32_t x,int32_t y)2857   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
2858     uint32_t ux = static_cast<uint32_t>(x);
2859     uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
2860     return static_cast<int32_t>(ux >> uy);
2861   }
2862 
Evaluate(int64_t x,int64_t y)2863   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
2864     uint64_t ux = static_cast<uint64_t>(x);
2865     uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
2866     return static_cast<int64_t>(ux >> uy);
2867   }
2868 
2869   DECLARE_INSTRUCTION(UShr);
2870 
2871  private:
2872   DISALLOW_COPY_AND_ASSIGN(HUShr);
2873 };
2874 
2875 class HAnd : public HBinaryOperation {
2876  public:
HAnd(Primitive::Type result_type,HInstruction * left,HInstruction * right)2877   HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2878       : HBinaryOperation(result_type, left, right) {}
2879 
IsCommutative()2880   bool IsCommutative() const OVERRIDE { return true; }
2881 
Evaluate(int32_t x,int32_t y)2882   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
Evaluate(int64_t x,int64_t y)2883   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
2884 
2885   DECLARE_INSTRUCTION(And);
2886 
2887  private:
2888   DISALLOW_COPY_AND_ASSIGN(HAnd);
2889 };
2890 
2891 class HOr : public HBinaryOperation {
2892  public:
HOr(Primitive::Type result_type,HInstruction * left,HInstruction * right)2893   HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2894       : HBinaryOperation(result_type, left, right) {}
2895 
IsCommutative()2896   bool IsCommutative() const OVERRIDE { return true; }
2897 
Evaluate(int32_t x,int32_t y)2898   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
Evaluate(int64_t x,int64_t y)2899   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
2900 
2901   DECLARE_INSTRUCTION(Or);
2902 
2903  private:
2904   DISALLOW_COPY_AND_ASSIGN(HOr);
2905 };
2906 
2907 class HXor : public HBinaryOperation {
2908  public:
HXor(Primitive::Type result_type,HInstruction * left,HInstruction * right)2909   HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
2910       : HBinaryOperation(result_type, left, right) {}
2911 
IsCommutative()2912   bool IsCommutative() const OVERRIDE { return true; }
2913 
Evaluate(int32_t x,int32_t y)2914   int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
Evaluate(int64_t x,int64_t y)2915   int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
2916 
2917   DECLARE_INSTRUCTION(Xor);
2918 
2919  private:
2920   DISALLOW_COPY_AND_ASSIGN(HXor);
2921 };
2922 
2923 // The value of a parameter in this method. Its location depends on
2924 // the calling convention.
2925 class HParameterValue : public HExpression<0> {
2926  public:
2927   HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
HExpression(parameter_type,SideEffects::None ())2928       : HExpression(parameter_type, SideEffects::None()), index_(index), is_this_(is_this) {}
2929 
GetIndex()2930   uint8_t GetIndex() const { return index_; }
2931 
CanBeNull()2932   bool CanBeNull() const OVERRIDE { return !is_this_; }
2933 
2934   DECLARE_INSTRUCTION(ParameterValue);
2935 
2936  private:
2937   // The index of this parameter in the parameters list. Must be less
2938   // than HGraph::number_of_in_vregs_.
2939   const uint8_t index_;
2940 
2941   // Whether or not the parameter value corresponds to 'this' argument.
2942   const bool is_this_;
2943 
2944   DISALLOW_COPY_AND_ASSIGN(HParameterValue);
2945 };
2946 
2947 class HNot : public HUnaryOperation {
2948  public:
HNot(Primitive::Type result_type,HInstruction * input)2949   explicit HNot(Primitive::Type result_type, HInstruction* input)
2950       : HUnaryOperation(result_type, input) {}
2951 
CanBeMoved()2952   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)2953   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2954     UNUSED(other);
2955     return true;
2956   }
2957 
Evaluate(int32_t x)2958   int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
Evaluate(int64_t x)2959   int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
2960 
2961   DECLARE_INSTRUCTION(Not);
2962 
2963  private:
2964   DISALLOW_COPY_AND_ASSIGN(HNot);
2965 };
2966 
2967 class HBooleanNot : public HUnaryOperation {
2968  public:
HBooleanNot(HInstruction * input)2969   explicit HBooleanNot(HInstruction* input)
2970       : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
2971 
CanBeMoved()2972   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)2973   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2974     UNUSED(other);
2975     return true;
2976   }
2977 
Evaluate(int32_t x)2978   int32_t Evaluate(int32_t x) const OVERRIDE {
2979     DCHECK(IsUint<1>(x));
2980     return !x;
2981   }
2982 
Evaluate(int64_t x ATTRIBUTE_UNUSED)2983   int64_t Evaluate(int64_t x ATTRIBUTE_UNUSED) const OVERRIDE {
2984     LOG(FATAL) << DebugName() << " cannot be used with 64-bit values";
2985     UNREACHABLE();
2986   }
2987 
2988   DECLARE_INSTRUCTION(BooleanNot);
2989 
2990  private:
2991   DISALLOW_COPY_AND_ASSIGN(HBooleanNot);
2992 };
2993 
2994 class HTypeConversion : public HExpression<1> {
2995  public:
2996   // Instantiate a type conversion of `input` to `result_type`.
HTypeConversion(Primitive::Type result_type,HInstruction * input,uint32_t dex_pc)2997   HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
2998       : HExpression(result_type, SideEffects::None()), dex_pc_(dex_pc) {
2999     SetRawInputAt(0, input);
3000     DCHECK_NE(input->GetType(), result_type);
3001   }
3002 
GetInput()3003   HInstruction* GetInput() const { return InputAt(0); }
GetInputType()3004   Primitive::Type GetInputType() const { return GetInput()->GetType(); }
GetResultType()3005   Primitive::Type GetResultType() const { return GetType(); }
3006 
3007   // Required by the x86 and ARM code generators when producing calls
3008   // to the runtime.
GetDexPc()3009   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3010 
CanBeMoved()3011   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other ATTRIBUTE_UNUSED)3012   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
3013 
3014   DECLARE_INSTRUCTION(TypeConversion);
3015 
3016  private:
3017   const uint32_t dex_pc_;
3018 
3019   DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
3020 };
3021 
3022 static constexpr uint32_t kNoRegNumber = -1;
3023 
3024 class HPhi : public HInstruction {
3025  public:
HPhi(ArenaAllocator * arena,uint32_t reg_number,size_t number_of_inputs,Primitive::Type type)3026   HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
3027       : HInstruction(SideEffects::None()),
3028         inputs_(arena, number_of_inputs),
3029         reg_number_(reg_number),
3030         type_(type),
3031         is_live_(false),
3032         can_be_null_(true) {
3033     inputs_.SetSize(number_of_inputs);
3034   }
3035 
3036   // Returns a type equivalent to the given `type`, but that a `HPhi` can hold.
ToPhiType(Primitive::Type type)3037   static Primitive::Type ToPhiType(Primitive::Type type) {
3038     switch (type) {
3039       case Primitive::kPrimBoolean:
3040       case Primitive::kPrimByte:
3041       case Primitive::kPrimShort:
3042       case Primitive::kPrimChar:
3043         return Primitive::kPrimInt;
3044       default:
3045         return type;
3046     }
3047   }
3048 
InputCount()3049   size_t InputCount() const OVERRIDE { return inputs_.Size(); }
3050 
3051   void AddInput(HInstruction* input);
3052   void RemoveInputAt(size_t index);
3053 
GetType()3054   Primitive::Type GetType() const OVERRIDE { return type_; }
SetType(Primitive::Type type)3055   void SetType(Primitive::Type type) { type_ = type; }
3056 
CanBeNull()3057   bool CanBeNull() const OVERRIDE { return can_be_null_; }
SetCanBeNull(bool can_be_null)3058   void SetCanBeNull(bool can_be_null) { can_be_null_ = can_be_null; }
3059 
GetRegNumber()3060   uint32_t GetRegNumber() const { return reg_number_; }
3061 
SetDead()3062   void SetDead() { is_live_ = false; }
SetLive()3063   void SetLive() { is_live_ = true; }
IsDead()3064   bool IsDead() const { return !is_live_; }
IsLive()3065   bool IsLive() const { return is_live_; }
3066 
3067   // Returns the next equivalent phi (starting from the current one) or null if there is none.
3068   // An equivalent phi is a phi having the same dex register and type.
3069   // It assumes that phis with the same dex register are adjacent.
GetNextEquivalentPhiWithSameType()3070   HPhi* GetNextEquivalentPhiWithSameType() {
3071     HInstruction* next = GetNext();
3072     while (next != nullptr && next->AsPhi()->GetRegNumber() == reg_number_) {
3073       if (next->GetType() == GetType()) {
3074         return next->AsPhi();
3075       }
3076       next = next->GetNext();
3077     }
3078     return nullptr;
3079   }
3080 
3081   DECLARE_INSTRUCTION(Phi);
3082 
3083  protected:
InputRecordAt(size_t i)3084   const HUserRecord<HInstruction*> InputRecordAt(size_t i) const OVERRIDE { return inputs_.Get(i); }
3085 
SetRawInputRecordAt(size_t index,const HUserRecord<HInstruction * > & input)3086   void SetRawInputRecordAt(size_t index, const HUserRecord<HInstruction*>& input) OVERRIDE {
3087     inputs_.Put(index, input);
3088   }
3089 
3090  private:
3091   GrowableArray<HUserRecord<HInstruction*> > inputs_;
3092   const uint32_t reg_number_;
3093   Primitive::Type type_;
3094   bool is_live_;
3095   bool can_be_null_;
3096 
3097   DISALLOW_COPY_AND_ASSIGN(HPhi);
3098 };
3099 
3100 class HNullCheck : public HExpression<1> {
3101  public:
HNullCheck(HInstruction * value,uint32_t dex_pc)3102   HNullCheck(HInstruction* value, uint32_t dex_pc)
3103       : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
3104     SetRawInputAt(0, value);
3105   }
3106 
CanBeMoved()3107   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)3108   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3109     UNUSED(other);
3110     return true;
3111   }
3112 
NeedsEnvironment()3113   bool NeedsEnvironment() const OVERRIDE { return true; }
3114 
CanThrow()3115   bool CanThrow() const OVERRIDE { return true; }
3116 
CanBeNull()3117   bool CanBeNull() const OVERRIDE { return false; }
3118 
GetDexPc()3119   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3120 
3121   DECLARE_INSTRUCTION(NullCheck);
3122 
3123  private:
3124   const uint32_t dex_pc_;
3125 
3126   DISALLOW_COPY_AND_ASSIGN(HNullCheck);
3127 };
3128 
3129 class FieldInfo : public ValueObject {
3130  public:
FieldInfo(MemberOffset field_offset,Primitive::Type field_type,bool is_volatile)3131   FieldInfo(MemberOffset field_offset, Primitive::Type field_type, bool is_volatile)
3132       : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile) {}
3133 
GetFieldOffset()3134   MemberOffset GetFieldOffset() const { return field_offset_; }
GetFieldType()3135   Primitive::Type GetFieldType() const { return field_type_; }
IsVolatile()3136   bool IsVolatile() const { return is_volatile_; }
3137 
3138  private:
3139   const MemberOffset field_offset_;
3140   const Primitive::Type field_type_;
3141   const bool is_volatile_;
3142 };
3143 
3144 class HInstanceFieldGet : public HExpression<1> {
3145  public:
HInstanceFieldGet(HInstruction * value,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile)3146   HInstanceFieldGet(HInstruction* value,
3147                     Primitive::Type field_type,
3148                     MemberOffset field_offset,
3149                     bool is_volatile)
3150       : HExpression(field_type, SideEffects::DependsOnSomething()),
3151         field_info_(field_offset, field_type, is_volatile) {
3152     SetRawInputAt(0, value);
3153   }
3154 
CanBeMoved()3155   bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
3156 
InstructionDataEquals(HInstruction * other)3157   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3158     HInstanceFieldGet* other_get = other->AsInstanceFieldGet();
3159     return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
3160   }
3161 
CanDoImplicitNullCheckOn(HInstruction * obj)3162   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3163     return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
3164   }
3165 
ComputeHashCode()3166   size_t ComputeHashCode() const OVERRIDE {
3167     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3168   }
3169 
GetFieldInfo()3170   const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()3171   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()3172   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()3173   bool IsVolatile() const { return field_info_.IsVolatile(); }
3174 
3175   DECLARE_INSTRUCTION(InstanceFieldGet);
3176 
3177  private:
3178   const FieldInfo field_info_;
3179 
3180   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
3181 };
3182 
3183 class HInstanceFieldSet : public HTemplateInstruction<2> {
3184  public:
HInstanceFieldSet(HInstruction * object,HInstruction * value,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile)3185   HInstanceFieldSet(HInstruction* object,
3186                     HInstruction* value,
3187                     Primitive::Type field_type,
3188                     MemberOffset field_offset,
3189                     bool is_volatile)
3190       : HTemplateInstruction(SideEffects::ChangesSomething()),
3191         field_info_(field_offset, field_type, is_volatile) {
3192     SetRawInputAt(0, object);
3193     SetRawInputAt(1, value);
3194   }
3195 
CanDoImplicitNullCheckOn(HInstruction * obj)3196   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3197     return (obj == InputAt(0)) && GetFieldOffset().Uint32Value() < kPageSize;
3198   }
3199 
GetFieldInfo()3200   const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()3201   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()3202   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()3203   bool IsVolatile() const { return field_info_.IsVolatile(); }
GetValue()3204   HInstruction* GetValue() const { return InputAt(1); }
3205 
3206   DECLARE_INSTRUCTION(InstanceFieldSet);
3207 
3208  private:
3209   const FieldInfo field_info_;
3210 
3211   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
3212 };
3213 
3214 class HArrayGet : public HExpression<2> {
3215  public:
HArrayGet(HInstruction * array,HInstruction * index,Primitive::Type type)3216   HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
3217       : HExpression(type, SideEffects::DependsOnSomething()) {
3218     SetRawInputAt(0, array);
3219     SetRawInputAt(1, index);
3220   }
3221 
CanBeMoved()3222   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)3223   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3224     UNUSED(other);
3225     return true;
3226   }
CanDoImplicitNullCheckOn(HInstruction * obj)3227   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3228     UNUSED(obj);
3229     // TODO: We can be smarter here.
3230     // Currently, the array access is always preceded by an ArrayLength or a NullCheck
3231     // which generates the implicit null check. There are cases when these can be removed
3232     // to produce better code. If we ever add optimizations to do so we should allow an
3233     // implicit check here (as long as the address falls in the first page).
3234     return false;
3235   }
3236 
SetType(Primitive::Type type)3237   void SetType(Primitive::Type type) { type_ = type; }
3238 
GetArray()3239   HInstruction* GetArray() const { return InputAt(0); }
GetIndex()3240   HInstruction* GetIndex() const { return InputAt(1); }
3241 
3242   DECLARE_INSTRUCTION(ArrayGet);
3243 
3244  private:
3245   DISALLOW_COPY_AND_ASSIGN(HArrayGet);
3246 };
3247 
3248 class HArraySet : public HTemplateInstruction<3> {
3249  public:
HArraySet(HInstruction * array,HInstruction * index,HInstruction * value,Primitive::Type expected_component_type,uint32_t dex_pc)3250   HArraySet(HInstruction* array,
3251             HInstruction* index,
3252             HInstruction* value,
3253             Primitive::Type expected_component_type,
3254             uint32_t dex_pc)
3255       : HTemplateInstruction(SideEffects::ChangesSomething()),
3256         dex_pc_(dex_pc),
3257         expected_component_type_(expected_component_type),
3258         needs_type_check_(value->GetType() == Primitive::kPrimNot) {
3259     SetRawInputAt(0, array);
3260     SetRawInputAt(1, index);
3261     SetRawInputAt(2, value);
3262   }
3263 
NeedsEnvironment()3264   bool NeedsEnvironment() const OVERRIDE {
3265     // We currently always call a runtime method to catch array store
3266     // exceptions.
3267     return needs_type_check_;
3268   }
3269 
CanDoImplicitNullCheckOn(HInstruction * obj)3270   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3271     UNUSED(obj);
3272     // TODO: Same as for ArrayGet.
3273     return false;
3274   }
3275 
ClearNeedsTypeCheck()3276   void ClearNeedsTypeCheck() {
3277     needs_type_check_ = false;
3278   }
3279 
NeedsTypeCheck()3280   bool NeedsTypeCheck() const { return needs_type_check_; }
3281 
GetDexPc()3282   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3283 
GetArray()3284   HInstruction* GetArray() const { return InputAt(0); }
GetIndex()3285   HInstruction* GetIndex() const { return InputAt(1); }
GetValue()3286   HInstruction* GetValue() const { return InputAt(2); }
3287 
GetComponentType()3288   Primitive::Type GetComponentType() const {
3289     // The Dex format does not type floating point index operations. Since the
3290     // `expected_component_type_` is set during building and can therefore not
3291     // be correct, we also check what is the value type. If it is a floating
3292     // point type, we must use that type.
3293     Primitive::Type value_type = GetValue()->GetType();
3294     return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
3295         ? value_type
3296         : expected_component_type_;
3297   }
3298 
3299   DECLARE_INSTRUCTION(ArraySet);
3300 
3301  private:
3302   const uint32_t dex_pc_;
3303   const Primitive::Type expected_component_type_;
3304   bool needs_type_check_;
3305 
3306   DISALLOW_COPY_AND_ASSIGN(HArraySet);
3307 };
3308 
3309 class HArrayLength : public HExpression<1> {
3310  public:
HArrayLength(HInstruction * array)3311   explicit HArrayLength(HInstruction* array)
3312       : HExpression(Primitive::kPrimInt, SideEffects::None()) {
3313     // Note that arrays do not change length, so the instruction does not
3314     // depend on any write.
3315     SetRawInputAt(0, array);
3316   }
3317 
CanBeMoved()3318   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)3319   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3320     UNUSED(other);
3321     return true;
3322   }
CanDoImplicitNullCheckOn(HInstruction * obj)3323   bool CanDoImplicitNullCheckOn(HInstruction* obj) const OVERRIDE {
3324     return obj == InputAt(0);
3325   }
3326 
3327   DECLARE_INSTRUCTION(ArrayLength);
3328 
3329  private:
3330   DISALLOW_COPY_AND_ASSIGN(HArrayLength);
3331 };
3332 
3333 class HBoundsCheck : public HExpression<2> {
3334  public:
HBoundsCheck(HInstruction * index,HInstruction * length,uint32_t dex_pc)3335   HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
3336       : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
3337     DCHECK(index->GetType() == Primitive::kPrimInt);
3338     SetRawInputAt(0, index);
3339     SetRawInputAt(1, length);
3340   }
3341 
CanBeMoved()3342   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)3343   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3344     UNUSED(other);
3345     return true;
3346   }
3347 
NeedsEnvironment()3348   bool NeedsEnvironment() const OVERRIDE { return true; }
3349 
CanThrow()3350   bool CanThrow() const OVERRIDE { return true; }
3351 
GetDexPc()3352   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3353 
3354   DECLARE_INSTRUCTION(BoundsCheck);
3355 
3356  private:
3357   const uint32_t dex_pc_;
3358 
3359   DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
3360 };
3361 
3362 /**
3363  * Some DEX instructions are folded into multiple HInstructions that need
3364  * to stay live until the last HInstruction. This class
3365  * is used as a marker for the baseline compiler to ensure its preceding
3366  * HInstruction stays live. `index` represents the stack location index of the
3367  * instruction (the actual offset is computed as index * vreg_size).
3368  */
3369 class HTemporary : public HTemplateInstruction<0> {
3370  public:
HTemporary(size_t index)3371   explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
3372 
GetIndex()3373   size_t GetIndex() const { return index_; }
3374 
GetType()3375   Primitive::Type GetType() const OVERRIDE {
3376     // The previous instruction is the one that will be stored in the temporary location.
3377     DCHECK(GetPrevious() != nullptr);
3378     return GetPrevious()->GetType();
3379   }
3380 
3381   DECLARE_INSTRUCTION(Temporary);
3382 
3383  private:
3384   const size_t index_;
3385 
3386   DISALLOW_COPY_AND_ASSIGN(HTemporary);
3387 };
3388 
3389 class HSuspendCheck : public HTemplateInstruction<0> {
3390  public:
HSuspendCheck(uint32_t dex_pc)3391   explicit HSuspendCheck(uint32_t dex_pc)
3392       : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc), slow_path_(nullptr) {}
3393 
NeedsEnvironment()3394   bool NeedsEnvironment() const OVERRIDE {
3395     return true;
3396   }
3397 
GetDexPc()3398   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
SetSlowPath(SlowPathCode * slow_path)3399   void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
GetSlowPath()3400   SlowPathCode* GetSlowPath() const { return slow_path_; }
3401 
3402   DECLARE_INSTRUCTION(SuspendCheck);
3403 
3404  private:
3405   const uint32_t dex_pc_;
3406 
3407   // Only used for code generation, in order to share the same slow path between back edges
3408   // of a same loop.
3409   SlowPathCode* slow_path_;
3410 
3411   DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
3412 };
3413 
3414 /**
3415  * Instruction to load a Class object.
3416  */
3417 class HLoadClass : public HExpression<0> {
3418  public:
HLoadClass(uint16_t type_index,bool is_referrers_class,uint32_t dex_pc)3419   HLoadClass(uint16_t type_index,
3420              bool is_referrers_class,
3421              uint32_t dex_pc)
3422       : HExpression(Primitive::kPrimNot, SideEffects::None()),
3423         type_index_(type_index),
3424         is_referrers_class_(is_referrers_class),
3425         dex_pc_(dex_pc),
3426         generate_clinit_check_(false),
3427         loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
3428 
CanBeMoved()3429   bool CanBeMoved() const OVERRIDE { return true; }
3430 
InstructionDataEquals(HInstruction * other)3431   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3432     return other->AsLoadClass()->type_index_ == type_index_;
3433   }
3434 
ComputeHashCode()3435   size_t ComputeHashCode() const OVERRIDE { return type_index_; }
3436 
GetDexPc()3437   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
GetTypeIndex()3438   uint16_t GetTypeIndex() const { return type_index_; }
IsReferrersClass()3439   bool IsReferrersClass() const { return is_referrers_class_; }
CanBeNull()3440   bool CanBeNull() const OVERRIDE { return false; }
3441 
NeedsEnvironment()3442   bool NeedsEnvironment() const OVERRIDE {
3443     // Will call runtime and load the class if the class is not loaded yet.
3444     // TODO: finer grain decision.
3445     return !is_referrers_class_;
3446   }
3447 
MustGenerateClinitCheck()3448   bool MustGenerateClinitCheck() const {
3449     return generate_clinit_check_;
3450   }
3451 
SetMustGenerateClinitCheck()3452   void SetMustGenerateClinitCheck() {
3453     generate_clinit_check_ = true;
3454   }
3455 
CanCallRuntime()3456   bool CanCallRuntime() const {
3457     return MustGenerateClinitCheck() || !is_referrers_class_;
3458   }
3459 
CanThrow()3460   bool CanThrow() const OVERRIDE {
3461     // May call runtime and and therefore can throw.
3462     // TODO: finer grain decision.
3463     return !is_referrers_class_;
3464   }
3465 
GetLoadedClassRTI()3466   ReferenceTypeInfo GetLoadedClassRTI() {
3467     return loaded_class_rti_;
3468   }
3469 
SetLoadedClassRTI(ReferenceTypeInfo rti)3470   void SetLoadedClassRTI(ReferenceTypeInfo rti) {
3471     // Make sure we only set exact types (the loaded class should never be merged).
3472     DCHECK(rti.IsExact());
3473     loaded_class_rti_ = rti;
3474   }
3475 
IsResolved()3476   bool IsResolved() {
3477     return loaded_class_rti_.IsExact();
3478   }
3479 
NeedsDexCache()3480   bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
3481 
3482   DECLARE_INSTRUCTION(LoadClass);
3483 
3484  private:
3485   const uint16_t type_index_;
3486   const bool is_referrers_class_;
3487   const uint32_t dex_pc_;
3488   // Whether this instruction must generate the initialization check.
3489   // Used for code generation.
3490   bool generate_clinit_check_;
3491 
3492   ReferenceTypeInfo loaded_class_rti_;
3493 
3494   DISALLOW_COPY_AND_ASSIGN(HLoadClass);
3495 };
3496 
3497 class HLoadString : public HExpression<0> {
3498  public:
HLoadString(uint32_t string_index,uint32_t dex_pc)3499   HLoadString(uint32_t string_index, uint32_t dex_pc)
3500       : HExpression(Primitive::kPrimNot, SideEffects::None()),
3501         string_index_(string_index),
3502         dex_pc_(dex_pc) {}
3503 
CanBeMoved()3504   bool CanBeMoved() const OVERRIDE { return true; }
3505 
InstructionDataEquals(HInstruction * other)3506   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3507     return other->AsLoadString()->string_index_ == string_index_;
3508   }
3509 
ComputeHashCode()3510   size_t ComputeHashCode() const OVERRIDE { return string_index_; }
3511 
GetDexPc()3512   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
GetStringIndex()3513   uint32_t GetStringIndex() const { return string_index_; }
3514 
3515   // TODO: Can we deopt or debug when we resolve a string?
NeedsEnvironment()3516   bool NeedsEnvironment() const OVERRIDE { return false; }
NeedsDexCache()3517   bool NeedsDexCache() const OVERRIDE { return true; }
3518 
3519   DECLARE_INSTRUCTION(LoadString);
3520 
3521  private:
3522   const uint32_t string_index_;
3523   const uint32_t dex_pc_;
3524 
3525   DISALLOW_COPY_AND_ASSIGN(HLoadString);
3526 };
3527 
3528 /**
3529  * Performs an initialization check on its Class object input.
3530  */
3531 class HClinitCheck : public HExpression<1> {
3532  public:
HClinitCheck(HLoadClass * constant,uint32_t dex_pc)3533   explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
3534       : HExpression(Primitive::kPrimNot, SideEffects::ChangesSomething()),
3535         dex_pc_(dex_pc) {
3536     SetRawInputAt(0, constant);
3537   }
3538 
CanBeMoved()3539   bool CanBeMoved() const OVERRIDE { return true; }
InstructionDataEquals(HInstruction * other)3540   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3541     UNUSED(other);
3542     return true;
3543   }
3544 
NeedsEnvironment()3545   bool NeedsEnvironment() const OVERRIDE {
3546     // May call runtime to initialize the class.
3547     return true;
3548   }
3549 
GetDexPc()3550   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3551 
GetLoadClass()3552   HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
3553 
3554   DECLARE_INSTRUCTION(ClinitCheck);
3555 
3556  private:
3557   const uint32_t dex_pc_;
3558 
3559   DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
3560 };
3561 
3562 class HStaticFieldGet : public HExpression<1> {
3563  public:
HStaticFieldGet(HInstruction * cls,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile)3564   HStaticFieldGet(HInstruction* cls,
3565                   Primitive::Type field_type,
3566                   MemberOffset field_offset,
3567                   bool is_volatile)
3568       : HExpression(field_type, SideEffects::DependsOnSomething()),
3569         field_info_(field_offset, field_type, is_volatile) {
3570     SetRawInputAt(0, cls);
3571   }
3572 
3573 
CanBeMoved()3574   bool CanBeMoved() const OVERRIDE { return !IsVolatile(); }
3575 
InstructionDataEquals(HInstruction * other)3576   bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
3577     HStaticFieldGet* other_get = other->AsStaticFieldGet();
3578     return GetFieldOffset().SizeValue() == other_get->GetFieldOffset().SizeValue();
3579   }
3580 
ComputeHashCode()3581   size_t ComputeHashCode() const OVERRIDE {
3582     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
3583   }
3584 
GetFieldInfo()3585   const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()3586   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()3587   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()3588   bool IsVolatile() const { return field_info_.IsVolatile(); }
3589 
3590   DECLARE_INSTRUCTION(StaticFieldGet);
3591 
3592  private:
3593   const FieldInfo field_info_;
3594 
3595   DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
3596 };
3597 
3598 class HStaticFieldSet : public HTemplateInstruction<2> {
3599  public:
HStaticFieldSet(HInstruction * cls,HInstruction * value,Primitive::Type field_type,MemberOffset field_offset,bool is_volatile)3600   HStaticFieldSet(HInstruction* cls,
3601                   HInstruction* value,
3602                   Primitive::Type field_type,
3603                   MemberOffset field_offset,
3604                   bool is_volatile)
3605       : HTemplateInstruction(SideEffects::ChangesSomething()),
3606         field_info_(field_offset, field_type, is_volatile) {
3607     SetRawInputAt(0, cls);
3608     SetRawInputAt(1, value);
3609   }
3610 
GetFieldInfo()3611   const FieldInfo& GetFieldInfo() const { return field_info_; }
GetFieldOffset()3612   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
GetFieldType()3613   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
IsVolatile()3614   bool IsVolatile() const { return field_info_.IsVolatile(); }
3615 
GetValue()3616   HInstruction* GetValue() const { return InputAt(1); }
3617 
3618   DECLARE_INSTRUCTION(StaticFieldSet);
3619 
3620  private:
3621   const FieldInfo field_info_;
3622 
3623   DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
3624 };
3625 
3626 // Implement the move-exception DEX instruction.
3627 class HLoadException : public HExpression<0> {
3628  public:
HLoadException()3629   HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
3630 
3631   DECLARE_INSTRUCTION(LoadException);
3632 
3633  private:
3634   DISALLOW_COPY_AND_ASSIGN(HLoadException);
3635 };
3636 
3637 class HThrow : public HTemplateInstruction<1> {
3638  public:
HThrow(HInstruction * exception,uint32_t dex_pc)3639   HThrow(HInstruction* exception, uint32_t dex_pc)
3640       : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
3641     SetRawInputAt(0, exception);
3642   }
3643 
IsControlFlow()3644   bool IsControlFlow() const OVERRIDE { return true; }
3645 
NeedsEnvironment()3646   bool NeedsEnvironment() const OVERRIDE { return true; }
3647 
CanThrow()3648   bool CanThrow() const OVERRIDE { return true; }
3649 
GetDexPc()3650   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3651 
3652   DECLARE_INSTRUCTION(Throw);
3653 
3654  private:
3655   const uint32_t dex_pc_;
3656 
3657   DISALLOW_COPY_AND_ASSIGN(HThrow);
3658 };
3659 
3660 class HInstanceOf : public HExpression<2> {
3661  public:
HInstanceOf(HInstruction * object,HLoadClass * constant,bool class_is_final,uint32_t dex_pc)3662   HInstanceOf(HInstruction* object,
3663               HLoadClass* constant,
3664               bool class_is_final,
3665               uint32_t dex_pc)
3666       : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
3667         class_is_final_(class_is_final),
3668         must_do_null_check_(true),
3669         dex_pc_(dex_pc) {
3670     SetRawInputAt(0, object);
3671     SetRawInputAt(1, constant);
3672   }
3673 
CanBeMoved()3674   bool CanBeMoved() const OVERRIDE { return true; }
3675 
InstructionDataEquals(HInstruction * other ATTRIBUTE_UNUSED)3676   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3677     return true;
3678   }
3679 
NeedsEnvironment()3680   bool NeedsEnvironment() const OVERRIDE {
3681     return false;
3682   }
3683 
GetDexPc()3684   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3685 
IsClassFinal()3686   bool IsClassFinal() const { return class_is_final_; }
3687 
3688   // Used only in code generation.
MustDoNullCheck()3689   bool MustDoNullCheck() const { return must_do_null_check_; }
ClearMustDoNullCheck()3690   void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3691 
3692   DECLARE_INSTRUCTION(InstanceOf);
3693 
3694  private:
3695   const bool class_is_final_;
3696   bool must_do_null_check_;
3697   const uint32_t dex_pc_;
3698 
3699   DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
3700 };
3701 
3702 class HBoundType : public HExpression<1> {
3703  public:
HBoundType(HInstruction * input,ReferenceTypeInfo bound_type)3704   HBoundType(HInstruction* input, ReferenceTypeInfo bound_type)
3705       : HExpression(Primitive::kPrimNot, SideEffects::None()),
3706         bound_type_(bound_type) {
3707     DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
3708     SetRawInputAt(0, input);
3709   }
3710 
GetBoundType()3711   const ReferenceTypeInfo& GetBoundType() const { return bound_type_; }
3712 
CanBeNull()3713   bool CanBeNull() const OVERRIDE {
3714     // `null instanceof ClassX` always return false so we can't be null.
3715     return false;
3716   }
3717 
3718   DECLARE_INSTRUCTION(BoundType);
3719 
3720  private:
3721   // Encodes the most upper class that this instruction can have. In other words
3722   // it is always the case that GetBoundType().IsSupertypeOf(GetReferenceType()).
3723   // It is used to bound the type in cases like `if (x instanceof ClassX) {}`
3724   const ReferenceTypeInfo bound_type_;
3725 
3726   DISALLOW_COPY_AND_ASSIGN(HBoundType);
3727 };
3728 
3729 class HCheckCast : public HTemplateInstruction<2> {
3730  public:
HCheckCast(HInstruction * object,HLoadClass * constant,bool class_is_final,uint32_t dex_pc)3731   HCheckCast(HInstruction* object,
3732              HLoadClass* constant,
3733              bool class_is_final,
3734              uint32_t dex_pc)
3735       : HTemplateInstruction(SideEffects::None()),
3736         class_is_final_(class_is_final),
3737         must_do_null_check_(true),
3738         dex_pc_(dex_pc) {
3739     SetRawInputAt(0, object);
3740     SetRawInputAt(1, constant);
3741   }
3742 
CanBeMoved()3743   bool CanBeMoved() const OVERRIDE { return true; }
3744 
InstructionDataEquals(HInstruction * other ATTRIBUTE_UNUSED)3745   bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
3746     return true;
3747   }
3748 
NeedsEnvironment()3749   bool NeedsEnvironment() const OVERRIDE {
3750     // Instruction may throw a CheckCastError.
3751     return true;
3752   }
3753 
CanThrow()3754   bool CanThrow() const OVERRIDE { return true; }
3755 
MustDoNullCheck()3756   bool MustDoNullCheck() const { return must_do_null_check_; }
ClearMustDoNullCheck()3757   void ClearMustDoNullCheck() { must_do_null_check_ = false; }
3758 
GetDexPc()3759   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3760 
IsClassFinal()3761   bool IsClassFinal() const { return class_is_final_; }
3762 
3763   DECLARE_INSTRUCTION(CheckCast);
3764 
3765  private:
3766   const bool class_is_final_;
3767   bool must_do_null_check_;
3768   const uint32_t dex_pc_;
3769 
3770   DISALLOW_COPY_AND_ASSIGN(HCheckCast);
3771 };
3772 
3773 class HMemoryBarrier : public HTemplateInstruction<0> {
3774  public:
HMemoryBarrier(MemBarrierKind barrier_kind)3775   explicit HMemoryBarrier(MemBarrierKind barrier_kind)
3776       : HTemplateInstruction(SideEffects::None()),
3777         barrier_kind_(barrier_kind) {}
3778 
GetBarrierKind()3779   MemBarrierKind GetBarrierKind() { return barrier_kind_; }
3780 
3781   DECLARE_INSTRUCTION(MemoryBarrier);
3782 
3783  private:
3784   const MemBarrierKind barrier_kind_;
3785 
3786   DISALLOW_COPY_AND_ASSIGN(HMemoryBarrier);
3787 };
3788 
3789 class HMonitorOperation : public HTemplateInstruction<1> {
3790  public:
3791   enum OperationKind {
3792     kEnter,
3793     kExit,
3794   };
3795 
HMonitorOperation(HInstruction * object,OperationKind kind,uint32_t dex_pc)3796   HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
3797     : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
3798     SetRawInputAt(0, object);
3799   }
3800 
3801   // Instruction may throw a Java exception, so we need an environment.
NeedsEnvironment()3802   bool NeedsEnvironment() const OVERRIDE { return true; }
CanThrow()3803   bool CanThrow() const OVERRIDE { return true; }
3804 
GetDexPc()3805   uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
3806 
IsEnter()3807   bool IsEnter() const { return kind_ == kEnter; }
3808 
3809   DECLARE_INSTRUCTION(MonitorOperation);
3810 
3811  private:
3812   const OperationKind kind_;
3813   const uint32_t dex_pc_;
3814 
3815  private:
3816   DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
3817 };
3818 
3819 class MoveOperands : public ArenaObject<kArenaAllocMisc> {
3820  public:
MoveOperands(Location source,Location destination,Primitive::Type type,HInstruction * instruction)3821   MoveOperands(Location source,
3822                Location destination,
3823                Primitive::Type type,
3824                HInstruction* instruction)
3825       : source_(source), destination_(destination), type_(type), instruction_(instruction) {}
3826 
GetSource()3827   Location GetSource() const { return source_; }
GetDestination()3828   Location GetDestination() const { return destination_; }
3829 
SetSource(Location value)3830   void SetSource(Location value) { source_ = value; }
SetDestination(Location value)3831   void SetDestination(Location value) { destination_ = value; }
3832 
3833   // The parallel move resolver marks moves as "in-progress" by clearing the
3834   // destination (but not the source).
MarkPending()3835   Location MarkPending() {
3836     DCHECK(!IsPending());
3837     Location dest = destination_;
3838     destination_ = Location::NoLocation();
3839     return dest;
3840   }
3841 
ClearPending(Location dest)3842   void ClearPending(Location dest) {
3843     DCHECK(IsPending());
3844     destination_ = dest;
3845   }
3846 
IsPending()3847   bool IsPending() const {
3848     DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3849     return destination_.IsInvalid() && !source_.IsInvalid();
3850   }
3851 
3852   // True if this blocks a move from the given location.
Blocks(Location loc)3853   bool Blocks(Location loc) const {
3854     return !IsEliminated() && source_.OverlapsWith(loc);
3855   }
3856 
3857   // A move is redundant if it's been eliminated, if its source and
3858   // destination are the same, or if its destination is unneeded.
IsRedundant()3859   bool IsRedundant() const {
3860     return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
3861   }
3862 
3863   // We clear both operands to indicate move that's been eliminated.
Eliminate()3864   void Eliminate() {
3865     source_ = destination_ = Location::NoLocation();
3866   }
3867 
IsEliminated()3868   bool IsEliminated() const {
3869     DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
3870     return source_.IsInvalid();
3871   }
3872 
GetType()3873   Primitive::Type GetType() const { return type_; }
3874 
Is64BitMove()3875   bool Is64BitMove() const {
3876     return Primitive::Is64BitType(type_);
3877   }
3878 
GetInstruction()3879   HInstruction* GetInstruction() const { return instruction_; }
3880 
3881  private:
3882   Location source_;
3883   Location destination_;
3884   // The type this move is for.
3885   Primitive::Type type_;
3886   // The instruction this move is assocatied with. Null when this move is
3887   // for moving an input in the expected locations of user (including a phi user).
3888   // This is only used in debug mode, to ensure we do not connect interval siblings
3889   // in the same parallel move.
3890   HInstruction* instruction_;
3891 };
3892 
3893 static constexpr size_t kDefaultNumberOfMoves = 4;
3894 
3895 class HParallelMove : public HTemplateInstruction<0> {
3896  public:
HParallelMove(ArenaAllocator * arena)3897   explicit HParallelMove(ArenaAllocator* arena)
3898       : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
3899 
AddMove(Location source,Location destination,Primitive::Type type,HInstruction * instruction)3900   void AddMove(Location source,
3901                Location destination,
3902                Primitive::Type type,
3903                HInstruction* instruction) {
3904     DCHECK(source.IsValid());
3905     DCHECK(destination.IsValid());
3906     if (kIsDebugBuild) {
3907       if (instruction != nullptr) {
3908         for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
3909           if (moves_.Get(i).GetInstruction() == instruction) {
3910             // Special case the situation where the move is for the spill slot
3911             // of the instruction.
3912             if ((GetPrevious() == instruction)
3913                 || ((GetPrevious() == nullptr)
3914                     && instruction->IsPhi()
3915                     && instruction->GetBlock() == GetBlock())) {
3916               DCHECK_NE(destination.GetKind(), moves_.Get(i).GetDestination().GetKind())
3917                   << "Doing parallel moves for the same instruction.";
3918             } else {
3919               DCHECK(false) << "Doing parallel moves for the same instruction.";
3920             }
3921           }
3922         }
3923       }
3924       for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
3925         DCHECK(!destination.OverlapsWith(moves_.Get(i).GetDestination()))
3926             << "Overlapped destination for two moves in a parallel move.";
3927       }
3928     }
3929     moves_.Add(MoveOperands(source, destination, type, instruction));
3930   }
3931 
MoveOperandsAt(size_t index)3932   MoveOperands* MoveOperandsAt(size_t index) const {
3933     return moves_.GetRawStorage() + index;
3934   }
3935 
NumMoves()3936   size_t NumMoves() const { return moves_.Size(); }
3937 
3938   DECLARE_INSTRUCTION(ParallelMove);
3939 
3940  private:
3941   GrowableArray<MoveOperands> moves_;
3942 
3943   DISALLOW_COPY_AND_ASSIGN(HParallelMove);
3944 };
3945 
3946 class HGraphVisitor : public ValueObject {
3947  public:
HGraphVisitor(HGraph * graph)3948   explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
~HGraphVisitor()3949   virtual ~HGraphVisitor() {}
3950 
VisitInstruction(HInstruction * instruction)3951   virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
3952   virtual void VisitBasicBlock(HBasicBlock* block);
3953 
3954   // Visit the graph following basic block insertion order.
3955   void VisitInsertionOrder();
3956 
3957   // Visit the graph following dominator tree reverse post-order.
3958   void VisitReversePostOrder();
3959 
GetGraph()3960   HGraph* GetGraph() const { return graph_; }
3961 
3962   // Visit functions for instruction classes.
3963 #define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
3964   virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
3965 
3966   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3967 
3968 #undef DECLARE_VISIT_INSTRUCTION
3969 
3970  private:
3971   HGraph* const graph_;
3972 
3973   DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
3974 };
3975 
3976 class HGraphDelegateVisitor : public HGraphVisitor {
3977  public:
HGraphDelegateVisitor(HGraph * graph)3978   explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
~HGraphDelegateVisitor()3979   virtual ~HGraphDelegateVisitor() {}
3980 
3981   // Visit functions that delegate to to super class.
3982 #define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
3983   void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
3984 
3985   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
3986 
3987 #undef DECLARE_VISIT_INSTRUCTION
3988 
3989  private:
3990   DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
3991 };
3992 
3993 class HInsertionOrderIterator : public ValueObject {
3994  public:
HInsertionOrderIterator(const HGraph & graph)3995   explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
3996 
Done()3997   bool Done() const { return index_ == graph_.GetBlocks().Size(); }
Current()3998   HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
Advance()3999   void Advance() { ++index_; }
4000 
4001  private:
4002   const HGraph& graph_;
4003   size_t index_;
4004 
4005   DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
4006 };
4007 
4008 class HReversePostOrderIterator : public ValueObject {
4009  public:
HReversePostOrderIterator(const HGraph & graph)4010   explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {
4011     // Check that reverse post order of the graph has been built.
4012     DCHECK(!graph.GetReversePostOrder().IsEmpty());
4013   }
4014 
Done()4015   bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
Current()4016   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
Advance()4017   void Advance() { ++index_; }
4018 
4019  private:
4020   const HGraph& graph_;
4021   size_t index_;
4022 
4023   DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
4024 };
4025 
4026 class HPostOrderIterator : public ValueObject {
4027  public:
HPostOrderIterator(const HGraph & graph)4028   explicit HPostOrderIterator(const HGraph& graph)
4029       : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {
4030     // Check that reverse post order of the graph has been built.
4031     DCHECK(!graph.GetReversePostOrder().IsEmpty());
4032   }
4033 
Done()4034   bool Done() const { return index_ == 0; }
Current()4035   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
Advance()4036   void Advance() { --index_; }
4037 
4038  private:
4039   const HGraph& graph_;
4040   size_t index_;
4041 
4042   DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
4043 };
4044 
4045 class HLinearPostOrderIterator : public ValueObject {
4046  public:
HLinearPostOrderIterator(const HGraph & graph)4047   explicit HLinearPostOrderIterator(const HGraph& graph)
4048       : order_(graph.GetLinearOrder()), index_(graph.GetLinearOrder().Size()) {}
4049 
Done()4050   bool Done() const { return index_ == 0; }
4051 
Current()4052   HBasicBlock* Current() const { return order_.Get(index_ -1); }
4053 
Advance()4054   void Advance() {
4055     --index_;
4056     DCHECK_GE(index_, 0U);
4057   }
4058 
4059  private:
4060   const GrowableArray<HBasicBlock*>& order_;
4061   size_t index_;
4062 
4063   DISALLOW_COPY_AND_ASSIGN(HLinearPostOrderIterator);
4064 };
4065 
4066 class HLinearOrderIterator : public ValueObject {
4067  public:
HLinearOrderIterator(const HGraph & graph)4068   explicit HLinearOrderIterator(const HGraph& graph)
4069       : order_(graph.GetLinearOrder()), index_(0) {}
4070 
Done()4071   bool Done() const { return index_ == order_.Size(); }
Current()4072   HBasicBlock* Current() const { return order_.Get(index_); }
Advance()4073   void Advance() { ++index_; }
4074 
4075  private:
4076   const GrowableArray<HBasicBlock*>& order_;
4077   size_t index_;
4078 
4079   DISALLOW_COPY_AND_ASSIGN(HLinearOrderIterator);
4080 };
4081 
4082 // Iterator over the blocks that art part of the loop. Includes blocks part
4083 // of an inner loop. The order in which the blocks are iterated is on their
4084 // block id.
4085 class HBlocksInLoopIterator : public ValueObject {
4086  public:
HBlocksInLoopIterator(const HLoopInformation & info)4087   explicit HBlocksInLoopIterator(const HLoopInformation& info)
4088       : blocks_in_loop_(info.GetBlocks()),
4089         blocks_(info.GetHeader()->GetGraph()->GetBlocks()),
4090         index_(0) {
4091     if (!blocks_in_loop_.IsBitSet(index_)) {
4092       Advance();
4093     }
4094   }
4095 
Done()4096   bool Done() const { return index_ == blocks_.Size(); }
Current()4097   HBasicBlock* Current() const { return blocks_.Get(index_); }
Advance()4098   void Advance() {
4099     ++index_;
4100     for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4101       if (blocks_in_loop_.IsBitSet(index_)) {
4102         break;
4103       }
4104     }
4105   }
4106 
4107  private:
4108   const BitVector& blocks_in_loop_;
4109   const GrowableArray<HBasicBlock*>& blocks_;
4110   size_t index_;
4111 
4112   DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopIterator);
4113 };
4114 
4115 // Iterator over the blocks that art part of the loop. Includes blocks part
4116 // of an inner loop. The order in which the blocks are iterated is reverse
4117 // post order.
4118 class HBlocksInLoopReversePostOrderIterator : public ValueObject {
4119  public:
HBlocksInLoopReversePostOrderIterator(const HLoopInformation & info)4120   explicit HBlocksInLoopReversePostOrderIterator(const HLoopInformation& info)
4121       : blocks_in_loop_(info.GetBlocks()),
4122         blocks_(info.GetHeader()->GetGraph()->GetReversePostOrder()),
4123         index_(0) {
4124     if (!blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
4125       Advance();
4126     }
4127   }
4128 
Done()4129   bool Done() const { return index_ == blocks_.Size(); }
Current()4130   HBasicBlock* Current() const { return blocks_.Get(index_); }
Advance()4131   void Advance() {
4132     ++index_;
4133     for (size_t e = blocks_.Size(); index_ < e; ++index_) {
4134       if (blocks_in_loop_.IsBitSet(blocks_.Get(index_)->GetBlockId())) {
4135         break;
4136       }
4137     }
4138   }
4139 
4140  private:
4141   const BitVector& blocks_in_loop_;
4142   const GrowableArray<HBasicBlock*>& blocks_;
4143   size_t index_;
4144 
4145   DISALLOW_COPY_AND_ASSIGN(HBlocksInLoopReversePostOrderIterator);
4146 };
4147 
Int64FromConstant(HConstant * constant)4148 inline int64_t Int64FromConstant(HConstant* constant) {
4149   DCHECK(constant->IsIntConstant() || constant->IsLongConstant());
4150   return constant->IsIntConstant() ? constant->AsIntConstant()->GetValue()
4151                                    : constant->AsLongConstant()->GetValue();
4152 }
4153 
4154 }  // namespace art
4155 
4156 #endif  // ART_COMPILER_OPTIMIZING_NODES_H_
4157