Skip to content

Commit 4977922

Browse files
jaskarthTobiHartmann
authored andcommittedNov 27, 2023
8320330: Improve implementation of RShift Value
Reviewed-by: thartmann, chagedorn
1 parent a40d8d9 commit 4977922

File tree

3 files changed

+214
-11
lines changed

3 files changed

+214
-11
lines changed
 

‎src/hotspot/share/opto/mulnode.cpp

+30-11
Original file line numberDiff line numberDiff line change
@@ -1297,15 +1297,12 @@ const Type* RShiftINode::Value(PhaseGVN* phase) const {
12971297
if (t1 == Type::BOTTOM || t2 == Type::BOTTOM)
12981298
return TypeInt::INT;
12991299

1300-
if (t2 == TypeInt::INT)
1301-
return TypeInt::INT;
1302-
13031300
const TypeInt *r1 = t1->is_int(); // Handy access
13041301
const TypeInt *r2 = t2->is_int(); // Handy access
13051302

13061303
// If the shift is a constant, just shift the bounds of the type.
13071304
// For example, if the shift is 31, we just propagate sign bits.
1308-
if (r2->is_con()) {
1305+
if (!r1->is_con() && r2->is_con()) {
13091306
uint shift = r2->get_con();
13101307
shift &= BitsPerJavaInteger-1; // semantics of Java shifts
13111308
// Shift by a multiple of 32 does nothing:
@@ -1327,11 +1324,22 @@ const Type* RShiftINode::Value(PhaseGVN* phase) const {
13271324
return ti;
13281325
}
13291326

1330-
if( !r1->is_con() || !r2->is_con() )
1327+
if (!r1->is_con() || !r2->is_con()) {
1328+
// If the left input is non-negative the result must also be non-negative, regardless of what the right input is.
1329+
if (r1->_lo >= 0) {
1330+
return TypeInt::make(0, r1->_hi, MAX2(r1->_widen, r2->_widen));
1331+
}
1332+
1333+
// Conversely, if the left input is negative then the result must be negative.
1334+
if (r1->_hi <= -1) {
1335+
return TypeInt::make(r1->_lo, -1, MAX2(r1->_widen, r2->_widen));
1336+
}
1337+
13311338
return TypeInt::INT;
1339+
}
13321340

13331341
// Signed shift right
1334-
return TypeInt::make( r1->get_con() >> (r2->get_con()&31) );
1342+
return TypeInt::make(r1->get_con() >> (r2->get_con() & 31));
13351343
}
13361344

13371345
//=============================================================================
@@ -1359,15 +1367,12 @@ const Type* RShiftLNode::Value(PhaseGVN* phase) const {
13591367
if (t1 == Type::BOTTOM || t2 == Type::BOTTOM)
13601368
return TypeLong::LONG;
13611369

1362-
if (t2 == TypeInt::INT)
1363-
return TypeLong::LONG;
1364-
13651370
const TypeLong *r1 = t1->is_long(); // Handy access
13661371
const TypeInt *r2 = t2->is_int (); // Handy access
13671372

13681373
// If the shift is a constant, just shift the bounds of the type.
13691374
// For example, if the shift is 63, we just propagate sign bits.
1370-
if (r2->is_con()) {
1375+
if (!r1->is_con() && r2->is_con()) {
13711376
uint shift = r2->get_con();
13721377
shift &= (2*BitsPerJavaInteger)-1; // semantics of Java shifts
13731378
// Shift by a multiple of 64 does nothing:
@@ -1389,7 +1394,21 @@ const Type* RShiftLNode::Value(PhaseGVN* phase) const {
13891394
return tl;
13901395
}
13911396

1392-
return TypeLong::LONG; // Give up
1397+
if (!r1->is_con() || !r2->is_con()) {
1398+
// If the left input is non-negative the result must also be non-negative, regardless of what the right input is.
1399+
if (r1->_lo >= 0) {
1400+
return TypeLong::make(0, r1->_hi, MAX2(r1->_widen, r2->_widen));
1401+
}
1402+
1403+
// Conversely, if the left input is negative then the result must be negative.
1404+
if (r1->_hi <= -1) {
1405+
return TypeLong::make(r1->_lo, -1, MAX2(r1->_widen, r2->_widen));
1406+
}
1407+
1408+
return TypeLong::LONG;
1409+
}
1410+
1411+
return TypeLong::make(r1->get_con() >> (r2->get_con() & 63));
13931412
}
13941413

13951414
//=============================================================================
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package compiler.c2.irTests;
24+
25+
import jdk.test.lib.Asserts;
26+
import compiler.lib.ir_framework.*;
27+
28+
/*
29+
* @test
30+
* @bug 8320330
31+
* @summary Test that RShiftINode optimizations are being performed as expected.
32+
* @library /test/lib /
33+
* @run driver compiler.c2.irTests.RShiftINodeIdealizationTests
34+
*/
35+
public class RShiftINodeIdealizationTests {
36+
public static void main(String[] args) {
37+
TestFramework.run();
38+
}
39+
40+
@Run(test = { "test1", "test2", "test3", "test4" })
41+
public void runMethod() {
42+
int a = RunInfo.getRandom().nextInt();
43+
int b = RunInfo.getRandom().nextInt();
44+
int c = RunInfo.getRandom().nextInt();
45+
int d = RunInfo.getRandom().nextInt();
46+
47+
int min = Integer.MIN_VALUE;
48+
int max = Integer.MAX_VALUE;
49+
50+
assertResult(a, 0);
51+
assertResult(a, b);
52+
assertResult(b, a);
53+
assertResult(c, d);
54+
assertResult(d, c);
55+
assertResult(min, max);
56+
assertResult(max, min);
57+
assertResult(min, min);
58+
assertResult(max, max);
59+
}
60+
61+
@DontCompile
62+
public void assertResult(int x, int y) {
63+
Asserts.assertEQ((x >> y) >= 0 ? 0 : 1, test1(x, y));
64+
Asserts.assertEQ(((x & 127) >> y) >= 0 ? 0 : 1, test2(x, y));
65+
Asserts.assertEQ(((-(x & 127) - 1) >> y) >= 0 ? 0 : 1, test3(x, y));
66+
Asserts.assertEQ((x >> 30) > 4 ? 0 : 1, test4(x, y));
67+
}
68+
69+
@Test
70+
@IR(counts = { IRNode.RSHIFT, "1" })
71+
public int test1(int x, int y) {
72+
return (x >> y) >= 0 ? 0 : 1;
73+
}
74+
75+
@Test
76+
@IR(failOn = { IRNode.RSHIFT })
77+
public int test2(int x, int y) {
78+
return ((x & 127) >> y) >= 0 ? 0 : 1;
79+
}
80+
81+
@Test
82+
@IR(failOn = { IRNode.RSHIFT })
83+
public int test3(int x, int y) {
84+
return ((-(x & 127) - 1) >> y) >= 0 ? 0 : 1;
85+
}
86+
87+
@Test
88+
@IR(failOn = { IRNode.RSHIFT })
89+
public int test4(int x, int y) {
90+
return (x >> 30) > 4 ? 0 : 1;
91+
}
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package compiler.c2.irTests;
24+
25+
import jdk.test.lib.Asserts;
26+
import compiler.lib.ir_framework.*;
27+
28+
/*
29+
* @test
30+
* @bug 8320330
31+
* @summary Test that RShiftLNode optimizations are being performed as expected.
32+
* @library /test/lib /
33+
* @run driver compiler.c2.irTests.RShiftLNodeIdealizationTests
34+
*/
35+
public class RShiftLNodeIdealizationTests {
36+
public static void main(String[] args) {
37+
TestFramework.run();
38+
}
39+
40+
@Run(test = { "test1", "test2", "test3", "test4" })
41+
public void runMethod() {
42+
long a = RunInfo.getRandom().nextLong();
43+
long b = RunInfo.getRandom().nextLong();
44+
long c = RunInfo.getRandom().nextLong();
45+
long d = RunInfo.getRandom().nextLong();
46+
47+
long min = Long.MIN_VALUE;
48+
long max = Long.MAX_VALUE;
49+
50+
assertResult(a, 0);
51+
assertResult(a, b);
52+
assertResult(b, a);
53+
assertResult(c, d);
54+
assertResult(d, c);
55+
assertResult(min, max);
56+
assertResult(max, min);
57+
assertResult(min, min);
58+
assertResult(max, max);
59+
}
60+
61+
@DontCompile
62+
public void assertResult(long x, long y) {
63+
Asserts.assertEQ((x >> y) >= 0 ? 0L : 1L, test1(x, y));
64+
Asserts.assertEQ(((x & 127) >> y) >= 0 ? 0L : 1L, test2(x, y));
65+
Asserts.assertEQ(((-(x & 127) - 1) >> y) >= 0 ? 0L : 1L, test3(x, y));
66+
Asserts.assertEQ((x >> 62) > 4 ? 0L : 1L, test4(x, y));
67+
}
68+
69+
@Test
70+
@IR(counts = { IRNode.RSHIFT, "1" })
71+
public long test1(long x, long y) {
72+
return (x >> y) >= 0 ? 0 : 1;
73+
}
74+
75+
@Test
76+
@IR(failOn = { IRNode.RSHIFT })
77+
public long test2(long x, long y) {
78+
return ((x & 127) >> y) >= 0 ? 0L : 1L;
79+
}
80+
81+
@Test
82+
@IR(failOn = { IRNode.RSHIFT })
83+
public long test3(long x, long y) {
84+
return ((-(x & 127) - 1) >> y) >= 0 ? 0L : 1L;
85+
}
86+
87+
@Test
88+
@IR(failOn = { IRNode.RSHIFT })
89+
public long test4(long x, long y) {
90+
return (x >> 62) > 4 ? 0L : 1L;
91+
}
92+
}

0 commit comments

Comments
 (0)