1 /* |
1 /* |
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test |
25 * @test |
26 * @bug 8078262 |
26 * @bug 8078262 8177095 |
27 * @summary Tests correct dominator information after loop peeling. |
27 * @summary Tests correct dominator information after loop peeling. |
28 * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,TestLoopPeeling::test* TestLoopPeeling |
28 * |
|
29 * @run main/othervm -Xcomp |
|
30 * -XX:CompileCommand=compileonly,compiler.loopopts.TestLoopPeeling::test* |
|
31 * compiler.loopopts.TestLoopPeeling |
29 */ |
32 */ |
|
33 |
|
34 package compiler.loopopts; |
|
35 |
30 public class TestLoopPeeling { |
36 public class TestLoopPeeling { |
31 |
37 |
32 public int[] array = new int[100]; |
38 public int[] array = new int[100]; |
33 |
39 |
34 public static void main(String args[]) { |
40 public static void main(String args[]) { |
35 TestLoopPeeling test = new TestLoopPeeling(); |
41 TestLoopPeeling test = new TestLoopPeeling(); |
36 try { |
42 try { |
37 test.testArrayAccess(0, 1); |
43 test.testArrayAccess1(0, 1); |
|
44 test.testArrayAccess2(0); |
|
45 test.testArrayAccess3(0, false); |
38 test.testArrayAllocation(0, 1); |
46 test.testArrayAllocation(0, 1); |
39 } catch (Exception e) { |
47 } catch (Exception e) { |
40 // Ignore exceptions |
48 // Ignore exceptions |
41 } |
49 } |
42 } |
50 } |
43 |
51 |
44 public void testArrayAccess(int index, int inc) { |
52 public void testArrayAccess1(int index, int inc) { |
45 int storeIndex = -1; |
53 int storeIndex = -1; |
46 |
54 |
47 for (; index < 10; index += inc) { |
55 for (; index < 10; index += inc) { |
48 // This loop invariant check triggers loop peeling because it can |
56 // This loop invariant check triggers loop peeling because it can |
49 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). |
57 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). |
55 // address computation (see 'PhaseIdealLoop::split_if_with_blocks_post'). |
63 // address computation (see 'PhaseIdealLoop::split_if_with_blocks_post'). |
56 if (storeIndex > 0 && array[storeIndex] == 42) return; |
64 if (storeIndex > 0 && array[storeIndex] == 42) return; |
57 |
65 |
58 if (index == 42) { |
66 if (index == 42) { |
59 // This store and the corresponding range check are moved out of the |
67 // This store and the corresponding range check are moved out of the |
60 // loop and both used after old loop and the peeled iteration exit. |
68 // loop and both used after main loop and the peeled iteration exit. |
61 // For the peeled iteration, storeIndex is always -1 and the ConvI2L |
69 // For the peeled iteration, storeIndex is always -1 and the ConvI2L |
62 // is replaced by TOP. However, the range check is not folded because |
70 // is replaced by TOP. However, the range check is not folded because |
63 // we don't do the split if optimization in PhaseIdealLoop2. |
71 // we don't do the split if optimization in PhaseIdealLoop2. |
64 // As a result, we have a (dead) control path from the peeled iteration |
72 // As a result, we have a (dead) control path from the peeled iteration |
65 // to the StoreI but the data path is removed. |
73 // to the StoreI but the data path is removed. |
69 |
77 |
70 storeIndex++; |
78 storeIndex++; |
71 } |
79 } |
72 } |
80 } |
73 |
81 |
|
82 public int testArrayAccess2(int index) { |
|
83 // Load1 and the corresponding range check are moved out of the loop |
|
84 // and both are used after the main loop and the peeled iteration exit. |
|
85 // For the peeled iteration, storeIndex is always Integer.MIN_VALUE and |
|
86 // for the main loop it is 0. Hence, the merging phi has type int:<=0. |
|
87 // Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1))) |
|
88 // where the CastII is range check dependent and has type int:>=0. |
|
89 // The CastII gets pushed through the AddI and its type is changed to int:>=1 |
|
90 // which does not overlap with the input type of storeIndex (int:<=0). |
|
91 // The CastII is replaced by TOP causing a cascade of other eliminations. |
|
92 // Since the control path through the range check CmpU(AddI(storeIndex, -1)) |
|
93 // is not eliminated, the graph is in a corrupted state. We fail once we merge |
|
94 // with the result of Load2 because we get data from a non-dominating region. |
|
95 int storeIndex = Integer.MIN_VALUE; |
|
96 for (; index < 10; ++index) { |
|
97 if (index == 42) { |
|
98 return array[storeIndex-1]; // Load1 |
|
99 } |
|
100 storeIndex = 0; |
|
101 } |
|
102 return array[42]; // Load2 |
|
103 } |
|
104 |
|
105 public int testArrayAccess3(int index, boolean b) { |
|
106 // Same as testArrayAccess2 but manifests as crash in register allocator. |
|
107 int storeIndex = Integer.MIN_VALUE; |
|
108 for (; index < 10; ++index) { |
|
109 if (b) { |
|
110 return 0; |
|
111 } |
|
112 if (index == 42) { |
|
113 return array[storeIndex-1]; // Load1 |
|
114 } |
|
115 storeIndex = 0; |
|
116 } |
|
117 return array[42]; // Load2 |
|
118 } |
|
119 |
74 public byte[] testArrayAllocation(int index, int inc) { |
120 public byte[] testArrayAllocation(int index, int inc) { |
75 int allocationCount = -1; |
121 int allocationCount = -1; |
76 byte[] result; |
122 byte[] result; |
77 |
123 |
78 for (; index < 10; index += inc) { |
124 for (; index < 10; index += inc) { |
80 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). |
126 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). |
81 if (inc == 42) return null; |
127 if (inc == 42) return null; |
82 |
128 |
83 if (index == 42) { |
129 if (index == 42) { |
84 // This allocation and the corresponding size check are moved out of the |
130 // This allocation and the corresponding size check are moved out of the |
85 // loop and both used after old loop and the peeled iteration exit. |
131 // loop and both used after main loop and the peeled iteration exit. |
86 // For the peeled iteration, allocationCount is always -1 and the ConvI2L |
132 // For the peeled iteration, allocationCount is always -1 and the ConvI2L |
87 // is replaced by TOP. However, the size check is not folded because |
133 // is replaced by TOP. However, the size check is not folded because |
88 // we don't do the split if optimization in PhaseIdealLoop2. |
134 // we don't do the split if optimization in PhaseIdealLoop2. |
89 // As a result, we have a (dead) control path from the peeled iteration |
135 // As a result, we have a (dead) control path from the peeled iteration |
90 // to the allocation but the data path is removed. |
136 // to the allocation but the data path is removed. |