| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 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 |  | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 20 | #include "locations.h" | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 21 | #include "offsets.h" | 
| Ian Rogers | e63db27 | 2014-07-15 15:36:11 -0700 | [diff] [blame] | 22 | #include "primitive.h" | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 23 | #include "utils/allocation.h" | 
| Nicolas Geoffray | 0e33643 | 2014-02-26 18:24:38 +0000 | [diff] [blame] | 24 | #include "utils/arena_bit_vector.h" | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 25 | #include "utils/growable_array.h" | 
 | 26 |  | 
 | 27 | namespace art { | 
 | 28 |  | 
 | 29 | class HBasicBlock; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 30 | class HEnvironment; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 31 | class HInstruction; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 32 | class HIntConstant; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 33 | class HGraphVisitor; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 34 | class HPhi; | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 35 | class HSuspendCheck; | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 36 | class LiveInterval; | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 37 | class LocationSummary; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 38 |  | 
 | 39 | static const int kDefaultNumberOfBlocks = 8; | 
 | 40 | static const int kDefaultNumberOfSuccessors = 2; | 
 | 41 | static const int kDefaultNumberOfPredecessors = 2; | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 42 | static const int kDefaultNumberOfDominatedBlocks = 1; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 43 | static const int kDefaultNumberOfBackEdges = 1; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 44 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 45 | enum IfCondition { | 
 | 46 |   kCondEQ, | 
 | 47 |   kCondNE, | 
 | 48 |   kCondLT, | 
 | 49 |   kCondLE, | 
 | 50 |   kCondGT, | 
 | 51 |   kCondGE, | 
 | 52 | }; | 
 | 53 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 54 | class HInstructionList { | 
 | 55 |  public: | 
 | 56 |   HInstructionList() : first_instruction_(nullptr), last_instruction_(nullptr) {} | 
 | 57 |  | 
 | 58 |   void AddInstruction(HInstruction* instruction); | 
 | 59 |   void RemoveInstruction(HInstruction* instruction); | 
 | 60 |  | 
| Roland Levillain | 6b46923 | 2014-09-25 10:10:38 +0100 | [diff] [blame] | 61 |   // Return true if this list contains `instruction`. | 
 | 62 |   bool Contains(HInstruction* instruction) const; | 
 | 63 |  | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 64 |   // Return true if `instruction1` is found before `instruction2` in | 
 | 65 |   // this instruction list and false otherwise.  Abort if none | 
 | 66 |   // of these instructions is found. | 
 | 67 |   bool FoundBefore(const HInstruction* instruction1, | 
 | 68 |                    const HInstruction* instruction2) const; | 
 | 69 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 70 |  private: | 
 | 71 |   HInstruction* first_instruction_; | 
 | 72 |   HInstruction* last_instruction_; | 
 | 73 |  | 
 | 74 |   friend class HBasicBlock; | 
 | 75 |   friend class HInstructionIterator; | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 76 |   friend class HBackwardInstructionIterator; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 77 |  | 
 | 78 |   DISALLOW_COPY_AND_ASSIGN(HInstructionList); | 
 | 79 | }; | 
 | 80 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 81 | // Control-flow graph of a method. Contains a list of basic blocks. | 
 | 82 | class HGraph : public ArenaObject { | 
 | 83 |  public: | 
 | 84 |   explicit HGraph(ArenaAllocator* arena) | 
 | 85 |       : arena_(arena), | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 86 |         blocks_(arena, kDefaultNumberOfBlocks), | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 87 |         reverse_post_order_(arena, kDefaultNumberOfBlocks), | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 88 |         maximum_number_of_out_vregs_(0), | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 89 |         number_of_vregs_(0), | 
 | 90 |         number_of_in_vregs_(0), | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 91 |         number_of_temporaries_(0), | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 92 |         current_instruction_id_(0) {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 93 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 94 |   ArenaAllocator* GetArena() const { return arena_; } | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 95 |   const GrowableArray<HBasicBlock*>& GetBlocks() const { return blocks_; } | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 96 |   HBasicBlock* GetBlock(size_t id) const { return blocks_.Get(id); } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 97 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 98 |   HBasicBlock* GetEntryBlock() const { return entry_block_; } | 
 | 99 |   HBasicBlock* GetExitBlock() const { return exit_block_; } | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 100 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 101 |   void SetEntryBlock(HBasicBlock* block) { entry_block_ = block; } | 
 | 102 |   void SetExitBlock(HBasicBlock* block) { exit_block_ = block; } | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 103 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 104 |   void AddBlock(HBasicBlock* block); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 105 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 106 |   void BuildDominatorTree(); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 107 |   void TransformToSSA(); | 
 | 108 |   void SimplifyCFG(); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 109 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 110 |   // Find all natural loops in this graph. Aborts computation and returns false | 
| Nicolas Geoffray | f635e63 | 2014-05-14 09:43:38 +0100 | [diff] [blame] | 111 |   // if one loop is not natural, that is the header does not dominate the back | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 112 |   // edge. | 
 | 113 |   bool FindNaturalLoops() const; | 
 | 114 |  | 
 | 115 |   void SplitCriticalEdge(HBasicBlock* block, HBasicBlock* successor); | 
 | 116 |   void SimplifyLoop(HBasicBlock* header); | 
 | 117 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 118 |   int GetNextInstructionId() { | 
 | 119 |     return current_instruction_id_++; | 
 | 120 |   } | 
 | 121 |  | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 122 |   uint16_t GetMaximumNumberOfOutVRegs() const { | 
 | 123 |     return maximum_number_of_out_vregs_; | 
 | 124 |   } | 
 | 125 |  | 
 | 126 |   void UpdateMaximumNumberOfOutVRegs(uint16_t new_value) { | 
 | 127 |     maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_); | 
 | 128 |   } | 
 | 129 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 130 |   void UpdateNumberOfTemporaries(size_t count) { | 
 | 131 |     number_of_temporaries_ = std::max(count, number_of_temporaries_); | 
 | 132 |   } | 
 | 133 |  | 
 | 134 |   size_t GetNumberOfTemporaries() const { | 
 | 135 |     return number_of_temporaries_; | 
 | 136 |   } | 
 | 137 |  | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 138 |   void SetNumberOfVRegs(uint16_t number_of_vregs) { | 
 | 139 |     number_of_vregs_ = number_of_vregs; | 
 | 140 |   } | 
 | 141 |  | 
 | 142 |   uint16_t GetNumberOfVRegs() const { | 
 | 143 |     return number_of_vregs_; | 
 | 144 |   } | 
 | 145 |  | 
 | 146 |   void SetNumberOfInVRegs(uint16_t value) { | 
 | 147 |     number_of_in_vregs_ = value; | 
 | 148 |   } | 
 | 149 |  | 
 | 150 |   uint16_t GetNumberOfInVRegs() const { | 
 | 151 |     return number_of_in_vregs_; | 
 | 152 |   } | 
 | 153 |  | 
| Nicolas Geoffray | ab032bc | 2014-07-15 12:55:21 +0100 | [diff] [blame] | 154 |   uint16_t GetNumberOfLocalVRegs() const { | 
 | 155 |     return number_of_vregs_ - number_of_in_vregs_; | 
 | 156 |   } | 
 | 157 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 158 |   const GrowableArray<HBasicBlock*>& GetReversePostOrder() const { | 
 | 159 |     return reverse_post_order_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 160 |   } | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 161 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 162 |  private: | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 163 |   HBasicBlock* FindCommonDominator(HBasicBlock* first, HBasicBlock* second) const; | 
 | 164 |   void VisitBlockForDominatorTree(HBasicBlock* block, | 
 | 165 |                                   HBasicBlock* predecessor, | 
 | 166 |                                   GrowableArray<size_t>* visits); | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 167 |   void FindBackEdges(ArenaBitVector* visited); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 168 |   void VisitBlockForBackEdges(HBasicBlock* block, | 
 | 169 |                               ArenaBitVector* visited, | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 170 |                               ArenaBitVector* visiting); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 171 |   void RemoveDeadBlocks(const ArenaBitVector& visited) const; | 
 | 172 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 173 |   ArenaAllocator* const arena_; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 174 |  | 
 | 175 |   // List of blocks in insertion order. | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 176 |   GrowableArray<HBasicBlock*> blocks_; | 
 | 177 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 178 |   // List of blocks to perform a reverse post order tree traversal. | 
 | 179 |   GrowableArray<HBasicBlock*> reverse_post_order_; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 180 |  | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 181 |   HBasicBlock* entry_block_; | 
 | 182 |   HBasicBlock* exit_block_; | 
 | 183 |  | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 184 |   // The maximum number of virtual registers arguments passed to a HInvoke in this graph. | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 185 |   uint16_t maximum_number_of_out_vregs_; | 
 | 186 |  | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 187 |   // The number of virtual registers in this method. Contains the parameters. | 
 | 188 |   uint16_t number_of_vregs_; | 
 | 189 |  | 
 | 190 |   // The number of virtual registers used by parameters of this method. | 
 | 191 |   uint16_t number_of_in_vregs_; | 
 | 192 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 193 |   // The number of temporaries that will be needed for the baseline compiler. | 
 | 194 |   size_t number_of_temporaries_; | 
 | 195 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 196 |   // The current id to assign to a newly added instruction. See HInstruction.id_. | 
 | 197 |   int current_instruction_id_; | 
 | 198 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 199 |   DISALLOW_COPY_AND_ASSIGN(HGraph); | 
 | 200 | }; | 
 | 201 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 202 | class HLoopInformation : public ArenaObject { | 
 | 203 |  public: | 
 | 204 |   HLoopInformation(HBasicBlock* header, HGraph* graph) | 
 | 205 |       : header_(header), | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 206 |         suspend_check_(nullptr), | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 207 |         back_edges_(graph->GetArena(), kDefaultNumberOfBackEdges), | 
| Nicolas Geoffray | b09aacb | 2014-09-17 18:21:53 +0100 | [diff] [blame] | 208 |         // Make bit vector growable, as the number of blocks may change. | 
 | 209 |         blocks_(graph->GetArena(), graph->GetBlocks().Size(), true) {} | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 210 |  | 
 | 211 |   HBasicBlock* GetHeader() const { | 
 | 212 |     return header_; | 
 | 213 |   } | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 214 |  | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 215 |   HSuspendCheck* GetSuspendCheck() const { return suspend_check_; } | 
 | 216 |   void SetSuspendCheck(HSuspendCheck* check) { suspend_check_ = check; } | 
 | 217 |   bool HasSuspendCheck() const { return suspend_check_ != nullptr; } | 
 | 218 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 219 |   void AddBackEdge(HBasicBlock* back_edge) { | 
 | 220 |     back_edges_.Add(back_edge); | 
 | 221 |   } | 
 | 222 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 223 |   void RemoveBackEdge(HBasicBlock* back_edge) { | 
 | 224 |     back_edges_.Delete(back_edge); | 
 | 225 |   } | 
 | 226 |  | 
 | 227 |   bool IsBackEdge(HBasicBlock* block) { | 
 | 228 |     for (size_t i = 0, e = back_edges_.Size(); i < e; ++i) { | 
 | 229 |       if (back_edges_.Get(i) == block) return true; | 
 | 230 |     } | 
 | 231 |     return false; | 
 | 232 |   } | 
 | 233 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 234 |   int NumberOfBackEdges() const { | 
 | 235 |     return back_edges_.Size(); | 
 | 236 |   } | 
 | 237 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 238 |   HBasicBlock* GetPreHeader() const; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 239 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 240 |   const GrowableArray<HBasicBlock*>& GetBackEdges() const { | 
 | 241 |     return back_edges_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 242 |   } | 
 | 243 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 244 |   void ClearBackEdges() { | 
 | 245 |     back_edges_.Reset(); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 246 |   } | 
 | 247 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 248 |   // Find blocks that are part of this loop. Returns whether the loop is a natural loop, | 
 | 249 |   // that is the header dominates the back edge. | 
 | 250 |   bool Populate(); | 
 | 251 |  | 
 | 252 |   // Returns whether this loop information contains `block`. | 
 | 253 |   // Note that this loop information *must* be populated before entering this function. | 
 | 254 |   bool Contains(const HBasicBlock& block) const; | 
 | 255 |  | 
 | 256 |   // Returns whether this loop information is an inner loop of `other`. | 
 | 257 |   // Note that `other` *must* be populated before entering this function. | 
 | 258 |   bool IsIn(const HLoopInformation& other) const; | 
 | 259 |  | 
 | 260 |   const ArenaBitVector& GetBlocks() const { return blocks_; } | 
 | 261 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 262 |  private: | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 263 |   // Internal recursive implementation of `Populate`. | 
 | 264 |   void PopulateRecursive(HBasicBlock* block); | 
 | 265 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 266 |   HBasicBlock* header_; | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 267 |   HSuspendCheck* suspend_check_; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 268 |   GrowableArray<HBasicBlock*> back_edges_; | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 269 |   ArenaBitVector blocks_; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 270 |  | 
 | 271 |   DISALLOW_COPY_AND_ASSIGN(HLoopInformation); | 
 | 272 | }; | 
 | 273 |  | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 274 | static constexpr size_t kNoLifetime = -1; | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 275 | static constexpr uint32_t kNoDexPc = -1; | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 276 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 277 | // A block in a method. Contains the list of instructions represented | 
 | 278 | // as a double linked list. Each block knows its predecessors and | 
 | 279 | // successors. | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 280 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 281 | class HBasicBlock : public ArenaObject { | 
 | 282 |  public: | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 283 |   explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc) | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 284 |       : graph_(graph), | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 285 |         predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors), | 
 | 286 |         successors_(graph->GetArena(), kDefaultNumberOfSuccessors), | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 287 |         loop_information_(nullptr), | 
 | 288 |         dominator_(nullptr), | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 289 |         dominated_blocks_(graph->GetArena(), kDefaultNumberOfDominatedBlocks), | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 290 |         block_id_(-1), | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 291 |         dex_pc_(dex_pc), | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 292 |         lifetime_start_(kNoLifetime), | 
 | 293 |         lifetime_end_(kNoLifetime) {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 294 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 295 |   const GrowableArray<HBasicBlock*>& GetPredecessors() const { | 
 | 296 |     return predecessors_; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 297 |   } | 
 | 298 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 299 |   const GrowableArray<HBasicBlock*>& GetSuccessors() const { | 
 | 300 |     return successors_; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 301 |   } | 
 | 302 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 303 |   const GrowableArray<HBasicBlock*>& GetDominatedBlocks() const { | 
 | 304 |     return dominated_blocks_; | 
 | 305 |   } | 
 | 306 |  | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 307 |   bool IsEntryBlock() const { | 
 | 308 |     return graph_->GetEntryBlock() == this; | 
 | 309 |   } | 
 | 310 |  | 
 | 311 |   bool IsExitBlock() const { | 
 | 312 |     return graph_->GetExitBlock() == this; | 
 | 313 |   } | 
 | 314 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 315 |   void AddBackEdge(HBasicBlock* back_edge) { | 
 | 316 |     if (loop_information_ == nullptr) { | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 317 |       loop_information_ = new (graph_->GetArena()) HLoopInformation(this, graph_); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 318 |     } | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 319 |     DCHECK_EQ(loop_information_->GetHeader(), this); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 320 |     loop_information_->AddBackEdge(back_edge); | 
 | 321 |   } | 
 | 322 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 323 |   HGraph* GetGraph() const { return graph_; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 324 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 325 |   int GetBlockId() const { return block_id_; } | 
 | 326 |   void SetBlockId(int id) { block_id_ = id; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 327 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 328 |   HBasicBlock* GetDominator() const { return dominator_; } | 
 | 329 |   void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; } | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 330 |   void AddDominatedBlock(HBasicBlock* block) { dominated_blocks_.Add(block); } | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 331 |  | 
 | 332 |   int NumberOfBackEdges() const { | 
 | 333 |     return loop_information_ == nullptr | 
 | 334 |         ? 0 | 
 | 335 |         : loop_information_->NumberOfBackEdges(); | 
 | 336 |   } | 
 | 337 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 338 |   HInstruction* GetFirstInstruction() const { return instructions_.first_instruction_; } | 
 | 339 |   HInstruction* GetLastInstruction() const { return instructions_.last_instruction_; } | 
| Nicolas Geoffray | f635e63 | 2014-05-14 09:43:38 +0100 | [diff] [blame] | 340 |   const HInstructionList& GetInstructions() const { return instructions_; } | 
 | 341 |   const HInstructionList& GetPhis() const { return phis_; } | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 342 |   HInstruction* GetFirstPhi() const { return phis_.first_instruction_; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 343 |  | 
 | 344 |   void AddSuccessor(HBasicBlock* block) { | 
 | 345 |     successors_.Add(block); | 
 | 346 |     block->predecessors_.Add(this); | 
 | 347 |   } | 
 | 348 |  | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 349 |   void ReplaceSuccessor(HBasicBlock* existing, HBasicBlock* new_block) { | 
 | 350 |     size_t successor_index = GetSuccessorIndexOf(existing); | 
 | 351 |     DCHECK_NE(successor_index, static_cast<size_t>(-1)); | 
 | 352 |     existing->RemovePredecessor(this); | 
 | 353 |     new_block->predecessors_.Add(this); | 
 | 354 |     successors_.Put(successor_index, new_block); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 355 |   } | 
 | 356 |  | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 357 |   void RemovePredecessor(HBasicBlock* block) { | 
 | 358 |     predecessors_.Delete(block); | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 359 |   } | 
 | 360 |  | 
 | 361 |   void ClearAllPredecessors() { | 
 | 362 |     predecessors_.Reset(); | 
 | 363 |   } | 
 | 364 |  | 
 | 365 |   void AddPredecessor(HBasicBlock* block) { | 
 | 366 |     predecessors_.Add(block); | 
 | 367 |     block->successors_.Add(this); | 
 | 368 |   } | 
 | 369 |  | 
| Nicolas Geoffray | 604c6e4 | 2014-09-17 12:08:44 +0100 | [diff] [blame] | 370 |   void SwapPredecessors() { | 
| Nicolas Geoffray | c83d441 | 2014-09-18 16:46:20 +0100 | [diff] [blame] | 371 |     DCHECK_EQ(predecessors_.Size(), 2u); | 
| Nicolas Geoffray | 604c6e4 | 2014-09-17 12:08:44 +0100 | [diff] [blame] | 372 |     HBasicBlock* temp = predecessors_.Get(0); | 
 | 373 |     predecessors_.Put(0, predecessors_.Get(1)); | 
 | 374 |     predecessors_.Put(1, temp); | 
 | 375 |   } | 
 | 376 |  | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 377 |   size_t GetPredecessorIndexOf(HBasicBlock* predecessor) { | 
 | 378 |     for (size_t i = 0, e = predecessors_.Size(); i < e; ++i) { | 
 | 379 |       if (predecessors_.Get(i) == predecessor) { | 
 | 380 |         return i; | 
 | 381 |       } | 
 | 382 |     } | 
 | 383 |     return -1; | 
 | 384 |   } | 
 | 385 |  | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 386 |   size_t GetSuccessorIndexOf(HBasicBlock* successor) { | 
 | 387 |     for (size_t i = 0, e = successors_.Size(); i < e; ++i) { | 
 | 388 |       if (successors_.Get(i) == successor) { | 
 | 389 |         return i; | 
 | 390 |       } | 
 | 391 |     } | 
 | 392 |     return -1; | 
 | 393 |   } | 
 | 394 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 395 |   void AddInstruction(HInstruction* instruction); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 396 |   void RemoveInstruction(HInstruction* instruction); | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 397 |   void InsertInstructionBefore(HInstruction* instruction, HInstruction* cursor); | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 398 |   // Replace instruction `initial` with `replacement` within this block. | 
 | 399 |   void ReplaceAndRemoveInstructionWith(HInstruction* initial, | 
 | 400 |                                        HInstruction* replacement); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 401 |   void AddPhi(HPhi* phi); | 
 | 402 |   void RemovePhi(HPhi* phi); | 
 | 403 |  | 
 | 404 |   bool IsLoopHeader() const { | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 405 |     return (loop_information_ != nullptr) && (loop_information_->GetHeader() == this); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 406 |   } | 
 | 407 |  | 
| Roland Levillain | 6b879dd | 2014-09-22 17:13:44 +0100 | [diff] [blame] | 408 |   bool IsLoopPreHeaderFirstPredecessor() const { | 
 | 409 |     DCHECK(IsLoopHeader()); | 
 | 410 |     DCHECK(!GetPredecessors().IsEmpty()); | 
 | 411 |     return GetPredecessors().Get(0) == GetLoopInformation()->GetPreHeader(); | 
 | 412 |   } | 
 | 413 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 414 |   HLoopInformation* GetLoopInformation() const { | 
 | 415 |     return loop_information_; | 
 | 416 |   } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 417 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 418 |   // Set the loop_information_ on this block. This method overrides the current | 
 | 419 |   // loop_information if it is an outer loop of the passed loop information. | 
 | 420 |   void SetInLoop(HLoopInformation* info) { | 
 | 421 |     if (IsLoopHeader()) { | 
 | 422 |       // Nothing to do. This just means `info` is an outer loop. | 
 | 423 |     } else if (loop_information_ == nullptr) { | 
 | 424 |       loop_information_ = info; | 
 | 425 |     } else if (loop_information_->Contains(*info->GetHeader())) { | 
 | 426 |       // Block is currently part of an outer loop. Make it part of this inner loop. | 
 | 427 |       // Note that a non loop header having a loop information means this loop information | 
 | 428 |       // has already been populated | 
 | 429 |       loop_information_ = info; | 
 | 430 |     } else { | 
 | 431 |       // Block is part of an inner loop. Do not update the loop information. | 
 | 432 |       // Note that we cannot do the check `info->Contains(loop_information_)->GetHeader()` | 
 | 433 |       // at this point, because this method is being called while populating `info`. | 
 | 434 |     } | 
 | 435 |   } | 
 | 436 |  | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 437 |   bool IsInLoop() const { return loop_information_ != nullptr; } | 
 | 438 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 439 |   // Returns wheter this block dominates the blocked passed as parameter. | 
 | 440 |   bool Dominates(HBasicBlock* block) const; | 
 | 441 |  | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 442 |   size_t GetLifetimeStart() const { return lifetime_start_; } | 
 | 443 |   size_t GetLifetimeEnd() const { return lifetime_end_; } | 
 | 444 |  | 
 | 445 |   void SetLifetimeStart(size_t start) { lifetime_start_ = start; } | 
 | 446 |   void SetLifetimeEnd(size_t end) { lifetime_end_ = end; } | 
 | 447 |  | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 448 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 449 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 450 |  private: | 
 | 451 |   HGraph* const graph_; | 
 | 452 |   GrowableArray<HBasicBlock*> predecessors_; | 
 | 453 |   GrowableArray<HBasicBlock*> successors_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 454 |   HInstructionList instructions_; | 
 | 455 |   HInstructionList phis_; | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 456 |   HLoopInformation* loop_information_; | 
 | 457 |   HBasicBlock* dominator_; | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 458 |   GrowableArray<HBasicBlock*> dominated_blocks_; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 459 |   int block_id_; | 
| Nicolas Geoffray | 3c04974 | 2014-09-24 18:10:46 +0100 | [diff] [blame] | 460 |   // The dex program counter of the first instruction of this block. | 
 | 461 |   const uint32_t dex_pc_; | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 462 |   size_t lifetime_start_; | 
 | 463 |   size_t lifetime_end_; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 464 |  | 
 | 465 |   DISALLOW_COPY_AND_ASSIGN(HBasicBlock); | 
 | 466 | }; | 
 | 467 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 468 | #define FOR_EACH_CONCRETE_INSTRUCTION(M)                   \ | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 469 |   M(Add)                                                   \ | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 470 |   M(Condition)                                             \ | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 471 |   M(Equal)                                                 \ | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 472 |   M(NotEqual)                                              \ | 
 | 473 |   M(LessThan)                                              \ | 
 | 474 |   M(LessThanOrEqual)                                       \ | 
 | 475 |   M(GreaterThan)                                           \ | 
 | 476 |   M(GreaterThanOrEqual)                                    \ | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 477 |   M(Exit)                                                  \ | 
 | 478 |   M(Goto)                                                  \ | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 479 |   M(If)                                                    \ | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 480 |   M(IntConstant)                                           \ | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 481 |   M(InvokeStatic)                                          \ | 
| Nicolas Geoffray | e982f0b | 2014-08-13 02:11:24 +0100 | [diff] [blame] | 482 |   M(InvokeVirtual)                                         \ | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 483 |   M(LoadLocal)                                             \ | 
 | 484 |   M(Local)                                                 \ | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 485 |   M(LongConstant)                                          \ | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 486 |   M(NewInstance)                                           \ | 
| Nicolas Geoffray | b55f835 | 2014-04-07 15:26:35 +0100 | [diff] [blame] | 487 |   M(Not)                                                   \ | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 488 |   M(ParameterValue)                                        \ | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 489 |   M(ParallelMove)                                          \ | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 490 |   M(Phi)                                                   \ | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 491 |   M(Return)                                                \ | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 492 |   M(ReturnVoid)                                            \ | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 493 |   M(StoreLocal)                                            \ | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 494 |   M(Sub)                                                   \ | 
| Nicolas Geoffray | 412f10c | 2014-06-19 10:00:34 +0100 | [diff] [blame] | 495 |   M(Compare)                                               \ | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 496 |   M(InstanceFieldGet)                                      \ | 
 | 497 |   M(InstanceFieldSet)                                      \ | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 498 |   M(ArrayGet)                                              \ | 
 | 499 |   M(ArraySet)                                              \ | 
 | 500 |   M(ArrayLength)                                           \ | 
 | 501 |   M(BoundsCheck)                                           \ | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 502 |   M(NullCheck)                                             \ | 
 | 503 |   M(Temporary)                                             \ | 
| Nicolas Geoffray | fbc695f | 2014-09-15 15:33:30 +0000 | [diff] [blame] | 504 |   M(SuspendCheck)                                          \ | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 505 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 506 | #define FOR_EACH_INSTRUCTION(M)                            \ | 
 | 507 |   FOR_EACH_CONCRETE_INSTRUCTION(M)                         \ | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 508 |   M(Constant)                                              \ | 
 | 509 |   M(BinaryOperation) | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 510 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 511 | #define FORWARD_DECLARATION(type) class H##type; | 
 | 512 | FOR_EACH_INSTRUCTION(FORWARD_DECLARATION) | 
 | 513 | #undef FORWARD_DECLARATION | 
 | 514 |  | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 515 | #define DECLARE_INSTRUCTION(type)                                       \ | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 516 |   virtual InstructionKind GetKind() const { return k##type; }           \ | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 517 |   virtual const char* DebugName() const { return #type; }               \ | 
 | 518 |   virtual const H##type* As##type() const OVERRIDE { return this; }     \ | 
 | 519 |   virtual H##type* As##type() OVERRIDE { return this; }                 \ | 
 | 520 |   virtual bool InstructionTypeEquals(HInstruction* other) const {       \ | 
 | 521 |     return other->Is##type();                                           \ | 
 | 522 |   }                                                                     \ | 
 | 523 |   virtual void Accept(HGraphVisitor* visitor) | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 524 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 525 | template <typename T> | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 526 | class HUseListNode : public ArenaObject { | 
 | 527 |  public: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 528 |   HUseListNode(T* user, size_t index, HUseListNode* tail) | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 529 |       : user_(user), index_(index), tail_(tail) {} | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 530 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 531 |   HUseListNode* GetTail() const { return tail_; } | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 532 |   T* GetUser() const { return user_; } | 
 | 533 |   size_t GetIndex() const { return index_; } | 
 | 534 |  | 
 | 535 |   void SetTail(HUseListNode<T>* node) { tail_ = node; } | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 536 |  | 
 | 537 |  private: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 538 |   T* const user_; | 
 | 539 |   const size_t index_; | 
 | 540 |   HUseListNode<T>* tail_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 541 |  | 
 | 542 |   DISALLOW_COPY_AND_ASSIGN(HUseListNode); | 
 | 543 | }; | 
 | 544 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 545 | // Represents the side effects an instruction may have. | 
 | 546 | class SideEffects : public ValueObject { | 
 | 547 |  public: | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 548 |   SideEffects() : flags_(0) {} | 
 | 549 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 550 |   static SideEffects None() { | 
 | 551 |     return SideEffects(0); | 
 | 552 |   } | 
 | 553 |  | 
 | 554 |   static SideEffects All() { | 
 | 555 |     return SideEffects(ChangesSomething().flags_ | DependsOnSomething().flags_); | 
 | 556 |   } | 
 | 557 |  | 
 | 558 |   static SideEffects ChangesSomething() { | 
 | 559 |     return SideEffects((1 << kFlagChangesCount) - 1); | 
 | 560 |   } | 
 | 561 |  | 
 | 562 |   static SideEffects DependsOnSomething() { | 
 | 563 |     int count = kFlagDependsOnCount - kFlagChangesCount; | 
 | 564 |     return SideEffects(((1 << count) - 1) << kFlagChangesCount); | 
 | 565 |   } | 
 | 566 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 567 |   SideEffects Union(SideEffects other) const { | 
 | 568 |     return SideEffects(flags_ | other.flags_); | 
 | 569 |   } | 
 | 570 |  | 
| Roland Levillain | 72bceff | 2014-09-15 18:29:00 +0100 | [diff] [blame] | 571 |   bool HasSideEffects() const { | 
 | 572 |     size_t all_bits_set = (1 << kFlagChangesCount) - 1; | 
 | 573 |     return (flags_ & all_bits_set) != 0; | 
 | 574 |   } | 
 | 575 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 576 |   bool HasAllSideEffects() const { | 
 | 577 |     size_t all_bits_set = (1 << kFlagChangesCount) - 1; | 
 | 578 |     return all_bits_set == (flags_ & all_bits_set); | 
 | 579 |   } | 
 | 580 |  | 
 | 581 |   bool DependsOn(SideEffects other) const { | 
 | 582 |     size_t depends_flags = other.ComputeDependsFlags(); | 
 | 583 |     return (flags_ & depends_flags) != 0; | 
 | 584 |   } | 
 | 585 |  | 
 | 586 |   bool HasDependencies() const { | 
 | 587 |     int count = kFlagDependsOnCount - kFlagChangesCount; | 
 | 588 |     size_t all_bits_set = (1 << count) - 1; | 
 | 589 |     return ((flags_ >> kFlagChangesCount) & all_bits_set) != 0; | 
 | 590 |   } | 
 | 591 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 592 |  private: | 
 | 593 |   static constexpr int kFlagChangesSomething = 0; | 
 | 594 |   static constexpr int kFlagChangesCount = kFlagChangesSomething + 1; | 
 | 595 |  | 
 | 596 |   static constexpr int kFlagDependsOnSomething = kFlagChangesCount; | 
 | 597 |   static constexpr int kFlagDependsOnCount = kFlagDependsOnSomething + 1; | 
 | 598 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 599 |   explicit SideEffects(size_t flags) : flags_(flags) {} | 
 | 600 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 601 |   size_t ComputeDependsFlags() const { | 
 | 602 |     return flags_ << kFlagChangesCount; | 
 | 603 |   } | 
 | 604 |  | 
 | 605 |   size_t flags_; | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 606 | }; | 
 | 607 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 608 | class HInstruction : public ArenaObject { | 
 | 609 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 610 |   explicit HInstruction(SideEffects side_effects) | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 611 |       : previous_(nullptr), | 
 | 612 |         next_(nullptr), | 
 | 613 |         block_(nullptr), | 
 | 614 |         id_(-1), | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 615 |         ssa_index_(-1), | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 616 |         uses_(nullptr), | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 617 |         env_uses_(nullptr), | 
 | 618 |         environment_(nullptr), | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 619 |         locations_(nullptr), | 
 | 620 |         live_interval_(nullptr), | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 621 |         lifetime_position_(kNoLifetime), | 
 | 622 |         side_effects_(side_effects) {} | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 623 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 624 |   virtual ~HInstruction() {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 625 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 626 | #define DECLARE_KIND(type) k##type, | 
 | 627 |   enum InstructionKind { | 
 | 628 |     FOR_EACH_INSTRUCTION(DECLARE_KIND) | 
 | 629 |   }; | 
 | 630 | #undef DECLARE_KIND | 
 | 631 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 632 |   HInstruction* GetNext() const { return next_; } | 
 | 633 |   HInstruction* GetPrevious() const { return previous_; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 634 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 635 |   HBasicBlock* GetBlock() const { return block_; } | 
 | 636 |   void SetBlock(HBasicBlock* block) { block_ = block; } | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 637 |   bool IsInBlock() const { return block_ != nullptr; } | 
 | 638 |   bool IsInLoop() const { return block_->IsInLoop(); } | 
| Nicolas Geoffray | 3ac17fc | 2014-08-06 23:02:54 +0100 | [diff] [blame] | 639 |   bool IsLoopHeaderPhi() { return IsPhi() && block_->IsLoopHeader(); } | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 640 |  | 
| Roland Levillain | 6b879dd | 2014-09-22 17:13:44 +0100 | [diff] [blame] | 641 |   virtual size_t InputCount() const = 0; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 642 |   virtual HInstruction* InputAt(size_t i) const = 0; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 643 |  | 
 | 644 |   virtual void Accept(HGraphVisitor* visitor) = 0; | 
 | 645 |   virtual const char* DebugName() const = 0; | 
 | 646 |  | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 647 |   virtual Primitive::Type GetType() const { return Primitive::kPrimVoid; } | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 648 |   virtual void SetRawInputAt(size_t index, HInstruction* input) = 0; | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 649 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 650 |   virtual bool NeedsEnvironment() const { return false; } | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 651 |   virtual bool IsControlFlow() const { return false; } | 
| Roland Levillain | 72bceff | 2014-09-15 18:29:00 +0100 | [diff] [blame] | 652 |   bool HasSideEffects() const { return side_effects_.HasSideEffects(); } | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 653 |  | 
 | 654 |   void AddUseAt(HInstruction* user, size_t index) { | 
 | 655 |     uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HInstruction>(user, index, uses_); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 656 |   } | 
 | 657 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 658 |   void AddEnvUseAt(HEnvironment* user, size_t index) { | 
| Nicolas Geoffray | 724c963 | 2014-09-22 12:27:27 +0100 | [diff] [blame] | 659 |     DCHECK(user != nullptr); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 660 |     env_uses_ = new (block_->GetGraph()->GetArena()) HUseListNode<HEnvironment>( | 
 | 661 |         user, index, env_uses_); | 
 | 662 |   } | 
 | 663 |  | 
 | 664 |   void RemoveUser(HInstruction* user, size_t index); | 
| Nicolas Geoffray | 724c963 | 2014-09-22 12:27:27 +0100 | [diff] [blame] | 665 |   void RemoveEnvironmentUser(HEnvironment* user, size_t index); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 666 |  | 
 | 667 |   HUseListNode<HInstruction>* GetUses() const { return uses_; } | 
 | 668 |   HUseListNode<HEnvironment>* GetEnvUses() const { return env_uses_; } | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 669 |  | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 670 |   bool HasUses() const { return uses_ != nullptr || env_uses_ != nullptr; } | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 671 |   bool HasEnvironmentUses() const { return env_uses_ != nullptr; } | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 672 |  | 
| Nicolas Geoffray | f635e63 | 2014-05-14 09:43:38 +0100 | [diff] [blame] | 673 |   size_t NumberOfUses() const { | 
| Nicolas Geoffray | 0d3f578 | 2014-05-14 09:43:38 +0100 | [diff] [blame] | 674 |     // TODO: Optimize this method if it is used outside of the HGraphVisualizer. | 
| Nicolas Geoffray | f635e63 | 2014-05-14 09:43:38 +0100 | [diff] [blame] | 675 |     size_t result = 0; | 
 | 676 |     HUseListNode<HInstruction>* current = uses_; | 
 | 677 |     while (current != nullptr) { | 
 | 678 |       current = current->GetTail(); | 
 | 679 |       ++result; | 
 | 680 |     } | 
 | 681 |     return result; | 
 | 682 |   } | 
 | 683 |  | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 684 |   // Does this instruction dominate `other_instruction`?  Aborts if | 
 | 685 |   // this instruction and `other_instruction` are both phis. | 
 | 686 |   bool Dominates(HInstruction* other_instruction) const; | 
 | 687 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 688 |   int GetId() const { return id_; } | 
 | 689 |   void SetId(int id) { id_ = id; } | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 690 |  | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 691 |   int GetSsaIndex() const { return ssa_index_; } | 
 | 692 |   void SetSsaIndex(int ssa_index) { ssa_index_ = ssa_index; } | 
 | 693 |   bool HasSsaIndex() const { return ssa_index_ != -1; } | 
 | 694 |  | 
 | 695 |   bool HasEnvironment() const { return environment_ != nullptr; } | 
 | 696 |   HEnvironment* GetEnvironment() const { return environment_; } | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 697 |   void SetEnvironment(HEnvironment* environment) { environment_ = environment; } | 
 | 698 |  | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 699 |   // Returns the number of entries in the environment. Typically, that is the | 
 | 700 |   // number of dex registers in a method. It could be more in case of inlining. | 
 | 701 |   size_t EnvironmentSize() const; | 
 | 702 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 703 |   LocationSummary* GetLocations() const { return locations_; } | 
 | 704 |   void SetLocations(LocationSummary* locations) { locations_ = locations; } | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 705 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 706 |   void ReplaceWith(HInstruction* instruction); | 
 | 707 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 708 |   bool HasOnlyOneUse() const { | 
 | 709 |     return uses_ != nullptr && uses_->GetTail() == nullptr; | 
 | 710 |   } | 
 | 711 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 712 | #define INSTRUCTION_TYPE_CHECK(type)                                           \ | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 713 |   bool Is##type() const { return (As##type() != nullptr); }                    \ | 
 | 714 |   virtual const H##type* As##type() const { return nullptr; }                  \ | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 715 |   virtual H##type* As##type() { return nullptr; } | 
 | 716 |  | 
 | 717 |   FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK) | 
 | 718 | #undef INSTRUCTION_TYPE_CHECK | 
 | 719 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 720 |   // Returns whether the instruction can be moved within the graph. | 
 | 721 |   virtual bool CanBeMoved() const { return false; } | 
 | 722 |  | 
 | 723 |   // Returns whether the two instructions are of the same kind. | 
 | 724 |   virtual bool InstructionTypeEquals(HInstruction* other) const { return false; } | 
 | 725 |  | 
 | 726 |   // Returns whether any data encoded in the two instructions is equal. | 
 | 727 |   // This method does not look at the inputs. Both instructions must be | 
 | 728 |   // of the same type, otherwise the method has undefined behavior. | 
 | 729 |   virtual bool InstructionDataEquals(HInstruction* other) const { return false; } | 
 | 730 |  | 
 | 731 |   // Returns whether two instructions are equal, that is: | 
 | 732 |   // 1) They have the same type and contain the same data, | 
 | 733 |   // 2) Their inputs are identical. | 
 | 734 |   bool Equals(HInstruction* other) const; | 
 | 735 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 736 |   virtual InstructionKind GetKind() const = 0; | 
 | 737 |  | 
 | 738 |   virtual size_t ComputeHashCode() const { | 
 | 739 |     size_t result = GetKind(); | 
 | 740 |     for (size_t i = 0, e = InputCount(); i < e; ++i) { | 
 | 741 |       result = (result * 31) + InputAt(i)->GetId(); | 
 | 742 |     } | 
 | 743 |     return result; | 
 | 744 |   } | 
 | 745 |  | 
 | 746 |   SideEffects GetSideEffects() const { return side_effects_; } | 
 | 747 |  | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 748 |   size_t GetLifetimePosition() const { return lifetime_position_; } | 
 | 749 |   void SetLifetimePosition(size_t position) { lifetime_position_ = position; } | 
 | 750 |   LiveInterval* GetLiveInterval() const { return live_interval_; } | 
 | 751 |   void SetLiveInterval(LiveInterval* interval) { live_interval_ = interval; } | 
 | 752 |   bool HasLiveInterval() const { return live_interval_ != nullptr; } | 
 | 753 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 754 |  private: | 
 | 755 |   HInstruction* previous_; | 
 | 756 |   HInstruction* next_; | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 757 |   HBasicBlock* block_; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 758 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 759 |   // An instruction gets an id when it is added to the graph. | 
 | 760 |   // It reflects creation order. A negative id means the instruction | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 761 |   // has not been added to the graph. | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 762 |   int id_; | 
 | 763 |  | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 764 |   // When doing liveness analysis, instructions that have uses get an SSA index. | 
 | 765 |   int ssa_index_; | 
 | 766 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 767 |   // List of instructions that have this instruction as input. | 
 | 768 |   HUseListNode<HInstruction>* uses_; | 
 | 769 |  | 
 | 770 |   // List of environments that contain this instruction. | 
 | 771 |   HUseListNode<HEnvironment>* env_uses_; | 
 | 772 |  | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 773 |   // The environment associated with this instruction. Not null if the instruction | 
 | 774 |   // might jump out of the method. | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 775 |   HEnvironment* environment_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 776 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 777 |   // Set by the code generator. | 
 | 778 |   LocationSummary* locations_; | 
 | 779 |  | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 780 |   // Set by the liveness analysis. | 
 | 781 |   LiveInterval* live_interval_; | 
 | 782 |  | 
 | 783 |   // Set by the liveness analysis, this is the position in a linear | 
 | 784 |   // order of blocks where this instruction's live interval start. | 
 | 785 |   size_t lifetime_position_; | 
 | 786 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 787 |   const SideEffects side_effects_; | 
 | 788 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 789 |   friend class HBasicBlock; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 790 |   friend class HInstructionList; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 791 |  | 
 | 792 |   DISALLOW_COPY_AND_ASSIGN(HInstruction); | 
 | 793 | }; | 
 | 794 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 795 | template<typename T> | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 796 | class HUseIterator : public ValueObject { | 
 | 797 |  public: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 798 |   explicit HUseIterator(HUseListNode<T>* uses) : current_(uses) {} | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 799 |  | 
 | 800 |   bool Done() const { return current_ == nullptr; } | 
 | 801 |  | 
 | 802 |   void Advance() { | 
 | 803 |     DCHECK(!Done()); | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 804 |     current_ = current_->GetTail(); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 805 |   } | 
 | 806 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 807 |   HUseListNode<T>* Current() const { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 808 |     DCHECK(!Done()); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 809 |     return current_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 810 |   } | 
 | 811 |  | 
 | 812 |  private: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 813 |   HUseListNode<T>* current_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 814 |  | 
 | 815 |   friend class HValue; | 
 | 816 | }; | 
 | 817 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 818 | // A HEnvironment object contains the values of virtual registers at a given location. | 
 | 819 | class HEnvironment : public ArenaObject { | 
 | 820 |  public: | 
 | 821 |   HEnvironment(ArenaAllocator* arena, size_t number_of_vregs) : vregs_(arena, number_of_vregs) { | 
 | 822 |     vregs_.SetSize(number_of_vregs); | 
 | 823 |     for (size_t i = 0; i < number_of_vregs; i++) { | 
 | 824 |       vregs_.Put(i, nullptr); | 
 | 825 |     } | 
 | 826 |   } | 
 | 827 |  | 
 | 828 |   void Populate(const GrowableArray<HInstruction*>& env) { | 
 | 829 |     for (size_t i = 0; i < env.Size(); i++) { | 
 | 830 |       HInstruction* instruction = env.Get(i); | 
 | 831 |       vregs_.Put(i, instruction); | 
 | 832 |       if (instruction != nullptr) { | 
 | 833 |         instruction->AddEnvUseAt(this, i); | 
 | 834 |       } | 
 | 835 |     } | 
 | 836 |   } | 
 | 837 |  | 
 | 838 |   void SetRawEnvAt(size_t index, HInstruction* instruction) { | 
 | 839 |     vregs_.Put(index, instruction); | 
 | 840 |   } | 
 | 841 |  | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 842 |   HInstruction* GetInstructionAt(size_t index) const { | 
 | 843 |     return vregs_.Get(index); | 
 | 844 |   } | 
 | 845 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 846 |   GrowableArray<HInstruction*>* GetVRegs() { | 
 | 847 |     return &vregs_; | 
 | 848 |   } | 
 | 849 |  | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 850 |   size_t Size() const { return vregs_.Size(); } | 
 | 851 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 852 |  private: | 
 | 853 |   GrowableArray<HInstruction*> vregs_; | 
 | 854 |  | 
 | 855 |   DISALLOW_COPY_AND_ASSIGN(HEnvironment); | 
 | 856 | }; | 
 | 857 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 858 | class HInputIterator : public ValueObject { | 
 | 859 |  public: | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 860 |   explicit HInputIterator(HInstruction* instruction) : instruction_(instruction), index_(0) {} | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 861 |  | 
 | 862 |   bool Done() const { return index_ == instruction_->InputCount(); } | 
 | 863 |   HInstruction* Current() const { return instruction_->InputAt(index_); } | 
 | 864 |   void Advance() { index_++; } | 
 | 865 |  | 
 | 866 |  private: | 
 | 867 |   HInstruction* instruction_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 868 |   size_t index_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 869 |  | 
 | 870 |   DISALLOW_COPY_AND_ASSIGN(HInputIterator); | 
 | 871 | }; | 
 | 872 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 873 | class HInstructionIterator : public ValueObject { | 
 | 874 |  public: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 875 |   explicit HInstructionIterator(const HInstructionList& instructions) | 
 | 876 |       : instruction_(instructions.first_instruction_) { | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 877 |     next_ = Done() ? nullptr : instruction_->GetNext(); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 878 |   } | 
 | 879 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 880 |   bool Done() const { return instruction_ == nullptr; } | 
 | 881 |   HInstruction* Current() const { return instruction_; } | 
 | 882 |   void Advance() { | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 883 |     instruction_ = next_; | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 884 |     next_ = Done() ? nullptr : instruction_->GetNext(); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 885 |   } | 
 | 886 |  | 
 | 887 |  private: | 
 | 888 |   HInstruction* instruction_; | 
 | 889 |   HInstruction* next_; | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 890 |  | 
 | 891 |   DISALLOW_COPY_AND_ASSIGN(HInstructionIterator); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 892 | }; | 
 | 893 |  | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 894 | class HBackwardInstructionIterator : public ValueObject { | 
 | 895 |  public: | 
 | 896 |   explicit HBackwardInstructionIterator(const HInstructionList& instructions) | 
 | 897 |       : instruction_(instructions.last_instruction_) { | 
 | 898 |     next_ = Done() ? nullptr : instruction_->GetPrevious(); | 
 | 899 |   } | 
 | 900 |  | 
 | 901 |   bool Done() const { return instruction_ == nullptr; } | 
 | 902 |   HInstruction* Current() const { return instruction_; } | 
 | 903 |   void Advance() { | 
 | 904 |     instruction_ = next_; | 
 | 905 |     next_ = Done() ? nullptr : instruction_->GetPrevious(); | 
 | 906 |   } | 
 | 907 |  | 
 | 908 |  private: | 
 | 909 |   HInstruction* instruction_; | 
 | 910 |   HInstruction* next_; | 
| Nicolas Geoffray | ddb311f | 2014-05-16 09:28:54 +0100 | [diff] [blame] | 911 |  | 
 | 912 |   DISALLOW_COPY_AND_ASSIGN(HBackwardInstructionIterator); | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 913 | }; | 
 | 914 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 915 | // An embedded container with N elements of type T.  Used (with partial | 
 | 916 | // specialization for N=0) because embedded arrays cannot have size 0. | 
 | 917 | template<typename T, intptr_t N> | 
 | 918 | class EmbeddedArray { | 
 | 919 |  public: | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 920 |   EmbeddedArray() : elements_() {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 921 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 922 |   intptr_t GetLength() const { return N; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 923 |  | 
 | 924 |   const T& operator[](intptr_t i) const { | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 925 |     DCHECK_LT(i, GetLength()); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 926 |     return elements_[i]; | 
 | 927 |   } | 
 | 928 |  | 
 | 929 |   T& operator[](intptr_t i) { | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 930 |     DCHECK_LT(i, GetLength()); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 931 |     return elements_[i]; | 
 | 932 |   } | 
 | 933 |  | 
 | 934 |   const T& At(intptr_t i) const { | 
 | 935 |     return (*this)[i]; | 
 | 936 |   } | 
 | 937 |  | 
 | 938 |   void SetAt(intptr_t i, const T& val) { | 
 | 939 |     (*this)[i] = val; | 
 | 940 |   } | 
 | 941 |  | 
 | 942 |  private: | 
 | 943 |   T elements_[N]; | 
 | 944 | }; | 
 | 945 |  | 
 | 946 | template<typename T> | 
 | 947 | class EmbeddedArray<T, 0> { | 
 | 948 |  public: | 
 | 949 |   intptr_t length() const { return 0; } | 
 | 950 |   const T& operator[](intptr_t i) const { | 
 | 951 |     LOG(FATAL) << "Unreachable"; | 
 | 952 |     static T sentinel = 0; | 
 | 953 |     return sentinel; | 
 | 954 |   } | 
 | 955 |   T& operator[](intptr_t i) { | 
 | 956 |     LOG(FATAL) << "Unreachable"; | 
 | 957 |     static T sentinel = 0; | 
 | 958 |     return sentinel; | 
 | 959 |   } | 
 | 960 | }; | 
 | 961 |  | 
 | 962 | template<intptr_t N> | 
 | 963 | class HTemplateInstruction: public HInstruction { | 
 | 964 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 965 |   HTemplateInstruction<N>(SideEffects side_effects) | 
 | 966 |       : HInstruction(side_effects), inputs_() {} | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 967 |   virtual ~HTemplateInstruction() {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 968 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 969 |   virtual size_t InputCount() const { return N; } | 
 | 970 |   virtual HInstruction* InputAt(size_t i) const { return inputs_[i]; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 971 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 972 |  protected: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 973 |   virtual void SetRawInputAt(size_t i, HInstruction* instruction) { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 974 |     inputs_[i] = instruction; | 
 | 975 |   } | 
 | 976 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 977 |  private: | 
 | 978 |   EmbeddedArray<HInstruction*, N> inputs_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 979 |  | 
 | 980 |   friend class SsaBuilder; | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 981 | }; | 
 | 982 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 983 | template<intptr_t N> | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 984 | class HExpression : public HTemplateInstruction<N> { | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 985 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 986 |   HExpression<N>(Primitive::Type type, SideEffects side_effects) | 
 | 987 |       : HTemplateInstruction<N>(side_effects), type_(type) {} | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 988 |   virtual ~HExpression() {} | 
 | 989 |  | 
 | 990 |   virtual Primitive::Type GetType() const { return type_; } | 
 | 991 |  | 
 | 992 |  private: | 
 | 993 |   const Primitive::Type type_; | 
 | 994 | }; | 
 | 995 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 996 | // Represents dex's RETURN_VOID opcode. A HReturnVoid is a control flow | 
 | 997 | // instruction that branches to the exit block. | 
 | 998 | class HReturnVoid : public HTemplateInstruction<0> { | 
 | 999 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1000 |   HReturnVoid() : HTemplateInstruction(SideEffects::None()) {} | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 1001 |  | 
 | 1002 |   virtual bool IsControlFlow() const { return true; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1003 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1004 |   DECLARE_INSTRUCTION(ReturnVoid); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1005 |  | 
 | 1006 |  private: | 
 | 1007 |   DISALLOW_COPY_AND_ASSIGN(HReturnVoid); | 
 | 1008 | }; | 
 | 1009 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1010 | // Represents dex's RETURN opcodes. A HReturn is a control flow | 
 | 1011 | // instruction that branches to the exit block. | 
 | 1012 | class HReturn : public HTemplateInstruction<1> { | 
 | 1013 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1014 |   explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) { | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1015 |     SetRawInputAt(0, value); | 
 | 1016 |   } | 
 | 1017 |  | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 1018 |   virtual bool IsControlFlow() const { return true; } | 
 | 1019 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1020 |   DECLARE_INSTRUCTION(Return); | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1021 |  | 
 | 1022 |  private: | 
 | 1023 |   DISALLOW_COPY_AND_ASSIGN(HReturn); | 
 | 1024 | }; | 
 | 1025 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1026 | // The exit instruction is the only instruction of the exit block. | 
 | 1027 | // Instructions aborting the method (HTrow and HReturn) must branch to the | 
 | 1028 | // exit block. | 
 | 1029 | class HExit : public HTemplateInstruction<0> { | 
 | 1030 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1031 |   HExit() : HTemplateInstruction(SideEffects::None()) {} | 
| Nicolas Geoffray | ec7e472 | 2014-06-06 11:24:33 +0100 | [diff] [blame] | 1032 |  | 
 | 1033 |   virtual bool IsControlFlow() const { return true; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1034 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1035 |   DECLARE_INSTRUCTION(Exit); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1036 |  | 
 | 1037 |  private: | 
 | 1038 |   DISALLOW_COPY_AND_ASSIGN(HExit); | 
 | 1039 | }; | 
 | 1040 |  | 
 | 1041 | // Jumps from one block to another. | 
 | 1042 | class HGoto : public HTemplateInstruction<0> { | 
 | 1043 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1044 |   HGoto() : HTemplateInstruction(SideEffects::None()) {} | 
 | 1045 |  | 
 | 1046 |   virtual bool IsControlFlow() const { return true; } | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1047 |  | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 1048 |   HBasicBlock* GetSuccessor() const { | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1049 |     return GetBlock()->GetSuccessors().Get(0); | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 1050 |   } | 
 | 1051 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1052 |   DECLARE_INSTRUCTION(Goto); | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1053 |  | 
 | 1054 |  private: | 
 | 1055 |   DISALLOW_COPY_AND_ASSIGN(HGoto); | 
 | 1056 | }; | 
 | 1057 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1058 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 1059 | // Conditional branch. A block ending with an HIf instruction must have | 
 | 1060 | // two successors. | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1061 | class HIf : public HTemplateInstruction<1> { | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 1062 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1063 |   explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1064 |     SetRawInputAt(0, input); | 
 | 1065 |   } | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 1066 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1067 |   virtual bool IsControlFlow() const { return true; } | 
 | 1068 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1069 |   HBasicBlock* IfTrueSuccessor() const { | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1070 |     return GetBlock()->GetSuccessors().Get(0); | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1071 |   } | 
 | 1072 |  | 
 | 1073 |   HBasicBlock* IfFalseSuccessor() const { | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1074 |     return GetBlock()->GetSuccessors().Get(1); | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1075 |   } | 
 | 1076 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1077 |   DECLARE_INSTRUCTION(If); | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 1078 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1079 |   virtual bool IsIfInstruction() const { return true; } | 
 | 1080 |  | 
| Nicolas Geoffray | be9a92a | 2014-02-25 14:22:56 +0000 | [diff] [blame] | 1081 |  private: | 
 | 1082 |   DISALLOW_COPY_AND_ASSIGN(HIf); | 
 | 1083 | }; | 
 | 1084 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1085 | class HBinaryOperation : public HExpression<2> { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1086 |  public: | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1087 |   HBinaryOperation(Primitive::Type result_type, | 
 | 1088 |                    HInstruction* left, | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1089 |                    HInstruction* right) : HExpression(result_type, SideEffects::None()) { | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1090 |     SetRawInputAt(0, left); | 
 | 1091 |     SetRawInputAt(1, right); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1092 |   } | 
 | 1093 |  | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1094 |   HInstruction* GetLeft() const { return InputAt(0); } | 
 | 1095 |   HInstruction* GetRight() const { return InputAt(1); } | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1096 |   Primitive::Type GetResultType() const { return GetType(); } | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1097 |  | 
 | 1098 |   virtual bool IsCommutative() { return false; } | 
 | 1099 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1100 |   virtual bool CanBeMoved() const { return true; } | 
 | 1101 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1102 |  | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1103 |   // Try to statically evaluate `operation` and return an HConstant | 
 | 1104 |   // containing the result of this evaluation.  If `operation` cannot | 
 | 1105 |   // be evaluated as a constant, return nullptr. | 
 | 1106 |   HConstant* TryStaticEvaluation(ArenaAllocator* allocator) const; | 
 | 1107 |  | 
 | 1108 |   // Apply this operation to `x` and `y`. | 
 | 1109 |   virtual int32_t Evaluate(int32_t x, int32_t y) const = 0; | 
 | 1110 |   virtual int64_t Evaluate(int64_t x, int64_t y) const = 0; | 
 | 1111 |  | 
| Roland Levillain | ccc07a9 | 2014-09-16 14:48:16 +0100 | [diff] [blame] | 1112 |   DECLARE_INSTRUCTION(BinaryOperation); | 
 | 1113 |  | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1114 |  private: | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1115 |   DISALLOW_COPY_AND_ASSIGN(HBinaryOperation); | 
 | 1116 | }; | 
 | 1117 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1118 | class HCondition : public HBinaryOperation { | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1119 |  public: | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1120 |   HCondition(HInstruction* first, HInstruction* second) | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1121 |       : HBinaryOperation(Primitive::kPrimBoolean, first, second) {} | 
 | 1122 |  | 
 | 1123 |   virtual bool IsCommutative() { return true; } | 
| Nicolas Geoffray | 18efde5 | 2014-09-22 15:51:11 +0100 | [diff] [blame] | 1124 |  | 
 | 1125 |   // For register allocation purposes, returns whether this instruction needs to be | 
 | 1126 |   // materialized (that is, not just be in the processor flags). | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1127 |   bool NeedsMaterialization() const; | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1128 |  | 
| Nicolas Geoffray | 18efde5 | 2014-09-22 15:51:11 +0100 | [diff] [blame] | 1129 |   // For code generation purposes, returns whether this instruction is just before | 
 | 1130 |   // `if_`, and disregard moves in between. | 
 | 1131 |   bool IsBeforeWhenDisregardMoves(HIf* if_) const; | 
 | 1132 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1133 |   DECLARE_INSTRUCTION(Condition); | 
 | 1134 |  | 
 | 1135 |   virtual IfCondition GetCondition() const = 0; | 
 | 1136 |  | 
 | 1137 |  private: | 
 | 1138 |   DISALLOW_COPY_AND_ASSIGN(HCondition); | 
 | 1139 | }; | 
 | 1140 |  | 
 | 1141 | // Instruction to check if two inputs are equal to each other. | 
 | 1142 | class HEqual : public HCondition { | 
 | 1143 |  public: | 
 | 1144 |   HEqual(HInstruction* first, HInstruction* second) | 
 | 1145 |       : HCondition(first, second) {} | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1146 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1147 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1148 |     return x == y ? 1 : 0; | 
 | 1149 |   } | 
 | 1150 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1151 |     return x == y ? 1 : 0; | 
 | 1152 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1153 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1154 |   DECLARE_INSTRUCTION(Equal); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1155 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1156 |   virtual IfCondition GetCondition() const { | 
 | 1157 |     return kCondEQ; | 
 | 1158 |   } | 
 | 1159 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1160 |  private: | 
 | 1161 |   DISALLOW_COPY_AND_ASSIGN(HEqual); | 
 | 1162 | }; | 
 | 1163 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1164 | class HNotEqual : public HCondition { | 
 | 1165 |  public: | 
 | 1166 |   HNotEqual(HInstruction* first, HInstruction* second) | 
 | 1167 |       : HCondition(first, second) {} | 
 | 1168 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1169 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1170 |     return x != y ? 1 : 0; | 
 | 1171 |   } | 
 | 1172 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1173 |     return x != y ? 1 : 0; | 
 | 1174 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1175 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1176 |   DECLARE_INSTRUCTION(NotEqual); | 
 | 1177 |  | 
 | 1178 |   virtual IfCondition GetCondition() const { | 
 | 1179 |     return kCondNE; | 
 | 1180 |   } | 
 | 1181 |  | 
 | 1182 |  private: | 
 | 1183 |   DISALLOW_COPY_AND_ASSIGN(HNotEqual); | 
 | 1184 | }; | 
 | 1185 |  | 
 | 1186 | class HLessThan : public HCondition { | 
 | 1187 |  public: | 
 | 1188 |   HLessThan(HInstruction* first, HInstruction* second) | 
 | 1189 |       : HCondition(first, second) {} | 
 | 1190 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1191 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1192 |     return x < y ? 1 : 0; | 
 | 1193 |   } | 
 | 1194 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1195 |     return x < y ? 1 : 0; | 
 | 1196 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1197 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1198 |   DECLARE_INSTRUCTION(LessThan); | 
 | 1199 |  | 
 | 1200 |   virtual IfCondition GetCondition() const { | 
 | 1201 |     return kCondLT; | 
 | 1202 |   } | 
 | 1203 |  | 
 | 1204 |  private: | 
 | 1205 |   DISALLOW_COPY_AND_ASSIGN(HLessThan); | 
 | 1206 | }; | 
 | 1207 |  | 
 | 1208 | class HLessThanOrEqual : public HCondition { | 
 | 1209 |  public: | 
 | 1210 |   HLessThanOrEqual(HInstruction* first, HInstruction* second) | 
 | 1211 |       : HCondition(first, second) {} | 
 | 1212 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1213 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1214 |     return x <= y ? 1 : 0; | 
 | 1215 |   } | 
 | 1216 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1217 |     return x <= y ? 1 : 0; | 
 | 1218 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1219 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1220 |   DECLARE_INSTRUCTION(LessThanOrEqual); | 
 | 1221 |  | 
 | 1222 |   virtual IfCondition GetCondition() const { | 
 | 1223 |     return kCondLE; | 
 | 1224 |   } | 
 | 1225 |  | 
 | 1226 |  private: | 
 | 1227 |   DISALLOW_COPY_AND_ASSIGN(HLessThanOrEqual); | 
 | 1228 | }; | 
 | 1229 |  | 
 | 1230 | class HGreaterThan : public HCondition { | 
 | 1231 |  public: | 
 | 1232 |   HGreaterThan(HInstruction* first, HInstruction* second) | 
 | 1233 |       : HCondition(first, second) {} | 
 | 1234 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1235 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1236 |     return x > y ? 1 : 0; | 
 | 1237 |   } | 
 | 1238 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1239 |     return x > y ? 1 : 0; | 
 | 1240 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1241 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1242 |   DECLARE_INSTRUCTION(GreaterThan); | 
 | 1243 |  | 
 | 1244 |   virtual IfCondition GetCondition() const { | 
 | 1245 |     return kCondGT; | 
 | 1246 |   } | 
 | 1247 |  | 
 | 1248 |  private: | 
 | 1249 |   DISALLOW_COPY_AND_ASSIGN(HGreaterThan); | 
 | 1250 | }; | 
 | 1251 |  | 
 | 1252 | class HGreaterThanOrEqual : public HCondition { | 
 | 1253 |  public: | 
 | 1254 |   HGreaterThanOrEqual(HInstruction* first, HInstruction* second) | 
 | 1255 |       : HCondition(first, second) {} | 
 | 1256 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1257 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1258 |     return x >= y ? 1 : 0; | 
 | 1259 |   } | 
 | 1260 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1261 |     return x >= y ? 1 : 0; | 
 | 1262 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1263 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1264 |   DECLARE_INSTRUCTION(GreaterThanOrEqual); | 
 | 1265 |  | 
 | 1266 |   virtual IfCondition GetCondition() const { | 
 | 1267 |     return kCondGE; | 
 | 1268 |   } | 
 | 1269 |  | 
 | 1270 |  private: | 
 | 1271 |   DISALLOW_COPY_AND_ASSIGN(HGreaterThanOrEqual); | 
 | 1272 | }; | 
 | 1273 |  | 
 | 1274 |  | 
