Skip to content

Commit c619666

Browse files
Fei GaoDamonFool
authored andcommitted
8276673: Optimize abs operations in C2 compiler
Reviewed-by: thartmann, jiefu
1 parent fef8f2d commit c619666

File tree

5 files changed

+303
-5
lines changed

5 files changed

+303
-5
lines changed

src/hotspot/share/opto/subnode.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, 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
@@ -1847,6 +1847,64 @@ bool BoolNode::is_counted_loop_exit_test() {
18471847
return false;
18481848
}
18491849

1850+
//=============================================================================
1851+
//------------------------------Value------------------------------------------
1852+
const Type* AbsNode::Value(PhaseGVN* phase) const {
1853+
const Type* t1 = phase->type(in(1));
1854+
if (t1 == Type::TOP) return Type::TOP;
1855+
1856+
switch (t1->base()) {
1857+
case Type::Int: {
1858+
const TypeInt* ti = t1->is_int();
1859+
if (ti->is_con()) {
1860+
return TypeInt::make(uabs(ti->get_con()));
1861+
}
1862+
break;
1863+
}
1864+
case Type::Long: {
1865+
const TypeLong* tl = t1->is_long();
1866+
if (tl->is_con()) {
1867+
return TypeLong::make(uabs(tl->get_con()));
1868+
}
1869+
break;
1870+
}
1871+
case Type::FloatCon:
1872+
return TypeF::make(abs(t1->getf()));
1873+
case Type::DoubleCon:
1874+
return TypeD::make(abs(t1->getd()));
1875+
default:
1876+
break;
1877+
}
1878+
1879+
return bottom_type();
1880+
}
1881+
1882+
//------------------------------Identity----------------------------------------
1883+
Node* AbsNode::Identity(PhaseGVN* phase) {
1884+
Node* in1 = in(1);
1885+
// No need to do abs for non-negative values
1886+
if (phase->type(in1)->higher_equal(TypeInt::POS) ||
1887+
phase->type(in1)->higher_equal(TypeLong::POS)) {
1888+
return in1;
1889+
}
1890+
// Convert "abs(abs(x))" into "abs(x)"
1891+
if (in1->Opcode() == Opcode()) {
1892+
return in1;
1893+
}
1894+
return this;
1895+
}
1896+
1897+
//------------------------------Ideal------------------------------------------
1898+
Node* AbsNode::Ideal(PhaseGVN* phase, bool can_reshape) {
1899+
Node* in1 = in(1);
1900+
// Convert "abs(0-x)" into "abs(x)"
1901+
if (in1->is_Sub() && phase->type(in1->in(1))->is_zero_type()) {
1902+
set_req_X(1, in1->in(2), phase);
1903+
return this;
1904+
}
1905+
return NULL;
1906+
}
1907+
18501908
//=============================================================================
18511909
//------------------------------Value------------------------------------------
18521910
// Compute sqrt

