[14] RFR(M): 8233033: Results of execution differ for C2 and C1/Xint
Christian Hagedorn
christian.hagedorn at oracle.com
Thu Nov 28 09:24:06 UTC 2019
Hi
Please review the following patch:
https://bugs.openjdk.java.net/browse/JDK-8233033
http://cr.openjdk.java.net/~chagedorn/8233033/webrev.00/
The C2 compiled code produces a wrong result for 'iFld' in the test
case. It is -8 instead of -7. The loop in the test case is partially
peeled and then unswitched. The wrong result is produced because a wrong
state is transferred to the interpreter when an uncommon trap is hit in
the C2 compiled code in the fast version of the unswitched loop.
The problem is when unswitching the loop, we clone the original loop
predicates for the slow and fast version of the loop [1] but we do not
account for partially peeled statements that are control dependent on
the loop predicates (i.e. need to be executed after the predicates). As
a result, these are executed before the cloned loop predicates.
The situation of the test case method PartialPeelingUnswitch::test() is
visualized in [2]. IfTrue 118, the entry control of the original loop
which follows right after the loop predicates, has an output edge to the
StoreI 353 node. This node belongs to the "iFld += -7" statement which
was partially peeled before. When creating the slow version of the loop
and cloning the predicates in
PhaseIdealLoop::create_slow_version_of_loop(), this control dependency
is lost. StoreI 353 is still dependent on IfTrue 118 instead of IfTrue
472 (fast loop entry control) and IfTrue 476 (slow loop entry control).
The original loop predicates are later removed and thus, when hitting
the uncommon trap in the fast loop, we accidentally executed "iFld +=
-7" (StoreI 353) already even though the interpreter assumes C2 has not
executed any statements in the loop. As a result, "iFld += -7" is
executed twice in a row which produces a wrong result.
The fix is to replace the control input of all statements that have a
control input from the original loop entry control (and are not the
"loop selection" IfNode) with the fast and slow entry control,
respectively. Since the statements cannot have two control inputs they
need to be cloned together with all following nodes on a path to the
loop phi nodes. The output of the last node before a loop phi on such a
path needs to be adjusted to only point to the phi node belonging to the
fast loop. The last node on the cloned path is set to the phi node
belonging to the slow loop. The fix is visualized in [3]. The control
input of StoreI 353 is now the entry control of the fast loop (IfTrue
472) and its output only points to the corresponding Phi 442 of the fast
loop. The same was done for the cloned node StoreI 476 of StoreI 353 for
the slow loop.
This bug can also be reproduced with JDK 11. Should we target this fix
to 14 or defer it to 15 (since it's a more complex one)?
Thank you!
Best regards,
Christian
[1]
http://hg.openjdk.java.net/jdk/jdk/file/6f42d2a19117/src/hotspot/share/opto/loopUnswitch.cpp#l272
[2]
https://bugs.openjdk.java.net/secure/attachment/85593/wrong_dependencies.png
[3]
https://bugs.openjdk.java.net/secure/attachment/85592/fixed_dependencies.png
More information about the hotspot-compiler-dev
mailing list