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