diff options
Diffstat (limited to 'compiler/optimizing/licm.cc')
-rw-r--r-- | compiler/optimizing/licm.cc | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/compiler/optimizing/licm.cc b/compiler/optimizing/licm.cc index 7af1a20f98..d3a0376e9c 100644 --- a/compiler/optimizing/licm.cc +++ b/compiler/optimizing/licm.cc @@ -129,10 +129,25 @@ void LICM::Run() { !inst_it.Done(); inst_it.Advance()) { HInstruction* instruction = inst_it.Current(); - if (instruction->CanBeMoved() - && (!instruction->CanThrow() || !found_first_non_hoisted_visible_instruction_in_loop) - && !instruction->GetSideEffects().MayDependOn(loop_effects) - && InputsAreDefinedBeforeLoop(instruction)) { + bool can_move = false; + if (instruction->CanBeMoved() && InputsAreDefinedBeforeLoop(instruction)) { + if (instruction->CanThrow()) { + if (!found_first_non_hoisted_visible_instruction_in_loop) { + DCHECK(instruction->GetBlock()->IsLoopHeader()); + if (instruction->IsClinitCheck()) { + // clinit is only done once, and since all visible instructions + // in the loop header so far have been hoisted out, we can hoist + // the clinit check out also. + can_move = true; + } else if (!instruction->GetSideEffects().MayDependOn(loop_effects)) { + can_move = true; + } + } + } else if (!instruction->GetSideEffects().MayDependOn(loop_effects)) { + can_move = true; + } + } + if (can_move) { // We need to update the environment if the instruction has a loop header // phi in it. if (instruction->NeedsEnvironment()) { @@ -142,7 +157,9 @@ void LICM::Run() { } instruction->MoveBefore(pre_header->GetLastInstruction()); MaybeRecordStat(stats_, MethodCompilationStat::kLoopInvariantMoved); - } else if (instruction->CanThrow() || instruction->DoesAnyWrite()) { + } + + if (!can_move && (instruction->CanThrow() || instruction->DoesAnyWrite())) { // If `instruction` can do something visible (throw or write), // we cannot move further instructions that can throw. found_first_non_hoisted_visible_instruction_in_loop = true; |