| Nicolas Geoffray | 412f10c | 2014-06-19 10:00:34 +0100 | [diff] [blame] | 1275 | // Instruction to check how two inputs compare to each other. | 
 | 1276 | // Result is 0 if input0 == input1, 1 if input0 > input1, or -1 if input0 < input1. | 
 | 1277 | class HCompare : public HBinaryOperation { | 
 | 1278 |  public: | 
 | 1279 |   HCompare(Primitive::Type type, HInstruction* first, HInstruction* second) | 
 | 1280 |       : HBinaryOperation(Primitive::kPrimInt, first, second) { | 
 | 1281 |     DCHECK_EQ(type, first->GetType()); | 
 | 1282 |     DCHECK_EQ(type, second->GetType()); | 
 | 1283 |   } | 
 | 1284 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1285 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1286 |     return | 
 | 1287 |       x == y ? 0 : | 
 | 1288 |       x > y ? 1 : | 
 | 1289 |       -1; | 
 | 1290 |   } | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1291 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1292 |     return | 
 | 1293 |       x == y ? 0 : | 
 | 1294 |       x > y ? 1 : | 
 | 1295 |       -1; | 
 | 1296 |   } | 
 | 1297 |  | 
| Nicolas Geoffray | 412f10c | 2014-06-19 10:00:34 +0100 | [diff] [blame] | 1298 |   DECLARE_INSTRUCTION(Compare); | 
 | 1299 |  | 
 | 1300 |  private: | 
 | 1301 |   DISALLOW_COPY_AND_ASSIGN(HCompare); | 
 | 1302 | }; | 
 | 1303 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1304 | // A local in the graph. Corresponds to a Dex register. | 
 | 1305 | class HLocal : public HTemplateInstruction<0> { | 
 | 1306 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1307 |   explicit HLocal(uint16_t reg_number) | 
 | 1308 |       : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {} | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1309 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1310 |   DECLARE_INSTRUCTION(Local); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1311 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 1312 |   uint16_t GetRegNumber() const { return reg_number_; } | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1313 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1314 |  private: | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1315 |   // The Dex register number. | 
 | 1316 |   const uint16_t reg_number_; | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1317 |  | 
 | 1318 |   DISALLOW_COPY_AND_ASSIGN(HLocal); | 
 | 1319 | }; | 
 | 1320 |  | 
 | 1321 | // Load a given local. The local is an input of this instruction. | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1322 | class HLoadLocal : public HExpression<1> { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1323 |  public: | 
