Skip to content

Commit 8569227

Browse files
CptGitTobiHartmann
authored andcommitted
8322589: Add Ideal transformation: (~a) & (~b) => ~(a | b)
Reviewed-by: thartmann, epeter
1 parent f4ca41a commit 8569227

File tree

6 files changed

+132
-11
lines changed

6 files changed

+132
-11
lines changed

src/hotspot/share/opto/addnode.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -253,6 +253,22 @@ AddNode* AddNode::make(Node* in1, Node* in2, BasicType bt) {
253253
return nullptr;
254254
}
255255

256+
bool AddNode::is_not(PhaseGVN* phase, Node* n, BasicType bt) {
257+
return n->Opcode() == Op_Xor(bt) && phase->type(n->in(2)) == TypeInteger::minus_1(bt);
258+
}
259+
260+
AddNode* AddNode::make_not(PhaseGVN* phase, Node* n, BasicType bt) {
261+
switch (bt) {
262+
case T_INT:
263+
return new XorINode(n, phase->intcon(-1));
264+
case T_LONG:
265+
return new XorLNode(n, phase->longcon(-1L));
266+
default:
267+
fatal("Not implemented for %s", type2name(bt));
268+
}
269+
return nullptr;
270+
}
271+
256272
//=============================================================================
257273
//------------------------------Idealize---------------------------------------
258274
Node* AddNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) {

src/hotspot/share/opto/addnode.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -78,6 +78,13 @@ class AddNode : public Node {
7878
virtual int min_opcode() const = 0;
7979

8080
static AddNode* make(Node* in1, Node* in2, BasicType bt);
81+
82+
// Utility function to check if the given node is a NOT operation,
83+
// i.e., n == m ^ (-1).
84+
static bool is_not(PhaseGVN* phase, Node* n, BasicType bt);
85+
86+
// Utility function to make a NOT operation, i.e., returning n ^ (-1).
87+
static AddNode* make_not(PhaseGVN* phase, Node* n, BasicType bt);
8188
};
8289

8390
//------------------------------AddINode---------------------------------------

src/hotspot/share/opto/mulnode.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -610,6 +610,13 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
610610
return progress;
611611
}
612612

613+
// Convert "(~a) & (~b)" into "~(a | b)"
614+
if (AddNode::is_not(phase, in(1), T_INT) && AddNode::is_not(phase, in(2), T_INT)) {
615+
Node* or_a_b = new OrINode(in(1)->in(1), in(2)->in(1));
616+
Node* tn = phase->transform(or_a_b);
617+
return AddNode::make_not(phase, tn, T_INT);
618+
}
619+
613620
// Special case constant AND mask
614621
const TypeInt *t2 = phase->type( in(2) )->isa_int();
615622
if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape);
@@ -750,6 +757,13 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
750757
return progress;
751758
}
752759

760+
// Convert "(~a) & (~b)" into "~(a | b)"
761+
if (AddNode::is_not(phase, in(1), T_LONG) && AddNode::is_not(phase, in(2), T_LONG)) {
762+
Node* or_a_b = new OrLNode(in(1)->in(1), in(2)->in(1));
763+
Node* tn = phase->transform(or_a_b);
764+
return AddNode::make_not(phase, tn, T_LONG);
765+
}
766+
753767
// Special case constant AND mask
754768
const TypeLong *t2 = phase->type( in(2) )->isa_long();
755769
if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape);

test/hotspot/jtreg/compiler/c2/irTests/AndINodeIdealizationTests.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -38,22 +38,24 @@ public static void main(String[] args) {
3838
TestFramework.run();
3939
}
4040

41-
@Run(test = { "test1" })
41+
@Run(test = { "test1", "test2" })
4242
public void runMethod() {
4343
int a = RunInfo.getRandom().nextInt();
44+
int b = RunInfo.getRandom().nextInt();
4445

4546
int min = Integer.MIN_VALUE;
4647
int max = Integer.MAX_VALUE;
4748

48-
assertResult(0);
49-
assertResult(a);
50-
assertResult(min);
51-
assertResult(max);
49+
assertResult(0, 0);
50+
assertResult(a, b);
51+
assertResult(min, min);
52+
assertResult(max, max);
5253
}
5354

5455
@DontCompile
55-
public void assertResult(int a) {
56+
public void assertResult(int a, int b) {
5657
Asserts.assertEQ((0 - a) & 1, test1(a));
58+
Asserts.assertEQ((~a) & (~b), test2(a, b));
5759
}
5860

5961
@Test
@@ -63,4 +65,13 @@ public void assertResult(int a) {
6365
public int test1(int x) {
6466
return (0 - x) & 1;
6567
}
68+
69+
@Test
70+
@IR(failOn = { IRNode.AND })
71+
@IR(counts = { IRNode.OR, "1",
72+
IRNode.XOR, "1" })
73+
// Checks (~a) & (~b) => ~(a | b)
74+
public int test2(int a, int b) {
75+
return (~a) & (~b);
76+
}
6677
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2024, 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 8322589
31+
* @summary Test that Ideal transformations of AndLNode* are being performed as expected.
32+
* @library /test/lib /
33+
* @run driver compiler.c2.irTests.AndLNodeIdealizationTests
34+
*/
35+
public class AndLNodeIdealizationTests {
36+
37+
public static void main(String[] args) {
38+
TestFramework.run();
39+
}
40+
41+
@Run(test = { "test1" })
42+
public void runMethod() {
43+
long a = RunInfo.getRandom().nextLong();
44+
long b = RunInfo.getRandom().nextLong();
45+
46+
long min = Long.MIN_VALUE;
47+
long max = Long.MAX_VALUE;
48+
49+
assertResult(0, 0);
50+
assertResult(a, b);
51+
assertResult(min, min);
52+
assertResult(max, max);
53+
}
54+
55+
@DontCompile
56+
public void assertResult(long a, long b) {
57+
Asserts.assertEQ((~a) & (~b), test1(a, b));
58+
}
59+
60+
@Test
61+
@IR(failOn = { IRNode.AND })
62+
@IR(counts = { IRNode.OR, "1",
63+
IRNode.XOR, "1" })
64+
// Checks (~a) & (~b) => ~(a | b)
65+
public long test1(long a, long b) {
66+
return (~a) & (~b);
67+
}
68+
}

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -298,6 +298,11 @@ public class IRNode {
298298
optoOnly(ALLOC_ARRAY_OF, regex);
299299
}
300300

301+
public static final String OR = PREFIX + "OR" + POSTFIX;
302+
static {
303+
beforeMatchingNameRegex(OR, "Or(I|L)");
304+
}
305+
301306
public static final String AND = PREFIX + "AND" + POSTFIX;
302307
static {
303308
beforeMatchingNameRegex(AND, "And(I|L)");

0 commit comments

Comments
 (0)