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