| Roland Levillain | 5799fc0 | 2014-09-25 12:15:20 +0100 | [diff] [blame] | 1324 |   HLoadLocal(HLocal* local, Primitive::Type type) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1325 |       : HExpression(type, SideEffects::None()) { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1326 |     SetRawInputAt(0, local); | 
 | 1327 |   } | 
 | 1328 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1329 |   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } | 
 | 1330 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1331 |   DECLARE_INSTRUCTION(LoadLocal); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1332 |  | 
 | 1333 |  private: | 
 | 1334 |   DISALLOW_COPY_AND_ASSIGN(HLoadLocal); | 
 | 1335 | }; | 
 | 1336 |  | 
 | 1337 | // Store a value in a given local. This instruction has two inputs: the value | 
 | 1338 | // and the local. | 
 | 1339 | class HStoreLocal : public HTemplateInstruction<2> { | 
 | 1340 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1341 |   HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1342 |     SetRawInputAt(0, local); | 
 | 1343 |     SetRawInputAt(1, value); | 
 | 1344 |   } | 
 | 1345 |  | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1346 |   HLocal* GetLocal() const { return reinterpret_cast<HLocal*>(InputAt(0)); } | 
 | 1347 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1348 |   DECLARE_INSTRUCTION(StoreLocal); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1349 |  | 
 | 1350 |  private: | 
 | 1351 |   DISALLOW_COPY_AND_ASSIGN(HStoreLocal); | 
 | 1352 | }; | 
 | 1353 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1354 | class HConstant : public HExpression<0> { | 
 | 1355 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1356 |   explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {} | 
 | 1357 |  | 
 | 1358 |   virtual bool CanBeMoved() const { return true; } | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1359 |  | 
 | 1360 |   DECLARE_INSTRUCTION(Constant); | 
 | 1361 |  | 
 | 1362 |  private: | 
 | 1363 |   DISALLOW_COPY_AND_ASSIGN(HConstant); | 
 | 1364 | }; | 
 | 1365 |  | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1366 | // Constants of the type int. Those can be from Dex instructions, or | 
 | 1367 | // synthesized (for example with the if-eqz instruction). | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1368 | class HIntConstant : public HConstant { | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1369 |  public: | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1370 |   explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {} | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1371 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 1372 |   int32_t GetValue() const { return value_; } | 
