Skip to content

Commit 55c6904

Browse files
author
Theo Weidmann
committedJan 10, 2025
8331717: C2: Crash with SIGFPE Because Loop Predication Wrongly Hoists Division Requiring Zero Check
Reviewed-by: chagedorn, qamai, kvn
1 parent 1a0fe49 commit 55c6904

File tree

2 files changed

+90
-1
lines changed

2 files changed

+90
-1
lines changed
 

‎src/hotspot/share/opto/loopPredicate.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ class Invariance : public StackObj {
469469
// loop, it was marked invariant but n is only invariant if
470470
// it depends only on that test. Otherwise, unless that test
471471
// is out of the loop, it's not invariant.
472-
if (n->is_CFG() || n->depends_only_on_test() || n->in(0) == nullptr || !_phase->is_member(_lpt, n->in(0))) {
472+
if (n->is_CFG() || (n->depends_only_on_test() && _phase->igvn().no_dependent_zero_check(n)) || n->in(0) == nullptr || !_phase->is_member(_lpt, n->in(0))) {
473473
_invariant.set(n->_idx); // I am a invariant too
474474
}
475475
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright (c) 2024, 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 8331717
27+
* @summary C2: Crash with SIGFPE
28+
*
29+
* @run main/othervm -XX:CompileCommand=compileonly,*TestLoopPredicationDivZeroCheck*::* -XX:-TieredCompilation -Xbatch TestLoopPredicationDivZeroCheck
30+
*/
31+
32+
public class TestLoopPredicationDivZeroCheck {
33+
static int iArr[] = new int[100];
34+
static volatile long lFld;
35+
static int iFld;
36+
37+
public static void main(String[] strArr) {
38+
for (int i = 0; i < 10000; i++) {
39+
test();
40+
}
41+
for (int i = 0; i < 10000; i++) {
42+
test2();
43+
}
44+
}
45+
46+
/*
47+
* The division 2 / i4 requires a non-zero check. As the result is an array access, it will be the input to a range
48+
* check. Loop predication will try to move the range check and the division to right before the loop as the division
49+
* appears to be invariant (i4 is always 0). However, the division is not truly invariant as it requires the zero
50+
* check for i4 that can throw an exception. The bug fixed in 8331717 caused the division to still be moved before the
51+
* for loop with the range check.
52+
*/
53+
static void test() {
54+
int i1 = 0;
55+
56+
for (int i4 : iArr) {
57+
i4 = i1;
58+
try {
59+
iArr[0] = 1 / i4;
60+
i4 = iArr[2 / i4];
61+
} catch (ArithmeticException a_e) {
62+
}
63+
}
64+
}
65+
66+
/*
67+
* Loop predication will try to move 3 / y (input to the range check for bArr[x / 30]) before its containing for loop
68+
* but it may not as y must be zero-checked. The same problem as above occurred before the fix in 8331717.
69+
*/
70+
static void test2() {
71+
int x = 0;
72+
int y = iFld;
73+
long lArr[] = new long[400];
74+
boolean bArr[] = new boolean[400];
75+
for (int i = 0; i < 10000; i++) {
76+
for (int j = 1; j < 13; j++) {
77+
for (int k = 1; k < 2; k++) {
78+
lFld = 0;
79+
lArr[1] = 7;
80+
try {
81+
x = 3 / y;
82+
} catch (ArithmeticException a_e) {
83+
}
84+
bArr[x / 30] = true;
85+
}
86+
}
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)
Please sign in to comment.