JDK-8316105 : C2: Back to back Parse Predicates from different loops but with same deopt reason are wrongly grouped together
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 22
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2023-09-12
  • Updated: 2023-12-11
  • Resolved: 2023-09-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 22
22 b17Fixed
Related Reports
Relates :  
Relates :  
Description
Back to back Loop Limit Check Parse Predicates from different loops are wrongly grouped into a single Predicate Block when trying to find all Predicates of a loop. As a result, we do not eliminate the second Loop Limit Check Parse Predicate and the Parse Predicates above belonging to an already folded loop. In the test case, we then create a Hoisted Check Predicate with one of the Parse Predicate from the folded loop. This Hoisted Check Predicate fails at runtime and we jump to the wrong location in the interpreter. We re-execute a store and we observe a wrong execution.

The fix is to make sure each Predicate Block can only contain one Parse Predicate. This constraint was broken with JDK-8305636.


Original report
--------------------
Attached test run with:

$ javac Test.java FuzzerUtils.java -d .; java -XX:-BackgroundCompilation -XX:CompileOnly=Test::iMeth -XX:CompileCommand=quiet -XX:-UseOnStackReplacement   Test > out; java -XX:-BackgroundCompilation -Xint Test > out2; diff out out2
Note: FuzzerUtils.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
34c34
< vMeth1_check_sum: -13486
—
> vMeth1_check_sum: -13108




It doesn't reproduce with jdk 21.

iMeth is compiled multiple times. The last one is the one that looks wrong to me. I see:

ParsePredicate #242

IfTrue #251

ParsePredicate #300

IfTrue #309

CountedLoop #567




#242 is for Test::vMeth1 @ bci:84

#300 is for Test::iMeth @ bci:48

So they are back to back but not for the same loop.

StoreL #288 is control depend on #251

After some rounds of loop opts, #567 is unswitched. Predicates #242 is cloned above both unswitched loops. Problem is #242 is not for this loop and captures state before the StoreL but is now after it. I think a deoptimization at state from #242 causes the load, increment, store sequence to be wrongly reexecuted.
Comments
Changeset: ca47f5f0 Author: Christian Hagedorn <chagedorn@openjdk.org> Date: 2023-09-21 08:56:31 +0000 URL: https://git.openjdk.org/jdk/commit/ca47f5f06daebc3c50bf47b4cdf1fcf8edf1507d
21-09-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/15764 Date: 2023-09-15 14:47:07 +0000
15-09-2023

ILW = Wrong execution due to incorrect predicate cloning in loop unswitching, single fuzzer test, use -XX:-LoopUnswitching, -XX:-UseLoopPredicate or disable compilation of affected method = HLM = P3
12-09-2023

Starts to fail after JDK-8305636.
12-09-2023