Skip to content

Commit ef9294c

Browse files
committed
[GR-41102] Speculative guard movement: do not optimize condition if it will result in an unconditional deopt.
PullRequest: graal/13563
2 parents 856902d + 7732fa2 commit ef9294c

File tree

16 files changed

+523
-111
lines changed

16 files changed

+523
-111
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package org.graalvm.compiler.core.test;
26+
27+
import java.util.EnumSet;
28+
29+
import org.graalvm.compiler.api.directives.GraalDirectives;
30+
import org.junit.Test;
31+
32+
import jdk.vm.ci.meta.DeoptimizationReason;
33+
34+
public class SpeculativeGuardMovementTrivialDeoptTest extends GraalCompilerTest {
35+
36+
static class Node {
37+
int val;
38+
Node next;
39+
}
40+
41+
private static Node createList(int length) {
42+
Node head = new Node();
43+
for (int i = 1; i < length; i++) {
44+
Node newHead = new Node();
45+
newHead.val = i;
46+
newHead.next = head;
47+
head = newHead;
48+
}
49+
return head;
50+
}
51+
52+
public static long contradictingAfter(Node head) {
53+
Node cur = head;
54+
int i = 0;
55+
for (; GraalDirectives.injectIterationCount(10000, i < 500); i++) {
56+
if (GraalDirectives.injectBranchProbability(0.0001, cur == null)) {
57+
// this loop effectively ensures the guard below is never triggered
58+
break;
59+
}
60+
cur = cur.next;
61+
GraalDirectives.sideEffect(0);
62+
if (i == 123) {
63+
GraalDirectives.sideEffect(1);
64+
} else {
65+
GraalDirectives.sideEffect(2);
66+
}
67+
if (!(i + 1 < 101)) {
68+
GraalDirectives.deoptimizeAndInvalidate();
69+
}
70+
GraalDirectives.sideEffect(3);
71+
}
72+
return i;
73+
}
74+
75+
@Test
76+
public void testContradicting01() {
77+
test(getInitialOptions(), EnumSet.allOf(DeoptimizationReason.class), "contradictingAfter", createList(100));
78+
}
79+
80+
public static long contradictingAfterInnerOuter(Node head, int foo) {
81+
Node cur = head;
82+
83+
int outerPhi = 0;
84+
while (outerPhi < foo) {
85+
int i = outerPhi;
86+
for (; GraalDirectives.injectIterationCount(10000, i < 500); i++) {
87+
if (GraalDirectives.injectBranchProbability(0.0001, cur == null)) {
88+
// this loop effectively ensures the guard below is never triggered
89+
break;
90+
}
91+
cur = cur.next;
92+
GraalDirectives.sideEffect(0);
93+
if (i == 123) {
94+
GraalDirectives.sideEffect(1);
95+
} else {
96+
GraalDirectives.sideEffect(2);
97+
}
98+
if (!(i + 1 < 101)) {
99+
GraalDirectives.deoptimizeAndInvalidate();
100+
}
101+
GraalDirectives.sideEffect(3);
102+
}
103+
outerPhi++;
104+
}
105+
return outerPhi;
106+
}
107+
108+
@Test
109+
public void testContradicting02() {
110+
test(getInitialOptions(), EnumSet.allOf(DeoptimizationReason.class), "contradictingAfterInnerOuter", createList(100), 1);
111+
}
112+
113+
public static long contradictingAfterInnerOuter2(Node head, int foo, int bar) {
114+
Node cur = head;
115+
int outerOuterPhi = 0;
116+
while (outerOuterPhi < bar) {
117+
int outerPhi = outerOuterPhi;
118+
while (outerPhi < foo) {
119+
int i = outerPhi;
120+
for (; GraalDirectives.injectIterationCount(10000, i < 500); i++) {
121+
if (GraalDirectives.injectBranchProbability(0.0001, cur == null)) {
122+
// this loop effectively ensures the guard below is never triggered
123+
break;
124+
}
125+
cur = cur.next;
126+
GraalDirectives.sideEffect(0);
127+
if (i == 123) {
128+
GraalDirectives.sideEffect(1);
129+
} else {
130+
GraalDirectives.sideEffect(2);
131+
}
132+
if (!(i + 1 < 101)) {
133+
GraalDirectives.deoptimizeAndInvalidate();
134+
}
135+
GraalDirectives.sideEffect(3);
136+
}
137+
outerPhi++;
138+
}
139+
outerOuterPhi++;
140+
}
141+
return outerOuterPhi;
142+
}
143+
144+
@Test
145+
public void testContradicting03() {
146+
test(getInitialOptions(), EnumSet.allOf(DeoptimizationReason.class), "contradictingAfterInnerOuter2", createList(100), 1, 1);
147+
}
148+
149+
}

0 commit comments

Comments
 (0)