diff options
author | 2022-04-08 18:00:48 +0100 | |
---|---|---|
committer | 2022-04-14 14:51:30 +0100 | |
commit | 0eca098c263e3f93d9996dbd6070a53d09d4a6c6 (patch) | |
tree | e53180163e8cfcbfc0b8e6b80f45dc60c6bc4c8c /test/530-checker-loops-try-catch/src/Main.java | |
parent | d77cf74d29bf53d807b707e5f4da4f7176c08239 (diff) |
Enable LoopOptimization for graphs with try catch blocks
We can enable the optimization when the graph has try catch blocks,
but we do not perform the optimizations if the loops themselves
have try catch blocks.
Bug: 227283906
Change-Id: I8889d2ed7a5a260d5c2dcbbc5184cb7eaf3a8f9f
Diffstat (limited to 'test/530-checker-loops-try-catch/src/Main.java')
-rw-r--r-- | test/530-checker-loops-try-catch/src/Main.java | 1558 |
1 files changed, 1558 insertions, 0 deletions
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; +} |