test/compiler/loopopts/TestLoopPeeling.java

changeset 8727
3d8d14307428
parent 8285
535618ab1c04
equal deleted inserted replaced
8725:60d621df6c58 8727:3d8d14307428
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.

mercurial