| Nicolas Geoffray | bab4ed7 | 2014-03-11 17:53:17 +0000 | [diff] [blame] | 1373 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1374 |   virtual bool InstructionDataEquals(HInstruction* other) const { | 
 | 1375 |     return other->AsIntConstant()->value_ == value_; | 
 | 1376 |   } | 
 | 1377 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 1378 |   virtual size_t ComputeHashCode() const { return GetValue(); } | 
 | 1379 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1380 |   DECLARE_INSTRUCTION(IntConstant); | 
| Nicolas Geoffray | 3ff386a | 2014-03-04 14:46:47 +0000 | [diff] [blame] | 1381 |  | 
 | 1382 |  private: | 
 | 1383 |   const int32_t value_; | 
 | 1384 |  | 
 | 1385 |   DISALLOW_COPY_AND_ASSIGN(HIntConstant); | 
 | 1386 | }; | 
 | 1387 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1388 | class HLongConstant : public HConstant { | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1389 |  public: | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1390 |   explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {} | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1391 |  | 
 | 1392 |   int64_t GetValue() const { return value_; } | 
 | 1393 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1394 |   virtual bool InstructionDataEquals(HInstruction* other) const { | 
 | 1395 |     return other->AsLongConstant()->value_ == value_; | 
 | 1396 |   } | 
 | 1397 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 1398 |   virtual size_t ComputeHashCode() const { return static_cast<size_t>(GetValue()); } | 
 | 1399 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1400 |   DECLARE_INSTRUCTION(LongConstant); | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1401 |  | 
 | 1402 |  private: | 
 | 1403 |   const int64_t value_; | 
 | 1404 |  | 
 | 1405 |   DISALLOW_COPY_AND_ASSIGN(HLongConstant); | 
 | 1406 | }; | 
 | 1407 |  | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1408 | class HInvoke : public HInstruction { | 
 | 1409 |  public: | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1410 |   HInvoke(ArenaAllocator* arena, | 
 | 1411 |           uint32_t number_of_arguments, | 
 | 1412 |           Primitive::Type return_type, | 
 | 1413 |           uint32_t dex_pc) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1414 |     : HInstruction(SideEffects::All()), | 
 | 1415 |       inputs_(arena, number_of_arguments), | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1416 |       return_type_(return_type), | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1417 |       dex_pc_(dex_pc) { | 
 | 1418 |     inputs_.SetSize(number_of_arguments); | 
 | 1419 |   } | 
 | 1420 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1421 |   virtual size_t InputCount() const { return inputs_.Size(); } | 
 | 1422 |   virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); } | 
 | 1423 |  | 
 | 1424 |   // Runtime needs to walk the stack, so Dex -> Dex calls need to | 
 | 1425 |   // know their environment. | 
 | 1426 |   virtual bool NeedsEnvironment() const { return true; } | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1427 |  | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 1428 |   void SetArgumentAt(size_t index, HInstruction* argument) { | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1429 |     SetRawInputAt(index, argument); | 
 | 1430 |   } | 
 | 1431 |  | 
 | 1432 |   virtual void SetRawInputAt(size_t index, HInstruction* input) { | 
 | 1433 |     inputs_.Put(index, input); | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 1434 |   } | 
 | 1435 |  | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1436 |   virtual Primitive::Type GetType() const { return return_type_; } | 
 | 1437 |  | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1438 |   uint32_t GetDexPc() const { return dex_pc_; } | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1439 |  | 
 | 1440 |  protected: | 
 | 1441 |   GrowableArray<HInstruction*> inputs_; | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1442 |   const Primitive::Type return_type_; | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1443 |   const uint32_t dex_pc_; | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1444 |  | 
 | 1445 |  private: | 
 | 1446 |   DISALLOW_COPY_AND_ASSIGN(HInvoke); | 
 | 1447 | }; | 
 | 1448 |  | 
 | 1449 | class HInvokeStatic : public HInvoke { | 
 | 1450 |  public: | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 1451 |   HInvokeStatic(ArenaAllocator* arena, | 
 | 1452 |                 uint32_t number_of_arguments, | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1453 |                 Primitive::Type return_type, | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1454 |                 uint32_t dex_pc, | 
 | 1455 |                 uint32_t index_in_dex_cache) | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1456 |       : HInvoke(arena, number_of_arguments, return_type, dex_pc), | 
 | 1457 |         index_in_dex_cache_(index_in_dex_cache) {} | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1458 |  | 
 | 1459 |   uint32_t GetIndexInDexCache() const { return index_in_dex_cache_; } | 
 | 1460 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1461 |   DECLARE_INSTRUCTION(InvokeStatic); | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1462 |  | 
 | 1463 |  private: | 
| Nicolas Geoffray | 4a34a42 | 2014-04-03 10:38:37 +0100 | [diff] [blame] | 1464 |   const uint32_t index_in_dex_cache_; | 
| Nicolas Geoffray | 8ccc3f5 | 2014-03-19 10:34:11 +0000 | [diff] [blame] | 1465 |  | 
 | 1466 |   DISALLOW_COPY_AND_ASSIGN(HInvokeStatic); | 
 | 1467 | }; | 
 | 1468 |  | 
