Reduced fuzz test case:
public class Test {
static {
init();
}
public static void init() {
}
public void mainTest() {
int i = 8;
while ((i -= 3) > 0);
System.out.println("i" + i);
}
public static void main(String[] args) {
Test _instance = new Test();
_instance.mainTest();
_instance.mainTest();
}
}
Two steps to reproduce the bug:
Step1: Compile the test case with a 8u javac: javac Test.java
Step2: Run the test case with latest jdk14: java -XX:-BackgroundCompilation -XX:-TieredCompilation -Xcomp -XX:CompileCommand=compileonly,\*Test.\* Test
Expected output:
CompileCommand: compileonly *Test.*
i-1
i-1
Unexpected output:
CompileCommand: compileonly *Test.*
i-1
i/
Proposed fix which is currently under testing:
diff -r 5b5de2618756 src/hotspot/share/opto/loopTransform.cpp
--- a/src/hotspot/share/opto/loopTransform.cpp Mon Oct 07 17:13:59 2019 -0700
+++ b/src/hotspot/share/opto/loopTransform.cpp Wed Oct 09 15:39:42 2019 +0800
@@ -3129,6 +3129,13 @@
// We also need to replace the original limit to collapse loop exit.
Node* cmp = cl->loopexit()->cmp_node();
assert(cl->limit() == cmp->in(2), "sanity");
+ // Duplicate cmp node if it has other users
+ if (cmp->outcnt() > 1) {
+ cmp = cmp->clone();
+ cmp = phase->_igvn.register_new_node_with_optimizer(cmp);
+ BoolNode *bol = cl->loopexit()->in(CountedLoopEndNode::TestValue)->as_Bool();
+ phase->_igvn.replace_input_of(bol, 1, cmp); // put bol on worklist
+ }
phase->_igvn._worklist.push(cmp->in(2)); // put limit on worklist
phase->_igvn.replace_input_of(cmp, 2, exact_limit); // put cmp on worklist
}