RFR: 8309266: C2: assert(final_con == (jlong)final_int) failed: final value should be integer
Daohan Qu
duke at openjdk.org
Wed Jun 7 12:41:14 UTC 2023
This patch should fix [JDK-8309266](https://bugs.openjdk.org/browse/JDK-8309266). A `jtreg` test is also added. I'd appreciate any comments and reviews. Thanks in advance!
## Problem Analysis
For the following program,
public class Test {
static boolean flag;
public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
flag = !flag;
test();
}
}
public static void test() {
int limit = flag ? Integer.MAX_VALUE : 1000;
int i = 0;
while (i < limit) {
i += 3;
if (flag) {
return;
}
}
}
}
A `LoopLimitNode` will be generated and its `Limit` input is a `PhiNode`, as depicted in the following picture.
<img width="384" alt="phi_as_limit" src="https://github.com/openjdk/jdk/assets/18374295/c561bb09-9789-45c2-8fa8-5bc690ea8046">
During `PhaseCCP`, the `LoopLimitNode::Value()` tries to calculate the constant final value:
https://github.com/openjdk/jdk/blob/16ebf47fe3b0fac7b67acfa589a26abf8843306b/src/hotspot/share/opto/loopnode.cpp#L2289-L2301
The problem is that the assertion in `line 2299` could fail during CCP though it must hold true at the end of CCP. Here is the reason: `PhaseCCP` initializes all nodes with the type `TOP` and iterates in an "arbitrary" order. The following order may happen:
28 IfTrue => 34 Region => 36 Phi => 195 LoopLimit => ... => 29 IfFalse
1. In `ProjNode::Value()` (`IfTrue` inherits it), the type of `IfTrue` is set to `Type::CONTROL`
https://github.com/openjdk/jdk/blob/fa791119f0b73cd1e110d6a62d3bed58fee5740a/src/hotspot/share/opto/multnode.cpp#L168-L171
2. In `PhiNode::Value()`, only `28 IfTrue`'s correspondence `33 ConI` gets merged (as `29 IfFalse` has not been dealt with yet), then it has a value of `int:max`.
https://github.com/openjdk/jdk/blob/fa791119f0b73cd1e110d6a62d3bed58fee5740a/src/hotspot/share/opto/cfgnode.cpp#L1269-L1277
3. In `LoopLimitNode::Value()`, it finds its `Limit` input `36 Phi` is constant, which triggers the assertion, and the assertion fails since the final value calculated from that constant limit (`int:max`) overflows.
## Solution
Move the overflow check to the end of CCP, where it must not fail.
-------------
Commit messages:
- Add a jtreg test for this bug
- Move final value overflow check of LoopLimitNode to the end of CCP
- Add query and cast method for LoopLimitNode
Changes: https://git.openjdk.org/jdk/pull/14353/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=14353&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8309266
Stats: 119 lines in 5 files changed: 110 ins; 4 del; 5 mod
Patch: https://git.openjdk.org/jdk/pull/14353.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/14353/head:pull/14353
PR: https://git.openjdk.org/jdk/pull/14353
More information about the hotspot-compiler-dev
mailing list