49b86224aa
Reviewed-by: thartmann, kvn
409 lines
17 KiB
Java
409 lines
17 KiB
Java
/*
|
|
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/**
|
|
* @test
|
|
* @bug 8290850
|
|
* @summary Test cloning of pinned phi input nodes in create_new_if_for_predicate().
|
|
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestCreateNewIfForPredicateCloning::*
|
|
* compiler.loopopts.TestCreateNewIfForPredicateCloning
|
|
*/
|
|
|
|
package compiler.loopopts;
|
|
|
|
public class TestCreateNewIfForPredicateCloning {
|
|
static int iFld, iFld2, iFld3, nonZero = 2, nonZero2 = 3;
|
|
static boolean bFld = true, bFld2 = false;
|
|
static int[] iArrFld = new int[100];
|
|
|
|
public static void main(String[] args) {
|
|
try {
|
|
testUnswitching();
|
|
testLoopPredicatation();
|
|
testLoopPredicatationComplex();
|
|
testUnswitchingWithPredicates();
|
|
testUnswitchingWithPredicatesDiv();
|
|
testFuzzer1();
|
|
testFuzzer2();
|
|
testFuzzer3();
|
|
} catch (Exception e) {
|
|
// Expected
|
|
}
|
|
}
|
|
|
|
// Test case for the already fixed problem in 8271954: Calling create_new_if_for_predicate in
|
|
// clone_predicate_to_unswitched_loop(). This does not crash anymore. But still use it as sanity test here with the
|
|
// new fix.
|
|
static void testUnswitching() {
|
|
int x = 3;
|
|
|
|
// Block to delay precise type information to after CCP.
|
|
int limit = 2;
|
|
int constantAfterCCP = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
constantAfterCCP = 6; // Only known to be constant 6 after CCP.
|
|
}
|
|
|
|
for (int i = 51; i > 9; i -= 3) {
|
|
if (bFld) {
|
|
x *= 6;
|
|
}
|
|
// (1) after unswitching:
|
|
// if (bFld) {...}
|
|
// Since we have a back to back if now with the same condition, we can merge them together by using the
|
|
// split if optimization. That will create phi nodes for the UCT regions. Whenever we then call
|
|
// create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap
|
|
// projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But
|
|
// in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon
|
|
// trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph:
|
|
// the LCA of the old and new uncommon projection would be above the early control (control input of the
|
|
// CastII nodes).
|
|
//
|
|
// 8271954 fixes this when calling create_new_if_for_predicate() in
|
|
// clone_predicate_to_unswitched_loop().
|
|
x -= 5;
|
|
|
|
for (int j = 1; j < 10; j++) {
|
|
if (bFld) { // Unswitching on bFld such that this condition is moved to (1)
|
|
continue;
|
|
}
|
|
x = 34; // Redefine x such that x is only used in UCT before this loop after split if.
|
|
int y = 34;
|
|
if (constantAfterCCP == 2) {
|
|
// Known to be never taken after CCP, so y will always be 34.
|
|
y = 35;
|
|
}
|
|
if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching
|
|
continue;
|
|
}
|
|
iFld3 = 34; // Just another statement sucht that the second round of unswitching is done
|
|
|
|
}
|
|
}
|
|
|
|
// This loop is only needed to delay the second round of unswitching for the inner loop above.
|
|
for (int i = 0; i < iArrFld.length; i++) {
|
|
iArrFld[i] = 3;
|
|
}
|
|
}
|
|
|
|
// Similar to testUnswitching() but we are calling create_new_if_for_predicate in Loop Predication for:
|
|
// - Creating hoised range check predicate and skeleton predicate
|
|
// - Creating invariant check predicate
|
|
// which leads to a crash.
|
|
static void testLoopPredicatation() {
|
|
int x = 3;
|
|
|
|
// Block to delay precise type information to after CCP.
|
|
int limit = 2;
|
|
int constantAfterCCP = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
constantAfterCCP = 6; // Only known to be constant 6 after CCP.
|
|
}
|
|
|
|
for (int i = 51; i > 9; i -= 3) {
|
|
if (bFld) {
|
|
x *= 6;
|
|
}
|
|
// (1) after unswitching:
|
|
// if (bFld) {...}
|
|
// Since we have a back to back if now with the same condition, we can merge them together by using the
|
|
// split if optimization. That will create phi nodes for the UCT regions. Whenever we then call
|
|
// create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap
|
|
// projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But
|
|
// in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon
|
|
// trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph:
|
|
// the LCA of the old and new uncommon projection would be above the early control (control input of the
|
|
// CastII nodes).
|
|
x -= 5;
|
|
|
|
for (int j = 1; j < 10; j++) {
|
|
if (bFld) { // Unswitching on bFld such that this condition is moved to (1)
|
|
continue;
|
|
}
|
|
x = 34; // Redefine x such that x is only used in UCT before this loop after split if.
|
|
int y = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if.
|
|
}
|
|
}
|
|
|
|
// This loop is only needed to delay the second round of unswitching for the inner loop above.
|
|
for (int i = 0; i < iArrFld.length; i++) {
|
|
iArrFld[i] = 3;
|
|
}
|
|
}
|
|
|
|
// Similar to testLoopPredicatation() but we are adding some computations for x such that we sink more nodes which
|
|
// need to be cloned when calling create_new_if_for_predicate().
|
|
static void testLoopPredicatationComplex() {
|
|
int x = 3;
|
|
|
|
// Block to delay precise type information to after CCP.
|
|
int limit = 2;
|
|
int constantAfterCCP = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
constantAfterCCP = 6; // Only known to be constant 6 after CCP.
|
|
}
|
|
|
|
for (int i = 51; i > 9; i -= 3) {
|
|
if (bFld) {
|
|
x *= 6;
|
|
}
|
|
// (1) after unswitching:
|
|
// if (bFld) {...}
|
|
// Since we have a back to back if now with the same condition, we can merge them together by using the
|
|
// split if optimization. That will create phi nodes for the UCT regions. Whenever we then call
|
|
// create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap
|
|
// projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But
|
|
// in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon
|
|
// trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph:
|
|
// the LCA of the old and new uncommon projection would be above the early control (control input of the
|
|
// CastII nodes).
|
|
x -= 5;
|
|
|
|
// Add some more computations such that more nodes are sunk and therefore more nodes need to be cloned in
|
|
// create_new_if_for_predicate().
|
|
double d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
d1 = 5 + (double) x;
|
|
x = (int)((d1 + iFld2) - (d1 + iFld));
|
|
|
|
for (int j = 1; j < 10; j++) {
|
|
if (bFld) { // Unswitching on bFld such that this condition is moved to (1)
|
|
continue;
|
|
}
|
|
x = 34; // Redefine x such that x is only used in UCT before this loop after split if.
|
|
int y = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if.
|
|
}
|
|
}
|
|
|
|
// This loop is only needed to delay the second round of unswitching for the inner loop above.
|
|
for (int i = 0; i < iArrFld.length; i++) {
|
|
iArrFld[i] = 3;
|
|
}
|
|
}
|
|
|
|
// Combination of testUnswitching() and testLoopPredicatation(): After creating predicates in loop predication,
|
|
// we perform another round of loop unswitching where we additionally call create_new_if_for_predicate in
|
|
// clone_skeleton_predicate_for_unswitched_loops() which currently leads to a crash.
|
|
static void testUnswitchingWithPredicates() {
|
|
int x = 3;
|
|
if (iArrFld == null) {
|
|
// Makes sure to get rid of null check for iArrFld to only create range check predicate
|
|
return;
|
|
}
|
|
// Block to delay precise type information to after CCP.
|
|
int limit = 2;
|
|
int constantAfterCCP = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
constantAfterCCP = 6; // Only known to be constant 6 after CCP.
|
|
}
|
|
|
|
for (int i = 51; i > 9; i -= 3) {
|
|
if (bFld) {
|
|
x *= 6;
|
|
}
|
|
// (1) after unswitching:
|
|
// if (bFld) {...}
|
|
// Since we have a back to back if now with the same condition, we can merge them together by using the
|
|
// split if optimization. That will create phi nodes for the UCT regions. Whenever we then call
|
|
// create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap
|
|
// projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But
|
|
// in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon
|
|
// trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph:
|
|
// the LCA of the old and new uncommon projection would be above the early control (control input of the
|
|
// CastII nodes).
|
|
x -= 5;
|
|
|
|
for (int j = 1; j < 10; j++) {
|
|
if (bFld) { // Unswitching on bFld such that this condition is moved to (1)
|
|
continue;
|
|
}
|
|
x = 34; // Redefine x such that x is only used in UCT before this loop after split if.
|
|
int z = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if.
|
|
int y = 34;
|
|
if (constantAfterCCP == 2) {
|
|
// Known to be never taken after CCP, so y will always be 34.
|
|
y = 35;
|
|
}
|
|
if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching
|
|
continue;
|
|
}
|
|
iFld3 = 34; // Just another statement sucht that the second round of unswitching is done
|
|
}
|
|
}
|
|
|
|
// This loop is only needed to delay the second round of unswitching for the inner loop above.
|
|
for (int i = 0; i < iArrFld.length; i++) {
|
|
iArrFld[i] = 3;
|
|
}
|
|
}
|
|
|
|
// Same as testUnswitchingWithPredicates() but with a DivI node which has a control input which needs
|
|
// to be rewired as well.
|
|
static void testUnswitchingWithPredicatesDiv() {
|
|
int x = 3;
|
|
if (iArrFld == null) {
|
|
// Makes sure to get rid of null check for iArrFld to only create range check predicate
|
|
return;
|
|
}
|
|
// Block to delay precise type information to after CCP.
|
|
int limit = 2;
|
|
int constantAfterCCP = 2;
|
|
for (; limit < 4; limit *= 2);
|
|
for (int i = 2; i < limit; i++) {
|
|
constantAfterCCP = 6; // Only known to be constant 6 after CCP.
|
|
}
|
|
|
|
for (int i = 51; i > 9; i -= 3) {
|
|
if (bFld) {
|
|
x *= 6;
|
|
}
|
|
// (1) after unswitching:
|
|
// if (bFld) {...}
|
|
// Since we have a back to back if now with the same condition, we can merge them together by using the
|
|
// split if optimization. That will create phi nodes for the UCT regions. Whenever we then call
|
|
// create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap
|
|
// projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But
|
|
// in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon
|
|
// trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph:
|
|
// the LCA of the old and new uncommon projection would be above the early control (control input of the
|
|
// CastII nodes).
|
|
x -= 5;
|
|
|
|
double d = 5.5f + (double) x;
|
|
int a = (int)d;
|
|
x = (a / nonZero) - (a / nonZero2);
|
|
|
|
|
|
for (int j = 1; j < 10; j++) {
|
|
if (bFld) { // Unswitching on bFld such that this condition is moved to (1)
|
|
continue;
|
|
}
|
|
x = 34; // Redefine x such that x is only used in UCT before this loop after split if.
|
|
int z = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if.
|
|
int y = 34;
|
|
if (constantAfterCCP == 2) {
|
|
// Known to be never taken after CCP, so y will always be 34.
|
|
y = 35;
|
|
}
|
|
if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching
|
|
continue;
|
|
}
|
|
iFld3 = 34; // Just another statement sucht that the second round of unswitching is done
|
|
}
|
|
}
|
|
|
|
// This loop is only needed to delay the second round of unswitching for the inner loop above.
|
|
for (int i = 0; i < iArrFld.length; i++) {
|
|
iArrFld[i] = 3;
|
|
}
|
|
}
|
|
|
|
static void testFuzzer1() {
|
|
int x = 0;
|
|
int[] iArr = new int[400];
|
|
boolean b = true;
|
|
long[] lArr = new long[400];
|
|
for (long l1 : lArr) {
|
|
for (int i = 63; i > 1; i -= 3) {
|
|
for (int j = 1; j < 4; j++) {
|
|
if (!b) {
|
|
x -= 5;
|
|
}
|
|
}
|
|
for (int j = 1; j < 4; j++) {
|
|
if (!b) {
|
|
x = iArr[j];
|
|
}
|
|
if (i == 0) {
|
|
l1 += 5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void testFuzzer2() {
|
|
int i, i1, i17 = 6, i18;
|
|
short s1;
|
|
boolean b2 = true;
|
|
float f3;
|
|
long lArr[][] = new long[400][];
|
|
byte byArrFld[] = new byte[4];
|
|
i = 1;
|
|
do {
|
|
for (i1 = 14; 6 < i1; i1--)
|
|
;
|
|
i17 -= i18 = 1;
|
|
while (i18 < 4) {
|
|
i18 <<= i17 = 2;
|
|
switch (i1) {
|
|
case 114:
|
|
s1 = byArrFld[1];
|
|
break;
|
|
case 116:
|
|
lArr[1][i18] = iFld;
|
|
if (b2)
|
|
continue;
|
|
case 118:
|
|
f3 = iFld;
|
|
}
|
|
}
|
|
i++;
|
|
} while (i < 10000);
|
|
}
|
|
|
|
static void testFuzzer3() {
|
|
int x = 8;
|
|
int y = 4;
|
|
for (int i : iArrFld) {
|
|
x += 2;
|
|
if (bFld) {
|
|
x = 3;
|
|
} else {
|
|
y = 2;
|
|
}
|
|
for (int j = 0; j < 10; j++) {
|
|
x = 0;
|
|
y += 5;
|
|
if (!bFld) {
|
|
iArrFld[1] = 5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|