Skip to content

Commit 7c0d417

Browse files
committed
8251535: Partial peeling at unsigned test adds incorrect loop exit check
Reviewed-by: chagedorn, neliasso, kvn
1 parent 5145bed commit 7c0d417

File tree

2 files changed

+192
-1
lines changed

2 files changed

+192
-1
lines changed

src/hotspot/share/opto/loopopts.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2558,7 +2558,13 @@ IfNode* PhaseIdealLoop::insert_cmpi_loop_exit(IfNode* if_cmpu, IdealLoopTree *lo
25582558

25592559
ProjNode* lp_continue = lp_proj->as_Proj();
25602560
ProjNode* lp_exit = if_cmpu->proj_out(!lp_continue->is_IfTrue())->as_Proj();
2561-
2561+
if (!lp_exit->is_IfFalse()) {
2562+
// The loop exit condition is (i <u limit) ==> (i >= 0 && i < limit).
2563+
// We therefore can't add a single exit condition.
2564+
return NULL;
2565+
}
2566+
// The loop exit condition is !(i <u limit) ==> (i < 0 || i >= limit).
2567+
// Split out the exit condition (i < 0) for stride < 0 or (i >= limit) for stride > 0.
25622568
Node* limit = NULL;
25632569
if (stride > 0) {
25642570
limit = cmpu->in(2);
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2020, 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 8251535
27+
* @summary Tests partial peeling at unsigned tests.
28+
* @library /test/lib /
29+
* @run main/othervm -Xcomp -XX:-TieredCompilation
30+
* -XX:CompileCommand=compileonly,compiler.loopopts.TestPartialPeelAtUnsignedTests::test*
31+
* compiler.loopopts.TestPartialPeelAtUnsignedTests
32+
*/
33+
34+
package compiler.loopopts;
35+
36+
import jdk.test.lib.Asserts;
37+
38+
public class TestPartialPeelAtUnsignedTests {
39+
/*
40+
loop:
41+
i += 1000;
42+
if (i <u 10_000) {
43+
goto exit;
44+
}
45+
goto loop;
46+
exit:
47+
return i;
48+
49+
C2 splits the unsigned loop exit check to have a
50+
signed exit test as cut point for partial peeling:
51+
52+
loop:
53+
i += 1000;
54+
if (i < 10_000) { <-- This exit condition is wrong!
55+
goto exit;
56+
}
57+
if (i <u 10_000) {
58+
goto exit;
59+
}
60+
goto loop;
61+
exit:
62+
return i;
63+
*/
64+
static int test1(int i) {
65+
boolean cond = false;
66+
while (!cond) {
67+
i += 1000;
68+
// Converted to (i <u 10_000)
69+
cond = (0 <= i) && (i < 10_000);
70+
}
71+
return i;
72+
}
73+
74+
/*
75+
Same as test1 but with a negative stride.
76+
77+
loop:
78+
i -= 1000;
79+
if (i <u 10_000) {
80+
goto exit;
81+
}
82+
goto loop;
83+
exit:
84+
return i;
85+
86+
Converted to:
87+
88+
loop:
89+
i -= 1000;
90+
if (i >= 0) { <-- This exit condition is wrong!
91+
goto exit;
92+
}
93+
if (i <u 10_000) {
94+
goto exit;
95+
}
96+
goto loop;
97+
exit:
98+
return i;
99+
*/
100+
static int test2(int i) {
101+
boolean cond = false;
102+
while (!cond) {
103+
i -= 1000;
104+
cond = (0 <= i) && (i < 10_000);
105+
}
106+
return i;
107+
}
108+
109+
/*
110+
Same as test1 but with inverted exit condition.
111+
112+
loop:
113+
i += 1000;
114+
if (i <u 10_000) {
115+
goto loop;
116+
}
117+
goto exit;
118+
exit:
119+
return i;
120+
121+
Converted to:
122+
123+
loop:
124+
i += 1000;
125+
if (!(i < 10_000)) { <-- Correct exit condition.
126+
goto exit;
127+
}
128+
if (i <u 10_000) {
129+
goto loop;
130+
}
131+
goto exit;
132+
exit:
133+
return i;
134+
*/
135+
static int test3(int i) {
136+
boolean cond = true;
137+
while (cond) {
138+
i += 1000;
139+
cond = (0 <= i) && (i < 10_000);
140+
}
141+
return i;
142+
}
143+
144+
/*
145+
Same as test2 but with inverted exit condition.
146+
147+
loop:
148+
i -= 1000;
149+
if (i <u 10_000) {
150+
goto loop;
151+
}
152+
goto exit;
153+
exit:
154+
return i;
155+
156+
Converted to:
157+
158+
loop:
159+
i -= 1000;
160+
if (!(i >= 0)) { <-- Correct exit condition.
161+
goto exit;
162+
}
163+
if (i <u 10_000) {
164+
goto loop;
165+
}
166+
goto exit;
167+
exit:
168+
return i;
169+
*/
170+
static int test4(int i) {
171+
boolean cond = true;
172+
while (cond) {
173+
i -= 1000;
174+
cond = (0 <= i) && (i < 10_000);
175+
}
176+
return i;
177+
}
178+
179+
public static void main(String[] args) {
180+
Asserts.assertEQ(test1(10_000), 704);
181+
Asserts.assertEQ(test2(-10_000), 9296);
182+
Asserts.assertEQ(test3(0), 10000);
183+
Asserts.assertEQ(test4(9999), -1);
184+
}
185+
}

0 commit comments

Comments
 (0)