Skip to content

Commit de801fe

Browse files
SirYwelleme64
authored andcommitted
8353551: C2: Constant folding for ReverseBytes nodes
Reviewed-by: epeter, vlivanov
1 parent d7cb933 commit de801fe

File tree

3 files changed

+235
-8
lines changed

3 files changed

+235
-8
lines changed

src/hotspot/share/opto/subnode.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2021,6 +2021,27 @@ const Type* SqrtHFNode::Value(PhaseGVN* phase) const {
20212021
return TypeH::make((float)sqrt((double)f));
20222022
}
20232023

2024+
static const Type* reverse_bytes(int opcode, const Type* con) {
2025+
switch (opcode) {
2026+
case Op_ReverseBytesS: return TypeInt::make(byteswap(checked_cast<jshort>(con->is_int()->get_con())));
2027+
case Op_ReverseBytesUS: return TypeInt::make(byteswap(checked_cast<jchar>(con->is_int()->get_con())));
2028+
case Op_ReverseBytesI: return TypeInt::make(byteswap(checked_cast<jint>(con->is_int()->get_con())));
2029+
case Op_ReverseBytesL: return TypeLong::make(byteswap(checked_cast<jlong>(con->is_long()->get_con())));
2030+
default: ShouldNotReachHere();
2031+
}
2032+
}
2033+
2034+
const Type* ReverseBytesNode::Value(PhaseGVN* phase) const {
2035+
const Type* type = phase->type(in(1));
2036+
if (type == Type::TOP) {
2037+
return Type::TOP;
2038+
}
2039+
if (type->singleton()) {
2040+
return reverse_bytes(Opcode(), type);
2041+
}
2042+
return bottom_type();
2043+
}
2044+
20242045
const Type* ReverseINode::Value(PhaseGVN* phase) const {
20252046
const Type *t1 = phase->type( in(1) );
20262047
if (t1 == Type::TOP) {

src/hotspot/share/opto/subnode.hpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -561,41 +561,49 @@ class SqrtHFNode : public Node {
561561
virtual const Type* Value(PhaseGVN* phase) const;
562562
};
563563

564+
565+
class ReverseBytesNode : public InvolutionNode {
566+
public:
567+
ReverseBytesNode(Node* in) : InvolutionNode(in) {}
568+
virtual const Type* Value(PhaseGVN* phase) const;
569+
};
564570
//-------------------------------ReverseBytesINode--------------------------------
565571
// reverse bytes of an integer
566-
class ReverseBytesINode : public InvolutionNode {
572+
class ReverseBytesINode : public ReverseBytesNode {
567573
public:
568-
ReverseBytesINode(Node* in) : InvolutionNode(in) {}
574+
ReverseBytesINode(Node* in) : ReverseBytesNode(in) {
575+
}
576+
569577
virtual int Opcode() const;
570578
const Type* bottom_type() const { return TypeInt::INT; }
571579
virtual uint ideal_reg() const { return Op_RegI; }
572580
};
573581

574582
//-------------------------------ReverseBytesLNode--------------------------------
575583
// reverse bytes of a long
576-
class ReverseBytesLNode : public InvolutionNode {
584+
class ReverseBytesLNode : public ReverseBytesNode {
577585
public:
578-
ReverseBytesLNode(Node* in) : InvolutionNode(in) {}
586+
ReverseBytesLNode(Node* in) : ReverseBytesNode(in) {}
579587
virtual int Opcode() const;
580588
const Type* bottom_type() const { return TypeLong::LONG; }
581589
virtual uint ideal_reg() const { return Op_RegL; }
582590
};
583591

584592
//-------------------------------ReverseBytesUSNode--------------------------------
585593
// reverse bytes of an unsigned short / char
586-
class ReverseBytesUSNode : public InvolutionNode {
594+
class ReverseBytesUSNode : public ReverseBytesNode {
587595
public:
588-
ReverseBytesUSNode(Node* in1) : InvolutionNode(in1) {}
596+
ReverseBytesUSNode(Node* in1) : ReverseBytesNode(in1) {}
589597
virtual int Opcode() const;
590598
const Type* bottom_type() const { return TypeInt::CHAR; }
591599
virtual uint ideal_reg() const { return Op_RegI; }
592600
};
593601

594602
//-------------------------------ReverseBytesSNode--------------------------------
595603
// reverse bytes of a short
596-
class ReverseBytesSNode : public InvolutionNode {
604+
class ReverseBytesSNode : public ReverseBytesNode {
597605
public:
598-
ReverseBytesSNode(Node* in) : InvolutionNode(in) {}
606+
ReverseBytesSNode(Node* in) : ReverseBytesNode(in) {}
599607
virtual int Opcode() const;
600608
const Type* bottom_type() const { return TypeInt::SHORT; }
601609
virtual uint ideal_reg() const { return Op_RegI; }
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*
2+
* Copyright (c) 2025, 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.gvn;
24+
25+
import compiler.lib.generators.Generators;
26+
import compiler.lib.generators.RestrictableGenerator;
27+
import compiler.lib.ir_framework.DontCompile;
28+
import compiler.lib.ir_framework.IR;
29+
import compiler.lib.ir_framework.IRNode;
30+
import compiler.lib.ir_framework.Run;
31+
import compiler.lib.ir_framework.Test;
32+
import compiler.lib.ir_framework.TestFramework;
33+
import jdk.test.lib.Asserts;
34+
35+
/*
36+
* @test
37+
* @bug 8353551
38+
* @summary Test that ReverseBytes operations constant-fold.
39+
* @library /test/lib /
40+
* @run driver compiler.c2.gvn.ReverseBytesConstantsTests
41+
*/
42+
public class ReverseBytesConstantsTests {
43+
44+
private static final RestrictableGenerator<Integer> GEN_CHAR = Generators.G.safeRestrict(Generators.G.ints(), Character.MIN_VALUE, Character.MAX_VALUE);
45+
private static final char C_CHAR = (char) GEN_CHAR.next().intValue();
46+
private static final RestrictableGenerator<Integer> GEN_SHORT = Generators.G.safeRestrict(Generators.G.ints(), Short.MIN_VALUE, Short.MAX_VALUE);
47+
private static final short C_SHORT = GEN_SHORT.next().shortValue();
48+
private static final RestrictableGenerator<Long> GEN_LONG = Generators.G.longs();
49+
private static final long C_LONG = GEN_LONG.next();
50+
private static final RestrictableGenerator<Integer> GEN_INT = Generators.G.ints();
51+
private static final int C_INT = GEN_INT.next();
52+
53+
public static void main(String[] args) {
54+
TestFramework.run();
55+
}
56+
57+
@Run(test = {
58+
"testI1", "testI2", "testI3",
59+
"testL1", "testL2", "testL3",
60+
"testS1", "testS2", "testS3",
61+
"testUS1", "testUS2", "testUS3",
62+
})
63+
public void runMethod() {
64+
assertResultI();
65+
assertResultL();
66+
assertResultS();
67+
assertResultUS();
68+
}
69+
70+
@DontCompile
71+
public void assertResultI() {
72+
Asserts.assertEQ(Integer.reverseBytes(0x04030201), testI1());
73+
Asserts.assertEQ(Integer.reverseBytes(0x50607080), testI2());
74+
Asserts.assertEQ(Integer.reverseBytes(0x80706050), testI3());
75+
Asserts.assertEQ(Integer.reverseBytes(C_INT), testI4());
76+
}
77+
78+
@DontCompile
79+
public void assertResultL() {
80+
Asserts.assertEQ(Long.reverseBytes(0x0807060504030201L), testL1());
81+
Asserts.assertEQ(Long.reverseBytes(0x1020304050607080L), testL2());
82+
Asserts.assertEQ(Long.reverseBytes(0x8070605040302010L), testL3());
83+
Asserts.assertEQ(Long.reverseBytes(C_LONG), testL4());
84+
}
85+
86+
@DontCompile
87+
public void assertResultS() {
88+
Asserts.assertEQ(Short.reverseBytes((short) 0x0201), testS1());
89+
Asserts.assertEQ(Short.reverseBytes((short) 0x7080), testS2());
90+
Asserts.assertEQ(Short.reverseBytes((short) 0x8070), testS3());
91+
Asserts.assertEQ(Short.reverseBytes(C_SHORT), testS4());
92+
}
93+
94+
@DontCompile
95+
public void assertResultUS() {
96+
Asserts.assertEQ(Character.reverseBytes((char) 0x0201), testUS1());
97+
Asserts.assertEQ(Character.reverseBytes((char) 0x7080), testUS2());
98+
Asserts.assertEQ(Character.reverseBytes((char) 0x8070), testUS3());
99+
Asserts.assertEQ(Character.reverseBytes(C_CHAR), testUS4());
100+
}
101+
102+
@Test
103+
@IR(failOn = {IRNode.REVERSE_BYTES_I})
104+
public int testI1() {
105+
return Integer.reverseBytes(0x04030201);
106+
}
107+
108+
@Test
109+
@IR(failOn = {IRNode.REVERSE_BYTES_I})
110+
public int testI2() {
111+
return Integer.reverseBytes(0x50607080);
112+
}
113+
114+
@Test
115+
@IR(failOn = {IRNode.REVERSE_BYTES_I})
116+
public int testI3() {
117+
return Integer.reverseBytes(0x80706050);
118+
}
119+
120+
@Test
121+
@IR(failOn = {IRNode.REVERSE_BYTES_I})
122+
public int testI4() {
123+
return Integer.reverseBytes(C_INT);
124+
}
125+
126+
@Test
127+
@IR(failOn = {IRNode.REVERSE_BYTES_L})
128+
public long testL1() {
129+
return Long.reverseBytes(0x0807060504030201L);
130+
}
131+
132+
@Test
133+
@IR(failOn = {IRNode.REVERSE_BYTES_L})
134+
public long testL2() {
135+
return Long.reverseBytes(0x1020304050607080L);
136+
}
137+
138+
@Test
139+
@IR(failOn = {IRNode.REVERSE_BYTES_L})
140+
public long testL3() {
141+
return Long.reverseBytes(0x8070605040302010L);
142+
}
143+
144+
@Test
145+
@IR(failOn = {IRNode.REVERSE_BYTES_L})
146+
public long testL4() {
147+
return Long.reverseBytes(C_LONG);
148+
}
149+
150+
@Test
151+
@IR(failOn = {IRNode.REVERSE_BYTES_S})
152+
public short testS1() {
153+
return Short.reverseBytes((short) 0x0201);
154+
}
155+
156+
@Test
157+
@IR(failOn = {IRNode.REVERSE_BYTES_S})
158+
public short testS2() {
159+
return Short.reverseBytes((short) 0x7080);
160+
}
161+
162+
@Test
163+
@IR(failOn = {IRNode.REVERSE_BYTES_S})
164+
public short testS3() {
165+
return Short.reverseBytes((short) 0x8070);
166+
}
167+
168+
@Test
169+
@IR(failOn = {IRNode.REVERSE_BYTES_S})
170+
public short testS4() {
171+
return Short.reverseBytes(C_SHORT);
172+
}
173+
174+
@Test
175+
@IR(failOn = {IRNode.REVERSE_BYTES_US})
176+
public char testUS1() {
177+
return Character.reverseBytes((char) 0x0201);
178+
}
179+
180+
@Test
181+
@IR(failOn = {IRNode.REVERSE_BYTES_US})
182+
public char testUS2() {
183+
return Character.reverseBytes((char) 0x7080);
184+
}
185+
186+
@Test
187+
@IR(failOn = {IRNode.REVERSE_BYTES_US})
188+
public char testUS3() {
189+
return Character.reverseBytes((char) 0x8070);
190+
}
191+
192+
@Test
193+
@IR(failOn = {IRNode.REVERSE_BYTES_US})
194+
public char testUS4() {
195+
return Character.reverseBytes(C_CHAR);
196+
}
197+
198+
}

0 commit comments

Comments
 (0)