Skip to content

Commit 7f44f57

Browse files
vamsi-parasaJatin Bhateja
authored and
Jatin Bhateja
committedJun 2, 2022
8285868: x86 intrinsics for floating point method isInfinite
Reviewed-by: kvn, jbhateja
1 parent 13596cd commit 7f44f57

18 files changed

+513
-0
lines changed
 

‎src/hotspot/cpu/x86/assembler_x86.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -10410,6 +10410,26 @@ void Assembler::vzeroupper_uncached() {
1041010410
}
1041110411
}
1041210412

10413+
void Assembler::vfpclassss(KRegister kdst, XMMRegister src, uint8_t imm8) {
10414+
// Encoding: EVEX.LIG.66.0F3A.W0 67 /r ib
10415+
assert(VM_Version::supports_evex(), "");
10416+
assert(VM_Version::supports_avx512dq(), "");
10417+
InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
10418+
attributes.set_is_evex_instruction();
10419+
int encode = vex_prefix_and_encode(kdst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
10420+
emit_int24((unsigned char)0x67, (unsigned char)(0xC0 | encode), imm8);
10421+
}
10422+
10423+
void Assembler::vfpclasssd(KRegister kdst, XMMRegister src, uint8_t imm8) {
10424+
// Encoding: EVEX.LIG.66.0F3A.W1 67 /r ib
10425+
assert(VM_Version::supports_evex(), "");
10426+
assert(VM_Version::supports_avx512dq(), "");
10427+
InstructionAttr attributes(AVX_128bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false);
10428+
attributes.set_is_evex_instruction();
10429+
int encode = vex_prefix_and_encode(kdst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
10430+
emit_int24((unsigned char)0x67, (unsigned char)(0xC0 | encode), imm8);
10431+
}
10432+
1041310433
void Assembler::fld_x(Address adr) {
1041410434
InstructionMark im(this);
1041510435
emit_int8((unsigned char)0xDB);

‎src/hotspot/cpu/x86/assembler_x86.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -2746,6 +2746,10 @@ class Assembler : public AbstractAssembler {
27462746
void evpmovm2d(XMMRegister dst, KRegister src, int vector_len);
27472747
void evpmovm2q(XMMRegister dst, KRegister src, int vector_len);
27482748

2749+
// floating point class tests
2750+
void vfpclassss(KRegister kdst, XMMRegister src, uint8_t imm8);
2751+
void vfpclasssd(KRegister kdst, XMMRegister src, uint8_t imm8);
2752+
27492753
// Vector blends
27502754
void blendvps(XMMRegister dst, XMMRegister src);
27512755
void blendvpd(XMMRegister dst, XMMRegister src);

‎src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -5316,3 +5316,4 @@ void C2_MacroAssembler::udivmodL(Register rax, Register divisor, Register rdx, R
53165316
bind(done);
53175317
}
53185318
#endif
5319+

‎src/hotspot/cpu/x86/x86.ad

+32
Original file line numberDiff line numberDiff line change
@@ -1462,6 +1462,12 @@ const bool Matcher::match_rule_supported(int opcode) {
14621462
return false;
14631463
}
14641464
break;
1465+
case Op_IsInfiniteF:
1466+
case Op_IsInfiniteD:
1467+
if (!VM_Version::supports_avx512dq()) {
1468+
return false;
1469+
}
1470+
break;
14651471
case Op_SqrtVD:
14661472
case Op_SqrtVF:
14671473
case Op_VectorMaskCmp:
@@ -10136,3 +10142,29 @@ instruct castVVLeg(legVec dst)
1013610142
ins_cost(0);
1013710143
ins_pipe(empty);
1013810144
%}
10145+
10146+
instruct FloatClassCheck_reg_reg_vfpclass(rRegI dst, regF src, kReg ktmp, rFlagsReg cr)
10147+
%{
10148+
match(Set dst (IsInfiniteF src));
10149+
effect(TEMP ktmp, KILL cr);
10150+
format %{ "float_class_check $dst, $src" %}
10151+
ins_encode %{
10152+
__ vfpclassss($ktmp$$KRegister, $src$$XMMRegister, 0x18);
10153+
__ kmovbl($dst$$Register, $ktmp$$KRegister);
10154+
%}
10155+
ins_pipe(pipe_slow);
10156+
%}
10157+
10158+
instruct DoubleClassCheck_reg_reg_vfpclass(rRegI dst, regD src, kReg ktmp, rFlagsReg cr)
10159+
%{
10160+
match(Set dst (IsInfiniteD src));
10161+
effect(TEMP ktmp, KILL cr);
10162+
format %{ "double_class_check $dst, $src" %}
10163+
ins_encode %{
10164+
__ vfpclasssd($ktmp$$KRegister, $src$$XMMRegister, 0x18);
10165+
__ kmovbl($dst$$Register, $ktmp$$KRegister);
10166+
%}
10167+
ins_pipe(pipe_slow);
10168+
%}
10169+
10170+

‎src/hotspot/share/classfile/vmIntrinsics.hpp

+4
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ class methodHandle;
203203
/* Special flavor of dsqrt intrinsic to handle the "native" method in StrictMath. Otherwise the same as in Math. */ \
204204
do_intrinsic(_dsqrt_strict, java_lang_StrictMath, sqrt_name, double_double_signature, F_SN) \
205205
\
206+
do_intrinsic(_floatIsInfinite, java_lang_Float, isInfinite_name, float_bool_signature, F_S) \
207+
do_name( isInfinite_name, "isInfinite") \
208+
do_intrinsic(_doubleIsInfinite, java_lang_Double, isInfinite_name, double_bool_signature, F_S) \
209+
\
206210
do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_SN) \
207211
do_name( floatToRawIntBits_name, "floatToRawIntBits") \
208212
do_intrinsic(_floatToIntBits, java_lang_Float, floatToIntBits_name, float_int_signature, F_S) \

‎src/hotspot/share/classfile/vmSymbols.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,8 @@
555555
template(char_char_signature, "(C)C") \
556556
template(short_short_signature, "(S)S") \
557557
template(int_bool_signature, "(I)Z") \
558+
template(float_bool_signature, "(F)Z") \
559+
template(double_bool_signature, "(D)Z") \
558560
template(float_int_signature, "(F)I") \
559561
template(double_long_signature, "(D)J") \
560562
template(double_double_signature, "(D)D") \

‎src/hotspot/share/opto/c2compiler.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,12 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
518518
case vmIntrinsics::_fsignum:
519519
if (!Matcher::match_rule_supported(Op_SignumF)) return false;
520520
break;
521+
case vmIntrinsics::_floatIsInfinite:
522+
if (!Matcher::match_rule_supported(Op_IsInfiniteF)) return false;
523+
break;
524+
case vmIntrinsics::_doubleIsInfinite:
525+
if (!Matcher::match_rule_supported(Op_IsInfiniteD)) return false;
526+
break;
521527
case vmIntrinsics::_hashCode:
522528
case vmIntrinsics::_identityHashCode:
523529
case vmIntrinsics::_getClass:

‎src/hotspot/share/opto/classes.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ macro(MoveI2F)
245245
macro(MoveF2I)
246246
macro(MoveL2D)
247247
macro(MoveD2L)
248+
macro(IsInfiniteF)
249+
macro(IsInfiniteD)
248250
macro(MulD)
249251
macro(MulF)
250252
macro(MulHiL)

‎src/hotspot/share/opto/intrinsicnode.hpp

+18
Original file line numberDiff line numberDiff line change
@@ -262,4 +262,22 @@ class SignumFNode : public Node {
262262
virtual uint ideal_reg() const { return Op_RegF; }
263263
};
264264

265+
//---------- IsInfiniteFNode -----------------------------------------------------
266+
class IsInfiniteFNode : public Node {
267+
public:
268+
IsInfiniteFNode(Node* in1) : Node(0, in1) {}
269+
virtual int Opcode() const;
270+
const Type* bottom_type() const { return TypeInt::BOOL; }
271+
virtual uint ideal_reg() const { return Op_RegI; }
272+
};
273+
274+
//---------- IsInfiniteDNode -----------------------------------------------------
275+
class IsInfiniteDNode : public Node {
276+
public:
277+
IsInfiniteDNode(Node* in1) : Node(0, in1) {}
278+
virtual int Opcode() const;
279+
const Type* bottom_type() const { return TypeInt::BOOL; }
280+
virtual uint ideal_reg() const { return Op_RegI; }
281+
};
282+
265283
#endif // SHARE_OPTO_INTRINSICNODE_HPP

‎src/hotspot/share/opto/library_call.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
516516
case vmIntrinsics::_doubleToLongBits:
517517
case vmIntrinsics::_longBitsToDouble: return inline_fp_conversions(intrinsic_id());
518518

519+
case vmIntrinsics::_floatIsInfinite:
520+
case vmIntrinsics::_doubleIsInfinite: return inline_fp_range_check(intrinsic_id());
521+
519522
case vmIntrinsics::_numberOfLeadingZeros_i:
520523
case vmIntrinsics::_numberOfLeadingZeros_l:
521524
case vmIntrinsics::_numberOfTrailingZeros_i:
@@ -4642,6 +4645,25 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) {
46424645
return true;
46434646
}
46444647

4648+
bool LibraryCallKit::inline_fp_range_check(vmIntrinsics::ID id) {
4649+
Node* arg = argument(0);
4650+
Node* result = NULL;
4651+
4652+
switch (id) {
4653+
case vmIntrinsics::_floatIsInfinite:
4654+
result = new IsInfiniteFNode(arg);
4655+
break;
4656+
case vmIntrinsics::_doubleIsInfinite:
4657+
result = new IsInfiniteDNode(arg);
4658+
break;
4659+
default:
4660+
fatal_unexpected_iid(id);
4661+
break;
4662+
}
4663+
set_result(_gvn.transform(result));
4664+
return true;
4665+
}
4666+
46454667
//----------------------inline_unsafe_copyMemory-------------------------
46464668
// public native void Unsafe.copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
46474669

‎src/hotspot/share/opto/library_call.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class LibraryCallKit : public GraphKit {
274274
bool inline_unsafe_fence(vmIntrinsics::ID id);
275275
bool inline_onspinwait();
276276
bool inline_fp_conversions(vmIntrinsics::ID id);
277+
bool inline_fp_range_check(vmIntrinsics::ID id);
277278
bool inline_number_methods(vmIntrinsics::ID id);
278279
bool inline_divmod_methods(vmIntrinsics::ID id);
279280
bool inline_reference_get();

‎src/hotspot/share/runtime/vmStructs.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1847,6 +1847,8 @@
18471847
declare_c2_type(CopySignFNode, Node) \
18481848
declare_c2_type(SignumDNode, Node) \
18491849
declare_c2_type(SignumFNode, Node) \
1850+
declare_c2_type(IsInfiniteFNode, Node) \
1851+
declare_c2_type(IsInfiniteDNode, Node) \
18501852
declare_c2_type(LoadVectorGatherNode, LoadVectorNode) \
18511853
declare_c2_type(StoreVectorScatterNode, StoreVectorNode) \
18521854
declare_c2_type(VectorLoadMaskNode, VectorNode) \

‎src/java.base/share/classes/java/lang/Double.java

+1
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,7 @@ public static boolean isNaN(double v) {
754754
* @return {@code true} if the value of the argument is positive
755755
* infinity or negative infinity; {@code false} otherwise.
756756
*/
757+
@IntrinsicCandidate
757758
public static boolean isInfinite(double v) {
758759
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
759760
}

‎src/java.base/share/classes/java/lang/Float.java

+1
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,7 @@ public static boolean isNaN(float v) {
575575
* @return {@code true} if the argument is positive infinity or
576576
* negative infinity; {@code false} otherwise.
577577
*/
578+
@IntrinsicCandidate
578579
public static boolean isInfinite(float v) {
579580
return (v == POSITIVE_INFINITY) || (v == NEGATIVE_INFINITY);
580581
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (c) 2022, 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+
* @test
26+
* @summary Test x86_64 intrinsics for Double methods isNaN, isFinite, isInfinite.
27+
* @requires vm.cpu.features ~= ".*avx512dq.*"
28+
* @library /test/lib /
29+
* @run driver compiler.intrinsics.TestDoubleClassCheck
30+
*/
31+
32+
package compiler.intrinsics;
33+
import compiler.lib.ir_framework.*;
34+
import java.util.random.RandomGenerator;
35+
import java.util.random.RandomGeneratorFactory;
36+
37+
public class TestDoubleClassCheck {
38+
RandomGenerator rng;
39+
int BUFFER_SIZE = 1024;
40+
double[] inputs;
41+
boolean[] outputs;
42+
43+
public static void main(String args[]) {
44+
TestFramework.run(TestDoubleClassCheck.class);
45+
}
46+
47+
public TestDoubleClassCheck() {
48+
outputs = new boolean[BUFFER_SIZE];
49+
inputs = new double[BUFFER_SIZE];
50+
RandomGenerator rng = RandomGeneratorFactory.getDefault().create(0);
51+
double input;
52+
for (int i = 0; i < BUFFER_SIZE; i++) {
53+
if (i % 5 == 0) {
54+
input = (i%2 == 0) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
55+
}
56+
else if (i % 3 == 0) input = Double.NaN;
57+
else input = rng.nextDouble();
58+
inputs[i] = input;
59+
}
60+
}
61+
62+
@Test // needs to be run in (fast) debug mode
63+
@Warmup(10000)
64+
@IR(counts = {"IsInfiniteD", ">= 1"}) // Atleast one IsInfiniteD node is generated if intrinsic is used
65+
public void testIsInfinite() {
66+
for (int i = 0; i < BUFFER_SIZE; i++) {
67+
outputs[i] = Double.isInfinite(inputs[i]);
68+
}
69+
checkResult("isInfinite");
70+
}
71+
72+
73+
public void checkResult(String method) {
74+
for (int i=0; i < BUFFER_SIZE; i++) {
75+
boolean expected = doubleClassCheck(inputs[i], method);
76+
if (expected != outputs[i]) {
77+
String errorMsg = "Correctness check failed for Double." + method +
78+
"() for input = " + inputs[i];
79+
throw new RuntimeException(errorMsg);
80+
}
81+
}
82+
}
83+
84+
public boolean doubleClassCheck(double f, String method) {
85+
long infBits = Double.doubleToRawLongBits(Double.POSITIVE_INFINITY);
86+
long bits = Double.doubleToRawLongBits(f);
87+
bits = bits & Long.MAX_VALUE;
88+
switch (method) {
89+
case "isFinite": return (bits < infBits);
90+
case "isInfinite": return (bits == infBits);
91+
case "isNaN": return (bits > infBits);
92+
default: throw new IllegalArgumentException("incorrect method for Double");
93+
}
94+
}
95+
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright (c) 2022, 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+
* @test
26+
* @summary Test x86_64 intrinsics for Float methods isNaN, isFinite, isInfinite.
27+
* @requires vm.cpu.features ~= ".*avx512dq.*"
28+
* @library /test/lib /
29+
* @run driver compiler.intrinsics.TestFloatClassCheck
30+
*/
31+
32+
package compiler.intrinsics;
33+
import compiler.lib.ir_framework.*;
34+
import java.util.random.RandomGenerator;
35+
import java.util.random.RandomGeneratorFactory;
36+
37+
public class TestFloatClassCheck {
38+
RandomGenerator rng;
39+
int BUFFER_SIZE = 1024;
40+
float[] inputs;
41+
boolean[] outputs;
42+
43+
public static void main(String args[]) {
44+
TestFramework.run(TestFloatClassCheck.class);
45+
}
46+
47+
public TestFloatClassCheck() {
48+
outputs = new boolean[BUFFER_SIZE];
49+
inputs = new float[BUFFER_SIZE];
50+
RandomGenerator rng = RandomGeneratorFactory.getDefault().create(0);
51+
float input;
52+
for (int i = 0; i < BUFFER_SIZE; i++) {
53+
if (i % 5 == 0) {
54+
input = (i%2 == 0) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
55+
}
56+
else if (i % 3 == 0) input = Float.NaN;
57+
else input = rng.nextFloat();
58+
inputs[i] = input;
59+
}
60+
}
61+
62+
@Test // needs to be run in (fast) debug mode
63+
@Warmup(10000)
64+
@IR(counts = {"IsInfiniteF", ">= 1"}) // Atleast one IsInfiniteF node is generated if intrinsic is used
65+
public void testIsInfinite() {
66+
for (int i = 0; i < BUFFER_SIZE; i++) {
67+
outputs[i] = Float.isInfinite(inputs[i]);
68+
}
69+
checkResult("isInfinite");
70+
}
71+
72+
public void checkResult(String method) {
73+
for (int i=0; i < BUFFER_SIZE; i++) {
74+
boolean expected = floatClassCheck(inputs[i], method);
75+
if (expected != outputs[i]) {
76+
String errorMsg = "Correctness check failed for Float." + method +
77+
"() for input = " + inputs[i];
78+
throw new RuntimeException(errorMsg);
79+
}
80+
}
81+
}
82+
83+
public boolean floatClassCheck(float f, String method) {
84+
int infBits = Float.floatToRawIntBits(Float.POSITIVE_INFINITY);
85+
int bits = Float.floatToRawIntBits(f);
86+
bits = bits & Integer.MAX_VALUE;
87+
switch (method) {
88+
case "isFinite": return (bits < infBits);
89+
case "isInfinite": return (bits == infBits);
90+
case "isNaN": return (bits > infBits);
91+
default: throw new IllegalArgumentException("incorrect method for Float");
92+
}
93+
}
94+
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright (c) 2022, 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 org.openjdk.bench.java.lang;
24+
25+
import org.openjdk.jmh.annotations.Benchmark;
26+
import org.openjdk.jmh.annotations.BenchmarkMode;
27+
import org.openjdk.jmh.annotations.CompilerControl;
28+
import org.openjdk.jmh.annotations.Fork;
29+
import org.openjdk.jmh.annotations.Mode;
30+
import org.openjdk.jmh.annotations.OperationsPerInvocation;
31+
import org.openjdk.jmh.annotations.OutputTimeUnit;
32+
import org.openjdk.jmh.annotations.Scope;
33+
import org.openjdk.jmh.annotations.Setup;
34+
import org.openjdk.jmh.annotations.State;
35+
import org.openjdk.jmh.annotations.Param;
36+
import java.util.random.RandomGenerator;
37+
import java.util.random.RandomGeneratorFactory;
38+
import java.util.concurrent.TimeUnit;
39+
40+
@BenchmarkMode(Mode.AverageTime)
41+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
42+
@State(Scope.Thread)
43+
@Fork(1)
44+
public class DoubleClassCheck {
45+
46+
RandomGenerator rng;
47+
static final int BUFFER_SIZE = 1024;
48+
double[] inputs;
49+
boolean[] storeOutputs;
50+
int[] cmovOutputs;
51+
int[] branchOutputs;
52+
53+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
54+
static int call() {
55+
return 1;
56+
}
57+
58+
@Setup
59+
public void setup() {
60+
storeOutputs = new boolean[BUFFER_SIZE];
61+
cmovOutputs = new int[BUFFER_SIZE];
62+
branchOutputs = new int[BUFFER_SIZE];
63+
inputs = new double[BUFFER_SIZE];
64+
RandomGenerator rng = RandomGeneratorFactory.getDefault().create(0);
65+
double input;
66+
for (int i = 0; i < BUFFER_SIZE; i++) {
67+
if (i % 5 == 0) {
68+
input = (i%2 == 0) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
69+
}
70+
else if (i % 3 == 0) input = Double.NaN;
71+
else input = rng.nextDouble();
72+
inputs[i] = input;
73+
}
74+
}
75+
76+
@Benchmark
77+
@OperationsPerInvocation(BUFFER_SIZE)
78+
public void testIsInfiniteStore() {
79+
for (int i = 0; i < BUFFER_SIZE; i++) {
80+
storeOutputs[i] = Double.isInfinite(inputs[i]);
81+
}
82+
}
83+
84+
85+
@Benchmark
86+
@OperationsPerInvocation(BUFFER_SIZE)
87+
public void testIsInfiniteCMov() {
88+
for (int i = 0; i < BUFFER_SIZE; i++) {
89+
cmovOutputs[i] = Double.isInfinite(inputs[i]) ? 9 : 7;
90+
}
91+
}
92+
93+
94+
@Benchmark
95+
@OperationsPerInvocation(BUFFER_SIZE)
96+
public void testIsInfiniteBranch() {
97+
for (int i = 0; i < BUFFER_SIZE; i++) {
98+
cmovOutputs[i] = Double.isInfinite(inputs[i]) ? call() : 7;
99+
}
100+
}
101+
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright (c) 2022, 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 org.openjdk.bench.java.lang;
24+
25+
import org.openjdk.jmh.annotations.Benchmark;
26+
import org.openjdk.jmh.annotations.BenchmarkMode;
27+
import org.openjdk.jmh.annotations.CompilerControl;
28+
import org.openjdk.jmh.annotations.Fork;
29+
import org.openjdk.jmh.annotations.Mode;
30+
import org.openjdk.jmh.annotations.OperationsPerInvocation;
31+
import org.openjdk.jmh.annotations.OutputTimeUnit;
32+
import org.openjdk.jmh.annotations.Scope;
33+
import org.openjdk.jmh.annotations.Setup;
34+
import org.openjdk.jmh.annotations.State;
35+
import org.openjdk.jmh.annotations.Param;
36+
import java.util.random.RandomGenerator;
37+
import java.util.random.RandomGeneratorFactory;
38+
import java.util.concurrent.TimeUnit;
39+
40+
@BenchmarkMode(Mode.AverageTime)
41+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
42+
@State(Scope.Thread)
43+
@Fork(1)
44+
public class FloatClassCheck {
45+
46+
RandomGenerator rng;
47+
static final int BUFFER_SIZE = 1024;
48+
float[] inputs;
49+
boolean[] storeOutputs;
50+
int[] cmovOutputs;
51+
int[] branchOutputs;
52+
53+
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
54+
static int call() {
55+
return 1;
56+
}
57+
58+
@Setup
59+
public void setup() {
60+
storeOutputs = new boolean[BUFFER_SIZE];
61+
cmovOutputs = new int[BUFFER_SIZE];
62+
branchOutputs = new int[BUFFER_SIZE];
63+
inputs = new float[BUFFER_SIZE];
64+
RandomGenerator rng = RandomGeneratorFactory.getDefault().create(0);
65+
float input;
66+
for (int i = 0; i < BUFFER_SIZE; i++) {
67+
if (i % 5 == 0) {
68+
input = (i % 2 == 0) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
69+
} else if (i % 3 == 0)
70+
input = Float.NaN;
71+
else
72+
input = rng.nextFloat();
73+
inputs[i] = input;
74+
}
75+
}
76+
77+
78+
@Benchmark
79+
@OperationsPerInvocation(BUFFER_SIZE)
80+
public void testIsInfiniteStore() {
81+
for (int i = 0; i < BUFFER_SIZE; i++) {
82+
storeOutputs[i] = Float.isInfinite(inputs[i]);
83+
}
84+
}
85+
86+
87+
@Benchmark
88+
@OperationsPerInvocation(BUFFER_SIZE)
89+
public void testIsInfiniteCMov() {
90+
for (int i = 0; i < BUFFER_SIZE; i++) {
91+
cmovOutputs[i] = Float.isInfinite(inputs[i]) ? 9 : 7;
92+
}
93+
}
94+
95+
96+
@Benchmark
97+
@OperationsPerInvocation(BUFFER_SIZE)
98+
public void testIsInfiniteBranch() {
99+
for (int i = 0; i < BUFFER_SIZE; i++) {
100+
cmovOutputs[i] = Float.isInfinite(inputs[i]) ? call() : 7;
101+
}
102+
}
103+
104+
}

0 commit comments

Comments
 (0)
Please sign in to comment.