mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-10 21:50:07 +00:00
8288564: C2: LShiftLNode::Ideal produces wrong result after JDK-8278114
Reviewed-by: kvn, iveresov, thartmann
This commit is contained in:
parent
ae030bcbc5
commit
ed714af854
@ -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));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ import compiler.lib.ir_framework.*;
|
||||
|
||||
/*
|
||||
* @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
|
||||
@ -149,4 +149,34 @@ public class TestIRLShiftIdeal_XPlusX_LShiftC {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user