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