Skip to content

Commit f301663

Browse files
committed
8352893: C2: OrL/INode::add_ring optimize (x | -1) to -1
Reviewed-by: epeter, thartmann, kvn
1 parent 15d36ee commit f301663

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

src/hotspot/share/opto/addnode.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,12 @@ const Type *OrINode::add_ring( const Type *t0, const Type *t1 ) const {
854854
}
855855
}
856856

857+
// If either input is all ones, the output is all ones.
858+
// x | ~0 == ~0 <==> x | -1 == -1
859+
if (r0 == TypeInt::MINUS_1 || r1 == TypeInt::MINUS_1) {
860+
return TypeInt::MINUS_1;
861+
}
862+
857863
// If either input is not a constant, just return all integers.
858864
if( !r0->is_con() || !r1->is_con() )
859865
return TypeInt::INT; // Any integer, but still no symbols.
@@ -911,6 +917,12 @@ const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const {
911917
const TypeLong *r0 = t0->is_long(); // Handy access
912918
const TypeLong *r1 = t1->is_long();
913919

920+
// If either input is all ones, the output is all ones.
921+
// x | ~0 == ~0 <==> x | -1 == -1
922+
if (r0 == TypeLong::MINUS_1 || r1 == TypeLong::MINUS_1) {
923+
return TypeLong::MINUS_1;
924+
}
925+
914926
// If either input is not a constant, just return all integers.
915927
if( !r0->is_con() || !r1->is_con() )
916928
return TypeLong::LONG; // Any integer, but still no symbols.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
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+
*/
24+
25+
package compiler.integerArithmetic;
26+
27+
import compiler.lib.ir_framework.*;
28+
import java.util.Random;
29+
import jdk.test.lib.Utils;
30+
import jdk.test.lib.Asserts;
31+
32+
/*
33+
* @test
34+
* @bug 8352893
35+
* @summary Test that an or with all bits set is folded to all bits (x | -1 == -1).
36+
* @key randomness
37+
* @library / /test/lib
38+
* @run driver compiler.integerArithmetic.TestOrSaturate
39+
*/
40+
41+
public class TestOrSaturate {
42+
public static void main(String[] args) {
43+
TestFramework.run();
44+
}
45+
46+
private static final Random random = Utils.getRandomInstance();
47+
48+
@Run(test = {"testL", "testI", "testDelayed"})
49+
public static void check() {
50+
Asserts.assertEQ(-1L, testL(random.nextLong()));
51+
Asserts.assertEQ(-1, testI(random.nextInt()));
52+
Asserts.assertEQ(-1, testDelayed(random.nextInt()));
53+
}
54+
55+
@Test
56+
@IR(failOn = { IRNode.OR_L })
57+
// Tests that the OrLNode is folded if one operand is -1.
58+
private static long testL(long x) {
59+
return x | -1L;
60+
}
61+
62+
@Test
63+
@IR(failOn = { IRNode.OR_I })
64+
// Tests that the OrINode is folded if one operand is -1.
65+
private static int testI(int x) {
66+
return x | -1;
67+
}
68+
69+
@Test
70+
@IR(counts = {IRNode.OR_I, "1"},
71+
phase = CompilePhase.AFTER_PARSING)
72+
@IR(failOn = { IRNode.OR_I })
73+
// Tests that the OrI node is folded after parsing if one operand is -1.
74+
private static int testDelayed(int x) {
75+
int min1 = 42;
76+
int limit = 2;
77+
78+
// Ensure that min1 == -1 is only known after some constant propagation.
79+
for (; limit < 4; limit *= 2) {}
80+
for (int i = 2; i < limit; i++) {
81+
min1 = -1;
82+
}
83+
84+
// Will only be folded after min1 == -1 is established.
85+
return x | min1;
86+
}
87+
}

test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,16 @@ public class IRNode {
14401440
optoOnly(OOPMAP_WITH, regex);
14411441
}
14421442

1443+
public static final String OR_I = PREFIX + "OR_I" + POSTFIX;
1444+
static {
1445+
beforeMatchingNameRegex(OR_I, "OrI");
1446+
}
1447+
1448+
public static final String OR_L = PREFIX + "OR_L" + POSTFIX;
1449+
static {
1450+
beforeMatchingNameRegex(OR_L, "OrL");
1451+
}
1452+
14431453
public static final String OR_VB = VECTOR_PREFIX + "OR_VB" + POSTFIX;
14441454
static {
14451455
vectorNode(OR_VB, "OrV", TYPE_BYTE);

0 commit comments

Comments
 (0)