Enable LoopOptimization for graphs with try catch blocks
We can enable the optimization when the graph has try catch blocks,
but we do not perform the optimizations if the loops themselves
have try catch blocks.
Bug: 227283906
Change-Id: I8889d2ed7a5a260d5c2dcbbc5184cb7eaf3a8f9f
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 77dfe68..2d7c208 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -491,9 +491,9 @@
}
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 @@
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 @@
loop_allocator_ = nullptr;
last_loop_ = top_loop_ = nullptr;
- return didLoopOpt;
+ return did_loop_opt;
}
//
@@ -519,7 +519,6 @@
//
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 @@
}
}
+ // 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_ = ↦
- 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_ = ↦
+ 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 @@
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 @@
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 @@
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 3acd5b1..b178616 100644
--- a/compiler/optimizing/loop_optimization.h
+++ b/compiler/optimizing/loop_optimization.h
@@ -57,12 +57,23 @@
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 @@
// 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 b46d193..a5f919c 100644
--- a/compiler/optimizing/superblock_cloner.cc
+++ b/compiler/optimizing/superblock_cloner.cc
@@ -855,11 +855,20 @@
}
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 0000000..e69de29
--- /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 0000000..b0aad4d
--- /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 0000000..5ff3c22
--- /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 0000000..8d44b65
--- /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 aee32b7..f909af3 100644
--- a/test/530-checker-peel-unroll/src/Main.java
+++ b/test/530-checker-peel-unroll/src/Main.java
@@ -78,9 +78,15 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
//
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
//
// 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 @@
/// 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 @@
/// 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 @@
/// 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 @@
/// 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++) {