summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/optimizing/loop_optimization.cc107
-rw-r--r--compiler/optimizing/loop_optimization.h18
-rw-r--r--compiler/optimizing/superblock_cloner.cc13
-rw-r--r--test/530-checker-loops-try-catch/expected-stderr.txt0
-rw-r--r--test/530-checker-loops-try-catch/expected-stdout.txt1
-rw-r--r--test/530-checker-loops-try-catch/info.txt1
-rw-r--r--test/530-checker-loops-try-catch/src/Main.java1558
-rw-r--r--test/530-checker-peel-unroll/src/Main.java494
8 files changed, 2076 insertions, 116 deletions
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 77dfe68bf6..2d7c20825c 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -491,9 +491,9 @@ HLoopOptimization::HLoopOptimization(HGraph* graph,
}
bool HLoopOptimization::Run() {
- // Skip if there is no loop or the graph has try-catch/irreducible loops.
+ // Skip if there is no loop or the graph has irreducible loops.
// TODO: make this less of a sledgehammer.
- if (!graph_->HasLoops() || graph_->HasTryCatch() || graph_->HasIrreducibleLoops()) {
+ if (!graph_->HasLoops() || graph_->HasIrreducibleLoops()) {
return false;
}
@@ -502,7 +502,7 @@ bool HLoopOptimization::Run() {
loop_allocator_ = &allocator;
// Perform loop optimizations.
- bool didLoopOpt = LocalRun();
+ const bool did_loop_opt = LocalRun();
if (top_loop_ == nullptr) {
graph_->SetHasLoops(false); // no more loops
}
@@ -511,7 +511,7 @@ bool HLoopOptimization::Run() {
loop_allocator_ = nullptr;
last_loop_ = top_loop_ = nullptr;
- return didLoopOpt;
+ return did_loop_opt;
}
//
@@ -519,7 +519,6 @@ bool HLoopOptimization::Run() {
//
bool HLoopOptimization::LocalRun() {
- bool didLoopOpt = false;
// Build the linear order using the phase-local allocator. This step enables building
// a loop hierarchy that properly reflects the outer-inner and previous-next relation.
ScopedArenaVector<HBasicBlock*> linear_order(loop_allocator_->Adapter(kArenaAllocLinearOrder));
@@ -532,34 +531,37 @@ bool HLoopOptimization::LocalRun() {
}
}
+ // TODO(solanes): How can `top_loop_` be null if `graph_->HasLoops()` is true?
+ if (top_loop_ == nullptr) {
+ return false;
+ }
+
// Traverse the loop hierarchy inner-to-outer and optimize. Traversal can use
// temporary data structures using the phase-local allocator. All new HIR
// should use the global allocator.
- if (top_loop_ != nullptr) {
- ScopedArenaSet<HInstruction*> iset(loop_allocator_->Adapter(kArenaAllocLoopOptimization));
- ScopedArenaSafeMap<HInstruction*, HInstruction*> reds(
- std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
- ScopedArenaSet<ArrayReference> refs(loop_allocator_->Adapter(kArenaAllocLoopOptimization));
- ScopedArenaSafeMap<HInstruction*, HInstruction*> map(
- std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
- ScopedArenaSafeMap<HInstruction*, HInstruction*> perm(
- std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
- // Attach.
- iset_ = &iset;
- reductions_ = &reds;
- vector_refs_ = &refs;
- vector_map_ = &map;
- vector_permanent_map_ = &perm;
- // Traverse.
- didLoopOpt = TraverseLoopsInnerToOuter(top_loop_);
- // Detach.
- iset_ = nullptr;
- reductions_ = nullptr;
- vector_refs_ = nullptr;
- vector_map_ = nullptr;
- vector_permanent_map_ = nullptr;
- }
- return didLoopOpt;
+ ScopedArenaSet<HInstruction*> iset(loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+ ScopedArenaSafeMap<HInstruction*, HInstruction*> reds(
+ std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+ ScopedArenaSet<ArrayReference> refs(loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+ ScopedArenaSafeMap<HInstruction*, HInstruction*> map(
+ std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+ ScopedArenaSafeMap<HInstruction*, HInstruction*> perm(
+ std::less<HInstruction*>(), loop_allocator_->Adapter(kArenaAllocLoopOptimization));
+ // Attach.
+ iset_ = &iset;
+ reductions_ = &reds;
+ vector_refs_ = &refs;
+ vector_map_ = &map;
+ vector_permanent_map_ = &perm;
+ // Traverse.
+ const bool did_loop_opt = TraverseLoopsInnerToOuter(top_loop_);
+ // Detach.
+ iset_ = nullptr;
+ reductions_ = nullptr;
+ vector_refs_ = nullptr;
+ vector_map_ = nullptr;
+ vector_permanent_map_ = nullptr;
+ return did_loop_opt;
}
void HLoopOptimization::AddLoop(HLoopInformation* loop_info) {
@@ -618,6 +620,18 @@ bool HLoopOptimization::TraverseLoopsInnerToOuter(LoopNode* node) {
induction_range_.ReVisit(node->loop_info);
changed = true;
}
+
+ CalculateAndSetTryCatchKind(node);
+ if (node->try_catch_kind == LoopNode::TryCatchKind::kHasTryCatch) {
+ // The current optimizations assume that the loops do not contain try/catches.
+ // TODO(solanes, 227283906): Assess if we can modify them to work with try/catches.
+ continue;
+ }
+
+ DCHECK(node->try_catch_kind == LoopNode::TryCatchKind::kNoTryCatch)
+ << "kind: " << static_cast<int>(node->try_catch_kind)
+ << ". LoopOptimization requires the loops to not have try catches.";
+
// Repeat simplifications in the loop-body until no more changes occur.
// Note that since each simplification consists of eliminating code (without
// introducing new code), this process is always finite.
@@ -635,6 +649,37 @@ bool HLoopOptimization::TraverseLoopsInnerToOuter(LoopNode* node) {
return changed;
}
+void HLoopOptimization::CalculateAndSetTryCatchKind(LoopNode* node) {
+ DCHECK(node != nullptr);
+ DCHECK(node->try_catch_kind == LoopNode::TryCatchKind::kUnknown)
+ << "kind: " << static_cast<int>(node->try_catch_kind)
+ << ". SetTryCatchKind should be called only once per LoopNode.";
+
+ // If a inner loop has a try catch, then the outer loop has one too (as it contains `inner`).
+ // Knowing this, we could skip iterating through all of the outer loop's parents with a simple
+ // check.
+ for (LoopNode* inner = node->inner; inner != nullptr; inner = inner->next) {
+ DCHECK(inner->try_catch_kind != LoopNode::TryCatchKind::kUnknown)
+ << "kind: " << static_cast<int>(inner->try_catch_kind)
+ << ". Should have updated the inner loop before the outer loop.";
+
+ if (inner->try_catch_kind == LoopNode::TryCatchKind::kHasTryCatch) {
+ node->try_catch_kind = LoopNode::TryCatchKind::kHasTryCatch;
+ return;
+ }
+ }
+
+ for (HBlocksInLoopIterator it_loop(*node->loop_info); !it_loop.Done(); it_loop.Advance()) {
+ HBasicBlock* block = it_loop.Current();
+ if (block->GetTryCatchInformation() != nullptr) {
+ node->try_catch_kind = LoopNode::TryCatchKind::kHasTryCatch;
+ return;
+ }
+ }
+
+ node->try_catch_kind = LoopNode::TryCatchKind::kNoTryCatch;
+}
+
//
// Optimization.
//
@@ -782,8 +827,6 @@ bool HLoopOptimization::OptimizeInnerLoop(LoopNode* node) {
return TryOptimizeInnerLoopFinite(node) || TryPeelingAndUnrolling(node);
}
-
-
//
// Scalar loop peeling and unrolling: generic part methods.
//
diff --git a/compiler/optimizing/loop_optimization.h b/compiler/optimizing/loop_optimization.h
index 3acd5b191b..b17861648f 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -57,12 +57,23 @@ class HLoopOptimization : public HOptimization {
outer(nullptr),
inner(nullptr),
previous(nullptr),
- next(nullptr) {}
+ next(nullptr),
+ try_catch_kind(TryCatchKind::kUnknown) {}
+
+ enum class TryCatchKind {
+ kUnknown,
+ // Either if we have a try catch in the loop, or if the loop is inside of an outer try catch,
+ // we set `kHasTryCatch`.
+ kHasTryCatch,
+ kNoTryCatch
+ };
+
HLoopInformation* loop_info;
LoopNode* outer;
LoopNode* inner;
LoopNode* previous;
LoopNode* next;
+ TryCatchKind try_catch_kind;
};
/*
@@ -131,6 +142,11 @@ class HLoopOptimization : public HOptimization {
// Returns true if loops nested inside current loop (node) have changed.
bool TraverseLoopsInnerToOuter(LoopNode* node);
+ // Calculates `node`'s `try_catch_kind` and sets it to:
+ // 1) kHasTryCatch if it has try catches (or if it's inside of an outer try catch)
+ // 2) kNoTryCatch otherwise.
+ void CalculateAndSetTryCatchKind(LoopNode* node);
+
//
// Optimization.
//
diff --git a/compiler/optimizing/superblock_cloner.cc b/compiler/optimizing/superblock_cloner.cc
index b46d193541..a5f919c31c 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -855,11 +855,20 @@ void SuperblockCloner::SetSuccessorRemappingInfo(const HEdgeSet* remap_orig_inte
}
bool SuperblockCloner::IsSubgraphClonable() const {
- // TODO: Support irreducible graphs and graphs with try-catch.
- if (graph_->HasIrreducibleLoops() || graph_->HasTryCatch()) {
+ // TODO: Support irreducible graphs and subgraphs with try-catch.
+ if (graph_->HasIrreducibleLoops()) {
return false;
}
+ for (HBasicBlock* block : graph_->GetReversePostOrder()) {
+ if (!IsInOrigBBSet(block)) {
+ continue;
+ }
+ if (block->GetTryCatchInformation() != nullptr) {
+ return false;
+ }
+ }
+
HInstructionMap live_outs(
std::less<HInstruction*>(), graph_->GetAllocator()->Adapter(kArenaAllocSuperblockCloner));
diff --git a/test/530-checker-loops-try-catch/expected-stderr.txt b/test/530-checker-loops-try-catch/expected-stderr.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/530-checker-loops-try-catch/expected-stderr.txt
diff --git a/test/530-checker-loops-try-catch/expected-stdout.txt b/test/530-checker-loops-try-catch/expected-stdout.txt
new file mode 100644
index 0000000000..b0aad4deb5
--- /dev/null
+++ b/test/530-checker-loops-try-catch/expected-stdout.txt
@@ -0,0 +1 @@
+passed
diff --git a/test/530-checker-loops-try-catch/info.txt b/test/530-checker-loops-try-catch/info.txt
new file mode 100644
index 0000000000..5ff3c22960
--- /dev/null
+++ b/test/530-checker-loops-try-catch/info.txt
@@ -0,0 +1 @@
+Test on loop optimizations, in particular with try catches.
diff --git a/test/530-checker-loops-try-catch/src/Main.java b/test/530-checker-loops-try-catch/src/Main.java
new file mode 100644
index 0000000000..8d44b65662
--- /dev/null
+++ b/test/530-checker-loops-try-catch/src/Main.java
@@ -0,0 +1,1558 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+//
+// Test on loop optimizations, in particular with try catches.
+//
+public class Main {
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo1(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo1(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Mul loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo1(int) loop_optimization (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 1410065408 loop:none
+ /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Mul>>,<<Zer>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$geo1(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$geo1(int a) {
+ for (int i = 0; i < 10; i++) {
+ a *= 10;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo1_Blocking(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo1_Blocking(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Mul loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo1_Blocking(int) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Mul loop:<<Loop>>
+ private static int $noinline$geo1_Blocking(int a) {
+ for (int i = 0; i < 10; i++) {
+ a *= 10;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo2(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo2(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo2(int) loop_optimization (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 1024 loop:none
+ /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Mul>>,<<Zer>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$geo2(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$geo2(int a) {
+ for (int i = 0; i < 10; i++) {
+ a <<= 1;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo2_Blocking(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo2_Blocking(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo2_Blocking(int) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+ private static int $noinline$geo2_Blocking(int a) {
+ for (int i = 0; i < 10; i++) {
+ a <<= 1;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo3(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo3(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Div loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo3(int) loop_optimization (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 59049 loop:none
+ /// CHECK-DAG: <<Div:i\d+>> Div [<<Par>>,<<Int>>] loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Div>>,<<Zer>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$geo3(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$geo3(int a) {
+ for (int i = 0; i < 10; i++) {
+ a /= 3;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo3_Blocking(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo3_Blocking(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Div loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo3_Blocking(int) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Div loop:<<Loop>>
+ private static int $noinline$geo3_Blocking(int a) {
+ for (int i = 0; i < 10; i++) {
+ a /= 3;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo4(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo4(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Rem loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo4(int) loop_optimization (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 7 loop:none
+ /// CHECK-DAG: <<Rem:i\d+>> Rem [<<Par>>,<<Int>>] loop:none
+ /// CHECK-DAG: Return [<<Rem>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$geo4(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$geo4(int a) {
+ for (int i = 0; i < 10; i++) {
+ a %= 7; // a wrap-around induction
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo4_Blocking(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo4_Blocking(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Rem loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo4_Blocking(int) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Rem loop:<<Loop>>
+ private static int $noinline$geo4_Blocking(int a) {
+ for (int i = 0; i < 10; i++) {
+ a %= 7; // a wrap-around induction
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo5() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo5() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shr loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo5() loop_optimization (after)
+ /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Int1:i\d+>> IntConstant 2147483647 loop:none
+ /// CHECK-DAG: <<Int2:i\d+>> IntConstant 1024 loop:none
+ /// CHECK-DAG: <<Div:i\d+>> Div [<<Int1>>,<<Int2>>] loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Div>>,<<Zero>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$geo5() loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$geo5() {
+ int a = 0x7fffffff;
+ for (int i = 0; i < 10; i++) {
+ a >>= 1;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$geo5_Blocking() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$geo5_Blocking() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shr loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$geo5_Blocking() loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shr loop:<<Loop>>
+ private static int $noinline$geo5_Blocking() {
+ int a = 0x7fffffff;
+ for (int i = 0; i < 10; i++) {
+ a >>= 1;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+ // Tests taken from 530-checker-loops4
+ private static void $noinline$loops4Tests() {
+ int m = 1410065408;
+ for (int i = -100; i <= 100; i++) {
+ expectEquals(m * i, $noinline$geo1(i));
+ expectEquals(m * i, $noinline$geo1_Blocking(i));
+ }
+ for (int i = 1; i <= 1000000000; i *= 10) {
+ expectEquals(m * i, $noinline$geo1(i));
+ expectEquals(m * i, $noinline$geo1_Blocking(i));
+ expectEquals(-m * i, $noinline$geo1(-i));
+ expectEquals(-m * i, $noinline$geo1_Blocking(-i));
+ }
+
+ for (int i = -100; i <= 100; i++) {
+ expectEquals(i << 10, $noinline$geo2(i));
+ expectEquals(i << 10, $noinline$geo2_Blocking(i));
+ }
+ for (int i = 0; i < 22; i++) {
+ expectEquals(1 << (i + 10), $noinline$geo2(1 << i));
+ expectEquals(1 << (i + 10), $noinline$geo2_Blocking(1 << i));
+ }
+ expectEquals(0x80000400, $noinline$geo2(0x00200001));
+ expectEquals(0x80000400, $noinline$geo2_Blocking(0x00200001));
+ expectEquals(0x00000000, $noinline$geo2(0x00400000));
+ expectEquals(0x00000000, $noinline$geo2_Blocking(0x00400000));
+ expectEquals(0x00000400, $noinline$geo2(0x00400001));
+ expectEquals(0x00000400, $noinline$geo2_Blocking(0x00400001));
+
+ int d = 59049;
+ for (int i = -100; i <= 100; i++) {
+ expectEquals(0, $noinline$geo3(i));
+ expectEquals(0, $noinline$geo3_Blocking(i));
+ }
+ for (int i = 1; i <= 100; i++) {
+ expectEquals(i, $noinline$geo3(i * d));
+ expectEquals(i, $noinline$geo3_Blocking(i * d));
+ expectEquals(i, $noinline$geo3(i * d + 1));
+ expectEquals(i, $noinline$geo3_Blocking(i * d + 1));
+ expectEquals(-i, $noinline$geo3(-i * d));
+ expectEquals(-i, $noinline$geo3_Blocking(-i * d));
+ expectEquals(-i, $noinline$geo3(-i * d - 1));
+ expectEquals(-i, $noinline$geo3_Blocking(-i * d - 1));
+ }
+
+ for (int i = -100; i <= 100; i++) {
+ expectEquals(i % 7, $noinline$geo4(i));
+ expectEquals(i % 7, $noinline$geo4_Blocking(i));
+ }
+
+ expectEquals(0x1fffff, $noinline$geo5());
+ expectEquals(0x1fffff, $noinline$geo5_Blocking());
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly1() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly1() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly1() loop_optimization (after)
+ /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 55 loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Zer>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$poly1() instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 55 loop:none
+ /// CHECK-DAG: Return [<<Int>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$poly1() loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$poly1() {
+ int a = 0;
+ for (int i = 0; i <= 10; i++) {
+ a += i;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly1_Blocking() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly1_Blocking() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly1_Blocking() loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ private static int $noinline$poly1_Blocking() {
+ int a = 0;
+ for (int i = 0; i <= 10; i++) {
+ a += i;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+
+ return a;
+ }
+
+ // Multiplication in linear induction has been optimized earlier,
+ // but that does not stop the induction variable recognition
+ // and loop optimizer.
+ //
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly2(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly2(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly2(int) loop_optimization (after)
+ /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant 185 loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Par>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$poly2(int) loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$poly2(int a) {
+ for (int i = 0; i < 10; i++) {
+ int k = 3 * i + 5;
+ a += k;
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly2_Blocking(int) loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly2_Blocking(int) loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly2_Blocking(int) loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Shl loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ private static int $noinline$poly2_Blocking(int a) {
+ for (int i = 0; i < 10; i++) {
+ int k = 3 * i + 5;
+ a += k;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly3() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly3() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly3() loop_optimization (after)
+ /// CHECK-DAG: <<Ini:i\d+>> IntConstant 12345 loop:none
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant -2146736968 loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Ini>>] loop:none
+ /// CHECK-DAG: Return [<<Add>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$poly3() instruction_simplifier$after_bce (after)
+ /// CHECK-DAG: <<Int:i\d+>> IntConstant -2146724623 loop:none
+ /// CHECK-DAG: Return [<<Int>>] loop:none
+
+ /// CHECK-START: int Main.$noinline$poly3() loop_optimization (after)
+ /// CHECK-NOT: Phi
+ private static int $noinline$poly3() {
+ int a = 12345;
+ for (int i = 0; i <= 10; i++) {
+ a += (2147483646 * i + 67890);
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ return a;
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: int Main.$noinline$poly3_Blocking() loop_optimization (before)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: int Main.$noinline$poly3_Blocking() loop_optimization (before)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+
+ /// CHECK-START: int Main.$noinline$poly3_Blocking() loop_optimization (after)
+ /// CHECK-DAG: Phi loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ /// CHECK-DAG: Add loop:<<Loop>>
+ private static int $noinline$poly3_Blocking() {
+ int a = 12345;
+ for (int i = 0; i <= 10; i++) {
+ a += (2147483646 * i + 67890);
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ return a;
+ }
+
+ // Tests taken from 530-checker-loops5
+ private static void $noinline$loops5Tests() {
+ expectEquals(55, $noinline$poly1());
+ expectEquals(55, $noinline$poly1_Blocking());
+ expectEquals(185, $noinline$poly2(0));
+ expectEquals(185, $noinline$poly2_Blocking(0));
+ expectEquals(192, $noinline$poly2(7));
+ expectEquals(192, $noinline$poly2_Blocking(7));
+ expectEquals(-2146724623, $noinline$poly3());
+ expectEquals(-2146724623, $noinline$poly3_Blocking());
+ }
+
+ // Constants used for peel unroll tests.
+ private static final int LENGTH = 4 * 1024;
+ private static final int RESULT_POS = 4;
+
+ private static final void initIntArray(int[] a) {
+ for (int i = 0; i < a.length; i++) {
+ a[i] = i % 4;
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (before)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<Phi>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<Phi>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
+ //
+ /// CHECK-DAG: <<CheckA:z\d+>> GreaterThanOrEqual [<<IndAdd>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IfA:v\d+>> If [<<Const0>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0A:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IndAddA:i\d+>> Add [<<IndAdd>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1A:i\d+>> ArrayGet [<<Array>>,<<IndAddA>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<AddA:i\d+>> Add [<<Get0A>>,<<Get1A>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<IndAdd>>,<<AddA>>] loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingLoadStoreElimination(int[] a) {
+ for (int i = 0; i < LENGTH - 2; i++) {
+ a[i] += a[i + 1];
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (before)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<Phi>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (after)
+ /// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 4094 loop:none
+ /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Limit>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<If:v\d+>> If [<<Check>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get0:i\d+>> ArrayGet [<<Array>>,<<Phi>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
+ /// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingLoadStoreElimination_Blocking(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingLoadStoreElimination_Blocking(int[] a) {
+ for (int i = 0; i < LENGTH - 2; i++) {
+ a[i] += a[i + 1];
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ // Each one of the three `for` loops has an `if`. The try catch has the 4th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ //
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ // Loop unrolling adds a 5th `if`. It is the one with `Const0` above.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingInTheNest(int[] a, int[] b, int x) {
+ for (int k = 0; k < 16; k++) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ a[i] = a[i] + 1;
+ }
+ }
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ //
+ /// CHECK-DAG: Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ // Each one of the three `for` loops has an `if`. The try catch has the 4th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ //
+ /// CHECK-DAG: Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_Blocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingInTheNest_Blocking(int[] a, int[] b, int x) {
+ for (int k = 0; k < 16; k++) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ a[i] = a[i] + 1;
+
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ }
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ //
+ /// CHECK-DAG: Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ // Each one of the three `for` loops has an `if`. The try catch has the 4th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: If [<<Check>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: <<AddI:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ //
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
+
+ // Loop unrolling adds a 5th `if`. It is the one with `Const0` above.
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingInTheNest_TryCatchNotBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingInTheNest_TryCatchNotBlocking(int[] a, int[] b, int x) {
+ for (int k = 0; k < 16; k++) {
+ for (int j = 0; j < 16; j++) {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ a[i] = a[i] + 1;
+ }
+ // Try catch does not block the optimization in the innermost loop.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // Each one of the three `for` loops has an `if`. Plus an `if` inside the outer `for`. The try catch has the 5th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: Add [<<AddI2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: Add [<<AddI3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // LoopOptimization adds two `if`s. One for each loop unrolling.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingTwoLoopsInTheNest(int[] a, int[] b, int x) {
+ for (int k = 0; k < 128; k++) {
+ if (x > 100) {
+ for (int j = 0; j < 128; j++) {
+ a[x]++;
+ }
+ } else {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ }
+ }
+ }
+
+ // Outer try catch does not block loop optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // Each one of the three `for` loops has an `if`. Plus an `if` inside the outer `for`. The try catch has the 5th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ // Unrelated to the optimization itself, the try catch has an if.
+ /// CHECK-DAG: <<Get:z\d+>> StaticFieldGet field_name:Main.doThrow
+ /// CHECK-DAG: If [<<Get>>]
+ //
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: Add [<<AddI3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // LoopOptimization adds two `if`s. One for each loop unrolling.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingTwoLoopsInTheNest_OneBlocking(int[] a, int[] b, int x) {
+ for (int k = 0; k < 128; k++) {
+ if (x > 100) {
+ for (int j = 0; j < 128; j++) {
+ a[x]++;
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ } else {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ }
+ }
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // Each one of the three `for` loops has an `if`. Plus an `if` inside the outer `for`. The try catch has the 5th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Const0>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: Add [<<AddI2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // LoopOptimization adds two `if`s. One for each loop unrolling.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingTwoLoopsInTheNest_OtherBlocking(int[] a, int[] b, int x) {
+ for (int k = 0; k < 128; k++) {
+ if (x > 100) {
+ for (int j = 0; j < 128; j++) {
+ a[x]++;
+ }
+ } else {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ }
+ }
+ }
+
+ // Consistency check to see we haven't eliminated the try/catch.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: TryBoundary
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ // Each one of the three `for` loops has an `if`. Plus an `if` inside the outer `for`. The try catchs have the 5th and 6th `if`.
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
+ /// CHECK-DAG: <<Limit:i\d+>> IntConstant 128 loop:none
+ /// CHECK-DAG: <<XThres:i\d+>> IntConstant 100 loop:none
+ /// CHECK-DAG: <<Phi1:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop1:B\d+>> outer_loop:none
+ //
+ /// CHECK-DAG: <<Phi2:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check2:z\d+>> GreaterThanOrEqual [<<Phi2>>,<<Limit>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check2>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ // Unrelated to the optimization itself, the try catch has an if.
+ /// CHECK-DAG: <<Get1:z\d+>> StaticFieldGet field_name:Main.doThrow
+ /// CHECK-DAG: If [<<Get1>>]
+ //
+ /// CHECK-DAG: <<AddI2:i\d+>> Add [<<Phi2>>,<<Const1>>] loop:<<Loop2>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<Phi3:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: <<Check3:z\d+>> GreaterThanOrEqual [<<Phi3>>,<<Limit>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: If [<<Check3>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
+ /// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
+ //
+ /// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.$noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+ private static final void $noinline$unrollingTwoLoopsInTheNest_BothBlocking(int[] a, int[] b, int x) {
+ for (int k = 0; k < 128; k++) {
+ if (x > 100) {
+ for (int j = 0; j < 128; j++) {
+ a[x]++;
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ } else {
+ for (int i = 0; i < 128; i++) {
+ b[x]++;
+ // Try catch blocks optimizations.
+ try {
+ if (doThrow) {
+ $noinline$unreachable();
+ }
+ } catch (Error e) {
+ System.out.println("Not expected");
+ }
+ }
+ }
+ }
+ }
+
+ // Tests taken from 530-checker-peel-unroll
+ private static void $noinline$peelUnrollTests() {
+ int[] a = new int[LENGTH];
+ int[] b = new int[LENGTH];
+ initIntArray(a);
+ initIntArray(b);
+
+ $noinline$unrollingLoadStoreElimination(a);
+ $noinline$unrollingLoadStoreElimination_Blocking(a);
+ $noinline$unrollingInTheNest(a, b, RESULT_POS);
+ $noinline$unrollingInTheNest_Blocking(a, b, RESULT_POS);
+ $noinline$unrollingInTheNest_TryCatchNotBlocking(a, b, RESULT_POS);
+ $noinline$unrollingTwoLoopsInTheNest(a, b, RESULT_POS);
+ $noinline$unrollingTwoLoopsInTheNest_OneBlocking(a, b, RESULT_POS);
+ $noinline$unrollingTwoLoopsInTheNest_OtherBlocking(a, b, RESULT_POS);
+ $noinline$unrollingTwoLoopsInTheNest_BothBlocking(a, b, RESULT_POS);
+ }
+
+ public static void main(String[] args) {
+ // Use existing tests to show that the difference between having a try catch inside or outside
+ // the loop.
+ $noinline$loops4Tests();
+ $noinline$loops5Tests();
+ $noinline$peelUnrollTests();
+
+ System.out.println("passed");
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void $noinline$unreachable() {
+ throw new Error("Unreachable");
+ }
+
+ private static boolean doThrow = false;
+}
diff --git a/test/530-checker-peel-unroll/src/Main.java b/test/530-checker-peel-unroll/src/Main.java
index aee32b7531..f909af3160 100644
--- a/test/530-checker-peel-unroll/src/Main.java
+++ b/test/530-checker-peel-unroll/src/Main.java
@@ -78,9 +78,15 @@ public class Main {
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (after)
/// CHECK-DAG: <<Array:l\d+>> ParameterValue loop:none
@@ -103,9 +109,18 @@ public class Main {
/// CHECK-DAG: <<Get1A:i\d+>> ArrayGet [<<Array>>,<<IndAddA>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<AddA:i\d+>> Add [<<Get0A>>,<<Get1A>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet [<<Array>>,<<IndAdd>>,<<AddA>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingLoadStoreElimination(int[] a) {
for (int i = 0; i < LENGTH - 2; i++) {
a[i] += a[i + 1];
@@ -124,9 +139,14 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
@@ -144,9 +164,16 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<AddI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingSwitch(int[] a) {
for (int i = 0; i < LENGTH; i++) {
switch (i % 3) {
@@ -173,9 +200,16 @@ public class Main {
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
@@ -197,9 +231,20 @@ public class Main {
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<AddI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingSwapElements(int[] array) {
for (int i = 0; i < LENGTH - 2; i++) {
if (array[i] > array[i + 1]) {
@@ -225,9 +270,21 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<PhiI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ // We have two other `ArrayGet` before the `If` that appears in the CHECK-DAG above.
+ /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
@@ -251,9 +308,25 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: Add [<<AddI>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: ArrayGet loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: ArraySet loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingRInnerproduct(double[][] result,
double[][] a,
double[][] b,
@@ -284,11 +357,24 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
/// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
/// CHECK-DAG: Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop2>>
- //
- /// CHECK-NOT: ArrayGet
- /// CHECK-NOT: ArraySet
+
+ // Each one of the three `for` loops has an `if`.
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
/// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
@@ -309,10 +395,28 @@ public class Main {
/// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
/// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop2>>
/// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop2>>
- //
- /// CHECK-NOT: ArrayGet
- /// CHECK-NOT: ArraySet
+
+ // Loop unrolling adds a 4th `if`. It is the one with `Const0` above.
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingInTheNest(int[] a, int[] b, int x) {
for (int k = 0; k < 16; k++) {
for (int j = 0; j < 16; j++) {
@@ -349,11 +453,25 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
/// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
/// CHECK-DAG: <<AddI3:i\d+>> Add [<<Phi3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
- //
- /// CHECK-NOT: ArrayGet
- /// CHECK-NOT: ArraySet
+
+ // Each one of the three `for` loops has an `if`. Plus an `if` inside the outer `for`.
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
+
/// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1 loop:none
@@ -382,10 +500,30 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop3>> outer_loop:<<Loop1>>
/// CHECK-DAG: ArraySet loop:<<Loop3>> outer_loop:<<Loop1>>
/// CHECK-DAG: Add [<<AddI3>>,<<Const1>>] loop:<<Loop3>> outer_loop:<<Loop1>>
- //
- /// CHECK-NOT: ArrayGet
- /// CHECK-NOT: ArraySet
+
+ // LoopOptimization adds two `if`s. One for each loop unrolling.
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void unrollingTwoLoopsInTheNest(int[] a, int[] b, int x) {
for (int k = 0; k < 128; k++) {
if (x > 100) {
@@ -423,7 +561,14 @@ public class Main {
/// CHECK-DAG: <<ZCheck:i\d+>> DivZeroCheck [<<STAdd>>] env:[[<<PhiS>>,<<PhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
/// CHECK-DAG: <<Div:i\d+>> Div [<<Const1>>,<<ZCheck>>] loop:none
/// CHECK-DAG: Return [<<Div>>] loop:none
+
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after)
@@ -461,8 +606,17 @@ public class Main {
/// CHECK-DAG: <<ZCheck:i\d+>> DivZeroCheck [<<STAdd>>] env:[[<<RetPhiS>>,<<RetPhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
/// CHECK-DAG: <<Div:i\d+>> Div [<<Const1>>,<<ZCheck>>] loop:none
/// CHECK-DAG: Return [<<Div>>] loop:none
- //
+
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final int unrollingSimpleLiveOuts(int[] a) {
int s = 1;
@@ -502,8 +656,14 @@ public class Main {
/// CHECK-DAG: ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>] loop:<<Loop1>> outer_loop:<<Loop0>>
//
/// CHECK-DAG: Add [<<OutPhiJ>>,<<Const1>>] loop:<<Loop0>> outer_loop:none
- //
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after)
@@ -545,8 +705,17 @@ public class Main {
//
/// CHECK-DAG: <<RetAdd:i\d+>> Add [<<OutPhiS>>,<<OutPhiT>>] loop:none
/// CHECK-DAG: Return [<<RetAdd>>] loop:none
- //
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final int unrollingLiveOutsNested(int[] a) {
int s = 1;
@@ -566,16 +735,21 @@ public class Main {
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: InstanceOf loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: InstanceOf
+
+ /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (before)
+ /// CHECK: InstanceOf
+ /// CHECK-NOT: InstanceOf
/// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: InstanceOf loop:<<Loop>> outer_loop:none
/// CHECK-DAG: InstanceOf loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: InstanceOf
+
+ /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (after)
+ /// CHECK: InstanceOf
+ /// CHECK: InstanceOf
+ /// CHECK-NOT: InstanceOf
public void unrollingInstanceOf(int[] a, Object[] obj_array) {
for (int i = 0; i < LENGTH_B; i++) {
if (obj_array[i] instanceof Integer) {
@@ -588,16 +762,21 @@ public class Main {
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: DivZeroCheck loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: DivZeroCheck
+
+ /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (before)
+ /// CHECK: DivZeroCheck
+ /// CHECK-NOT: DivZeroCheck
/// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: DivZeroCheck loop:<<Loop>> outer_loop:none
/// CHECK-DAG: DivZeroCheck loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: DivZeroCheck
+
+ /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (after)
+ /// CHECK: DivZeroCheck
+ /// CHECK: DivZeroCheck
+ /// CHECK-NOT: DivZeroCheck
public void unrollingDivZeroCheck(int[] a, int r) {
for (int i = 0; i < LENGTH_B; i++) {
a[i] += a[i] / r;
@@ -608,16 +787,21 @@ public class Main {
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: TypeConversion loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: TypeConversion
+
+ /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (before)
+ /// CHECK: TypeConversion
+ /// CHECK-NOT: TypeConversion
/// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: TypeConversion loop:<<Loop>> outer_loop:none
/// CHECK-DAG: TypeConversion loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: TypeConversion
+
+ /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (after)
+ /// CHECK: TypeConversion
+ /// CHECK: TypeConversion
+ /// CHECK-NOT: TypeConversion
public void unrollingTypeConversion(int[] a, double[] b) {
for (int i = 0; i < LENGTH_B; i++) {
a[i] = (int) b[i];
@@ -634,16 +818,21 @@ public class Main {
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: CheckCast loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: CheckCast
+
+ /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (before)
+ /// CHECK: CheckCast
+ /// CHECK-NOT: CheckCast
/// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0 loop:none
/// CHECK-DAG: Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: CheckCast loop:<<Loop>> outer_loop:none
/// CHECK-DAG: CheckCast loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: CheckCast
+
+ /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (after)
+ /// CHECK: CheckCast
+ /// CHECK: CheckCast
+ /// CHECK-NOT: CheckCast
public void unrollingCheckCast(int[] a, Object o) {
for (int i = 0; i < LENGTH_B; i++) {
if (((SubMain)o) == o) {
@@ -664,10 +853,22 @@ public class Main {
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
+ /// CHECK: Phi
/// CHECK-NOT: Phi
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
@@ -676,10 +877,22 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
+ /// CHECK: Phi
/// CHECK-NOT: Phi
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final void noUnrollingOddTripCount(int[] a) {
for (int i = 0; i < LENGTH - 1; i++) {
@@ -699,9 +912,24 @@ public class Main {
/// CHECK-DAG: <<Get1:i\d+>> ArrayGet [<<Array>>,<<IndAdd>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<Add:i\d+>> Add [<<Get0>>,<<Get1>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet [<<Array>>,<<Phi>>,<<Add>>] loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before)
+ /// CHECK: Phi
/// CHECK-NOT: Phi
+
+ // One `if` for the `for` loop, and another one for a deoptimize.
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
@@ -710,9 +938,23 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
+ /// CHECK: Phi
/// CHECK-NOT: Phi
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final void noUnrollingNotKnownTripCount(int[] a, int n) {
for (int i = 0; i < n; i++) {
@@ -732,9 +974,15 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: If
- /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (before)
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (after)
/// CHECK-DAG: <<Param:z\d+>> ParameterValue loop:none
@@ -754,9 +1002,18 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: If
- /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
/// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
/// CHECK-DAG: <<Param:z\d+>> ParameterValue loop:none
@@ -772,11 +1029,25 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: GreaterThanOrEqual
- /// CHECK-NOT: If
- /// CHECK-NOT: ArrayGet
- /// CHECK-NOT: ArraySet
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: GreaterThanOrEqual
+ /// CHECK-NOT: GreaterThanOrEqual
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK-NOT: ArraySet
private static final void peelingSimple(int[] a, boolean f) {
for (int i = 0; i < LENGTH; i++) {
if (f) {
@@ -808,8 +1079,13 @@ public class Main {
/// CHECK-DAG: <<Check:z\d+>> GreaterThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: If [<<Check>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
- //
- /// CHECK-NOT: If [<<Eq>>] loop:<<Loop>> outer_loop:none
+
+ // There's a 3rd `if` due to bounds checks.
+ /// CHECK-START: void Main.peelingAddInts(int[]) dead_code_elimination$final (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
private static final void peelingAddInts(int[] a) {
for (int i = 0; a != null && i < a.length; i++) {
a[i] += 1;
@@ -830,8 +1106,16 @@ public class Main {
/// CHECK-DAG: ArraySet loop:<<Loop1>> outer_loop:<<Loop0>>
/// CHECK-DAG: <<IndAdd1:i\d+>> Add [<<Phi1>>,<<Const1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
/// CHECK-DAG: <<IndAdd0:i\d+>> Add [<<Phi0>>,<<Const1>>] loop:<<Loop0>> outer_loop:none
- //
+
+ // The two loops have an `if`. The 3rd `if` is the explicit one in the innermost loop.
+ /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) loop_optimization (before)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) dead_code_elimination$final (after)
@@ -850,8 +1134,16 @@ public class Main {
/// CHECK-DAG: ArraySet loop:<<Loop1>> outer_loop:<<Loop0>>
/// CHECK-DAG: <<IndAdd1:i\d+>> Add [<<Phi1>>,<<Const1>>] loop:<<Loop1>> outer_loop:<<Loop0>>
/// CHECK-DAG: <<IndAdd0:i\d+>> Add [<<Phi0>>,<<Const1>>] loop:<<Loop0>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) dead_code_elimination$final (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final void peelingBreakFromNest(int[] a, boolean f) {
outer:
@@ -873,7 +1165,9 @@ public class Main {
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,{{i\d+}}] loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: If [<<Check>>] loop:<<Loop>> outer_loop:none
/// CHECK-DAG: <<IndAdd:i\d+>> Add [<<Phi>>,<<Const1>>] loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: int Main.peelingHoistOneControl(int) loop_optimization (before)
+ /// CHECK: If
/// CHECK-NOT: If
/// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after)
@@ -886,8 +1180,15 @@ public class Main {
//
// Check that the loop has no instruction except SuspendCheck and Goto (indefinite loop).
/// CHECK-NOT: loop:<<Loop>> outer_loop:none
+
+ /// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after)
+ /// CHECK: If
/// CHECK-NOT: If
+
+ /// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after)
/// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after)
/// CHECK-NOT: Add
private static final int peelingHoistOneControl(int x) {
int i = 0;
@@ -902,11 +1203,17 @@ public class Main {
/// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
- //
+
/// CHECK-START: int Main.peelingHoistOneControl(int, int) dead_code_elimination$final (after)
/// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: If loop:<<Loop>> outer_loop:none
+
+ // One `if` inside the loop (the one no longer invariant), two outside of it.
+ /// CHECK-START: int Main.peelingHoistOneControl(int, int) dead_code_elimination$final (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
private static final int peelingHoistOneControl(int x, int y) {
while (true) {
if (x == 0)
@@ -922,11 +1229,18 @@ public class Main {
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
- //
+
/// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) dead_code_elimination$final (after)
/// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
/// CHECK-DAG: If loop:<<Loop>> outer_loop:none
- /// CHECK-NOT: If loop:<<Loop>> outer_loop:none
+
+ // One `if` inside the loop (the one no longer invariant), three outside of it.
+ /// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) dead_code_elimination$final (after)
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK: If
+ /// CHECK-NOT: If
private static final int peelingHoistTwoControl(int x, int y, int z) {
while (true) {
if (x == 0)
@@ -948,8 +1262,14 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (before)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (before)
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
/// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (after)
@@ -970,8 +1290,20 @@ public class Main {
/// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
/// CHECK-DAG: If [<<Const1>>] loop:<<Loop>> outer_loop:none
- //
+
+ /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (after)
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
+ /// CHECK: ArrayGet
/// CHECK-NOT: ArrayGet
+
+ /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (after)
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
+ /// CHECK: ArraySet
/// CHECK-NOT: ArraySet
private static final void unrollingFull(int[] a) {
for (int i = 0; i < 2; i++) {