1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8078262 8177095 27 * @summary Tests correct dominator information after loop peeling. 28 * 29 * @run main/othervm -Xcomp 30 * -XX:CompileCommand=compileonly,compiler.loopopts.TestLoopPeeling::test* 31 * compiler.loopopts.TestLoopPeeling 32 */ 33 34 package compiler.loopopts; 35 36 public class TestLoopPeeling { 37 38 public int[] array = new int[100]; 39 main(String args[])40 public static void main(String args[]) { 41 TestLoopPeeling test = new TestLoopPeeling(); 42 try { 43 test.testArrayAccess1(0, 1); 44 test.testArrayAccess2(0); 45 test.testArrayAccess3(0, false); 46 test.testArrayAllocation(0, 1); 47 } catch (Exception e) { 48 // Ignore exceptions 49 } 50 } 51 testArrayAccess1(int index, int inc)52 public void testArrayAccess1(int index, int inc) { 53 int storeIndex = -1; 54 55 for (; index < 10; index += inc) { 56 // This loop invariant check triggers loop peeling because it can 57 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). 58 if (inc == 42) return; 59 60 // This loop variant usage of LShiftL( ConvI2L( Phi(storeIndex) ) ) 61 // prevents the split if optimization that would otherwise clone the 62 // LShiftL and ConvI2L nodes and assign them to their corresponding array 63 // address computation (see 'PhaseIdealLoop::split_if_with_blocks_post'). 64 if (storeIndex > 0 && array[storeIndex] == 42) return; 65 66 if (index == 42) { 67 // This store and the corresponding range check are moved out of the 68 // loop and both used after main loop and the peeled iteration exit. 69 // For the peeled iteration, storeIndex is always -1 and the ConvI2L 70 // is replaced by TOP. However, the range check is not folded because 71 // we don't do the split if optimization in PhaseIdealLoop2. 72 // As a result, we have a (dead) control path from the peeled iteration 73 // to the StoreI but the data path is removed. 74 array[storeIndex] = 1; 75 return; 76 } 77 78 storeIndex++; 79 } 80 } 81 testArrayAccess2(int index)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 testArrayAccess3(int index, boolean b)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 testArrayAllocation(int index, int inc)120 public byte[] testArrayAllocation(int index, int inc) { 121 int allocationCount = -1; 122 byte[] result; 123 124 for (; index < 10; index += inc) { 125 // This loop invariant check triggers loop peeling because it can 126 // be moved out of the loop (see 'IdealLoopTree::policy_peeling'). 127 if (inc == 42) return null; 128 129 if (index == 42) { 130 // This allocation and the corresponding size check are moved out of the 131 // loop and both used after main loop and the peeled iteration exit. 132 // For the peeled iteration, allocationCount is always -1 and the ConvI2L 133 // is replaced by TOP. However, the size check is not folded because 134 // we don't do the split if optimization in PhaseIdealLoop2. 135 // As a result, we have a (dead) control path from the peeled iteration 136 // to the allocation but the data path is removed. 137 result = new byte[allocationCount]; 138 return result; 139 } 140 141 allocationCount++; 142 } 143 return null; 144 } 145 } 146 147