Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8288564: C2: LShiftLNode::Ideal produces wrong result after JDK-8278114
Reviewed-by: kvn, iveresov, thartmann
  • Loading branch information
chhagedorn committed Jun 20, 2022
1 parent ae030bc commit ed714af
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 2 deletions.
9 changes: 8 additions & 1 deletion src/hotspot/share/opto/mulnode.cpp
Expand Up @@ -813,6 +813,8 @@ Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Left input is an add of the same number?
if (add1->in(1) == add1->in(2)) {
// Convert "(x + x) << c0" into "x << (c0 + 1)"
// In general, this optimization cannot be applied for c0 == 31 since
// 2x << 31 != x << 32 = x << 0 = x (e.g. x = 1: 2 << 31 = 0 != 1)
return new LShiftINode(add1->in(1), phase->intcon(con + 1));
}

Expand Down Expand Up @@ -930,8 +932,13 @@ Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
assert( add1 != add1->in(1), "dead loop in LShiftLNode::Ideal" );

// Left input is an add of the same number?
if (add1->in(1) == add1->in(2)) {
if (con != (BitsPerJavaLong - 1) && add1->in(1) == add1->in(2)) {
// Convert "(x + x) << c0" into "x << (c0 + 1)"
// Can only be applied if c0 != 63 because:
// (x + x) << 63 = 2x << 63, while
// (x + x) << 63 --transform--> x << 64 = x << 0 = x (!= 2x << 63, for example for x = 1)
// According to the Java spec, chapter 15.19, we only consider the six lowest-order bits of the right-hand operand
// (i.e. "right-hand operand" & 0b111111). Therefore, x << 64 is the same as x << 0 (64 = 0b10000000 & 0b0111111 = 0).
return new LShiftLNode(add1->in(1), phase->intcon(con + 1));
}

Expand Down
Expand Up @@ -28,7 +28,7 @@

/*
* @test
* @bug 8278114
* @bug 8278114 8288564
* @summary Test that transformation from (x + x) >> c to x >> (c + 1) works as intended.
* @library /test/lib /
* @requires vm.compiler2.enabled
Expand Down Expand Up @@ -149,4 +149,34 @@ private void assertC2Compiled(RunInfo info) {
Asserts.assertTrue(info.isTestC2Compiled());
}
}

@Test
@IR(failOn = {IRNode.MUL_I})
@IR(counts = {IRNode.LSHIFT_I, "1",
IRNode.ADD_I, "1"})
public int testIntRandom(int x) {
return (x + x) << 31;
}

@Run(test = "testIntRandom")
public void runTestIntRandom() {
int random = RunInfo.getRandom().nextInt();
int interpreterResult = (random + random) << 31;
Asserts.assertEQ(testIntRandom(random), interpreterResult);
}

@Test
@IR(failOn = {IRNode.MUL_L})
@IR(counts = {IRNode.LSHIFT_L, "1",
IRNode.ADD_L, "1"})
public long testLongRandom(long x) {
return (x + x) << 63;
}

@Run(test = "testLongRandom")
public void runTestLongRandom() {
long random = RunInfo.getRandom().nextLong();
long interpreterResult = (random + random) << 63;
Asserts.assertEQ(testLongRandom(random), interpreterResult);
}
}

0 comments on commit ed714af

Please sign in to comment.