| Nicolas Geoffray | e982f0b | 2014-08-13 02:11:24 +0100 | [diff] [blame] | 1469 | class HInvokeVirtual : public HInvoke { | 
 | 1470 |  public: | 
 | 1471 |   HInvokeVirtual(ArenaAllocator* arena, | 
 | 1472 |                  uint32_t number_of_arguments, | 
 | 1473 |                  Primitive::Type return_type, | 
 | 1474 |                  uint32_t dex_pc, | 
 | 1475 |                  uint32_t vtable_index) | 
 | 1476 |       : HInvoke(arena, number_of_arguments, return_type, dex_pc), | 
 | 1477 |         vtable_index_(vtable_index) {} | 
 | 1478 |  | 
 | 1479 |   uint32_t GetVTableIndex() const { return vtable_index_; } | 
 | 1480 |  | 
 | 1481 |   DECLARE_INSTRUCTION(InvokeVirtual); | 
 | 1482 |  | 
 | 1483 |  private: | 
 | 1484 |   const uint32_t vtable_index_; | 
 | 1485 |  | 
 | 1486 |   DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual); | 
 | 1487 | }; | 
 | 1488 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1489 | class HNewInstance : public HExpression<0> { | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1490 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1491 |   HNewInstance(uint32_t dex_pc, uint16_t type_index) | 
 | 1492 |       : HExpression(Primitive::kPrimNot, SideEffects::None()), | 
 | 1493 |         dex_pc_(dex_pc), | 
 | 1494 |         type_index_(type_index) {} | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1495 |  | 
 | 1496 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 1497 |   uint16_t GetTypeIndex() const { return type_index_; } | 
 | 1498 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1499 |   // Calls runtime so needs an environment. | 
 | 1500 |   virtual bool NeedsEnvironment() const { return true; } | 
 | 1501 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1502 |   DECLARE_INSTRUCTION(NewInstance); | 
| Nicolas Geoffray | 2e7038a | 2014-04-03 18:49:58 +0100 | [diff] [blame] | 1503 |  | 
 | 1504 |  private: | 
 | 1505 |   const uint32_t dex_pc_; | 
 | 1506 |   const uint16_t type_index_; | 
 | 1507 |  | 
 | 1508 |   DISALLOW_COPY_AND_ASSIGN(HNewInstance); | 
 | 1509 | }; | 
 | 1510 |  | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1511 | class HAdd : public HBinaryOperation { | 
 | 1512 |  public: | 
 | 1513 |   HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right) | 
 | 1514 |       : HBinaryOperation(result_type, left, right) {} | 
 | 1515 |  | 
 | 1516 |   virtual bool IsCommutative() { return true; } | 
 | 1517 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1518 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1519 |     return x + y; | 
 | 1520 |   } | 
 | 1521 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1522 |     return x + y; | 
 | 1523 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1524 |  | 
