diff options
author | Aart Bik <ajcbik@google.com> | 2016-11-03 17:51:43 -0700 |
---|---|---|
committer | Aart Bik <ajcbik@google.com> | 2016-11-04 08:14:23 -0700 |
commit | 807868eac75a39e79ee6309ed4cbe038407efa29 (patch) | |
tree | 74d9953120599bde842895ab4e7ed33fefb0fa13 /compiler/optimizing/loop_optimization.cc | |
parent | 3387b2a9e6ca4e7015c4182eee2f70a746972ca2 (diff) |
Account for early exit loop.
Rationale:
last value computation is obviously only right if
the loop does not have early exits; only needed
if cycle leaks to outside loop in any way.
Bug:32633772
Test: 623-checker-loop-regressions
Change-Id: Id60beca4704491cff611ad12a24bfc63c09d32c3
Diffstat (limited to 'compiler/optimizing/loop_optimization.cc')
-rw-r--r-- | compiler/optimizing/loop_optimization.cc | 42 |
1 files changed, 27 insertions, 15 deletions
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 |