diff options
Diffstat (limited to 'compiler/optimizing')
| -rw-r--r-- | compiler/optimizing/bounds_check_elimination.cc | 26 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier_arm.h | 2 | ||||
| -rw-r--r-- | compiler/optimizing/instruction_simplifier_arm64.h | 7 | ||||
| -rw-r--r-- | compiler/optimizing/loop_optimization.cc | 42 | ||||
| -rw-r--r-- | compiler/optimizing/loop_optimization.h | 4 |
5 files changed, 57 insertions, 24 deletions
diff --git a/compiler/optimizing/bounds_check_elimination.cc b/compiler/optimizing/bounds_check_elimination.cc index d2357a5d05..7dc094b25f 100644 --- a/compiler/optimizing/bounds_check_elimination.cc +++ b/compiler/optimizing/bounds_check_elimination.cc @@ -548,7 +548,21 @@ class BCEVisitor : public HGraphVisitor { void VisitBasicBlock(HBasicBlock* block) OVERRIDE { DCHECK(!IsAddedBlock(block)); first_index_bounds_check_map_.clear(); - HGraphVisitor::VisitBasicBlock(block); + // Visit phis and instructions using a safe iterator. The iteration protects + // against deleting the current instruction during iteration. However, it + // must advance next_ if that instruction is deleted during iteration. + for (HInstruction* instruction = block->GetFirstPhi(); instruction != nullptr;) { + DCHECK(instruction->IsInBlock()); + next_ = instruction->GetNext(); + instruction->Accept(this); + instruction = next_; + } + for (HInstruction* instruction = block->GetFirstInstruction(); instruction != nullptr;) { + DCHECK(instruction->IsInBlock()); + next_ = instruction->GetNext(); + instruction->Accept(this); + instruction = next_; + } // We should never deoptimize from an osr method, otherwise we might wrongly optimize // code dominated by the deoptimization. if (!GetGraph()->IsCompilingOsr()) { @@ -1798,7 +1812,12 @@ class BCEVisitor : public HGraphVisitor { } /** Helper method to replace an instruction with another instruction. */ - static void ReplaceInstruction(HInstruction* instruction, HInstruction* replacement) { + void ReplaceInstruction(HInstruction* instruction, HInstruction* replacement) { + // Safe iteration. + if (instruction == next_) { + next_ = next_->GetNext(); + } + // Replace and remove. instruction->ReplaceWith(replacement); instruction->GetBlock()->RemoveInstruction(instruction); } @@ -1831,6 +1850,9 @@ class BCEVisitor : public HGraphVisitor { // Range analysis based on induction variables. InductionVarRange induction_range_; + // Safe iteration. + HInstruction* next_; + DISALLOW_COPY_AND_ASSIGN(BCEVisitor); }; diff --git a/compiler/optimizing/instruction_simplifier_arm.h b/compiler/optimizing/instruction_simplifier_arm.h index 782110c40a..9b54511340 100644 --- a/compiler/optimizing/instruction_simplifier_arm.h +++ b/compiler/optimizing/instruction_simplifier_arm.h @@ -48,7 +48,7 @@ class InstructionSimplifierArmVisitor : public HGraphVisitor { class InstructionSimplifierArm : public HOptimization { public: InstructionSimplifierArm(HGraph* graph, OptimizingCompilerStats* stats) - : HOptimization(graph, kInstructionSimplifierArmPassName, stats) {} + : HOptimization(graph, kInstructionSimplifierArmPassName, stats) {} static constexpr const char* kInstructionSimplifierArmPassName = "instruction_simplifier_arm"; diff --git a/compiler/optimizing/instruction_simplifier_arm64.h b/compiler/optimizing/instruction_simplifier_arm64.h index f71684efe9..d4cb1f14b7 100644 --- a/compiler/optimizing/instruction_simplifier_arm64.h +++ b/compiler/optimizing/instruction_simplifier_arm64.h @@ -82,9 +82,10 @@ class InstructionSimplifierArm64Visitor : public HGraphVisitor { class InstructionSimplifierArm64 : public HOptimization { public: InstructionSimplifierArm64(HGraph* graph, OptimizingCompilerStats* stats) - : HOptimization(graph, kInstructionSimplifierArm64PassName, stats) {} - static constexpr const char* kInstructionSimplifierArm64PassName - = "instruction_simplifier_arm64"; + : HOptimization(graph, kInstructionSimplifierArm64PassName, stats) {} + + static constexpr const char* kInstructionSimplifierArm64PassName = "instruction_simplifier_arm64"; + void Run() OVERRIDE { InstructionSimplifierArm64Visitor visitor(graph_, stats_); visitor.VisitReversePostOrder(); diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index 55e1a2c409..f4616e39e6 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -28,7 +28,7 @@ static void RemoveFromCycle(HInstruction* instruction) { instruction->GetBlock()->RemoveInstructionOrPhi(instruction, /*ensure_safety=*/ false); } -// Detects a goto block and sets succ to the single successor. +// Detect a goto block and sets succ to the single successor. static bool IsGotoBlock(HBasicBlock* block, /*out*/ HBasicBlock** succ) { if (block->GetPredecessors().size() == 1 && block->GetSuccessors().size() == 1 && @@ -39,6 +39,19 @@ static bool IsGotoBlock(HBasicBlock* block, /*out*/ HBasicBlock** succ) { return false; } +// Detect an early exit loop. +static bool IsEarlyExit(HLoopInformation* loop_info) { + HBlocksInLoopReversePostOrderIterator it_loop(*loop_info); + for (it_loop.Advance(); !it_loop.Done(); it_loop.Advance()) { + for (HBasicBlock* successor : it_loop.Current()->GetSuccessors()) { + if (!loop_info->Contains(*successor)) { + return true; + } + } + } + return false; +} + // // Class methods. // @@ -179,7 +192,9 @@ void HLoopOptimization::SimplifyInduction(LoopNode* node) { int32_t use_count = 0; if (IsPhiInduction(phi) && IsOnlyUsedAfterLoop(node->loop_info, phi, &use_count) && - TryReplaceWithLastValue(phi, use_count, preheader)) { + // No uses, or no early-exit with proper replacement. + (use_count == 0 || + (!IsEarlyExit(node->loop_info) && TryReplaceWithLastValue(phi, preheader)))) { for (HInstruction* i : *iset_) { RemoveFromCycle(i); } @@ -277,7 +292,8 @@ void HLoopOptimization::RemoveIfEmptyInnerLoop(LoopNode* node) { if (IsEmptyHeader(header) && IsEmptyBody(body) && IsOnlyUsedAfterLoop(node->loop_info, header->GetFirstPhi(), &use_count) && - TryReplaceWithLastValue(header->GetFirstPhi(), use_count, preheader)) { + // No uses, or proper replacement. + (use_count == 0 || TryReplaceWithLastValue(header->GetFirstPhi(), preheader))) { body->DisconnectAndDelete(); exit->RemovePredecessor(header); header->RemoveSuccessor(exit); @@ -395,20 +411,16 @@ void HLoopOptimization::ReplaceAllUses(HInstruction* instruction, HInstruction* } } -bool HLoopOptimization::TryReplaceWithLastValue(HInstruction* instruction, - int32_t use_count, - HBasicBlock* block) { - // If true uses appear after the loop, replace these uses with the last value. Environment - // uses can consume this value too, since any first true use is outside the loop (although - // this may imply that de-opting may look "ahead" a bit on the phi value). If there are only - // environment uses, the value is dropped altogether, since the computations have no effect. - if (use_count > 0) { - if (!induction_range_.CanGenerateLastValue(instruction)) { - return false; - } +bool HLoopOptimization::TryReplaceWithLastValue(HInstruction* instruction, HBasicBlock* block) { + // Try to replace outside uses with the last value. Environment uses can consume this + // value too, since any first true use is outside the loop (although this may imply + // that de-opting may look "ahead" a bit on the phi value). If there are only environment + // uses, the value is dropped altogether, since the computations have no effect. + if (induction_range_.CanGenerateLastValue(instruction)) { ReplaceAllUses(instruction, induction_range_.GenerateLastValue(instruction, graph_, block)); + return true; } - return true; + return false; } } // namespace art diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h index e18d17531e..3391bef4e9 100644 --- a/compiler/optimizing/loop_optimization.h +++ b/compiler/optimizing/loop_optimization.h @@ -72,9 +72,7 @@ class HLoopOptimization : public HOptimization { HInstruction* instruction, /*out*/ int32_t* use_count); void ReplaceAllUses(HInstruction* instruction, HInstruction* replacement); - bool TryReplaceWithLastValue(HInstruction* instruction, - int32_t use_count, - HBasicBlock* block); + bool TryReplaceWithLastValue(HInstruction* instruction, HBasicBlock* block); // Range information based on prior induction variable analysis. InductionVarRange induction_range_; |