| Nicolas Geoffray | d8ee737 | 2014-03-28 15:43:40 +0000 | [diff] [blame] | 1525 |   DECLARE_INSTRUCTION(Add); | 
 | 1526 |  | 
 | 1527 |  private: | 
 | 1528 |   DISALLOW_COPY_AND_ASSIGN(HAdd); | 
 | 1529 | }; | 
 | 1530 |  | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 1531 | class HSub : public HBinaryOperation { | 
 | 1532 |  public: | 
 | 1533 |   HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right) | 
 | 1534 |       : HBinaryOperation(result_type, left, right) {} | 
 | 1535 |  | 
 | 1536 |   virtual bool IsCommutative() { return false; } | 
 | 1537 |  | 
| Roland Levillain | 9344568 | 2014-10-06 19:24:02 +0100 | [diff] [blame] | 1538 |   virtual int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { | 
 | 1539 |     return x - y; | 
 | 1540 |   } | 
 | 1541 |   virtual int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { | 
 | 1542 |     return x - y; | 
 | 1543 |   } | 
| Roland Levillain | 556c3d1 | 2014-09-18 15:25:07 +0100 | [diff] [blame] | 1544 |  | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 1545 |   DECLARE_INSTRUCTION(Sub); | 
 | 1546 |  | 
 | 1547 |  private: | 
 | 1548 |   DISALLOW_COPY_AND_ASSIGN(HSub); | 
 | 1549 | }; | 
 | 1550 |  | 
 | 1551 | // The value of a parameter in this method. Its location depends on | 
 | 1552 | // the calling convention. | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1553 | class HParameterValue : public HExpression<0> { | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 1554 |  public: | 
