diff options
6 files changed, 54 insertions, 4 deletions
diff --git a/compiler/optimizing/induction_var_range.cc b/compiler/optimizing/induction_var_range.cc index 767a149636..2f5a22ec0e 100644 --- a/compiler/optimizing/induction_var_range.cc +++ b/compiler/optimizing/induction_var_range.cc @@ -368,8 +368,8 @@ void InductionVarRange::Replace(HInstruction* instruction, for (HLoopInformation* lp = instruction->GetBlock()->GetLoopInformation(); // closest enveloping loop lp != nullptr; lp = lp->GetPreHeader()->GetLoopInformation()) { - // Update instruction's information. - ReplaceInduction(induction_analysis_->LookupInfo(lp, instruction), fetch, replacement); + // Update loop's InductionInfo about fetch. + ReplaceInduction(induction_analysis_->LookupInfo(lp, fetch), fetch, replacement); // Update loop's trip-count information. ReplaceInduction(induction_analysis_->LookupInfo(lp, GetLoopControl(lp)), fetch, replacement); } diff --git a/compiler/optimizing/induction_var_range.h b/compiler/optimizing/induction_var_range.h index a81227b41b..ab497414c9 100644 --- a/compiler/optimizing/induction_var_range.h +++ b/compiler/optimizing/induction_var_range.h @@ -128,8 +128,8 @@ class InductionVarRange { HInstruction* GenerateLastValue(HInstruction* instruction, HGraph* graph, HBasicBlock* block); /** - * Updates all matching fetches with the given replacement in all induction information - * that is associated with the given instruction. + * Updates all matching `fetch`es with the given `replacement` in all induction information + * that is present in the loops of the given `instruction`. */ void Replace(HInstruction* instruction, HInstruction* fetch, HInstruction* replacement); diff --git a/test/2279-second-inner-loop-references-first/expected-stderr.txt b/test/2279-second-inner-loop-references-first/expected-stderr.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2279-second-inner-loop-references-first/expected-stderr.txt diff --git a/test/2279-second-inner-loop-references-first/expected-stdout.txt b/test/2279-second-inner-loop-references-first/expected-stdout.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/2279-second-inner-loop-references-first/expected-stdout.txt diff --git a/test/2279-second-inner-loop-references-first/info.txt b/test/2279-second-inner-loop-references-first/info.txt new file mode 100644 index 0000000000..8a3a0eb52c --- /dev/null +++ b/test/2279-second-inner-loop-references-first/info.txt @@ -0,0 +1,2 @@ +Tests that we don't crash when optimizing a second inner loop that +references a deleted instruction from the first one. diff --git a/test/2279-second-inner-loop-references-first/src/Main.java b/test/2279-second-inner-loop-references-first/src/Main.java new file mode 100644 index 0000000000..122e370d8c --- /dev/null +++ b/test/2279-second-inner-loop-references-first/src/Main.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +class Main { + public static void main(String[] h) { + assertIntEquals(50, $noinline$SecondInnerLoopReferencesFirst()); + } + + static int $noinline$SecondInnerLoopReferencesFirst() { + int f = 0; + for (int outer = 0; outer < 5; outer++) { + // This will create a Phi[const_3, const_1] that we eliminate in loop optimization + byte ab = 3; + // This loop will be eliminated but the next loop will be referencing this one as the + // `ab` is used in the addition below, which used to lead to a crash. The reason for the + // crash is that we are not updating the induction variables correctly and they are + // pointing to a deleted instruction. + for (int first_inner = 0; first_inner < 5; first_inner++) { + ab = 1; + } + byte i = 0; + for (int second_inner = 0; second_inner < 10; second_inner++) { + i += ab; + } + f += (int) i; + } + return f; + } + + public static void assertIntEquals(int expected, int result) { + if (expected != result) { + throw new Error("Expected: " + expected + ", found: " + result); + } + } +} |