Discovered this while working on JDK-8350576.
java -XX:CompileCommand=compileonly,Test::test* -Xbatch -XX:+PrintIdeal Test.java
CompileCommand: compileonly Test.test* bool compileonly = true
AFTER: print_ideal
0 Root === 0 25 [[ 0 1 3 23 ]] inner
3 Start === 3 0 [[ 3 5 6 7 8 9 10 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:long, 6:half}
5 Parm === 3 [[ 25 ]] Control !jvms: Test::testL @ bci:-1 (line 3)
6 Parm === 3 [[ 25 ]] I_O !jvms: Test::testL @ bci:-1 (line 3)
7 Parm === 3 [[ 25 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: Test::testL @ bci:-1 (line 3)
8 Parm === 3 [[ 25 ]] FramePtr !jvms: Test::testL @ bci:-1 (line 3)
9 Parm === 3 [[ 25 ]] ReturnAdr !jvms: Test::testL @ bci:-1 (line 3)
10 Parm === 3 [[ 24 ]] Parm0: long !jvms: Test::testL @ bci:-1 (line 3)
23 ConL === 0 [[ 24 ]] #long:-1
24 OrL === _ 10 23 [[ 25 ]] !jvms: Test::testL @ bci:4 (line 3)
25 Return === 5 6 7 8 9 returns 24 [[ 0 ]]
AFTER: print_ideal
0 Root === 0 24 [[ 0 1 3 22 ]] inner
3 Start === 3 0 [[ 3 5 6 7 8 9 10 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:int}
5 Parm === 3 [[ 24 ]] Control !jvms: Test::testI @ bci:-1 (line 7)
6 Parm === 3 [[ 24 ]] I_O !jvms: Test::testI @ bci:-1 (line 7)
7 Parm === 3 [[ 24 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: Test::testI @ bci:-1 (line 7)
8 Parm === 3 [[ 24 ]] FramePtr !jvms: Test::testI @ bci:-1 (line 7)
9 Parm === 3 [[ 24 ]] ReturnAdr !jvms: Test::testI @ bci:-1 (line 7)
10 Parm === 3 [[ 23 ]] Parm0: int !jvms: Test::testI @ bci:-1 (line 7)
22 ConI === 0 [[ 23 ]] #int:-1
23 OrI === _ 10 22 [[ 24 ]] !jvms: Test::testI @ bci:2 (line 7)
24 Return === 5 6 7 8 9 returns 23 [[ 0 ]]
But doing OR with all ones (i.e. -1) should give us back all ones (i.e. -1). We could write an OrINode and OrLNode Value optimization like this:
diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp
index 8406fe8b69e..9192b5c67c3 100644
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -911,6 +911,13 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeLong *r0 = t0->is_long(); // Handy access
const TypeLong *r1 = t1->is_long();
+ // x | -1 => -1
+ if (!r0->is_con() && r1->get_con() == (jlong)-1) {
+ tty->print_cr("OrLNode -> fold!");
+ this->dump(1);
+ return r1;
+ }
+
// If either input is not a constant, just return all integers.
if( !r0->is_con() || !r1->is_con() )
return TypeLong::LONG; // Any integer, but still no symbols.
We can use the attached test, and turn it into an IR test to verify that there is no Or node in the final IR. And of course we should feed in random input values for x, and do result verification.
Interestingly, there is already a similar optimization for vectors:
2088 Node* OrVNode::Identity(PhaseGVN* phase) {
2089 // (OrV (Replicate m1) src) => (Replicate m1)
2090 // (OrVMask (MaskAll m1) src) => (MaskAll m1)
2091 if (VectorNode::is_all_ones_vector(in(1))) {
2092 return in(1);
2093 }
java -XX:CompileCommand=compileonly,Test::test* -Xbatch -XX:+PrintIdeal Test.java
CompileCommand: compileonly Test.test* bool compileonly = true
AFTER: print_ideal
0 Root === 0 25 [[ 0 1 3 23 ]] inner
3 Start === 3 0 [[ 3 5 6 7 8 9 10 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:long, 6:half}
5 Parm === 3 [[ 25 ]] Control !jvms: Test::testL @ bci:-1 (line 3)
6 Parm === 3 [[ 25 ]] I_O !jvms: Test::testL @ bci:-1 (line 3)
7 Parm === 3 [[ 25 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: Test::testL @ bci:-1 (line 3)
8 Parm === 3 [[ 25 ]] FramePtr !jvms: Test::testL @ bci:-1 (line 3)
9 Parm === 3 [[ 25 ]] ReturnAdr !jvms: Test::testL @ bci:-1 (line 3)
10 Parm === 3 [[ 24 ]] Parm0: long !jvms: Test::testL @ bci:-1 (line 3)
23 ConL === 0 [[ 24 ]] #long:-1
24 OrL === _ 10 23 [[ 25 ]] !jvms: Test::testL @ bci:4 (line 3)
25 Return === 5 6 7 8 9 returns 24 [[ 0 ]]
AFTER: print_ideal
0 Root === 0 24 [[ 0 1 3 22 ]] inner
3 Start === 3 0 [[ 3 5 6 7 8 9 10 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:int}
5 Parm === 3 [[ 24 ]] Control !jvms: Test::testI @ bci:-1 (line 7)
6 Parm === 3 [[ 24 ]] I_O !jvms: Test::testI @ bci:-1 (line 7)
7 Parm === 3 [[ 24 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: Test::testI @ bci:-1 (line 7)
8 Parm === 3 [[ 24 ]] FramePtr !jvms: Test::testI @ bci:-1 (line 7)
9 Parm === 3 [[ 24 ]] ReturnAdr !jvms: Test::testI @ bci:-1 (line 7)
10 Parm === 3 [[ 23 ]] Parm0: int !jvms: Test::testI @ bci:-1 (line 7)
22 ConI === 0 [[ 23 ]] #int:-1
23 OrI === _ 10 22 [[ 24 ]] !jvms: Test::testI @ bci:2 (line 7)
24 Return === 5 6 7 8 9 returns 23 [[ 0 ]]
But doing OR with all ones (i.e. -1) should give us back all ones (i.e. -1). We could write an OrINode and OrLNode Value optimization like this:
diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp
index 8406fe8b69e..9192b5c67c3 100644
--- a/src/hotspot/share/opto/addnode.cpp
+++ b/src/hotspot/share/opto/addnode.cpp
@@ -911,6 +911,13 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeLong *r0 = t0->is_long(); // Handy access
const TypeLong *r1 = t1->is_long();
+ // x | -1 => -1
+ if (!r0->is_con() && r1->get_con() == (jlong)-1) {
+ tty->print_cr("OrLNode -> fold!");
+ this->dump(1);
+ return r1;
+ }
+
// If either input is not a constant, just return all integers.
if( !r0->is_con() || !r1->is_con() )
return TypeLong::LONG; // Any integer, but still no symbols.
We can use the attached test, and turn it into an IR test to verify that there is no Or node in the final IR. And of course we should feed in random input values for x, and do result verification.
Interestingly, there is already a similar optimization for vectors:
2088 Node* OrVNode::Identity(PhaseGVN* phase) {
2089 // (OrV (Replicate m1) src) => (Replicate m1)
2090 // (OrVMask (MaskAll m1) src) => (MaskAll m1)
2091 if (VectorNode::is_all_ones_vector(in(1))) {
2092 return in(1);
2093 }
- relates to
-
JDK-8350576 C2: assert(false) failed: reduction has ctrl or bad vector_input
-
- Open
-
- links to
-
Review(master) openjdk/jdk/24289