src/hotspot/share/opto/subnode.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, 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
@@ -347,6 +347,9 @@ class BoolNode : public Node {
347347
class AbsNode : public Node {
348348
public:
349349
AbsNode( Node *value ) : Node(0,value) {}
350+
virtual Node* Identity(PhaseGVN* phase);
351+
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
352+
virtual const Type* Value(PhaseGVN* phase) const;
350353
};
351354

352355
//------------------------------AbsINode---------------------------------------

src/hotspot/share/opto/type.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, 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
@@ -593,7 +593,7 @@ class TypeInt : public TypeInteger {
593593

594594
// Check for single integer
595595
bool is_con() const { return _lo==_hi; }
596-
bool is_con(int i) const { return is_con() && _lo == i; }
596+
bool is_con(jint i) const { return is_con() && _lo == i; }
597597
jint get_con() const { assert(is_con(), "" ); return _lo; }
598598

599599
virtual bool is_finite() const; // Has a finite value
@@ -661,7 +661,7 @@ class TypeLong : public TypeInteger {
661661

662662
// Check for single integer
663663
bool is_con() const { return _lo==_hi; }
664-
bool is_con(int i) const { return is_con() && _lo == i; }
664+
bool is_con(jlong i) const { return is_con() && _lo == i; }
665665
jlong get_con() const { assert(is_con(), "" ); return _lo; }
666666

667667
// Check for positive 32-bit value.
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
/*
2+
* Copyright (c) 2022, Arm Limited. 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+
package compiler.c2.irTests;
25+
26+
import jdk.test.lib.Asserts;
27+
import compiler.lib.ir_framework.*;
28+
29+
/*
30+
* @test
31+
* @bug 8276673
32+
* @summary Test abs nodes optimization in C2.
33+
* @library /test/lib /
34+
* @run driver compiler.c2.irTests.TestIRAbs
35+
*/
36+
37+
public class TestIRAbs {
38+
39+
public static char [] cspecial = {
40+
0, 42, 128, 256, 1024, 4096, 65535
41+
};
42+
43+
public static int [] ispecial = {
44+
0, Integer.MAX_VALUE, Integer.MIN_VALUE, -42, 42, -1, 1
45+
};
46+
47+
public static long [] lspecial = {
48+
0, Long.MAX_VALUE, Long.MIN_VALUE, -42, 42, -1, 1
49+
};
50+
51+
public static float [] fspecial = {
52+
0.0f,
53+
-0.0f,
54+
Float.MAX_VALUE,
55+
Float.MIN_VALUE,
56+
-Float.MAX_VALUE,
57+
-Float.MIN_VALUE,
58+
Float.NaN,
59+
Float.POSITIVE_INFINITY,
60+
Float.NEGATIVE_INFINITY,
61+
Integer.MAX_VALUE,
62+
Integer.MIN_VALUE,
63+
Long.MAX_VALUE,
64+
Long.MIN_VALUE,
65+
-1.0f,
66+
1.0f,
67+
-42.0f,
68+
42.0f
69+
};
70+
71+
public static double [] dspecial = {
72+
0.0,
73+
-0.0,
74+
Double.MAX_VALUE,
75+
Double.MIN_VALUE,
76+
-Double.MAX_VALUE,
77+
-Double.MIN_VALUE,
78+
Double.NaN,
79+
Double.POSITIVE_INFINITY,
80+
Double.NEGATIVE_INFINITY,
81+
Integer.MAX_VALUE,
82+
Integer.MIN_VALUE,
83+
Long.MIN_VALUE,
84+
Long.MAX_VALUE,
85+
-1,
86+
1,
87+
42,
88+
-42,
89+
Math.PI,
90+
Math.E,
91+
Float.MAX_VALUE,
92+
Float.MIN_VALUE,
93+
-Float.MAX_VALUE,
94+
-Float.MIN_VALUE,
95+
Float.NaN,
96+
Float.POSITIVE_INFINITY,
97+
Float.NEGATIVE_INFINITY
98+
};
99+
100+
public static void main(String[] args) {
101+
TestFramework.run();
102+
}
103+
104+
@Test
105+
@IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D})
106+
public void testAbsConstant() {
107+
// Test abs(constant) optimization for int
108+
Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(Integer.MAX_VALUE));
109+
Asserts.assertEquals(Integer.MIN_VALUE, Math.abs(Integer.MIN_VALUE));
110+
Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(-Integer.MAX_VALUE));
111+
112+
// Test abs(constant) optimization for long
113+
Asserts.assertEquals(Long.MAX_VALUE, Math.abs(Long.MAX_VALUE));
114+
Asserts.assertEquals(Long.MIN_VALUE, Math.abs(Long.MIN_VALUE));
115+
Asserts.assertEquals(Long.MAX_VALUE, Math.abs(-Long.MAX_VALUE));
116+
117+
// Test abs(constant) optimization for float
118+
Asserts.assertTrue(Float.isNaN(Math.abs(Float.NaN)));
119+
Asserts.assertEquals(Float.POSITIVE_INFINITY, Math.abs(Float.NEGATIVE_INFINITY));
120+
Asserts.assertEquals(Float.POSITIVE_INFINITY, Math.abs(Float.POSITIVE_INFINITY));
121+
Asserts.assertEquals(0.0f, Math.abs(0.0f));
122+
Asserts.assertEquals(0.0f, Math.abs(-0.0f));
123+
Asserts.assertEquals(Float.MAX_VALUE, Math.abs(Float.MAX_VALUE));
124+
Asserts.assertEquals(Float.MIN_VALUE, Math.abs(Float.MIN_VALUE));
125+
Asserts.assertEquals(Float.MAX_VALUE, Math.abs(-Float.MAX_VALUE));
126+
Asserts.assertEquals(Float.MIN_VALUE, Math.abs(-Float.MIN_VALUE));
127+
128+
// Test abs(constant) optimization for double
129+
Asserts.assertTrue(Double.isNaN(Math.abs(Double.NaN)));
130+
Asserts.assertEquals(Double.POSITIVE_INFINITY, Math.abs(Double.NEGATIVE_INFINITY));
131+
Asserts.assertEquals(Double.POSITIVE_INFINITY, Math.abs(Double.POSITIVE_INFINITY));
132+
Asserts.assertEquals(0.0, Math.abs(0.0));
133+
Asserts.assertEquals(0.0, Math.abs(-0.0));
134+
Asserts.assertEquals(Double.MAX_VALUE, Math.abs(Double.MAX_VALUE));
135+
Asserts.assertEquals(Double.MIN_VALUE, Math.abs(Double.MIN_VALUE));
136+
Asserts.assertEquals(Double.MAX_VALUE, Math.abs(-Double.MAX_VALUE));
137+
Asserts.assertEquals(Double.MIN_VALUE, Math.abs(-Double.MIN_VALUE));
138+
}
139+
140+
@Test
141+
@IR(counts = {IRNode.ABS_I, "1"})
142+
public int testInt0(int x) {
143+
return Math.abs(Math.abs(x)); // transformed to Math.abs(x)
144+
}
145+
146+
@Test
147+
@IR(failOn = {IRNode.SUB_I})
148+
@IR(counts = {IRNode.ABS_I, "1"})
149+
public int testInt1(int x) {
150+
return Math.abs(0 - x); // transformed to Math.abs(x)
151+
}
152+
153+
@Run(test = {"testInt0", "testInt1"})
154+
public void checkTestInt(RunInfo info) {
155+
for (int i = 0; i < ispecial.length; i++) {
156+
Asserts.assertEquals(Math.abs(ispecial[i]), testInt0(ispecial[i]));
157+
Asserts.assertEquals(Math.abs(ispecial[i]), testInt1(ispecial[i]));
158+
}
159+
}
160+
161+
@Test
162+
@IR(counts = {IRNode.ABS_L, "1"})
163+
public long testLong0(long x) {
164+
return Math.abs(Math.abs(x)); // transformed to Math.abs(x)
165+
}
166+
167+
@Test
168+
@IR(failOn = {IRNode.SUB_L})
169+
@IR(counts = {IRNode.ABS_L, "1"})
170+
public long testLong1(long x) {
171+
return Math.abs(0 - x); // transformed to Math.abs(x)
172+
}
173+
174+
@Run(test = {"testLong0", "testLong1"})
175+
public void checkTestLong(RunInfo info) {
176+
for (int i = 0; i < lspecial.length; i++) {
177+
Asserts.assertEquals(Math.abs(lspecial[i]), testLong0(lspecial[i]));
178+
Asserts.assertEquals(Math.abs(lspecial[i]), testLong1(lspecial[i]));
179+
}
180+
}
181+
182+
@Test
183+
@IR(counts = {IRNode.ABS_F, "1"})
184+
public float testFloat0(float x) {
185+
return Math.abs(Math.abs(x)); // transformed to Math.abs(x)
186+
}
187+
188+
@Test
189+
@IR(failOn = {IRNode.SUB_F})
190+
@IR(counts = {IRNode.ABS_F, "1"})
191+
public float testFloat1(float x) {
192+
return Math.abs(0 - x); // transformed to Math.abs(x)
193+
}
194+
195+
@Run(test = {"testFloat0", "testFloat1"})
196+
public void checkTestFloat(RunInfo info) {
197+
for (int i = 0; i < fspecial.length; i++) {
198+
Asserts.assertEquals(Math.abs(fspecial[i]), testFloat0(fspecial[i]));
199+
Asserts.assertEquals(Math.abs(fspecial[i]), testFloat1(fspecial[i]));
200+
}
201+
}
202+
203+
@Test
204+
@IR(counts = {IRNode.ABS_D, "1"})
205+
public double testDouble0(double x) {
206+
return Math.abs(Math.abs(x)); // transformed to Math.abs(x)
207+
}
208+
209+
@Test
210+
@IR(failOn = {IRNode.SUB_D})
211+
@IR(counts = {IRNode.ABS_D, "1"})
212+
public double testDouble1(double x) {
213+
return Math.abs(0 - x); // transformed to Math.abs(x)
214+
}
215+
216+
@Run(test = {"testDouble0", "testDouble1"})
217+
public void checkTestDouble(RunInfo info) {
218+
for (int i = 0; i < dspecial.length; i++) {
219+
Asserts.assertEquals(Math.abs(dspecial[i]), testDouble0(dspecial[i]));
220+
Asserts.assertEquals(Math.abs(dspecial[i]), testDouble1(dspecial[i]));
221+
}
222+
}
223+
224+
@Test
225+
@IR(failOn = {IRNode.ABS_I})
226+
public void testChar() {
227+
for (int i = 0; i < cspecial.length; i++) {
228+
Asserts.assertEquals(cspecial[i], (char) Math.abs(cspecial[i]));
229+
}
230+
}
231+
}

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ public class IRNode {
136136
public static final String SCOPE_OBJECT = "(.*# ScObj.*" + END;
137137
public static final String MEMBAR = START + "MemBar" + MID + END;
138138

139+
public static final String ABS_I = START + "AbsI" + MID + END;
140+
public static final String ABS_L = START + "AbsL" + MID + END;
141+
public static final String ABS_F = START + "AbsF" + MID + END;
142+
public static final String ABS_D = START + "AbsD" + MID + END;
139143
public static final String AND_I = START + "AndI" + MID + END;
140144
public static final String AND_L = START + "AndL" + MID + END;
141145
public static final String LSHIFT_I = START + "LShiftI" + MID + END;
@@ -145,6 +149,8 @@ public class IRNode {
145149
public static final String ADD_VD = START + "AddVD" + MID + END;
146150
public static final String SUB_I = START + "SubI" + MID + END;
147151
public static final String SUB_L = START + "SubL" + MID + END;
152+
public static final String SUB_F = START + "SubF" + MID + END;
153+
public static final String SUB_D = START + "SubD" + MID + END;
148154
public static final String MUL_I = START + "MulI" + MID + END;
149155
public static final String MUL_L = START + "MulL" + MID + END;
150156
public static final String CONV_I2L = START + "ConvI2L" + MID + END;

0 commit comments

Comments
 (0)