| Nicolas Geoffray | 01bc96d | 2014-04-11 17:43:50 +0100 | [diff] [blame] | 1555 |   HParameterValue(uint8_t index, Primitive::Type parameter_type) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1556 |       : HExpression(parameter_type, SideEffects::None()), index_(index) {} | 
| Nicolas Geoffray | f583e59 | 2014-04-07 13:20:42 +0100 | [diff] [blame] | 1557 |  | 
 | 1558 |   uint8_t GetIndex() const { return index_; } | 
 | 1559 |  | 
 | 1560 |   DECLARE_INSTRUCTION(ParameterValue); | 
 | 1561 |  | 
 | 1562 |  private: | 
 | 1563 |   // The index of this parameter in the parameters list. Must be less | 
 | 1564 |   // than HGraph::number_of_in_vregs_; | 
 | 1565 |   const uint8_t index_; | 
 | 1566 |  | 
 | 1567 |   DISALLOW_COPY_AND_ASSIGN(HParameterValue); | 
 | 1568 | }; | 
 | 1569 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1570 | class HNot : public HExpression<1> { | 
| Nicolas Geoffray | b55f835 | 2014-04-07 15:26:35 +0100 | [diff] [blame] | 1571 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1572 |   explicit HNot(HInstruction* input) : HExpression(Primitive::kPrimBoolean, SideEffects::None()) { | 
| Nicolas Geoffray | b55f835 | 2014-04-07 15:26:35 +0100 | [diff] [blame] | 1573 |     SetRawInputAt(0, input); | 
 | 1574 |   } | 
 | 1575 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1576 |   virtual bool CanBeMoved() const { return true; } | 
 | 1577 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1578 |  | 
| Nicolas Geoffray | b55f835 | 2014-04-07 15:26:35 +0100 | [diff] [blame] | 1579 |   DECLARE_INSTRUCTION(Not); | 
 | 1580 |  | 
 | 1581 |  private: | 
 | 1582 |   DISALLOW_COPY_AND_ASSIGN(HNot); | 
 | 1583 | }; | 
 | 1584 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1585 | class HPhi : public HInstruction { | 
 | 1586 |  public: | 
 | 1587 |   HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1588 |       : HInstruction(SideEffects::None()), | 
 | 1589 |         inputs_(arena, number_of_inputs), | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1590 |         reg_number_(reg_number), | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 1591 |         type_(type), | 
 | 1592 |         is_live_(false) { | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1593 |     inputs_.SetSize(number_of_inputs); | 
 | 1594 |   } | 
 | 1595 |  | 
 | 1596 |   virtual size_t InputCount() const { return inputs_.Size(); } | 
 | 1597 |   virtual HInstruction* InputAt(size_t i) const { return inputs_.Get(i); } | 
 | 1598 |  | 
 | 1599 |   virtual void SetRawInputAt(size_t index, HInstruction* input) { | 
 | 1600 |     inputs_.Put(index, input); | 
 | 1601 |   } | 
 | 1602 |  | 
 | 1603 |   void AddInput(HInstruction* input); | 
 | 1604 |  | 
 | 1605 |   virtual Primitive::Type GetType() const { return type_; } | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1606 |   void SetType(Primitive::Type type) { type_ = type; } | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1607 |  | 
 | 1608 |   uint32_t GetRegNumber() const { return reg_number_; } | 
 | 1609 |  | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 1610 |   void SetDead() { is_live_ = false; } | 
 | 1611 |   void SetLive() { is_live_ = true; } | 
 | 1612 |   bool IsDead() const { return !is_live_; } | 
 | 1613 |   bool IsLive() const { return is_live_; } | 
 | 1614 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1615 |   DECLARE_INSTRUCTION(Phi); | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1616 |  | 
| Nicolas Geoffray | 96f89a2 | 2014-07-11 10:57:49 +0100 | [diff] [blame] | 1617 |  private: | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1618 |   GrowableArray<HInstruction*> inputs_; | 
 | 1619 |   const uint32_t reg_number_; | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1620 |   Primitive::Type type_; | 
| Nicolas Geoffray | 7dc206a | 2014-07-11 09:49:49 +0100 | [diff] [blame] | 1621 |   bool is_live_; | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1622 |  | 
| Nicolas Geoffray | c32e770 | 2014-04-24 12:43:16 +0100 | [diff] [blame] | 1623 |   DISALLOW_COPY_AND_ASSIGN(HPhi); | 
 | 1624 | }; | 
 | 1625 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1626 | class HNullCheck : public HExpression<1> { | 
 | 1627 |  public: | 
 | 1628 |   HNullCheck(HInstruction* value, uint32_t dex_pc) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1629 |       : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) { | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1630 |     SetRawInputAt(0, value); | 
 | 1631 |   } | 
 | 1632 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1633 |   virtual bool CanBeMoved() const { return true; } | 
 | 1634 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1635 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1636 |   virtual bool NeedsEnvironment() const { return true; } | 
 | 1637 |  | 
 | 1638 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 1639 |  | 
 | 1640 |   DECLARE_INSTRUCTION(NullCheck); | 
 | 1641 |  | 
 | 1642 |  private: | 
 | 1643 |   const uint32_t dex_pc_; | 
 | 1644 |  | 
 | 1645 |   DISALLOW_COPY_AND_ASSIGN(HNullCheck); | 
 | 1646 | }; | 
 | 1647 |  | 
 | 1648 | class FieldInfo : public ValueObject { | 
 | 1649 |  public: | 
| Roland Levillain | 5799fc0 | 2014-09-25 12:15:20 +0100 | [diff] [blame] | 1650 |   FieldInfo(MemberOffset field_offset, Primitive::Type field_type) | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1651 |       : field_offset_(field_offset), field_type_(field_type) {} | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1652 |  | 
 | 1653 |   MemberOffset GetFieldOffset() const { return field_offset_; } | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1654 |   Primitive::Type GetFieldType() const { return field_type_; } | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1655 |  | 
 | 1656 |  private: | 
 | 1657 |   const MemberOffset field_offset_; | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1658 |   const Primitive::Type field_type_; | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1659 | }; | 
 | 1660 |  | 
 | 1661 | class HInstanceFieldGet : public HExpression<1> { | 
 | 1662 |  public: | 
 | 1663 |   HInstanceFieldGet(HInstruction* value, | 
 | 1664 |                     Primitive::Type field_type, | 
 | 1665 |                     MemberOffset field_offset) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1666 |       : HExpression(field_type, SideEffects::DependsOnSomething()), | 
 | 1667 |         field_info_(field_offset, field_type) { | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1668 |     SetRawInputAt(0, value); | 
 | 1669 |   } | 
 | 1670 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1671 |   virtual bool CanBeMoved() const { return true; } | 
 | 1672 |   virtual bool InstructionDataEquals(HInstruction* other) const { | 
 | 1673 |     size_t other_offset = other->AsInstanceFieldGet()->GetFieldOffset().SizeValue(); | 
 | 1674 |     return other_offset == GetFieldOffset().SizeValue(); | 
 | 1675 |   } | 
 | 1676 |  | 
| Nicolas Geoffray | d31cf3d | 2014-09-08 17:30:24 +0100 | [diff] [blame] | 1677 |   virtual size_t ComputeHashCode() const { | 
 | 1678 |     return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue(); | 
 | 1679 |   } | 
 | 1680 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1681 |   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1682 |   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1683 |  | 
 | 1684 |   DECLARE_INSTRUCTION(InstanceFieldGet); | 
 | 1685 |  | 
 | 1686 |  private: | 
 | 1687 |   const FieldInfo field_info_; | 
 | 1688 |  | 
 | 1689 |   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldGet); | 
 | 1690 | }; | 
 | 1691 |  | 
 | 1692 | class HInstanceFieldSet : public HTemplateInstruction<2> { | 
 | 1693 |  public: | 
 | 1694 |   HInstanceFieldSet(HInstruction* object, | 
 | 1695 |                     HInstruction* value, | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1696 |                     Primitive::Type field_type, | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1697 |                     MemberOffset field_offset) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1698 |       : HTemplateInstruction(SideEffects::ChangesSomething()), | 
 | 1699 |         field_info_(field_offset, field_type) { | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1700 |     SetRawInputAt(0, object); | 
 | 1701 |     SetRawInputAt(1, value); | 
 | 1702 |   } | 
 | 1703 |  | 
 | 1704 |   MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1705 |   Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1706 |  | 
 | 1707 |   DECLARE_INSTRUCTION(InstanceFieldSet); | 
 | 1708 |  | 
 | 1709 |  private: | 
 | 1710 |   const FieldInfo field_info_; | 
 | 1711 |  | 
 | 1712 |   DISALLOW_COPY_AND_ASSIGN(HInstanceFieldSet); | 
 | 1713 | }; | 
 | 1714 |  | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1715 | class HArrayGet : public HExpression<2> { | 
 | 1716 |  public: | 
 | 1717 |   HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1718 |       : HExpression(type, SideEffects::DependsOnSomething()) { | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1719 |     SetRawInputAt(0, array); | 
 | 1720 |     SetRawInputAt(1, index); | 
 | 1721 |   } | 
 | 1722 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1723 |   virtual bool CanBeMoved() const { return true; } | 
 | 1724 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1725 |  | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1726 |   DECLARE_INSTRUCTION(ArrayGet); | 
 | 1727 |  | 
 | 1728 |  private: | 
 | 1729 |   DISALLOW_COPY_AND_ASSIGN(HArrayGet); | 
 | 1730 | }; | 
 | 1731 |  | 
 | 1732 | class HArraySet : public HTemplateInstruction<3> { | 
 | 1733 |  public: | 
 | 1734 |   HArraySet(HInstruction* array, | 
 | 1735 |             HInstruction* index, | 
 | 1736 |             HInstruction* value, | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1737 |             Primitive::Type component_type, | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1738 |             uint32_t dex_pc) | 
 | 1739 |       : HTemplateInstruction(SideEffects::ChangesSomething()), | 
 | 1740 |         dex_pc_(dex_pc), | 
 | 1741 |         component_type_(component_type) { | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1742 |     SetRawInputAt(0, array); | 
 | 1743 |     SetRawInputAt(1, index); | 
 | 1744 |     SetRawInputAt(2, value); | 
 | 1745 |   } | 
 | 1746 |  | 
 | 1747 |   virtual bool NeedsEnvironment() const { | 
 | 1748 |     // We currently always call a runtime method to catch array store | 
 | 1749 |     // exceptions. | 
 | 1750 |     return InputAt(2)->GetType() == Primitive::kPrimNot; | 
 | 1751 |   } | 
 | 1752 |  | 
 | 1753 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 1754 |  | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1755 |   Primitive::Type GetComponentType() const { return component_type_; } | 
 | 1756 |  | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1757 |   DECLARE_INSTRUCTION(ArraySet); | 
 | 1758 |  | 
 | 1759 |  private: | 
 | 1760 |   const uint32_t dex_pc_; | 
| Nicolas Geoffray | 3946844 | 2014-09-02 15:17:15 +0100 | [diff] [blame] | 1761 |   const Primitive::Type component_type_; | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1762 |  | 
 | 1763 |   DISALLOW_COPY_AND_ASSIGN(HArraySet); | 
 | 1764 | }; | 
 | 1765 |  | 
 | 1766 | class HArrayLength : public HExpression<1> { | 
 | 1767 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1768 |   explicit HArrayLength(HInstruction* array) | 
 | 1769 |       : HExpression(Primitive::kPrimInt, SideEffects::None()) { | 
 | 1770 |     // Note that arrays do not change length, so the instruction does not | 
 | 1771 |     // depend on any write. | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1772 |     SetRawInputAt(0, array); | 
 | 1773 |   } | 
 | 1774 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1775 |   virtual bool CanBeMoved() const { return true; } | 
 | 1776 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1777 |  | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1778 |   DECLARE_INSTRUCTION(ArrayLength); | 
 | 1779 |  | 
 | 1780 |  private: | 
 | 1781 |   DISALLOW_COPY_AND_ASSIGN(HArrayLength); | 
 | 1782 | }; | 
 | 1783 |  | 
 | 1784 | class HBoundsCheck : public HExpression<2> { | 
 | 1785 |  public: | 
 | 1786 |   HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc) | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1787 |       : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) { | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1788 |     DCHECK(index->GetType() == Primitive::kPrimInt); | 
 | 1789 |     SetRawInputAt(0, index); | 
 | 1790 |     SetRawInputAt(1, length); | 
 | 1791 |   } | 
 | 1792 |  | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1793 |   virtual bool CanBeMoved() const { return true; } | 
 | 1794 |   virtual bool InstructionDataEquals(HInstruction* other) const { return true; } | 
 | 1795 |  | 
