Path: blob/master/test/hotspot/jtreg/compiler/loopopts/TestLoopPeeling.java
41149 views
/*1* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8078262 817709526* @summary Tests correct dominator information after loop peeling.27*28* @run main/othervm -Xcomp29* -XX:CompileCommand=compileonly,compiler.loopopts.TestLoopPeeling::test*30* compiler.loopopts.TestLoopPeeling31*/3233package compiler.loopopts;3435public class TestLoopPeeling {3637public int[] array = new int[100];3839public static void main(String args[]) {40TestLoopPeeling test = new TestLoopPeeling();41try {42test.testArrayAccess1(0, 1);43test.testArrayAccess2(0);44test.testArrayAccess3(0, false);45test.testArrayAllocation(0, 1);46} catch (Exception e) {47// Ignore exceptions48}49}5051public void testArrayAccess1(int index, int inc) {52int storeIndex = -1;5354for (; index < 10; index += inc) {55// This loop invariant check triggers loop peeling because it can56// be moved out of the loop (see 'IdealLoopTree::policy_peeling').57if (inc == 42) return;5859// This loop variant usage of LShiftL( ConvI2L( Phi(storeIndex) ) )60// prevents the split if optimization that would otherwise clone the61// LShiftL and ConvI2L nodes and assign them to their corresponding array62// address computation (see 'PhaseIdealLoop::split_if_with_blocks_post').63if (storeIndex > 0 && array[storeIndex] == 42) return;6465if (index == 42) {66// This store and the corresponding range check are moved out of the67// loop and both used after main loop and the peeled iteration exit.68// For the peeled iteration, storeIndex is always -1 and the ConvI2L69// is replaced by TOP. However, the range check is not folded because70// we don't do the split if optimization in PhaseIdealLoop2.71// As a result, we have a (dead) control path from the peeled iteration72// to the StoreI but the data path is removed.73array[storeIndex] = 1;74return;75}7677storeIndex++;78}79}8081public int testArrayAccess2(int index) {82// Load1 and the corresponding range check are moved out of the loop83// and both are used after the main loop and the peeled iteration exit.84// For the peeled iteration, storeIndex is always Integer.MIN_VALUE and85// for the main loop it is 0. Hence, the merging phi has type int:<=0.86// Load1 reads the array at index ConvI2L(CastII(AddI(storeIndex, -1)))87// where the CastII is range check dependent and has type int:>=0.88// The CastII gets pushed through the AddI and its type is changed to int:>=189// which does not overlap with the input type of storeIndex (int:<=0).90// The CastII is replaced by TOP causing a cascade of other eliminations.91// Since the control path through the range check CmpU(AddI(storeIndex, -1))92// is not eliminated, the graph is in a corrupted state. We fail once we merge93// with the result of Load2 because we get data from a non-dominating region.94int storeIndex = Integer.MIN_VALUE;95for (; index < 10; ++index) {96if (index == 42) {97return array[storeIndex-1]; // Load198}99storeIndex = 0;100}101return array[42]; // Load2102}103104public int testArrayAccess3(int index, boolean b) {105// Same as testArrayAccess2 but manifests as crash in register allocator.106int storeIndex = Integer.MIN_VALUE;107for (; index < 10; ++index) {108if (b) {109return 0;110}111if (index == 42) {112return array[storeIndex-1]; // Load1113}114storeIndex = 0;115}116return array[42]; // Load2117}118119public byte[] testArrayAllocation(int index, int inc) {120int allocationCount = -1;121byte[] result;122123for (; index < 10; index += inc) {124// This loop invariant check triggers loop peeling because it can125// be moved out of the loop (see 'IdealLoopTree::policy_peeling').126if (inc == 42) return null;127128if (index == 42) {129// This allocation and the corresponding size check are moved out of the130// loop and both used after main loop and the peeled iteration exit.131// For the peeled iteration, allocationCount is always -1 and the ConvI2L132// is replaced by TOP. However, the size check is not folded because133// we don't do the split if optimization in PhaseIdealLoop2.134// As a result, we have a (dead) control path from the peeled iteration135// to the allocation but the data path is removed.136result = new byte[allocationCount];137return result;138}139140allocationCount++;141}142return null;143}144}145146147148