nodes.h revision cea28ec4b9e94ec942899acf1dbf20f8999b36b4
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_COMPILER_OPTIMIZING_NODES_H_
18#define ART_COMPILER_OPTIMIZING_NODES_H_
19
20#include "locations.h"
21#include "offsets.h"
22#include "primitive.h"
23#include "utils/arena_object.h"
24#include "utils/arena_bit_vector.h"
25#include "utils/growable_array.h"
26
27namespace art {
28
29class HBasicBlock;
30class HEnvironment;
31class HInstruction;
32class HIntConstant;
33class HGraphVisitor;
34class HPhi;
35class HSuspendCheck;
36class LiveInterval;
37class LocationSummary;
38
39static const int kDefaultNumberOfBlocks = 8;
40static const int kDefaultNumberOfSuccessors = 2;
41static const int kDefaultNumberOfPredecessors = 2;
42static const int kDefaultNumberOfDominatedBlocks = 1;
43static const int kDefaultNumberOfBackEdges = 1;
44
45static constexpr uint32_t kMaxIntShiftValue = 0x1f;
46static constexpr uint64_t kMaxLongShiftValue = 0x3f;
47
48enum IfCondition {
49  kCondEQ,
50  kCondNE,
51  kCondLT,
52  kCondLE,
53  kCondGT,
54  kCondGE,
55};
56
57class HInstructionList {
58 public:
59  HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {}
60
61  void AddInstruction(HInstruction* instruction);
62  void RemoveInstruction(HInstruction* instruction);
63
64  // Return true if this list contains `instruction`.
65  bool Contains(HInstruction* instruction) const;
66
67  // Return true if `instruction1` is found before `instruction2` in
68  // this instruction list and false otherwise.  Abort if none
69  // of these instructions is found.
70  bool FoundBefore(const HInstruction* instruction1,
71                   const HInstruction* instruction2) const;
72
73 private:
74  HInstruction* first_instruction_;
75  HInstruction* last_instruction_;
76
77  friend class HBasicBlock;
78  friend class HInstructionIterator;
79  friend class HBackwardInstructionIterator;
80
81  DISALLOW_COPY_AND_ASSIGN(HInstructionList);
82};
83
84// Control-flow graph of a method. Contains a list of basic blocks.
85class HGraph : public ArenaObject<kArenaAllocMisc> {
86 public:
87  explicit HGraph(ArenaAllocator* arena)
88      : arena_(arena),
89        blocks_(arena, kDefaultNumberOfBlocks),
90        reverse_post_order_(arena, kDefaultNumberOfBlocks),
91        entry_block_(nullptr),
92        exit_block_(nullptr),
93        maximum_number_of_out_vregs_(0),
94        number_of_vregs_(0),
95        number_of_in_vregs_(0),
96        temporaries_vreg_slots_(0),
97        current_instruction_id_(0) {}
98
99  ArenaAllocator* GetArena() const { return arena_; }
100  const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; }
101  HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); }
102
103  HBasicBlock* GetEntryBlock() const { return entry_block_; }
104  HBasicBlock* GetExitBlock() const { return exit_block_; }
105
106  void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; }
107  void SetExitBlock(HBasicBlock* block) { exit_block_ = block; }
108
109  void AddBlock(HBasicBlock* block);
110
111  void BuildDominatorTree();
112  void TransformToSSA();
113  void SimplifyCFG();
114
115  // Find all natural loops in this graph. Aborts computation and returns false
116  // if one loop is not natural, that is the header does not dominate the back
117  // edge.
118  bool FindNaturalLoops() const;
119
120  void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor);
121  void SimplifyLoop(HBasicBlock* header);
122
123  int GetNextInstructionId() {
124    return current_instruction_id_++;
125  }
126
127  uint16_t GetMaximumNumberOfOutVRegs() const {
128    return maximum_number_of_out_vregs_;
129  }
130
131  void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) {
132    maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_);
133  }
134
135  void UpdateTemporariesVRegSlots(size_t slots) {
136    temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_);
137  }
138
139  size_t GetTemporariesVRegSlots() const {
140    return temporaries_vreg_slots_;
141  }
142
143  void SetNumberOfVRegs(uint16_t number_of_vregs) {
144    number_of_vregs_ = number_of_vregs;
145  }
146
147  uint16_t GetNumberOfVRegs() const {
148    return number_of_vregs_;
149  }
150
151  void SetNumberOfInVRegs(uint16_t value) {
152    number_of_in_vregs_ = value;
153  }
154
155  uint16_t GetNumberOfInVRegs() const {
156    return number_of_in_vregs_;
157  }
158
159  uint16_t GetNumberOfLocalVRegs() const {
160    return number_of_vregs_ - number_of_in_vregs_;
161  }
162
163  const GrowableArray<HBasicBlock*>& GetReversePostOrder() const {
164    return reverse_post_order_;
165  }
166
167 private:
168  HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const;
169  void VisitBlockForDominatorTree(HBasicBlock* block,
170                                  HBasicBlock* predecessor,
171                                  GrowableArray<size_t>* visits);
172  void FindBackEdges(ArenaBitVector* visited);
173  void VisitBlockForBackEdges(HBasicBlock* block,
174                              ArenaBitVector* visited,
175                              ArenaBitVector* visiting);
176  void RemoveDeadBlocks(const ArenaBitVector& visited) const;
177
178  ArenaAllocator* const arena_;
179
180  // List of blocks in insertion order.
181  GrowableArray<HBasicBlock*> blocks_;
182
183  // List of blocks to perform a reverse post order tree traversal.
184  GrowableArray<HBasicBlock*> reverse_post_order_;
185
186  HBasicBlock* entry_block_;
187  HBasicBlock* exit_block_;
188
189  // The maximum number of virtual registers arguments passed to a HInvoke in this graph.
190  uint16_t maximum_number_of_out_vregs_;
191
192  // The number of virtual registers in this method. Contains the parameters.
193  uint16_t number_of_vregs_;
194
195  // The number of virtual registers used by parameters of this method.
196  uint16_t number_of_in_vregs_;
197
198  // Number of vreg size slots that the temporaries use (used in baseline compiler).
199  size_t temporaries_vreg_slots_;
200
201  // The current id to assign to a newly added instruction. See HInstruction.id_.
202  int current_instruction_id_;
203
204  DISALLOW_COPY_AND_ASSIGN(HGraph);
205};
206
207class HLoopInformation : public ArenaObject<kArenaAllocMisc> {
208 public:
209  HLoopInformation(HBasicBlock* header, HGraph* graph)
210      : header_(header),
211        suspend_check_(nullptr),
212        back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges),
213        // Make bit vector growable, as the number of blocks may change.
214        blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {}
215
216  HBasicBlock* GetHeader() const {
217    return header_;
218  }
219
220  HSuspendCheck* GetSuspendCheck() const { return suspend_check_; }
221  void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; }
222  bool HasSuspendCheck() const { return suspend_check_ != nullptr; }
223
224  void AddBackEdge(HBasicBlock* back_edge) {
225    back_edges_.Add(back_edge);
226  }
227
228  void RemoveBackEdge(HBasicBlock* back_edge) {
229    back_edges_.Delete(back_edge);
230  }
231
232  bool IsBackEdge(HBasicBlock* block) {
233    for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) {
234      if (back_edges_.Get(i) == block) return true;
235    }
236    return false;
237  }
238
239  size_t NumberOfBackEdges() const {
240    return back_edges_.Size();
241  }
242
243  HBasicBlock* GetPreHeader() const;
244
245  const GrowableArray<HBasicBlock*>& GetBackEdges() const {
246    return back_edges_;
247  }
248
249  void ClearBackEdges() {
250    back_edges_.Reset();
251  }
252
253  // Find blocks that are part of this loop. Returns whether the loop is a natural loop,
254  // that is the header dominates the back edge.
255  bool Populate();
256
257  // Returns whether this loop information contains `block`.
258  // Note that this loop information *must* be populated before entering this function.
259  bool Contains(const HBasicBlock& block) const;
260
261  // Returns whether this loop information is an inner loop of `other`.
262  // Note that `other` *must* be populated before entering this function.
263  bool IsIn(const HLoopInformation& other) const;
264
265  const ArenaBitVector& GetBlocks() const { return blocks_; }
266
267 private:
268  // Internal recursive implementation of `Populate`.
269  void PopulateRecursive(HBasicBlock* block);
270
271  HBasicBlock* header_;
272  HSuspendCheck* suspend_check_;
273  GrowableArray<HBasicBlock*> back_edges_;
274  ArenaBitVector blocks_;
275
276  DISALLOW_COPY_AND_ASSIGN(HLoopInformation);
277};
278
279static constexpr size_t kNoLifetime = -1;
280static constexpr uint32_t kNoDexPc = -1;
281
282// A block in a method. Contains the list of instructions represented
283// as a double linked list. Each block knows its predecessors and
284// successors.
285
286class HBasicBlock : public ArenaObject<kArenaAllocMisc> {
287 public:
288  explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
289      : graph_(graph),
290        predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
291        successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
292        loop_information_(nullptr),
293        dominator_(nullptr),
294        dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks),
295        block_id_(-1),
296        dex_pc_(dex_pc),
297        lifetime_start_(kNoLifetime),
298        lifetime_end_(kNoLifetime),
299        is_catch_block_(false) {}
300
301  const GrowableArray<HBasicBlock*>& GetPredecessors() const {
302    return predecessors_;
303  }
304
305  const GrowableArray<HBasicBlock*>& GetSuccessors() const {
306    return successors_;
307  }
308
309  const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const {
310    return dominated_blocks_;
311  }
312
313  bool IsEntryBlock() const {
314    return graph_->GetEntryBlock() == this;
315  }
316
317  bool IsExitBlock() const {
318    return graph_->GetExitBlock() == this;
319  }
320
321  void AddBackEdge(HBasicBlock* back_edge) {
322    if (loop_information_ == nullptr) {
323      loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_);
324    }
325    DCHECK_EQ(loop_information_->GetHeader(), this);
326    loop_information_->AddBackEdge(back_edge);
327  }
328
329  HGraph* GetGraph() const { return graph_; }
330
331  int GetBlockId() const { return block_id_; }
332  void SetBlockId(int id) { block_id_ = id; }
333
334  HBasicBlock* GetDominator() const { return dominator_; }
335  void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
336  void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); }
337
338  int NumberOfBackEdges() const {
339    return loop_information_ == nullptr
340        ? 0
341        : loop_information_->NumberOfBackEdges();
342  }
343
344  HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; }
345  HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; }
346  const HInstructionList& GetInstructions() const { return instructions_; }
347  const HInstructionList& GetPhis() const { return phis_; }
348  HInstruction* GetFirstPhi() const { return phis_.first_instruction_; }
349
350  void AddSuccessor(HBasicBlock* block) {
351    successors_.Add(block);
352    block->predecessors_.Add(this);
353  }
354
355  void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) {
356    size_t successor_index = GetSuccessorIndexOf(existing);
357    DCHECK_NE(successor_index, static_cast<size_t>(-1));
358    existing->RemovePredecessor(this);
359    new_block->predecessors_.Add(this);
360    successors_.Put(successor_index, new_block);
361  }
362
363  void RemovePredecessor(HBasicBlock* block) {
364    predecessors_.Delete(block);
365  }
366
367  void ClearAllPredecessors() {
368    predecessors_.Reset();
369  }
370
371  void AddPredecessor(HBasicBlock* block) {
372    predecessors_.Add(block);
373    block->successors_.Add(this);
374  }
375
376  void SwapPredecessors() {
377    DCHECK_EQ(predecessors_.Size(), 2u);
378    HBasicBlock* temp = predecessors_.Get(0);
379    predecessors_.Put(0, predecessors_.Get(1));
380    predecessors_.Put(1, temp);
381  }
382
383  size_t GetPredecessorIndexOf(HBasicBlock* predecessor) {
384    for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) {
385      if (predecessors_.Get(i) == predecessor) {
386        return i;
387      }
388    }
389    return -1;
390  }
391
392  size_t GetSuccessorIndexOf(HBasicBlock* successor) {
393    for (size_t i = 0, e = successors_.Size(); i < e; ++i) {
394      if (successors_.Get(i) == successor) {
395        return i;
396      }
397    }
398    return -1;
399  }
400
401  void AddInstruction(HInstruction* instruction);
402  void RemoveInstruction(HInstruction* instruction);
403  void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor);
404  // Replace instruction `initial` with `replacement` within this block.
405  void ReplaceAndRemoveInstructionWith(HInstruction* initial,
406                                       HInstruction* replacement);
407  void AddPhi(HPhi* phi);
408  void InsertPhiAfter(HPhi* instruction, HPhi* cursor);
409  void RemovePhi(HPhi* phi);
410
411  bool IsLoopHeader() const {
412    return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this);
413  }
414
415  bool IsLoopPreHeaderFirstPredecessor() const {
416    DCHECK(IsLoopHeader());
417    DCHECK(!GetPredecessors().IsEmpty());
418    return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader();
419  }
420
421  HLoopInformation* GetLoopInformation() const {
422    return loop_information_;
423  }
424
425  // Set the loop_information_ on this block. This method overrides the current
426  // loop_information if it is an outer loop of the passed loop information.
427  void SetInLoop(HLoopInformation* info) {
428    if (IsLoopHeader()) {
429      // Nothing to do. This just means `info` is an outer loop.
430    } else if (loop_information_ == nullptr) {
431      loop_information_ = info;
432    } else if (loop_information_->Contains(*info->GetHeader())) {
433      // Block is currently part of an outer loop. Make it part of this inner loop.
434      // Note that a non loop header having a loop information means this loop information
435      // has already been populated
436      loop_information_ = info;
437    } else {
438      // Block is part of an inner loop. Do not update the loop information.
439      // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()`
440      // at this point, because this method is being called while populating `info`.
441    }
442  }
443
444  bool IsInLoop() const { return loop_information_ != nullptr; }
445
446  // Returns wheter this block dominates the blocked passed as parameter.
447  bool Dominates(HBasicBlock* block) const;
448
449  size_t GetLifetimeStart() const { return lifetime_start_; }
450  size_t GetLifetimeEnd() const { return lifetime_end_; }
451
452  void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
453  void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
454
455  uint32_t GetDexPc() const { return dex_pc_; }
456
457  bool IsCatchBlock() const { return is_catch_block_; }
458  void SetIsCatchBlock() { is_catch_block_ = true; }
459
460 private:
461  HGraph* const graph_;
462  GrowableArray<HBasicBlock*> predecessors_;
463  GrowableArray<HBasicBlock*> successors_;
464  HInstructionList instructions_;
465  HInstructionList phis_;
466  HLoopInformation* loop_information_;
467  HBasicBlock* dominator_;
468  GrowableArray<HBasicBlock*> dominated_blocks_;
469  int block_id_;
470  // The dex program counter of the first instruction of this block.
471  const uint32_t dex_pc_;
472  size_t lifetime_start_;
473  size_t lifetime_end_;
474  bool is_catch_block_;
475
476  DISALLOW_COPY_AND_ASSIGN(HBasicBlock);
477};
478
479#define FOR_EACH_CONCRETE_INSTRUCTION(M)                                \
480  M(Add, BinaryOperation)                                               \
481  M(And, BinaryOperation)                                               \
482  M(ArrayGet, Instruction)                                              \
483  M(ArrayLength, Instruction)                                           \
484  M(ArraySet, Instruction)                                              \
485  M(BoundsCheck, Instruction)                                           \
486  M(CheckCast, Instruction)                                             \
487  M(ClinitCheck, Instruction)                                           \
488  M(Compare, BinaryOperation)                                           \
489  M(Condition, BinaryOperation)                                         \
490  M(Div, BinaryOperation)                                               \
491  M(DivZeroCheck, Instruction)                                          \
492  M(DoubleConstant, Constant)                                           \
493  M(Equal, Condition)                                                   \
494  M(Exit, Instruction)                                                  \
495  M(FloatConstant, Constant)                                            \
496  M(Goto, Instruction)                                                  \
497  M(GreaterThan, Condition)                                             \
498  M(GreaterThanOrEqual, Condition)                                      \
499  M(If, Instruction)                                                    \
500  M(InstanceFieldGet, Instruction)                                      \
501  M(InstanceFieldSet, Instruction)                                      \
502  M(InstanceOf, Instruction)                                            \
503  M(IntConstant, Constant)                                              \
504  M(InvokeInterface, Invoke)                                            \
505  M(InvokeStatic, Invoke)                                               \
506  M(InvokeVirtual, Invoke)                                              \
507  M(LessThan, Condition)                                                \
508  M(LessThanOrEqual, Condition)                                         \
509  M(LoadClass, Instruction)                                             \
510  M(LoadException, Instruction)                                         \
511  M(LoadLocal, Instruction)                                             \
512  M(LoadString, Instruction)                                            \
513  M(Local, Instruction)                                                 \
514  M(LongConstant, Constant)                                             \
515  M(MonitorOperation, Instruction)                                      \
516  M(Mul, BinaryOperation)                                               \
517  M(Neg, UnaryOperation)                                                \
518  M(NewArray, Instruction)                                              \
519  M(NewInstance, Instruction)                                           \
520  M(Not, UnaryOperation)                                                \
521  M(NotEqual, Condition)                                                \
522  M(NullCheck, Instruction)                                             \
523  M(Or, BinaryOperation)                                                \
524  M(ParallelMove, Instruction)                                          \
525  M(ParameterValue, Instruction)                                        \
526  M(Phi, Instruction)                                                   \
527  M(Rem, BinaryOperation)                                               \
528  M(Return, Instruction)                                                \
529  M(ReturnVoid, Instruction)                                            \
530  M(Shl, BinaryOperation)                                               \
531  M(Shr, BinaryOperation)                                               \
532  M(StaticFieldGet, Instruction)                                        \
533  M(StaticFieldSet, Instruction)                                        \
534  M(StoreLocal, Instruction)                                            \
535  M(Sub, BinaryOperation)                                               \
536  M(SuspendCheck, Instruction)                                          \
537  M(Temporary, Instruction)                                             \
538  M(Throw, Instruction)                                                 \
539  M(TypeConversion, Instruction)                                        \
540  M(UShr, BinaryOperation)                                              \
541  M(Xor, BinaryOperation)                                               \
542
543#define FOR_EACH_INSTRUCTION(M)                                         \
544  FOR_EACH_CONCRETE_INSTRUCTION(M)                                      \
545  M(Constant, Instruction)                                              \
546  M(UnaryOperation, Instruction)                                        \
547  M(BinaryOperation, Instruction)                                       \
548  M(Invoke, Instruction)
549
550#define FORWARD_DECLARATION(type, super) class H##type;
551FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
552#undef FORWARD_DECLARATION
553
554#define DECLARE_INSTRUCTION(type)                                       \
555  virtual InstructionKind GetKind() const { return k##type; }           \
556  virtual const char* DebugName() const { return #type; }               \
557  virtual const H##type* As##type() const OVERRIDE { return this; }     \
558  virtual H##type* As##type() OVERRIDE { return this; }                 \
559  virtual bool InstructionTypeEquals(HInstruction* other) const {       \
560    return other->Is##type();                                           \
561  }                                                                     \
562  virtual void Accept(HGraphVisitor* visitor)
563
564template <typename T>
565class HUseListNode : public ArenaObject<kArenaAllocMisc> {
566 public:
567  HUseListNode(T* user, size_t index, HUseListNode* tail)
568      : user_(user), index_(index), tail_(tail) {}
569
570  HUseListNode* GetTail() const { return tail_; }
571  T* GetUser() const { return user_; }
572  size_t GetIndex() const { return index_; }
573
574  void SetTail(HUseListNode<T>* node) { tail_ = node; }
575
576 private:
577  T* const user_;
578  const size_t index_;
579  HUseListNode<T>* tail_;
580
581  DISALLOW_COPY_AND_ASSIGN(HUseListNode);
582};
583
584// Represents the side effects an instruction may have.
585class SideEffects : public ValueObject {
586 public:
587  SideEffects() : flags_(0) {}
588
589  static SideEffects None() {
590    return SideEffects(0);
591  }
592
593  static SideEffects All() {
594    return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_);
595  }
596
597  static SideEffects ChangesSomething() {
598    return SideEffects((1 << kFlagChangesCount) - 1);
599  }
600
601  static SideEffects DependsOnSomething() {
602    int count = kFlagDependsOnCount - kFlagChangesCount;
603    return SideEffects(((1 << count) - 1) << kFlagChangesCount);
604  }
605
606  SideEffects Union(SideEffects other) const {
607    return SideEffects(flags_ | other.flags_);
608  }
609
610  bool HasSideEffects() const {
611    size_t all_bits_set = (1 << kFlagChangesCount) - 1;
612    return (flags_ & all_bits_set) != 0;
613  }
614
615  bool HasAllSideEffects() const {
616    size_t all_bits_set = (1 << kFlagChangesCount) - 1;
617    return all_bits_set == (flags_ & all_bits_set);
618  }
619
620  bool DependsOn(SideEffects other) const {
621    size_t depends_flags = other.ComputeDependsFlags();
622    return (flags_ & depends_flags) != 0;
623  }
624
625  bool HasDependencies() const {
626    int count = kFlagDependsOnCount - kFlagChangesCount;
627    size_t all_bits_set = (1 << count) - 1;
628    return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0;
629  }
630
631 private:
632  static constexpr int kFlagChangesSomething = 0;
633  static constexpr int kFlagChangesCount = kFlagChangesSomething + 1;
634
635  static constexpr int kFlagDependsOnSomething = kFlagChangesCount;
636  static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1;
637
638  explicit SideEffects(size_t flags) : flags_(flags) {}
639
640  size_t ComputeDependsFlags() const {
641    return flags_ << kFlagChangesCount;
642  }
643
644  size_t flags_;
645};
646
647class HInstruction : public ArenaObject<kArenaAllocMisc> {
648 public:
649  explicit HInstruction(SideEffects side_effects)
650      : previous_(nullptr),
651        next_(nullptr),
652        block_(nullptr),
653        id_(-1),
654        ssa_index_(-1),
655        uses_(nullptr),
656        env_uses_(nullptr),
657        environment_(nullptr),
658        locations_(nullptr),
659        live_interval_(nullptr),
660        lifetime_position_(kNoLifetime),
661        side_effects_(side_effects) {}
662
663  virtual ~HInstruction() {}
664
665#define DECLARE_KIND(type, super) k##type,
666  enum InstructionKind {
667    FOR_EACH_INSTRUCTION(DECLARE_KIND)
668  };
669#undef DECLARE_KIND
670
671  HInstruction* GetNext() const { return next_; }
672  HInstruction* GetPrevious() const { return previous_; }
673
674  HBasicBlock* GetBlock() const { return block_; }
675  void SetBlock(HBasicBlock* block) { block_ = block; }
676  bool IsInBlock() const { return block_ != nullptr; }
677  bool IsInLoop() const { return block_->IsInLoop(); }
678  bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); }
679
680  virtual size_t InputCount() const = 0;
681  virtual HInstruction* InputAt(size_t i) const = 0;
682
683  virtual void Accept(HGraphVisitor* visitor) = 0;
684  virtual const char* DebugName() const = 0;
685
686  virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; }
687  virtual void SetRawInputAt(size_t index, HInstruction* input) = 0;
688
689  virtual bool NeedsEnvironment() const { return false; }
690  virtual bool IsControlFlow() const { return false; }
691  virtual bool CanThrow() const { return false; }
692  bool HasSideEffects() const { return side_effects_.HasSideEffects(); }
693
694  void AddUseAt(HInstruction* user, size_t index) {
695    uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_);
696  }
697
698  void AddEnvUseAt(HEnvironment* user, size_t index) {
699    DCHECK(user != nullptr);
700    env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>(
701        user, index, env_uses_);
702  }
703
704  void RemoveUser(HInstruction* user, size_t index);
705  void RemoveEnvironmentUser(HEnvironment* user, size_t index);
706
707  HUseListNode<HInstruction>* GetUses() const { return uses_; }
708  HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; }
709
710  bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; }
711  bool HasEnvironmentUses() const { return env_uses_ != nullptr; }
712
713  size_t NumberOfUses() const {
714    // TODO: Optimize this method if it is used outside of the HGraphVisualizer.
715    size_t result = 0;
716    HUseListNode<HInstruction>* current = uses_;
717    while (current != nullptr) {
718      current = current->GetTail();
719      ++result;
720    }
721    return result;
722  }
723
724  // Does this instruction strictly dominate `other_instruction`?
725  // Returns false if this instruction and `other_instruction` are the same.
726  // Aborts if this instruction and `other_instruction` are both phis.
727  bool StrictlyDominates(HInstruction* other_instruction) const;
728
729  int GetId() const { return id_; }
730  void SetId(int id) { id_ = id; }
731
732  int GetSsaIndex() const { return ssa_index_; }
733  void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; }
734  bool HasSsaIndex() const { return ssa_index_ != -1; }
735
736  bool HasEnvironment() const { return environment_ != nullptr; }
737  HEnvironment* GetEnvironment() const { return environment_; }
738  void SetEnvironment(HEnvironment* environment) { environment_ = environment; }
739
740  // Returns the number of entries in the environment. Typically, that is the
741  // number of dex registers in a method. It could be more in case of inlining.
742  size_t EnvironmentSize() const;
743
744  LocationSummary* GetLocations() const { return locations_; }
745  void SetLocations(LocationSummary* locations) { locations_ = locations; }
746
747  void ReplaceWith(HInstruction* instruction);
748  void ReplaceInput(HInstruction* replacement, size_t index);
749
750  bool HasOnlyOneUse() const {
751    return uses_ != nullptr && uses_->GetTail() == nullptr;
752  }
753
754#define INSTRUCTION_TYPE_CHECK(type, super)                                    \
755  bool Is##type() const { return (As##type() != nullptr); }                    \
756  virtual const H##type* As##type() const { return nullptr; }                  \
757  virtual H##type* As##type() { return nullptr; }
758
759  FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
760#undef INSTRUCTION_TYPE_CHECK
761
762  // Returns whether the instruction can be moved within the graph.
763  virtual bool CanBeMoved() const { return false; }
764
765  // Returns whether the two instructions are of the same kind.
766  virtual bool InstructionTypeEquals(HInstruction* other) const {
767    UNUSED(other);
768    return false;
769  }
770
771  // Returns whether any data encoded in the two instructions is equal.
772  // This method does not look at the inputs. Both instructions must be
773  // of the same type, otherwise the method has undefined behavior.
774  virtual bool InstructionDataEquals(HInstruction* other) const {
775    UNUSED(other);
776    return false;
777  }
778
779  // Returns whether two instructions are equal, that is:
780  // 1) They have the same type and contain the same data,
781  // 2) Their inputs are identical.
782  bool Equals(HInstruction* other) const;
783
784  virtual InstructionKind GetKind() const = 0;
785
786  virtual size_t ComputeHashCode() const {
787    size_t result = GetKind();
788    for (size_t i = 0, e = InputCount(); i < e; ++i) {
789      result = (result * 31) + InputAt(i)->GetId();
790    }
791    return result;
792  }
793
794  SideEffects GetSideEffects() const { return side_effects_; }
795
796  size_t GetLifetimePosition() const { return lifetime_position_; }
797  void SetLifetimePosition(size_t position) { lifetime_position_ = position; }
798  LiveInterval* GetLiveInterval() const { return live_interval_; }
799  void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; }
800  bool HasLiveInterval() const { return live_interval_ != nullptr; }
801
802 private:
803  HInstruction* previous_;
804  HInstruction* next_;
805  HBasicBlock* block_;
806
807  // An instruction gets an id when it is added to the graph.
808  // It reflects creation order. A negative id means the instruction
809  // has not been added to the graph.
810  int id_;
811
812  // When doing liveness analysis, instructions that have uses get an SSA index.
813  int ssa_index_;
814
815  // List of instructions that have this instruction as input.
816  HUseListNode<HInstruction>* uses_;
817
818  // List of environments that contain this instruction.
819  HUseListNode<HEnvironment>* env_uses_;
820
821  // The environment associated with this instruction. Not null if the instruction
822  // might jump out of the method.
823  HEnvironment* environment_;
824
825  // Set by the code generator.
826  LocationSummary* locations_;
827
828  // Set by the liveness analysis.
829  LiveInterval* live_interval_;
830
831  // Set by the liveness analysis, this is the position in a linear
832  // order of blocks where this instruction's live interval start.
833  size_t lifetime_position_;
834
835  const SideEffects side_effects_;
836
837  friend class HBasicBlock;
838  friend class HInstructionList;
839
840  DISALLOW_COPY_AND_ASSIGN(HInstruction);
841};
842std::ostream& operator<<(std::ostream& os, const HInstruction::InstructionKind& rhs);
843
844template<typename T>
845class HUseIterator : public ValueObject {
846 public:
847  explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {}
848
849  bool Done() const { return current_ == nullptr; }
850
851  void Advance() {
852    DCHECK(!Done());
853    current_ = current_->GetTail();
854  }
855
856  HUseListNode<T>* Current() const {
857    DCHECK(!Done());
858    return current_;
859  }
860
861 private:
862  HUseListNode<T>* current_;
863
864  friend class HValue;
865};
866
867// A HEnvironment object contains the values of virtual registers at a given location.
868class HEnvironment : public ArenaObject<kArenaAllocMisc> {
869 public:
870  HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) {
871    vregs_.SetSize(number_of_vregs);
872    for (size_t i = 0; i < number_of_vregs; i++) {
873      vregs_.Put(i, nullptr);
874    }
875  }
876
877  void Populate(const GrowableArray<HInstruction*>& env) {
878    for (size_t i = 0; i < env.Size(); i++) {
879      HInstruction* instruction = env.Get(i);
880      vregs_.Put(i, instruction);
881      if (instruction != nullptr) {
882        instruction->AddEnvUseAt(this, i);
883      }
884    }
885  }
886
887  void SetRawEnvAt(size_t index, HInstruction* instruction) {
888    vregs_.Put(index, instruction);
889  }
890
891  HInstruction* GetInstructionAt(size_t index) const {
892    return vregs_.Get(index);
893  }
894
895  GrowableArray<HInstruction*>* GetVRegs() {
896    return &vregs_;
897  }
898
899  size_t Size() const { return vregs_.Size(); }
900
901 private:
902  GrowableArray<HInstruction*> vregs_;
903
904  DISALLOW_COPY_AND_ASSIGN(HEnvironment);
905};
906
907class HInputIterator : public ValueObject {
908 public:
909  explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {}
910
911  bool Done() const { return index_ == instruction_->InputCount(); }
912  HInstruction* Current() const { return instruction_->InputAt(index_); }
913  void Advance() { index_++; }
914
915 private:
916  HInstruction* instruction_;
917  size_t index_;
918
919  DISALLOW_COPY_AND_ASSIGN(HInputIterator);
920};
921
922class HInstructionIterator : public ValueObject {
923 public:
924  explicit HInstructionIterator(const HInstructionList& instructions)
925      : instruction_(instructions.first_instruction_) {
926    next_ = Done() ? nullptr : instruction_->GetNext();
927  }
928
929  bool Done() const { return instruction_ == nullptr; }
930  HInstruction* Current() const { return instruction_; }
931  void Advance() {
932    instruction_ = next_;
933    next_ = Done() ? nullptr : instruction_->GetNext();
934  }
935
936 private:
937  HInstruction* instruction_;
938  HInstruction* next_;
939
940  DISALLOW_COPY_AND_ASSIGN(HInstructionIterator);
941};
942
943class HBackwardInstructionIterator : public ValueObject {
944 public:
945  explicit HBackwardInstructionIterator(const HInstructionList& instructions)
946      : instruction_(instructions.last_instruction_) {
947    next_ = Done() ? nullptr : instruction_->GetPrevious();
948  }
949
950  bool Done() const { return instruction_ == nullptr; }
951  HInstruction* Current() const { return instruction_; }
952  void Advance() {
953    instruction_ = next_;
954    next_ = Done() ? nullptr : instruction_->GetPrevious();
955  }
956
957 private:
958  HInstruction* instruction_;
959  HInstruction* next_;
960
961  DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator);
962};
963
964// An embedded container with N elements of type T.  Used (with partial
965// specialization for N=0) because embedded arrays cannot have size 0.
966template<typename T, intptr_t N>
967class EmbeddedArray {
968 public:
969  EmbeddedArray() : elements_() {}
970
971  intptr_t GetLength() const { return N; }
972
973  const T& operator[](intptr_t i) const {
974    DCHECK_LT(i, GetLength());
975    return elements_[i];
976  }
977
978  T& operator[](intptr_t i) {
979    DCHECK_LT(i, GetLength());
980    return elements_[i];
981  }
982
983  const T& At(intptr_t i) const {
984    return (*this)[i];
985  }
986
987  void SetAt(intptr_t i, const T& val) {
988    (*this)[i] = val;
989  }
990
991 private:
992  T elements_[N];
993};
994
995template<typename T>
996class EmbeddedArray<T, 0> {
997 public:
998  intptr_t length() const { return 0; }
999  const T& operator[](intptr_t i) const {
1000    UNUSED(i);
1001    LOG(FATAL) << "Unreachable";
1002    UNREACHABLE();
1003  }
1004  T& operator[](intptr_t i) {
1005    UNUSED(i);
1006    LOG(FATAL) << "Unreachable";
1007    UNREACHABLE();
1008  }
1009};
1010
1011template<intptr_t N>
1012class HTemplateInstruction: public HInstruction {
1013 public:
1014  HTemplateInstruction<N>(SideEffects side_effects)
1015      : HInstruction(side_effects), inputs_() {}
1016  virtual ~HTemplateInstruction() {}
1017
1018  virtual size_t InputCount() const { return N; }
1019  virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; }
1020
1021 protected:
1022  virtual void SetRawInputAt(size_t i, HInstruction* instruction) {
1023    inputs_[i] = instruction;
1024  }
1025
1026 private:
1027  EmbeddedArray<HInstruction*, N> inputs_;
1028
1029  friend class SsaBuilder;
1030};
1031
1032template<intptr_t N>
1033class HExpression : public HTemplateInstruction<N> {
1034 public:
1035  HExpression<N>(Primitive::Type type, SideEffects side_effects)
1036      : HTemplateInstruction<N>(side_effects), type_(type) {}
1037  virtual ~HExpression() {}
1038
1039  virtual Primitive::Type GetType() const { return type_; }
1040
1041 protected:
1042  Primitive::Type type_;
1043};
1044
1045// Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow
1046// instruction that branches to the exit block.
1047class HReturnVoid : public HTemplateInstruction<0> {
1048 public:
1049  HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
1050
1051  virtual bool IsControlFlow() const { return true; }
1052
1053  DECLARE_INSTRUCTION(ReturnVoid);
1054
1055 private:
1056  DISALLOW_COPY_AND_ASSIGN(HReturnVoid);
1057};
1058
1059// Represents dex's RETURN opcodes. A HReturn is a control flow
1060// instruction that branches to the exit block.
1061class HReturn : public HTemplateInstruction<1> {
1062 public:
1063  explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
1064    SetRawInputAt(0, value);
1065  }
1066
1067  virtual bool IsControlFlow() const { return true; }
1068
1069  DECLARE_INSTRUCTION(Return);
1070
1071 private:
1072  DISALLOW_COPY_AND_ASSIGN(HReturn);
1073};
1074
1075// The exit instruction is the only instruction of the exit block.
1076// Instructions aborting the method (HThrow and HReturn) must branch to the
1077// exit block.
1078class HExit : public HTemplateInstruction<0> {
1079 public:
1080  HExit() : HTemplateInstruction(SideEffects::None()) {}
1081
1082  virtual bool IsControlFlow() const { return true; }
1083
1084  DECLARE_INSTRUCTION(Exit);
1085
1086 private:
1087  DISALLOW_COPY_AND_ASSIGN(HExit);
1088};
1089
1090// Jumps from one block to another.
1091class HGoto : public HTemplateInstruction<0> {
1092 public:
1093  HGoto() : HTemplateInstruction(SideEffects::None()) {}
1094
1095  bool IsControlFlow() const OVERRIDE { return true; }
1096
1097  HBasicBlock* GetSuccessor() const {
1098    return GetBlock()->GetSuccessors().Get(0);
1099  }
1100
1101  DECLARE_INSTRUCTION(Goto);
1102
1103 private:
1104  DISALLOW_COPY_AND_ASSIGN(HGoto);
1105};
1106
1107
1108// Conditional branch. A block ending with an HIf instruction must have
1109// two successors.
1110class HIf : public HTemplateInstruction<1> {
1111 public:
1112  explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
1113    SetRawInputAt(0, input);
1114  }
1115
1116  bool IsControlFlow() const OVERRIDE { return true; }
1117
1118  HBasicBlock* IfTrueSuccessor() const {
1119    return GetBlock()->GetSuccessors().Get(0);
1120  }
1121
1122  HBasicBlock* IfFalseSuccessor() const {
1123    return GetBlock()->GetSuccessors().Get(1);
1124  }
1125
1126  DECLARE_INSTRUCTION(If);
1127
1128  virtual bool IsIfInstruction() const { return true; }
1129
1130 private:
1131  DISALLOW_COPY_AND_ASSIGN(HIf);
1132};
1133
1134class HUnaryOperation : public HExpression<1> {
1135 public:
1136  HUnaryOperation(Primitive::Type result_type, HInstruction* input)
1137      : HExpression(result_type, SideEffects::None()) {
1138    SetRawInputAt(0, input);
1139  }
1140
1141  HInstruction* GetInput() const { return InputAt(0); }
1142  Primitive::Type GetResultType() const { return GetType(); }
1143
1144  virtual bool CanBeMoved() const { return true; }
1145  virtual bool InstructionDataEquals(HInstruction* other) const {
1146    UNUSED(other);
1147    return true;
1148  }
1149
1150  // Try to statically evaluate `operation` and return a HConstant
1151  // containing the result of this evaluation.  If `operation` cannot
1152  // be evaluated as a constant, return nullptr.
1153  HConstant* TryStaticEvaluation() const;
1154
1155  // Apply this operation to `x`.
1156  virtual int32_t Evaluate(int32_t x) const = 0;
1157  virtual int64_t Evaluate(int64_t x) const = 0;
1158
1159  DECLARE_INSTRUCTION(UnaryOperation);
1160
1161 private:
1162  DISALLOW_COPY_AND_ASSIGN(HUnaryOperation);
1163};
1164
1165class HBinaryOperation : public HExpression<2> {
1166 public:
1167  HBinaryOperation(Primitive::Type result_type,
1168                   HInstruction* left,
1169                   HInstruction* right) : HExpression(result_type, SideEffects::None()) {
1170    SetRawInputAt(0, left);
1171    SetRawInputAt(1, right);
1172  }
1173
1174  HInstruction* GetLeft() const { return InputAt(0); }
1175  HInstruction* GetRight() const { return InputAt(1); }
1176  Primitive::Type GetResultType() const { return GetType(); }
1177
1178  virtual bool IsCommutative() { return false; }
1179
1180  virtual bool CanBeMoved() const { return true; }
1181  virtual bool InstructionDataEquals(HInstruction* other) const {
1182    UNUSED(other);
1183    return true;
1184  }
1185
1186  // Try to statically evaluate `operation` and return a HConstant
1187  // containing the result of this evaluation.  If `operation` cannot
1188  // be evaluated as a constant, return nullptr.
1189  HConstant* TryStaticEvaluation() const;
1190
1191  // Apply this operation to `x` and `y`.
1192  virtual int32_t Evaluate(int32_t x, int32_t y) const = 0;
1193  virtual int64_t Evaluate(int64_t x, int64_t y) const = 0;
1194
1195  DECLARE_INSTRUCTION(BinaryOperation);
1196
1197 private:
1198  DISALLOW_COPY_AND_ASSIGN(HBinaryOperation);
1199};
1200
1201class HCondition : public HBinaryOperation {
1202 public:
1203  HCondition(HInstruction* first, HInstruction* second)
1204      : HBinaryOperation(Primitive::kPrimBoolean, first, second),
1205        needs_materialization_(true) {}
1206
1207  virtual bool IsCommutative() { return true; }
1208
1209  bool NeedsMaterialization() const { return needs_materialization_; }
1210  void ClearNeedsMaterialization() { needs_materialization_ = false; }
1211
1212  // For code generation purposes, returns whether this instruction is just before
1213  // `if_`, and disregard moves in between.
1214  bool IsBeforeWhenDisregardMoves(HIf* if_) const;
1215
1216  DECLARE_INSTRUCTION(Condition);
1217
1218  virtual IfCondition GetCondition() const = 0;
1219
1220 private:
1221  // For register allocation purposes, returns whether this instruction needs to be
1222  // materialized (that is, not just be in the processor flags).
1223  bool needs_materialization_;
1224
1225  DISALLOW_COPY_AND_ASSIGN(HCondition);
1226};
1227
1228// Instruction to check if two inputs are equal to each other.
1229class HEqual : public HCondition {
1230 public:
1231  HEqual(HInstruction* first, HInstruction* second)
1232      : HCondition(first, second) {}
1233
1234  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1235    return x == y ? 1 : 0;
1236  }
1237  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1238    return x == y ? 1 : 0;
1239  }
1240
1241  DECLARE_INSTRUCTION(Equal);
1242
1243  virtual IfCondition GetCondition() const {
1244    return kCondEQ;
1245  }
1246
1247 private:
1248  DISALLOW_COPY_AND_ASSIGN(HEqual);
1249};
1250
1251class HNotEqual : public HCondition {
1252 public:
1253  HNotEqual(HInstruction* first, HInstruction* second)
1254      : HCondition(first, second) {}
1255
1256  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1257    return x != y ? 1 : 0;
1258  }
1259  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1260    return x != y ? 1 : 0;
1261  }
1262
1263  DECLARE_INSTRUCTION(NotEqual);
1264
1265  virtual IfCondition GetCondition() const {
1266    return kCondNE;
1267  }
1268
1269 private:
1270  DISALLOW_COPY_AND_ASSIGN(HNotEqual);
1271};
1272
1273class HLessThan : public HCondition {
1274 public:
1275  HLessThan(HInstruction* first, HInstruction* second)
1276      : HCondition(first, second) {}
1277
1278  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1279    return x < y ? 1 : 0;
1280  }
1281  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1282    return x < y ? 1 : 0;
1283  }
1284
1285  DECLARE_INSTRUCTION(LessThan);
1286
1287  virtual IfCondition GetCondition() const {
1288    return kCondLT;
1289  }
1290
1291 private:
1292  DISALLOW_COPY_AND_ASSIGN(HLessThan);
1293};
1294
1295class HLessThanOrEqual : public HCondition {
1296 public:
1297  HLessThanOrEqual(HInstruction* first, HInstruction* second)
1298      : HCondition(first, second) {}
1299
1300  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1301    return x <= y ? 1 : 0;
1302  }
1303  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1304    return x <= y ? 1 : 0;
1305  }
1306
1307  DECLARE_INSTRUCTION(LessThanOrEqual);
1308
1309  virtual IfCondition GetCondition() const {
1310    return kCondLE;
1311  }
1312
1313 private:
1314  DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual);
1315};
1316
1317class HGreaterThan : public HCondition {
1318 public:
1319  HGreaterThan(HInstruction* first, HInstruction* second)
1320      : HCondition(first, second) {}
1321
1322  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1323    return x > y ? 1 : 0;
1324  }
1325  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1326    return x > y ? 1 : 0;
1327  }
1328
1329  DECLARE_INSTRUCTION(GreaterThan);
1330
1331  virtual IfCondition GetCondition() const {
1332    return kCondGT;
1333  }
1334
1335 private:
1336  DISALLOW_COPY_AND_ASSIGN(HGreaterThan);
1337};
1338
1339class HGreaterThanOrEqual : public HCondition {
1340 public:
1341  HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
1342      : HCondition(first, second) {}
1343
1344  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1345    return x >= y ? 1 : 0;
1346  }
1347  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1348    return x >= y ? 1 : 0;
1349  }
1350
1351  DECLARE_INSTRUCTION(GreaterThanOrEqual);
1352
1353  virtual IfCondition GetCondition() const {
1354    return kCondGE;
1355  }
1356
1357 private:
1358  DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual);
1359};
1360
1361
1362// Instruction to check how two inputs compare to each other.
1363// Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1.
1364class HCompare : public HBinaryOperation {
1365 public:
1366  // The bias applies for floating point operations and indicates how NaN
1367  // comparisons are treated:
1368  enum Bias {
1369    kNoBias,  // bias is not applicable (i.e. for long operation)
1370    kGtBias,  // return 1 for NaN comparisons
1371    kLtBias,  // return -1 for NaN comparisons
1372  };
1373
1374  HCompare(Primitive::Type type, HInstruction* first, HInstruction* second, Bias bias)
1375      : HBinaryOperation(Primitive::kPrimInt, first, second), bias_(bias) {
1376    DCHECK_EQ(type, first->GetType());
1377    DCHECK_EQ(type, second->GetType());
1378  }
1379
1380  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1381    return
1382      x == y ? 0 :
1383      x > y ? 1 :
1384      -1;
1385  }
1386
1387  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1388    return
1389      x == y ? 0 :
1390      x > y ? 1 :
1391      -1;
1392  }
1393
1394  bool IsGtBias() { return bias_ == kGtBias; }
1395
1396  DECLARE_INSTRUCTION(Compare);
1397
1398 private:
1399  Bias bias_;
1400
1401  DISALLOW_COPY_AND_ASSIGN(HCompare);
1402};
1403
1404// A local in the graph. Corresponds to a Dex register.
1405class HLocal : public HTemplateInstruction<0> {
1406 public:
1407  explicit HLocal(uint16_t reg_number)
1408      : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
1409
1410  DECLARE_INSTRUCTION(Local);
1411
1412  uint16_t GetRegNumber() const { return reg_number_; }
1413
1414 private:
1415  // The Dex register number.
1416  const uint16_t reg_number_;
1417
1418  DISALLOW_COPY_AND_ASSIGN(HLocal);
1419};
1420
1421// Load a given local. The local is an input of this instruction.
1422class HLoadLocal : public HExpression<1> {
1423 public:
1424  HLoadLocal(HLocal* local, Primitive::Type type)
1425      : HExpression(type, SideEffects::None()) {
1426    SetRawInputAt(0, local);
1427  }
1428
1429  HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1430
1431  DECLARE_INSTRUCTION(LoadLocal);
1432
1433 private:
1434  DISALLOW_COPY_AND_ASSIGN(HLoadLocal);
1435};
1436
1437// Store a value in a given local. This instruction has two inputs: the value
1438// and the local.
1439class HStoreLocal : public HTemplateInstruction<2> {
1440 public:
1441  HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
1442    SetRawInputAt(0, local);
1443    SetRawInputAt(1, value);
1444  }
1445
1446  HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); }
1447
1448  DECLARE_INSTRUCTION(StoreLocal);
1449
1450 private:
1451  DISALLOW_COPY_AND_ASSIGN(HStoreLocal);
1452};
1453
1454class HConstant : public HExpression<0> {
1455 public:
1456  explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
1457
1458  virtual bool CanBeMoved() const { return true; }
1459
1460  DECLARE_INSTRUCTION(Constant);
1461
1462 private:
1463  DISALLOW_COPY_AND_ASSIGN(HConstant);
1464};
1465
1466class HFloatConstant : public HConstant {
1467 public:
1468  explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
1469
1470  float GetValue() const { return value_; }
1471
1472  virtual bool InstructionDataEquals(HInstruction* other) const {
1473    return bit_cast<float, int32_t>(other->AsFloatConstant()->value_) ==
1474        bit_cast<float, int32_t>(value_);
1475  }
1476
1477  virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1478
1479  DECLARE_INSTRUCTION(FloatConstant);
1480
1481 private:
1482  const float value_;
1483
1484  DISALLOW_COPY_AND_ASSIGN(HFloatConstant);
1485};
1486
1487class HDoubleConstant : public HConstant {
1488 public:
1489  explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
1490
1491  double GetValue() const { return value_; }
1492
1493  virtual bool InstructionDataEquals(HInstruction* other) const {
1494    return bit_cast<double, int64_t>(other->AsDoubleConstant()->value_) ==
1495        bit_cast<double, int64_t>(value_);
1496  }
1497
1498  virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1499
1500  DECLARE_INSTRUCTION(DoubleConstant);
1501
1502 private:
1503  const double value_;
1504
1505  DISALLOW_COPY_AND_ASSIGN(HDoubleConstant);
1506};
1507
1508// Constants of the type int. Those can be from Dex instructions, or
1509// synthesized (for example with the if-eqz instruction).
1510class HIntConstant : public HConstant {
1511 public:
1512  explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
1513
1514  int32_t GetValue() const { return value_; }
1515
1516  virtual bool InstructionDataEquals(HInstruction* other) const {
1517    return other->AsIntConstant()->value_ == value_;
1518  }
1519
1520  virtual size_t ComputeHashCode() const { return GetValue(); }
1521
1522  DECLARE_INSTRUCTION(IntConstant);
1523
1524 private:
1525  const int32_t value_;
1526
1527  DISALLOW_COPY_AND_ASSIGN(HIntConstant);
1528};
1529
1530class HLongConstant : public HConstant {
1531 public:
1532  explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
1533
1534  int64_t GetValue() const { return value_; }
1535
1536  virtual bool InstructionDataEquals(HInstruction* other) const {
1537    return other->AsLongConstant()->value_ == value_;
1538  }
1539
1540  virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); }
1541
1542  DECLARE_INSTRUCTION(LongConstant);
1543
1544 private:
1545  const int64_t value_;
1546
1547  DISALLOW_COPY_AND_ASSIGN(HLongConstant);
1548};
1549
1550class HInvoke : public HInstruction {
1551 public:
1552  HInvoke(ArenaAllocator* arena,
1553          uint32_t number_of_arguments,
1554          Primitive::Type return_type,
1555          uint32_t dex_pc)
1556    : HInstruction(SideEffects::All()),
1557      inputs_(arena, number_of_arguments),
1558      return_type_(return_type),
1559      dex_pc_(dex_pc) {
1560    inputs_.SetSize(number_of_arguments);
1561  }
1562
1563  virtual size_t InputCount() const { return inputs_.Size(); }
1564  virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
1565
1566  // Runtime needs to walk the stack, so Dex -> Dex calls need to
1567  // know their environment.
1568  virtual bool NeedsEnvironment() const { return true; }
1569
1570  void SetArgumentAt(size_t index, HInstruction* argument) {
1571    SetRawInputAt(index, argument);
1572  }
1573
1574  virtual void SetRawInputAt(size_t index, HInstruction* input) {
1575    inputs_.Put(index, input);
1576  }
1577
1578  virtual Primitive::Type GetType() const { return return_type_; }
1579
1580  uint32_t GetDexPc() const { return dex_pc_; }
1581
1582  DECLARE_INSTRUCTION(Invoke);
1583
1584 protected:
1585  GrowableArray<HInstruction*> inputs_;
1586  const Primitive::Type return_type_;
1587  const uint32_t dex_pc_;
1588
1589 private:
1590  DISALLOW_COPY_AND_ASSIGN(HInvoke);
1591};
1592
1593class HInvokeStatic : public HInvoke {
1594 public:
1595  HInvokeStatic(ArenaAllocator* arena,
1596                uint32_t number_of_arguments,
1597                Primitive::Type return_type,
1598                uint32_t dex_pc,
1599                uint32_t index_in_dex_cache)
1600      : HInvoke(arena, number_of_arguments, return_type, dex_pc),
1601        index_in_dex_cache_(index_in_dex_cache) {}
1602
1603  uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; }
1604
1605  DECLARE_INSTRUCTION(InvokeStatic);
1606
1607 private:
1608  const uint32_t index_in_dex_cache_;
1609
1610  DISALLOW_COPY_AND_ASSIGN(HInvokeStatic);
1611};
1612
1613class HInvokeVirtual : public HInvoke {
1614 public:
1615  HInvokeVirtual(ArenaAllocator* arena,
1616                 uint32_t number_of_arguments,
1617                 Primitive::Type return_type,
1618                 uint32_t dex_pc,
1619                 uint32_t vtable_index)
1620      : HInvoke(arena, number_of_arguments, return_type, dex_pc),
1621        vtable_index_(vtable_index) {}
1622
1623  uint32_t GetVTableIndex() const { return vtable_index_; }
1624
1625  DECLARE_INSTRUCTION(InvokeVirtual);
1626
1627 private:
1628  const uint32_t vtable_index_;
1629
1630  DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual);
1631};
1632
1633class HInvokeInterface : public HInvoke {
1634 public:
1635  HInvokeInterface(ArenaAllocator* arena,
1636                   uint32_t number_of_arguments,
1637                   Primitive::Type return_type,
1638                   uint32_t dex_pc,
1639                   uint32_t dex_method_index,
1640                   uint32_t imt_index)
1641      : HInvoke(arena, number_of_arguments, return_type, dex_pc),
1642        dex_method_index_(dex_method_index),
1643        imt_index_(imt_index) {}
1644
1645  uint32_t GetImtIndex() const { return imt_index_; }
1646  uint32_t GetDexMethodIndex() const { return dex_method_index_; }
1647
1648  DECLARE_INSTRUCTION(InvokeInterface);
1649
1650 private:
1651  const uint32_t dex_method_index_;
1652  const uint32_t imt_index_;
1653
1654  DISALLOW_COPY_AND_ASSIGN(HInvokeInterface);
1655};
1656
1657class HNewInstance : public HExpression<0> {
1658 public:
1659  HNewInstance(uint32_t dex_pc, uint16_t type_index)
1660      : HExpression(Primitive::kPrimNot, SideEffects::None()),
1661        dex_pc_(dex_pc),
1662        type_index_(type_index) {}
1663
1664  uint32_t GetDexPc() const { return dex_pc_; }
1665  uint16_t GetTypeIndex() const { return type_index_; }
1666
1667  // Calls runtime so needs an environment.
1668  virtual bool NeedsEnvironment() const { return true; }
1669
1670  DECLARE_INSTRUCTION(NewInstance);
1671
1672 private:
1673  const uint32_t dex_pc_;
1674  const uint16_t type_index_;
1675
1676  DISALLOW_COPY_AND_ASSIGN(HNewInstance);
1677};
1678
1679class HNeg : public HUnaryOperation {
1680 public:
1681  explicit HNeg(Primitive::Type result_type, HInstruction* input)
1682      : HUnaryOperation(result_type, input) {}
1683
1684  virtual int32_t Evaluate(int32_t x) const OVERRIDE { return -x; }
1685  virtual int64_t Evaluate(int64_t x) const OVERRIDE { return -x; }
1686
1687  DECLARE_INSTRUCTION(Neg);
1688
1689 private:
1690  DISALLOW_COPY_AND_ASSIGN(HNeg);
1691};
1692
1693class HNewArray : public HExpression<1> {
1694 public:
1695  HNewArray(HInstruction* length, uint32_t dex_pc, uint16_t type_index)
1696      : HExpression(Primitive::kPrimNot, SideEffects::None()),
1697        dex_pc_(dex_pc),
1698        type_index_(type_index) {
1699    SetRawInputAt(0, length);
1700  }
1701
1702  uint32_t GetDexPc() const { return dex_pc_; }
1703  uint16_t GetTypeIndex() const { return type_index_; }
1704
1705  // Calls runtime so needs an environment.
1706  virtual bool NeedsEnvironment() const { return true; }
1707
1708  DECLARE_INSTRUCTION(NewArray);
1709
1710 private:
1711  const uint32_t dex_pc_;
1712  const uint16_t type_index_;
1713
1714  DISALLOW_COPY_AND_ASSIGN(HNewArray);
1715};
1716
1717class HAdd : public HBinaryOperation {
1718 public:
1719  HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1720      : HBinaryOperation(result_type, left, right) {}
1721
1722  virtual bool IsCommutative() { return true; }
1723
1724  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1725    return x + y;
1726  }
1727  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1728    return x + y;
1729  }
1730
1731  DECLARE_INSTRUCTION(Add);
1732
1733 private:
1734  DISALLOW_COPY_AND_ASSIGN(HAdd);
1735};
1736
1737class HSub : public HBinaryOperation {
1738 public:
1739  HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1740      : HBinaryOperation(result_type, left, right) {}
1741
1742  virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1743    return x - y;
1744  }
1745  virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1746    return x - y;
1747  }
1748
1749  DECLARE_INSTRUCTION(Sub);
1750
1751 private:
1752  DISALLOW_COPY_AND_ASSIGN(HSub);
1753};
1754
1755class HMul : public HBinaryOperation {
1756 public:
1757  HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1758      : HBinaryOperation(result_type, left, right) {}
1759
1760  virtual bool IsCommutative() { return true; }
1761
1762  virtual int32_t Evaluate(int32_t x, int32_t y) const { return x * y; }
1763  virtual int64_t Evaluate(int64_t x, int64_t y) const { return x * y; }
1764
1765  DECLARE_INSTRUCTION(Mul);
1766
1767 private:
1768  DISALLOW_COPY_AND_ASSIGN(HMul);
1769};
1770
1771class HDiv : public HBinaryOperation {
1772 public:
1773  HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
1774      : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
1775
1776  virtual int32_t Evaluate(int32_t x, int32_t y) const {
1777    // Our graph structure ensures we never have 0 for `y` during constant folding.
1778    DCHECK_NE(y, 0);
1779    // Special case -1 to avoid getting a SIGFPE on x86(_64).
1780    return (y == -1) ? -x : x / y;
1781  }
1782
1783  virtual int64_t Evaluate(int64_t x, int64_t y) const {
1784    DCHECK_NE(y, 0);
1785    // Special case -1 to avoid getting a SIGFPE on x86(_64).
1786    return (y == -1) ? -x : x / y;
1787  }
1788
1789  uint32_t GetDexPc() const { return dex_pc_; }
1790
1791  DECLARE_INSTRUCTION(Div);
1792
1793 private:
1794  const uint32_t dex_pc_;
1795
1796  DISALLOW_COPY_AND_ASSIGN(HDiv);
1797};
1798
1799class HRem : public HBinaryOperation {
1800 public:
1801  HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
1802      : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {}
1803
1804  virtual int32_t Evaluate(int32_t x, int32_t y) const {
1805    DCHECK_NE(y, 0);
1806    // Special case -1 to avoid getting a SIGFPE on x86(_64).
1807    return (y == -1) ? 0 : x % y;
1808  }
1809
1810  virtual int64_t Evaluate(int64_t x, int64_t y) const {
1811    DCHECK_NE(y, 0);
1812    // Special case -1 to avoid getting a SIGFPE on x86(_64).
1813    return (y == -1) ? 0 : x % y;
1814  }
1815
1816  uint32_t GetDexPc() const { return dex_pc_; }
1817
1818  DECLARE_INSTRUCTION(Rem);
1819
1820 private:
1821  const uint32_t dex_pc_;
1822
1823  DISALLOW_COPY_AND_ASSIGN(HRem);
1824};
1825
1826class HDivZeroCheck : public HExpression<1> {
1827 public:
1828  HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
1829      : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
1830    SetRawInputAt(0, value);
1831  }
1832
1833  bool CanBeMoved() const OVERRIDE { return true; }
1834
1835  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
1836    UNUSED(other);
1837    return true;
1838  }
1839
1840  bool NeedsEnvironment() const OVERRIDE { return true; }
1841  bool CanThrow() const OVERRIDE { return true; }
1842
1843  uint32_t GetDexPc() const { return dex_pc_; }
1844
1845  DECLARE_INSTRUCTION(DivZeroCheck);
1846
1847 private:
1848  const uint32_t dex_pc_;
1849
1850  DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
1851};
1852
1853class HShl : public HBinaryOperation {
1854 public:
1855  HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1856      : HBinaryOperation(result_type, left, right) {}
1857
1858  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x << (y & kMaxIntShiftValue); }
1859  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x << (y & kMaxLongShiftValue); }
1860
1861  DECLARE_INSTRUCTION(Shl);
1862
1863 private:
1864  DISALLOW_COPY_AND_ASSIGN(HShl);
1865};
1866
1867class HShr : public HBinaryOperation {
1868 public:
1869  HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1870      : HBinaryOperation(result_type, left, right) {}
1871
1872  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x >> (y & kMaxIntShiftValue); }
1873  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x >> (y & kMaxLongShiftValue); }
1874
1875  DECLARE_INSTRUCTION(Shr);
1876
1877 private:
1878  DISALLOW_COPY_AND_ASSIGN(HShr);
1879};
1880
1881class HUShr : public HBinaryOperation {
1882 public:
1883  HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1884      : HBinaryOperation(result_type, left, right) {}
1885
1886  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE {
1887    uint32_t ux = static_cast<uint32_t>(x);
1888    uint32_t uy = static_cast<uint32_t>(y) & kMaxIntShiftValue;
1889    return static_cast<int32_t>(ux >> uy);
1890  }
1891
1892  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE {
1893    uint64_t ux = static_cast<uint64_t>(x);
1894    uint64_t uy = static_cast<uint64_t>(y) & kMaxLongShiftValue;
1895    return static_cast<int64_t>(ux >> uy);
1896  }
1897
1898  DECLARE_INSTRUCTION(UShr);
1899
1900 private:
1901  DISALLOW_COPY_AND_ASSIGN(HUShr);
1902};
1903
1904class HAnd : public HBinaryOperation {
1905 public:
1906  HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1907      : HBinaryOperation(result_type, left, right) {}
1908
1909  bool IsCommutative() OVERRIDE { return true; }
1910
1911  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; }
1912  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; }
1913
1914  DECLARE_INSTRUCTION(And);
1915
1916 private:
1917  DISALLOW_COPY_AND_ASSIGN(HAnd);
1918};
1919
1920class HOr : public HBinaryOperation {
1921 public:
1922  HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1923      : HBinaryOperation(result_type, left, right) {}
1924
1925  bool IsCommutative() OVERRIDE { return true; }
1926
1927  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; }
1928  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; }
1929
1930  DECLARE_INSTRUCTION(Or);
1931
1932 private:
1933  DISALLOW_COPY_AND_ASSIGN(HOr);
1934};
1935
1936class HXor : public HBinaryOperation {
1937 public:
1938  HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
1939      : HBinaryOperation(result_type, left, right) {}
1940
1941  bool IsCommutative() OVERRIDE { return true; }
1942
1943  int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; }
1944  int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; }
1945
1946  DECLARE_INSTRUCTION(Xor);
1947
1948 private:
1949  DISALLOW_COPY_AND_ASSIGN(HXor);
1950};
1951
1952// The value of a parameter in this method. Its location depends on
1953// the calling convention.
1954class HParameterValue : public HExpression<0> {
1955 public:
1956  HParameterValue(uint8_t index, Primitive::Type parameter_type)
1957      : HExpression(parameter_type, SideEffects::None()), index_(index) {}
1958
1959  uint8_t GetIndex() const { return index_; }
1960
1961  DECLARE_INSTRUCTION(ParameterValue);
1962
1963 private:
1964  // The index of this parameter in the parameters list. Must be less
1965  // than HGraph::number_of_in_vregs_;
1966  const uint8_t index_;
1967
1968  DISALLOW_COPY_AND_ASSIGN(HParameterValue);
1969};
1970
1971class HNot : public HUnaryOperation {
1972 public:
1973  explicit HNot(Primitive::Type result_type, HInstruction* input)
1974      : HUnaryOperation(result_type, input) {}
1975
1976  virtual bool CanBeMoved() const { return true; }
1977  virtual bool InstructionDataEquals(HInstruction* other) const {
1978    UNUSED(other);
1979    return true;
1980  }
1981
1982  virtual int32_t Evaluate(int32_t x) const OVERRIDE { return ~x; }
1983  virtual int64_t Evaluate(int64_t x) const OVERRIDE { return ~x; }
1984
1985  DECLARE_INSTRUCTION(Not);
1986
1987 private:
1988  DISALLOW_COPY_AND_ASSIGN(HNot);
1989};
1990
1991class HTypeConversion : public HExpression<1> {
1992 public:
1993  // Instantiate a type conversion of `input` to `result_type`.
1994  HTypeConversion(Primitive::Type result_type, HInstruction* input)
1995      : HExpression(result_type, SideEffects::None()) {
1996    SetRawInputAt(0, input);
1997    DCHECK_NE(input->GetType(), result_type);
1998  }
1999
2000  HInstruction* GetInput() const { return InputAt(0); }
2001  Primitive::Type GetInputType() const { return GetInput()->GetType(); }
2002  Primitive::Type GetResultType() const { return GetType(); }
2003
2004  bool CanBeMoved() const OVERRIDE { return true; }
2005  bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
2006
2007  DECLARE_INSTRUCTION(TypeConversion);
2008
2009 private:
2010  DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
2011};
2012
2013class HPhi : public HInstruction {
2014 public:
2015  HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
2016      : HInstruction(SideEffects::None()),
2017        inputs_(arena, number_of_inputs),
2018        reg_number_(reg_number),
2019        type_(type),
2020        is_live_(false) {
2021    inputs_.SetSize(number_of_inputs);
2022  }
2023
2024  virtual size_t InputCount() const { return inputs_.Size(); }
2025  virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); }
2026
2027  virtual void SetRawInputAt(size_t index, HInstruction* input) {
2028    inputs_.Put(index, input);
2029  }
2030
2031  void AddInput(HInstruction* input);
2032
2033  virtual Primitive::Type GetType() const { return type_; }
2034  void SetType(Primitive::Type type) { type_ = type; }
2035
2036  uint32_t GetRegNumber() const { return reg_number_; }
2037
2038  void SetDead() { is_live_ = false; }
2039  void SetLive() { is_live_ = true; }
2040  bool IsDead() const { return !is_live_; }
2041  bool IsLive() const { return is_live_; }
2042
2043  DECLARE_INSTRUCTION(Phi);
2044
2045 private:
2046  GrowableArray<HInstruction*> inputs_;
2047  const uint32_t reg_number_;
2048  Primitive::Type type_;
2049  bool is_live_;
2050
2051  DISALLOW_COPY_AND_ASSIGN(HPhi);
2052};
2053
2054class HNullCheck : public HExpression<1> {
2055 public:
2056  HNullCheck(HInstruction* value, uint32_t dex_pc)
2057      : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2058    SetRawInputAt(0, value);
2059  }
2060
2061  virtual bool CanBeMoved() const { return true; }
2062  virtual bool InstructionDataEquals(HInstruction* other) const {
2063    UNUSED(other);
2064    return true;
2065  }
2066
2067  virtual bool NeedsEnvironment() const { return true; }
2068
2069  virtual bool CanThrow() const { return true; }
2070
2071  uint32_t GetDexPc() const { return dex_pc_; }
2072
2073  DECLARE_INSTRUCTION(NullCheck);
2074
2075 private:
2076  const uint32_t dex_pc_;
2077
2078  DISALLOW_COPY_AND_ASSIGN(HNullCheck);
2079};
2080
2081class FieldInfo : public ValueObject {
2082 public:
2083  FieldInfo(MemberOffset field_offset, Primitive::Type field_type)
2084      : field_offset_(field_offset), field_type_(field_type) {}
2085
2086  MemberOffset GetFieldOffset() const { return field_offset_; }
2087  Primitive::Type GetFieldType() const { return field_type_; }
2088
2089 private:
2090  const MemberOffset field_offset_;
2091  const Primitive::Type field_type_;
2092};
2093
2094class HInstanceFieldGet : public HExpression<1> {
2095 public:
2096  HInstanceFieldGet(HInstruction* value,
2097                    Primitive::Type field_type,
2098                    MemberOffset field_offset)
2099      : HExpression(field_type, SideEffects::DependsOnSomething()),
2100        field_info_(field_offset, field_type) {
2101    SetRawInputAt(0, value);
2102  }
2103
2104  virtual bool CanBeMoved() const { return true; }
2105  virtual bool InstructionDataEquals(HInstruction* other) const {
2106    size_t other_offset = other->AsInstanceFieldGet()->GetFieldOffset().SizeValue();
2107    return other_offset == GetFieldOffset().SizeValue();
2108  }
2109
2110  virtual size_t ComputeHashCode() const {
2111    return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
2112  }
2113
2114  MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2115  Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
2116
2117  DECLARE_INSTRUCTION(InstanceFieldGet);
2118
2119 private:
2120  const FieldInfo field_info_;
2121
2122  DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet);
2123};
2124
2125class HInstanceFieldSet : public HTemplateInstruction<2> {
2126 public:
2127  HInstanceFieldSet(HInstruction* object,
2128                    HInstruction* value,
2129                    Primitive::Type field_type,
2130                    MemberOffset field_offset)
2131      : HTemplateInstruction(SideEffects::ChangesSomething()),
2132        field_info_(field_offset, field_type) {
2133    SetRawInputAt(0, object);
2134    SetRawInputAt(1, value);
2135  }
2136
2137  MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2138  Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
2139
2140  HInstruction* GetValue() const { return InputAt(1); }
2141
2142  DECLARE_INSTRUCTION(InstanceFieldSet);
2143
2144 private:
2145  const FieldInfo field_info_;
2146
2147  DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet);
2148};
2149
2150class HArrayGet : public HExpression<2> {
2151 public:
2152  HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
2153      : HExpression(type, SideEffects::DependsOnSomething()) {
2154    SetRawInputAt(0, array);
2155    SetRawInputAt(1, index);
2156  }
2157
2158  bool CanBeMoved() const OVERRIDE { return true; }
2159  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2160    UNUSED(other);
2161    return true;
2162  }
2163  void SetType(Primitive::Type type) { type_ = type; }
2164
2165  HInstruction* GetArray() const { return InputAt(0); }
2166  HInstruction* GetIndex() const { return InputAt(1); }
2167
2168  DECLARE_INSTRUCTION(ArrayGet);
2169
2170 private:
2171  DISALLOW_COPY_AND_ASSIGN(HArrayGet);
2172};
2173
2174class HArraySet : public HTemplateInstruction<3> {
2175 public:
2176  HArraySet(HInstruction* array,
2177            HInstruction* index,
2178            HInstruction* value,
2179            Primitive::Type expected_component_type,
2180            uint32_t dex_pc)
2181      : HTemplateInstruction(SideEffects::ChangesSomething()),
2182        dex_pc_(dex_pc),
2183        expected_component_type_(expected_component_type),
2184        needs_type_check_(value->GetType() == Primitive::kPrimNot) {
2185    SetRawInputAt(0, array);
2186    SetRawInputAt(1, index);
2187    SetRawInputAt(2, value);
2188  }
2189
2190  bool NeedsEnvironment() const {
2191    // We currently always call a runtime method to catch array store
2192    // exceptions.
2193    return needs_type_check_;
2194  }
2195
2196  void ClearNeedsTypeCheck() {
2197    needs_type_check_ = false;
2198  }
2199
2200  bool NeedsTypeCheck() const { return needs_type_check_; }
2201
2202  uint32_t GetDexPc() const { return dex_pc_; }
2203
2204  HInstruction* GetArray() const { return InputAt(0); }
2205  HInstruction* GetIndex() const { return InputAt(1); }
2206  HInstruction* GetValue() const { return InputAt(2); }
2207
2208  Primitive::Type GetComponentType() const {
2209    // The Dex format does not type floating point index operations. Since the
2210    // `expected_component_type_` is set during building and can therefore not
2211    // be correct, we also check what is the value type. If it is a floating
2212    // point type, we must use that type.
2213    Primitive::Type value_type = GetValue()->GetType();
2214    return ((value_type == Primitive::kPrimFloat) || (value_type == Primitive::kPrimDouble))
2215        ? value_type
2216        : expected_component_type_;
2217  }
2218
2219  DECLARE_INSTRUCTION(ArraySet);
2220
2221 private:
2222  const uint32_t dex_pc_;
2223  const Primitive::Type expected_component_type_;
2224  bool needs_type_check_;
2225
2226  DISALLOW_COPY_AND_ASSIGN(HArraySet);
2227};
2228
2229class HArrayLength : public HExpression<1> {
2230 public:
2231  explicit HArrayLength(HInstruction* array)
2232      : HExpression(Primitive::kPrimInt, SideEffects::None()) {
2233    // Note that arrays do not change length, so the instruction does not
2234    // depend on any write.
2235    SetRawInputAt(0, array);
2236  }
2237
2238  virtual bool CanBeMoved() const { return true; }
2239  virtual bool InstructionDataEquals(HInstruction* other) const {
2240    UNUSED(other);
2241    return true;
2242  }
2243
2244  DECLARE_INSTRUCTION(ArrayLength);
2245
2246 private:
2247  DISALLOW_COPY_AND_ASSIGN(HArrayLength);
2248};
2249
2250class HBoundsCheck : public HExpression<2> {
2251 public:
2252  HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
2253      : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
2254    DCHECK(index->GetType() == Primitive::kPrimInt);
2255    SetRawInputAt(0, index);
2256    SetRawInputAt(1, length);
2257  }
2258
2259  virtual bool CanBeMoved() const { return true; }
2260  virtual bool InstructionDataEquals(HInstruction* other) const {
2261    UNUSED(other);
2262    return true;
2263  }
2264
2265  virtual bool NeedsEnvironment() const { return true; }
2266
2267  virtual bool CanThrow() const { return true; }
2268
2269  uint32_t GetDexPc() const { return dex_pc_; }
2270
2271  DECLARE_INSTRUCTION(BoundsCheck);
2272
2273 private:
2274  const uint32_t dex_pc_;
2275
2276  DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
2277};
2278
2279/**
2280 * Some DEX instructions are folded into multiple HInstructions that need
2281 * to stay live until the last HInstruction. This class
2282 * is used as a marker for the baseline compiler to ensure its preceding
2283 * HInstruction stays live. `index` represents the stack location index of the
2284 * instruction (the actual offset is computed as index * vreg_size).
2285 */
2286class HTemporary : public HTemplateInstruction<0> {
2287 public:
2288  explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
2289
2290  size_t GetIndex() const { return index_; }
2291
2292  Primitive::Type GetType() const OVERRIDE {
2293    // The previous instruction is the one that will be stored in the temporary location.
2294    DCHECK(GetPrevious() != nullptr);
2295    return GetPrevious()->GetType();
2296  }
2297
2298  DECLARE_INSTRUCTION(Temporary);
2299
2300 private:
2301  const size_t index_;
2302
2303  DISALLOW_COPY_AND_ASSIGN(HTemporary);
2304};
2305
2306class HSuspendCheck : public HTemplateInstruction<0> {
2307 public:
2308  explicit HSuspendCheck(uint32_t dex_pc)
2309      : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {}
2310
2311  virtual bool NeedsEnvironment() const {
2312    return true;
2313  }
2314
2315  uint32_t GetDexPc() const { return dex_pc_; }
2316
2317  DECLARE_INSTRUCTION(SuspendCheck);
2318
2319 private:
2320  const uint32_t dex_pc_;
2321
2322  DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
2323};
2324
2325/**
2326 * Instruction to load a Class object.
2327 */
2328class HLoadClass : public HExpression<0> {
2329 public:
2330  HLoadClass(uint16_t type_index,
2331             bool is_referrers_class,
2332             uint32_t dex_pc)
2333      : HExpression(Primitive::kPrimNot, SideEffects::None()),
2334        type_index_(type_index),
2335        is_referrers_class_(is_referrers_class),
2336        dex_pc_(dex_pc),
2337        generate_clinit_check_(false) {}
2338
2339  bool CanBeMoved() const OVERRIDE { return true; }
2340
2341  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2342    return other->AsLoadClass()->type_index_ == type_index_;
2343  }
2344
2345  size_t ComputeHashCode() const OVERRIDE { return type_index_; }
2346
2347  uint32_t GetDexPc() const { return dex_pc_; }
2348  uint16_t GetTypeIndex() const { return type_index_; }
2349  bool IsReferrersClass() const { return is_referrers_class_; }
2350
2351  bool NeedsEnvironment() const OVERRIDE {
2352    // Will call runtime and load the class if the class is not loaded yet.
2353    // TODO: finer grain decision.
2354    return !is_referrers_class_;
2355  }
2356
2357  bool MustGenerateClinitCheck() const {
2358    return generate_clinit_check_;
2359  }
2360
2361  void SetMustGenerateClinitCheck() {
2362    generate_clinit_check_ = true;
2363  }
2364
2365  bool CanCallRuntime() const {
2366    return MustGenerateClinitCheck() || !is_referrers_class_;
2367  }
2368
2369  DECLARE_INSTRUCTION(LoadClass);
2370
2371 private:
2372  const uint16_t type_index_;
2373  const bool is_referrers_class_;
2374  const uint32_t dex_pc_;
2375  // Whether this instruction must generate the initialization check.
2376  // Used for code generation.
2377  bool generate_clinit_check_;
2378
2379  DISALLOW_COPY_AND_ASSIGN(HLoadClass);
2380};
2381
2382class HLoadString : public HExpression<0> {
2383 public:
2384  HLoadString(uint32_t string_index, uint32_t dex_pc)
2385      : HExpression(Primitive::kPrimNot, SideEffects::None()),
2386        string_index_(string_index),
2387        dex_pc_(dex_pc) {}
2388
2389  bool CanBeMoved() const OVERRIDE { return true; }
2390
2391  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2392    return other->AsLoadString()->string_index_ == string_index_;
2393  }
2394
2395  size_t ComputeHashCode() const OVERRIDE { return string_index_; }
2396
2397  uint32_t GetDexPc() const { return dex_pc_; }
2398  uint32_t GetStringIndex() const { return string_index_; }
2399
2400  // TODO: Can we deopt or debug when we resolve a string?
2401  bool NeedsEnvironment() const OVERRIDE { return false; }
2402
2403  DECLARE_INSTRUCTION(LoadString);
2404
2405 private:
2406  const uint32_t string_index_;
2407  const uint32_t dex_pc_;
2408
2409  DISALLOW_COPY_AND_ASSIGN(HLoadString);
2410};
2411
2412// TODO: Pass this check to HInvokeStatic nodes.
2413/**
2414 * Performs an initialization check on its Class object input.
2415 */
2416class HClinitCheck : public HExpression<1> {
2417 public:
2418  explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
2419      : HExpression(Primitive::kPrimNot, SideEffects::All()),
2420        dex_pc_(dex_pc) {
2421    SetRawInputAt(0, constant);
2422  }
2423
2424  bool CanBeMoved() const OVERRIDE { return true; }
2425  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2426    UNUSED(other);
2427    return true;
2428  }
2429
2430  bool NeedsEnvironment() const OVERRIDE {
2431    // May call runtime to initialize the class.
2432    return true;
2433  }
2434
2435  uint32_t GetDexPc() const { return dex_pc_; }
2436
2437  HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
2438
2439  DECLARE_INSTRUCTION(ClinitCheck);
2440
2441 private:
2442  const uint32_t dex_pc_;
2443
2444  DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
2445};
2446
2447class HStaticFieldGet : public HExpression<1> {
2448 public:
2449  HStaticFieldGet(HInstruction* cls,
2450                  Primitive::Type field_type,
2451                  MemberOffset field_offset)
2452      : HExpression(field_type, SideEffects::DependsOnSomething()),
2453        field_info_(field_offset, field_type) {
2454    SetRawInputAt(0, cls);
2455  }
2456
2457  bool CanBeMoved() const OVERRIDE { return true; }
2458  bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
2459    size_t other_offset = other->AsStaticFieldGet()->GetFieldOffset().SizeValue();
2460    return other_offset == GetFieldOffset().SizeValue();
2461  }
2462
2463  size_t ComputeHashCode() const OVERRIDE {
2464    return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
2465  }
2466
2467  MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2468  Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
2469
2470  DECLARE_INSTRUCTION(StaticFieldGet);
2471
2472 private:
2473  const FieldInfo field_info_;
2474
2475  DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
2476};
2477
2478class HStaticFieldSet : public HTemplateInstruction<2> {
2479 public:
2480  HStaticFieldSet(HInstruction* cls,
2481                  HInstruction* value,
2482                  Primitive::Type field_type,
2483                  MemberOffset field_offset)
2484      : HTemplateInstruction(SideEffects::ChangesSomething()),
2485        field_info_(field_offset, field_type) {
2486    SetRawInputAt(0, cls);
2487    SetRawInputAt(1, value);
2488  }
2489
2490  MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
2491  Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
2492
2493  HInstruction* GetValue() const { return InputAt(1); }
2494
2495  DECLARE_INSTRUCTION(StaticFieldSet);
2496
2497 private:
2498  const FieldInfo field_info_;
2499
2500  DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
2501};
2502
2503// Implement the move-exception DEX instruction.
2504class HLoadException : public HExpression<0> {
2505 public:
2506  HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
2507
2508  DECLARE_INSTRUCTION(LoadException);
2509
2510 private:
2511  DISALLOW_COPY_AND_ASSIGN(HLoadException);
2512};
2513
2514class HThrow : public HTemplateInstruction<1> {
2515 public:
2516  HThrow(HInstruction* exception, uint32_t dex_pc)
2517      : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {
2518    SetRawInputAt(0, exception);
2519  }
2520
2521  bool IsControlFlow() const OVERRIDE { return true; }
2522
2523  bool NeedsEnvironment() const OVERRIDE { return true; }
2524
2525  uint32_t GetDexPc() const { return dex_pc_; }
2526
2527  DECLARE_INSTRUCTION(Throw);
2528
2529 private:
2530  uint32_t dex_pc_;
2531
2532  DISALLOW_COPY_AND_ASSIGN(HThrow);
2533};
2534
2535class HInstanceOf : public HExpression<2> {
2536 public:
2537  HInstanceOf(HInstruction* object,
2538              HLoadClass* constant,
2539              bool class_is_final,
2540              uint32_t dex_pc)
2541      : HExpression(Primitive::kPrimBoolean, SideEffects::None()),
2542        class_is_final_(class_is_final),
2543        dex_pc_(dex_pc) {
2544    SetRawInputAt(0, object);
2545    SetRawInputAt(1, constant);
2546  }
2547
2548  bool CanBeMoved() const OVERRIDE { return true; }
2549
2550  bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2551    return true;
2552  }
2553
2554  bool NeedsEnvironment() const OVERRIDE {
2555    return false;
2556  }
2557
2558  uint32_t GetDexPc() const { return dex_pc_; }
2559
2560  bool IsClassFinal() const { return class_is_final_; }
2561
2562  DECLARE_INSTRUCTION(InstanceOf);
2563
2564 private:
2565  const bool class_is_final_;
2566  const uint32_t dex_pc_;
2567
2568  DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
2569};
2570
2571class HCheckCast : public HTemplateInstruction<2> {
2572 public:
2573  HCheckCast(HInstruction* object,
2574             HLoadClass* constant,
2575             bool class_is_final,
2576             uint32_t dex_pc)
2577      : HTemplateInstruction(SideEffects::None()),
2578        class_is_final_(class_is_final),
2579        dex_pc_(dex_pc) {
2580    SetRawInputAt(0, object);
2581    SetRawInputAt(1, constant);
2582  }
2583
2584  bool CanBeMoved() const OVERRIDE { return true; }
2585
2586  bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE {
2587    return true;
2588  }
2589
2590  bool NeedsEnvironment() const OVERRIDE {
2591    // Instruction may throw a CheckCastError.
2592    return true;
2593  }
2594
2595  bool CanThrow() const OVERRIDE { return true; }
2596
2597  uint32_t GetDexPc() const { return dex_pc_; }
2598
2599  bool IsClassFinal() const { return class_is_final_; }
2600
2601  DECLARE_INSTRUCTION(CheckCast);
2602
2603 private:
2604  const bool class_is_final_;
2605  const uint32_t dex_pc_;
2606
2607  DISALLOW_COPY_AND_ASSIGN(HCheckCast);
2608};
2609
2610class HMonitorOperation : public HTemplateInstruction<1> {
2611 public:
2612  enum OperationKind {
2613    kEnter,
2614    kExit,
2615  };
2616
2617  HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
2618    : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) {
2619    SetRawInputAt(0, object);
2620  }
2621
2622  // Instruction may throw a Java exception, so we need an environment.
2623  bool NeedsEnvironment() const OVERRIDE { return true; }
2624  bool CanThrow() const OVERRIDE { return true; }
2625
2626  uint32_t GetDexPc() const { return dex_pc_; }
2627
2628  bool IsEnter() const { return kind_ == kEnter; }
2629
2630  DECLARE_INSTRUCTION(MonitorOperation);
2631
2632 protected:
2633  const OperationKind kind_;
2634  const uint32_t dex_pc_;
2635
2636 private:
2637  DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
2638};
2639
2640
2641class MoveOperands : public ArenaObject<kArenaAllocMisc> {
2642 public:
2643  MoveOperands(Location source, Location destination, HInstruction* instruction)
2644      : source_(source), destination_(destination), instruction_(instruction) {}
2645
2646  Location GetSource() const { return source_; }
2647  Location GetDestination() const { return destination_; }
2648
2649  void SetSource(Location value) { source_ = value; }
2650  void SetDestination(Location value) { destination_ = value; }
2651
2652  // The parallel move resolver marks moves as "in-progress" by clearing the
2653  // destination (but not the source).
2654  Location MarkPending() {
2655    DCHECK(!IsPending());
2656    Location dest = destination_;
2657    destination_ = Location::NoLocation();
2658    return dest;
2659  }
2660
2661  void ClearPending(Location dest) {
2662    DCHECK(IsPending());
2663    destination_ = dest;
2664  }
2665
2666  bool IsPending() const {
2667    DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
2668    return destination_.IsInvalid() && !source_.IsInvalid();
2669  }
2670
2671  // True if this blocks a move from the given location.
2672  bool Blocks(Location loc) const {
2673    return !IsEliminated() && source_.Equals(loc);
2674  }
2675
2676  // A move is redundant if it's been eliminated, if its source and
2677  // destination are the same, or if its destination is unneeded.
2678  bool IsRedundant() const {
2679    return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_);
2680  }
2681
2682  // We clear both operands to indicate move that's been eliminated.
2683  void Eliminate() {
2684    source_ = destination_ = Location::NoLocation();
2685  }
2686
2687  bool IsEliminated() const {
2688    DCHECK(!source_.IsInvalid() || destination_.IsInvalid());
2689    return source_.IsInvalid();
2690  }
2691
2692  HInstruction* GetInstruction() const { return instruction_; }
2693
2694 private:
2695  Location source_;
2696  Location destination_;
2697  // The instruction this move is assocatied with. Null when this move is
2698  // for moving an input in the expected locations of user (including a phi user).
2699  // This is only used in debug mode, to ensure we do not connect interval siblings
2700  // in the same parallel move.
2701  HInstruction* instruction_;
2702
2703  DISALLOW_COPY_AND_ASSIGN(MoveOperands);
2704};
2705
2706static constexpr size_t kDefaultNumberOfMoves = 4;
2707
2708class HParallelMove : public HTemplateInstruction<0> {
2709 public:
2710  explicit HParallelMove(ArenaAllocator* arena)
2711      : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
2712
2713  void AddMove(MoveOperands* move) {
2714    if (kIsDebugBuild && move->GetInstruction() != nullptr) {
2715      for (size_t i = 0, e = moves_.Size(); i < e; ++i) {
2716        DCHECK_NE(moves_.Get(i)->GetInstruction(), move->GetInstruction())
2717          << "Doing parallel moves for the same instruction.";
2718      }
2719    }
2720    moves_.Add(move);
2721  }
2722
2723  MoveOperands* MoveOperandsAt(size_t index) const {
2724    return moves_.Get(index);
2725  }
2726
2727  size_t NumMoves() const { return moves_.Size(); }
2728
2729  DECLARE_INSTRUCTION(ParallelMove);
2730
2731 private:
2732  GrowableArray<MoveOperands*> moves_;
2733
2734  DISALLOW_COPY_AND_ASSIGN(HParallelMove);
2735};
2736
2737class HGraphVisitor : public ValueObject {
2738 public:
2739  explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
2740  virtual ~HGraphVisitor() {}
2741
2742  virtual void VisitInstruction(HInstruction* instruction) { UNUSED(instruction); }
2743  virtual void VisitBasicBlock(HBasicBlock* block);
2744
2745  // Visit the graph following basic block insertion order.
2746  void VisitInsertionOrder();
2747
2748  // Visit the graph following dominator tree reverse post-order.
2749  void VisitReversePostOrder();
2750
2751  HGraph* GetGraph() const { return graph_; }
2752
2753  // Visit functions for instruction classes.
2754#define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
2755  virtual void Visit##name(H##name* instr) { VisitInstruction(instr); }
2756
2757  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
2758
2759#undef DECLARE_VISIT_INSTRUCTION
2760
2761 private:
2762  HGraph* const graph_;
2763
2764  DISALLOW_COPY_AND_ASSIGN(HGraphVisitor);
2765};
2766
2767class HGraphDelegateVisitor : public HGraphVisitor {
2768 public:
2769  explicit HGraphDelegateVisitor(HGraph* graph) : HGraphVisitor(graph) {}
2770  virtual ~HGraphDelegateVisitor() {}
2771
2772  // Visit functions that delegate to to super class.
2773#define DECLARE_VISIT_INSTRUCTION(name, super)                                        \
2774  virtual void Visit##name(H##name* instr) OVERRIDE { Visit##super(instr); }
2775
2776  FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION)
2777
2778#undef DECLARE_VISIT_INSTRUCTION
2779
2780 private:
2781  DISALLOW_COPY_AND_ASSIGN(HGraphDelegateVisitor);
2782};
2783
2784class HInsertionOrderIterator : public ValueObject {
2785 public:
2786  explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
2787
2788  bool Done() const { return index_ == graph_.GetBlocks().Size(); }
2789  HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); }
2790  void Advance() { ++index_; }
2791
2792 private:
2793  const HGraph& graph_;
2794  size_t index_;
2795
2796  DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator);
2797};
2798
2799class HReversePostOrderIterator : public ValueObject {
2800 public:
2801  explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {}
2802
2803  bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); }
2804  HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); }
2805  void Advance() { ++index_; }
2806
2807 private:
2808  const HGraph& graph_;
2809  size_t index_;
2810
2811  DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator);
2812};
2813
2814class HPostOrderIterator : public ValueObject {
2815 public:
2816  explicit HPostOrderIterator(const HGraph& graph)
2817      : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {}
2818
2819  bool Done() const { return index_ == 0; }
2820  HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); }
2821  void Advance() { --index_; }
2822
2823 private:
2824  const HGraph& graph_;
2825  size_t index_;
2826
2827  DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator);
2828};
2829
2830}  // namespace art
2831
2832#endif  // ART_COMPILER_OPTIMIZING_NODES_H_
2833