| Nicolas Geoffray | 3c7bb98 | 2014-07-23 16:04:16 +0100 | [diff] [blame] | 1796 |   virtual bool NeedsEnvironment() const { return true; } | 
 | 1797 |  | 
 | 1798 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 1799 |  | 
 | 1800 |   DECLARE_INSTRUCTION(BoundsCheck); | 
 | 1801 |  | 
 | 1802 |  private: | 
 | 1803 |   const uint32_t dex_pc_; | 
 | 1804 |  | 
 | 1805 |   DISALLOW_COPY_AND_ASSIGN(HBoundsCheck); | 
 | 1806 | }; | 
 | 1807 |  | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1808 | /** | 
 | 1809 |  * Some DEX instructions are folded into multiple HInstructions that need | 
 | 1810 |  * to stay live until the last HInstruction. This class | 
 | 1811 |  * is used as a marker for the baseline compiler to ensure its preceding | 
 | 1812 |  * HInstruction stays live. `index` is the temporary number that is used | 
 | 1813 |  * for knowing the stack offset where to store the instruction. | 
 | 1814 |  */ | 
 | 1815 | class HTemporary : public HTemplateInstruction<0> { | 
 | 1816 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1817 |   explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {} | 
| Nicolas Geoffray | e503832 | 2014-07-04 09:41:32 +0100 | [diff] [blame] | 1818 |  | 
 | 1819 |   size_t GetIndex() const { return index_; } | 
 | 1820 |  | 
 | 1821 |   DECLARE_INSTRUCTION(Temporary); | 
 | 1822 |  | 
 | 1823 |  private: | 
 | 1824 |   const size_t index_; | 
 | 1825 |  | 
 | 1826 |   DISALLOW_COPY_AND_ASSIGN(HTemporary); | 
 | 1827 | }; | 
 | 1828 |  | 
| Nicolas Geoffray | fbc695f | 2014-09-15 15:33:30 +0000 | [diff] [blame] | 1829 | class HSuspendCheck : public HTemplateInstruction<0> { | 
 | 1830 |  public: | 
 | 1831 |   explicit HSuspendCheck(uint32_t dex_pc) | 
| Nicolas Geoffray | 9ebc72c | 2014-09-25 16:33:42 +0100 | [diff] [blame] | 1832 |       : HTemplateInstruction(SideEffects::None()), dex_pc_(dex_pc) {} | 
| Nicolas Geoffray | fbc695f | 2014-09-15 15:33:30 +0000 | [diff] [blame] | 1833 |  | 
 | 1834 |   virtual bool NeedsEnvironment() const { | 
 | 1835 |     return true; | 
 | 1836 |   } | 
 | 1837 |  | 
 | 1838 |   uint32_t GetDexPc() const { return dex_pc_; } | 
 | 1839 |  | 
 | 1840 |   DECLARE_INSTRUCTION(SuspendCheck); | 
 | 1841 |  | 
 | 1842 |  private: | 
 | 1843 |   const uint32_t dex_pc_; | 
 | 1844 |  | 
 | 1845 |   DISALLOW_COPY_AND_ASSIGN(HSuspendCheck); | 
 | 1846 | }; | 
 | 1847 |  | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1848 | class MoveOperands : public ArenaObject { | 
 | 1849 |  public: | 
| Nicolas Geoffray | 740475d | 2014-09-29 10:33:25 +0100 | [diff] [blame] | 1850 |   MoveOperands(Location source, Location destination, HInstruction* instruction) | 
 | 1851 |       : source_(source), destination_(destination), instruction_(instruction) {} | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1852 |  | 
 | 1853 |   Location GetSource() const { return source_; } | 
 | 1854 |   Location GetDestination() const { return destination_; } | 
 | 1855 |  | 
 | 1856 |   void SetSource(Location value) { source_ = value; } | 
 | 1857 |   void SetDestination(Location value) { destination_ = value; } | 
 | 1858 |  | 
 | 1859 |   // The parallel move resolver marks moves as "in-progress" by clearing the | 
 | 1860 |   // destination (but not the source). | 
 | 1861 |   Location MarkPending() { | 
 | 1862 |     DCHECK(!IsPending()); | 
 | 1863 |     Location dest = destination_; | 
 | 1864 |     destination_ = Location::NoLocation(); | 
 | 1865 |     return dest; | 
 | 1866 |   } | 
 | 1867 |  | 
 | 1868 |   void ClearPending(Location dest) { | 
 | 1869 |     DCHECK(IsPending()); | 
 | 1870 |     destination_ = dest; | 
 | 1871 |   } | 
 | 1872 |  | 
 | 1873 |   bool IsPending() const { | 
 | 1874 |     DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); | 
 | 1875 |     return destination_.IsInvalid() && !source_.IsInvalid(); | 
 | 1876 |   } | 
 | 1877 |  | 
 | 1878 |   // True if this blocks a move from the given location. | 
 | 1879 |   bool Blocks(Location loc) const { | 
 | 1880 |     return !IsEliminated() && source_.Equals(loc); | 
 | 1881 |   } | 
 | 1882 |  | 
 | 1883 |   // A move is redundant if it's been eliminated, if its source and | 
 | 1884 |   // destination are the same, or if its destination is unneeded. | 
 | 1885 |   bool IsRedundant() const { | 
 | 1886 |     return IsEliminated() || destination_.IsInvalid() || source_.Equals(destination_); | 
 | 1887 |   } | 
 | 1888 |  | 
 | 1889 |   // We clear both operands to indicate move that's been eliminated. | 
 | 1890 |   void Eliminate() { | 
 | 1891 |     source_ = destination_ = Location::NoLocation(); | 
 | 1892 |   } | 
 | 1893 |  | 
 | 1894 |   bool IsEliminated() const { | 
 | 1895 |     DCHECK(!source_.IsInvalid() || destination_.IsInvalid()); | 
 | 1896 |     return source_.IsInvalid(); | 
 | 1897 |   } | 
 | 1898 |  | 
| Nicolas Geoffray | 740475d | 2014-09-29 10:33:25 +0100 | [diff] [blame] | 1899 |   HInstruction* GetInstruction() const { return instruction_; } | 
 | 1900 |  | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1901 |  private: | 
 | 1902 |   Location source_; | 
 | 1903 |   Location destination_; | 
| Nicolas Geoffray | 740475d | 2014-09-29 10:33:25 +0100 | [diff] [blame] | 1904 |   // The instruction this move is assocatied with. Null when this move is | 
 | 1905 |   // for moving an input in the expected locations of user (including a phi user). | 
 | 1906 |   // This is only used in debug mode, to ensure we do not connect interval siblings | 
 | 1907 |   // in the same parallel move. | 
 | 1908 |   HInstruction* instruction_; | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1909 |  | 
 | 1910 |   DISALLOW_COPY_AND_ASSIGN(MoveOperands); | 
 | 1911 | }; | 
 | 1912 |  | 
 | 1913 | static constexpr size_t kDefaultNumberOfMoves = 4; | 
 | 1914 |  | 
 | 1915 | class HParallelMove : public HTemplateInstruction<0> { | 
 | 1916 |  public: | 
| Nicolas Geoffray | 065bf77 | 2014-09-03 14:51:22 +0100 | [diff] [blame] | 1917 |   explicit HParallelMove(ArenaAllocator* arena) | 
 | 1918 |       : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {} | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1919 |  | 
 | 1920 |   void AddMove(MoveOperands* move) { | 
| Nicolas Geoffray | 740475d | 2014-09-29 10:33:25 +0100 | [diff] [blame] | 1921 |     if (kIsDebugBuild && move->GetInstruction() != nullptr) { | 
 | 1922 |       for (size_t i = 0, e = moves_.Size(); i < e; ++i) { | 
 | 1923 |         DCHECK_NE(moves_.Get(i)->GetInstruction(), move->GetInstruction()) | 
 | 1924 |           << "Doing parallel moves for the same instruction."; | 
 | 1925 |       } | 
 | 1926 |     } | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1927 |     moves_.Add(move); | 
 | 1928 |   } | 
 | 1929 |  | 
 | 1930 |   MoveOperands* MoveOperandsAt(size_t index) const { | 
 | 1931 |     return moves_.Get(index); | 
 | 1932 |   } | 
 | 1933 |  | 
 | 1934 |   size_t NumMoves() const { return moves_.Size(); } | 
 | 1935 |  | 
| Nicolas Geoffray | a7062e0 | 2014-05-22 12:50:17 +0100 | [diff] [blame] | 1936 |   DECLARE_INSTRUCTION(ParallelMove); | 
| Nicolas Geoffray | 4e3d23a | 2014-05-22 18:32:45 +0100 | [diff] [blame] | 1937 |  | 
 | 1938 |  private: | 
 | 1939 |   GrowableArray<MoveOperands*> moves_; | 
 | 1940 |  | 
 | 1941 |   DISALLOW_COPY_AND_ASSIGN(HParallelMove); | 
 | 1942 | }; | 
 | 1943 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1944 | class HGraphVisitor : public ValueObject { | 
 | 1945 |  public: | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1946 |   explicit HGraphVisitor(HGraph* graph) : graph_(graph) {} | 
 | 1947 |   virtual ~HGraphVisitor() {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1948 |  | 
| Dave Allison | 20dfc79 | 2014-06-16 20:44:29 -0700 | [diff] [blame] | 1949 |   virtual void VisitInstruction(HInstruction* instruction) {} | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1950 |   virtual void VisitBasicBlock(HBasicBlock* block); | 
 | 1951 |  | 
 | 1952 |   void VisitInsertionOrder(); | 
 | 1953 |  | 
| Nicolas Geoffray | 787c307 | 2014-03-17 10:20:19 +0000 | [diff] [blame] | 1954 |   HGraph* GetGraph() const { return graph_; } | 
| Nicolas Geoffray | d4dd255 | 2014-02-28 10:23:58 +0000 | [diff] [blame] | 1955 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 1956 |   // Visit functions for instruction classes. | 
 | 1957 | #define DECLARE_VISIT_INSTRUCTION(name)                                        \ | 
 | 1958 |   virtual void Visit##name(H##name* instr) { VisitInstruction(instr); } | 
 | 1959 |  | 
 | 1960 |   FOR_EACH_INSTRUCTION(DECLARE_VISIT_INSTRUCTION) | 
 | 1961 |  | 
 | 1962 | #undef DECLARE_VISIT_INSTRUCTION | 
 | 1963 |  | 
 | 1964 |  private: | 
 | 1965 |   HGraph* graph_; | 
 | 1966 |  | 
 | 1967 |   DISALLOW_COPY_AND_ASSIGN(HGraphVisitor); | 
 | 1968 | }; | 
 | 1969 |  | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 1970 | class HInsertionOrderIterator : public ValueObject { | 
 | 1971 |  public: | 
 | 1972 |   explicit HInsertionOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {} | 
 | 1973 |  | 
 | 1974 |   bool Done() const { return index_ == graph_.GetBlocks().Size(); } | 
 | 1975 |   HBasicBlock* Current() const { return graph_.GetBlocks().Get(index_); } | 
 | 1976 |   void Advance() { ++index_; } | 
 | 1977 |  | 
 | 1978 |  private: | 
 | 1979 |   const HGraph& graph_; | 
 | 1980 |   size_t index_; | 
 | 1981 |  | 
 | 1982 |   DISALLOW_COPY_AND_ASSIGN(HInsertionOrderIterator); | 
 | 1983 | }; | 
 | 1984 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1985 | class HReversePostOrderIterator : public ValueObject { | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 1986 |  public: | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1987 |   explicit HReversePostOrderIterator(const HGraph& graph) : graph_(graph), index_(0) {} | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 1988 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1989 |   bool Done() const { return index_ == graph_.GetReversePostOrder().Size(); } | 
 | 1990 |   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_); } | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 1991 |   void Advance() { ++index_; } | 
 | 1992 |  | 
 | 1993 |  private: | 
 | 1994 |   const HGraph& graph_; | 
 | 1995 |   size_t index_; | 
 | 1996 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 1997 |   DISALLOW_COPY_AND_ASSIGN(HReversePostOrderIterator); | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 1998 | }; | 
 | 1999 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 2000 | class HPostOrderIterator : public ValueObject { | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 2001 |  public: | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 2002 |   explicit HPostOrderIterator(const HGraph& graph) | 
 | 2003 |       : graph_(graph), index_(graph_.GetReversePostOrder().Size()) {} | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 2004 |  | 
 | 2005 |   bool Done() const { return index_ == 0; } | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 2006 |   HBasicBlock* Current() const { return graph_.GetReversePostOrder().Get(index_ - 1); } | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 2007 |   void Advance() { --index_; } | 
 | 2008 |  | 
 | 2009 |  private: | 
 | 2010 |   const HGraph& graph_; | 
 | 2011 |   size_t index_; | 
 | 2012 |  | 
| Nicolas Geoffray | 622d9c3 | 2014-05-12 16:11:02 +0100 | [diff] [blame] | 2013 |   DISALLOW_COPY_AND_ASSIGN(HPostOrderIterator); | 
| Nicolas Geoffray | 804d093 | 2014-05-02 08:46:00 +0100 | [diff] [blame] | 2014 | }; | 
 | 2015 |  | 
| Nicolas Geoffray | 818f210 | 2014-02-18 16:43:35 +0000 | [diff] [blame] | 2016 | }  // namespace art | 
 | 2017 |  | 
 | 2018 | #endif  // ART_COMPILER_OPTIMIZING_NODES_H_ |