Created
January 8, 2019 19:15
-
-
Save chriswhocodes/0ee21a9c33472d5bc35ce050fc961e03 to your computer and use it in GitHub Desktop.
OpenJDK hg diff for floating point min/max intrinsics hg diff -c 53041:f15af1e2c683
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/cpu/aarch64/aarch64.ad | |
--- a/src/hotspot/cpu/aarch64/aarch64.ad Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/cpu/aarch64/aarch64.ad Tue Dec 18 16:50:35 2018 +0000 | |
@@ -12601,6 +12601,63 @@ | |
%} | |
+// Math.max(FF)F | |
+instruct maxF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{ | |
+ match(Set dst (MaxF src1 src2)); | |
+ | |
+ format %{ "fmaxs $dst, $src1, $src2" %} | |
+ ins_encode %{ | |
+ __ fmaxs(as_FloatRegister($dst$$reg), | |
+ as_FloatRegister($src1$$reg), | |
+ as_FloatRegister($src2$$reg)); | |
+ %} | |
+ | |
+ ins_pipe(fp_dop_reg_reg_s); | |
+%} | |
+ | |
+// Math.min(FF)F | |
+instruct minF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{ | |
+ match(Set dst (MinF src1 src2)); | |
+ | |
+ format %{ "fmins $dst, $src1, $src2" %} | |
+ ins_encode %{ | |
+ __ fmins(as_FloatRegister($dst$$reg), | |
+ as_FloatRegister($src1$$reg), | |
+ as_FloatRegister($src2$$reg)); | |
+ %} | |
+ | |
+ ins_pipe(fp_dop_reg_reg_s); | |
+%} | |
+ | |
+// Math.max(DD)D | |
+instruct maxD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{ | |
+ match(Set dst (MaxD src1 src2)); | |
+ | |
+ format %{ "fmaxd $dst, $src1, $src2" %} | |
+ ins_encode %{ | |
+ __ fmaxd(as_FloatRegister($dst$$reg), | |
+ as_FloatRegister($src1$$reg), | |
+ as_FloatRegister($src2$$reg)); | |
+ %} | |
+ | |
+ ins_pipe(fp_dop_reg_reg_d); | |
+%} | |
+ | |
+// Math.min(DD)D | |
+instruct minD_reg_reg(vRegD dst, vRegD src1, vRegD src2) %{ | |
+ match(Set dst (MinD src1 src2)); | |
+ | |
+ format %{ "fmind $dst, $src1, $src2" %} | |
+ ins_encode %{ | |
+ __ fmind(as_FloatRegister($dst$$reg), | |
+ as_FloatRegister($src1$$reg), | |
+ as_FloatRegister($src2$$reg)); | |
+ %} | |
+ | |
+ ins_pipe(fp_dop_reg_reg_d); | |
+%} | |
+ | |
+ | |
instruct divF_reg_reg(vRegF dst, vRegF src1, vRegF src2) %{ | |
match(Set dst (DivF src1 src2)); | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/cpu/aarch64/assembler_aarch64.hpp | |
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -1826,12 +1826,16 @@ | |
INSN(fdivs, 0b000, 0b00, 0b0001); | |
INSN(fadds, 0b000, 0b00, 0b0010); | |
INSN(fsubs, 0b000, 0b00, 0b0011); | |
+ INSN(fmaxs, 0b000, 0b00, 0b0100); | |
+ INSN(fmins, 0b000, 0b00, 0b0101); | |
INSN(fnmuls, 0b000, 0b00, 0b1000); | |
INSN(fmuld, 0b000, 0b01, 0b0000); | |
INSN(fdivd, 0b000, 0b01, 0b0001); | |
INSN(faddd, 0b000, 0b01, 0b0010); | |
INSN(fsubd, 0b000, 0b01, 0b0011); | |
+ INSN(fmaxd, 0b000, 0b01, 0b0100); | |
+ INSN(fmind, 0b000, 0b01, 0b0101); | |
INSN(fnmuld, 0b000, 0b01, 0b1000); | |
#undef INSN | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/adlc/formssel.cpp | |
--- a/src/hotspot/share/adlc/formssel.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/adlc/formssel.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -3801,7 +3801,7 @@ | |
"AddVB","AddVS","AddVI","AddVL","AddVF","AddVD", | |
"AndI","AndL", | |
"AndV", | |
- "MaxI","MinI", | |
+ "MaxI","MinI","MaxF","MinF","MaxD","MinD", | |
"MulI","MulL","MulF","MulD", | |
"MulVS","MulVI","MulVL","MulVF","MulVD", | |
"OrI","OrL", | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/classfile/vmSymbols.cpp | |
--- a/src/hotspot/share/classfile/vmSymbols.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/classfile/vmSymbols.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -580,6 +580,10 @@ | |
case vmIntrinsics::_max: | |
case vmIntrinsics::_floatToIntBits: | |
case vmIntrinsics::_doubleToLongBits: | |
+ case vmIntrinsics::_maxF: | |
+ case vmIntrinsics::_minF: | |
+ case vmIntrinsics::_maxD: | |
+ case vmIntrinsics::_minD: | |
if (!InlineMathNatives) return true; | |
break; | |
case vmIntrinsics::_fmaD: | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/classfile/vmSymbols.hpp | |
--- a/src/hotspot/share/classfile/vmSymbols.hpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/classfile/vmSymbols.hpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -748,6 +748,7 @@ | |
do_class(java_lang_StrictMath, "java/lang/StrictMath") \ | |
do_signature(double2_double_signature, "(DD)D") \ | |
do_signature(double3_double_signature, "(DDD)D") \ | |
+ do_signature(float2_float_signature, "(FF)F") \ | |
do_signature(float3_float_signature, "(FFF)F") \ | |
do_signature(int2_int_signature, "(II)I") \ | |
do_signature(long2_long_signature, "(JJ)J") \ | |
@@ -794,6 +795,10 @@ | |
do_intrinsic(_subtractExactL, java_lang_Math, subtractExact_name, long2_long_signature, F_S) \ | |
do_intrinsic(_fmaD, java_lang_Math, fma_name, double3_double_signature, F_S) \ | |
do_intrinsic(_fmaF, java_lang_Math, fma_name, float3_float_signature, F_S) \ | |
+ do_intrinsic(_maxF, java_lang_Math, max_name, float2_float_signature, F_S) \ | |
+ do_intrinsic(_minF, java_lang_Math, min_name, float2_float_signature, F_S) \ | |
+ do_intrinsic(_maxD, java_lang_Math, max_name, double2_double_signature, F_S) \ | |
+ do_intrinsic(_minD, java_lang_Math, min_name, double2_double_signature, F_S) \ | |
\ | |
do_intrinsic(_floatToRawIntBits, java_lang_Float, floatToRawIntBits_name, float_int_signature, F_S) \ | |
do_name( floatToRawIntBits_name, "floatToRawIntBits") \ | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/addnode.hpp | |
--- a/src/hotspot/share/opto/addnode.hpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/addnode.hpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -249,4 +249,52 @@ | |
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |
}; | |
+//------------------------------MaxFNode--------------------------------------- | |
+// Maximum of 2 floats. | |
+class MaxFNode : public MaxNode { | |
+public: | |
+ MaxFNode(Node *in1, Node *in2) : MaxNode(in1, in2) {} | |
+ virtual int Opcode() const; | |
+ virtual const Type *add_ring(const Type*, const Type*) const { return Type::FLOAT; } | |
+ virtual const Type *add_id() const { return TypeF::NEG_INF; } | |
+ virtual const Type *bottom_type() const { return Type::FLOAT; } | |
+ virtual uint ideal_reg() const { return Op_RegF; } | |
+}; | |
+ | |
+//------------------------------MinFNode--------------------------------------- | |
+// Minimum of 2 floats. | |
+class MinFNode : public MaxNode { | |
+public: | |
+ MinFNode(Node *in1, Node *in2) : MaxNode(in1, in2) {} | |
+ virtual int Opcode() const; | |
+ virtual const Type *add_ring(const Type*, const Type*) const { return Type::FLOAT; } | |
+ virtual const Type *add_id() const { return TypeF::POS_INF; } | |
+ virtual const Type *bottom_type() const { return Type::FLOAT; } | |
+ virtual uint ideal_reg() const { return Op_RegF; } | |
+}; | |
+ | |
+//------------------------------MaxDNode--------------------------------------- | |
+// Maximum of 2 doubles. | |
+class MaxDNode : public MaxNode { | |
+public: | |
+ MaxDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {} | |
+ virtual int Opcode() const; | |
+ virtual const Type *add_ring(const Type*, const Type*) const { return Type::DOUBLE; } | |
+ virtual const Type *add_id() const { return TypeD::NEG_INF; } | |
+ virtual const Type *bottom_type() const { return Type::DOUBLE; } | |
+ virtual uint ideal_reg() const { return Op_RegD; } | |
+}; | |
+ | |
+//------------------------------MinDNode--------------------------------------- | |
+// Minimum of 2 doubles. | |
+class MinDNode : public MaxNode { | |
+public: | |
+ MinDNode(Node *in1, Node *in2) : MaxNode(in1, in2) {} | |
+ virtual int Opcode() const; | |
+ virtual const Type *add_ring(const Type*, const Type*) const { return Type::DOUBLE; } | |
+ virtual const Type *add_id() const { return TypeD::POS_INF; } | |
+ virtual const Type *bottom_type() const { return Type::DOUBLE; } | |
+ virtual uint ideal_reg() const { return Op_RegD; } | |
+}; | |
+ | |
#endif // SHARE_VM_OPTO_ADDNODE_HPP | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/c2compiler.cpp | |
--- a/src/hotspot/share/opto/c2compiler.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/c2compiler.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -440,6 +440,18 @@ | |
case vmIntrinsics::_isWhitespace: | |
if (!Matcher::match_rule_supported(Op_Whitespace)) return false; | |
break; | |
+ case vmIntrinsics::_maxF: | |
+ if (!Matcher::match_rule_supported(Op_MaxF)) return false; | |
+ break; | |
+ case vmIntrinsics::_minF: | |
+ if (!Matcher::match_rule_supported(Op_MinF)) return false; | |
+ break; | |
+ case vmIntrinsics::_maxD: | |
+ if (!Matcher::match_rule_supported(Op_MaxD)) return false; | |
+ break; | |
+ case vmIntrinsics::_minD: | |
+ if (!Matcher::match_rule_supported(Op_MinD)) return false; | |
+ break; | |
case vmIntrinsics::_hashCode: | |
case vmIntrinsics::_identityHashCode: | |
case vmIntrinsics::_getClass: | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/classes.hpp | |
--- a/src/hotspot/share/opto/classes.hpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/classes.hpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -202,6 +202,8 @@ | |
macro(Mach) | |
macro(MachProj) | |
macro(MulAddS2I) | |
+macro(MaxD) | |
+macro(MaxF) | |
macro(MaxI) | |
macro(MemBarAcquire) | |
macro(LoadFence) | |
@@ -214,6 +216,8 @@ | |
macro(MemBarVolatile) | |
macro(MemBarStoreStore) | |
macro(MergeMem) | |
+macro(MinD) | |
+macro(MinF) | |
macro(MinI) | |
macro(ModD) | |
macro(ModF) | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/library_call.cpp | |
--- a/src/hotspot/share/opto/library_call.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/library_call.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -325,6 +325,7 @@ | |
bool inline_vectorizedMismatch(); | |
bool inline_fma(vmIntrinsics::ID id); | |
bool inline_character_compare(vmIntrinsics::ID id); | |
+ bool inline_fp_min_max(vmIntrinsics::ID id); | |
bool inline_profileBoolean(); | |
bool inline_isCompileConstant(); | |
@@ -874,6 +875,12 @@ | |
case vmIntrinsics::_isWhitespace: | |
return inline_character_compare(intrinsic_id()); | |
+ case vmIntrinsics::_maxF: | |
+ case vmIntrinsics::_minF: | |
+ case vmIntrinsics::_maxD: | |
+ case vmIntrinsics::_minD: | |
+ return inline_fp_min_max(intrinsic_id()); | |
+ | |
default: | |
// If you get here, it may be that someone has added a new intrinsic | |
// to the list in vmSymbols.hpp without implementing it here. | |
@@ -6588,6 +6595,42 @@ | |
return true; | |
} | |
+//------------------------------inline_fp_min_max------------------------------ | |
+bool LibraryCallKit::inline_fp_min_max(vmIntrinsics::ID id) { | |
+ Node *a = NULL; | |
+ Node *b = NULL; | |
+ Node *n = NULL; | |
+ switch (id) { | |
+ case vmIntrinsics::_maxF: | |
+ case vmIntrinsics::_minF: | |
+ assert(callee()->signature()->size() == 2, "minF/maxF has 2 parameters of size 1 each."); | |
+ a = argument(0); | |
+ b = argument(1); | |
+ break; | |
+ case vmIntrinsics::_maxD: | |
+ case vmIntrinsics::_minD: | |
+ assert(callee()->signature()->size() == 4, "minD/maxD has 2 parameters of size 2 each."); | |
+ a = round_double_node(argument(0)); | |
+ b = round_double_node(argument(2)); | |
+ break; | |
+ default: | |
+ fatal_unexpected_iid(id); | |
+ break; | |
+ } | |
+ if (a->is_Con() || b->is_Con()) { | |
+ return false; | |
+ } | |
+ switch (id) { | |
+ case vmIntrinsics::_maxF: n = new MaxFNode(a, b); break; | |
+ case vmIntrinsics::_minF: n = new MinFNode(a, b); break; | |
+ case vmIntrinsics::_maxD: n = new MaxDNode(a, b); break; | |
+ case vmIntrinsics::_minD: n = new MinDNode(a, b); break; | |
+ default: fatal_unexpected_iid(id); break; | |
+ } | |
+ set_result(_gvn.transform(n)); | |
+ return true; | |
+} | |
+ | |
bool LibraryCallKit::inline_profileBoolean() { | |
Node* counts = argument(1); | |
const TypeAryPtr* ary = NULL; | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/type.cpp | |
--- a/src/hotspot/share/opto/type.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/type.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -416,6 +416,18 @@ | |
#define SMALLINT ((juint)3) // a value too insignificant to consider widening | |
+static double pos_dinf() { | |
+ union { int64_t i; double d; } v; | |
+ v.i = CONST64(0x7ff0000000000000); | |
+ return v.d; | |
+} | |
+ | |
+static float pos_finf() { | |
+ union { int32_t i; float f; } v; | |
+ v.i = 0x7f800000; | |
+ return v.f; | |
+} | |
+ | |
//--------------------------Initialize_shared---------------------------------- | |
void Type::Initialize_shared(Compile* current) { | |
// This method does not need to be locked because the first system | |
@@ -445,9 +457,13 @@ | |
TypeF::ZERO = TypeF::make(0.0); // Float 0 (positive zero) | |
TypeF::ONE = TypeF::make(1.0); // Float 1 | |
+ TypeF::POS_INF = TypeF::make(pos_finf()); | |
+ TypeF::NEG_INF = TypeF::make(-pos_finf()); | |
TypeD::ZERO = TypeD::make(0.0); // Double 0 (positive zero) | |
TypeD::ONE = TypeD::make(1.0); // Double 1 | |
+ TypeD::POS_INF = TypeD::make(pos_dinf()); | |
+ TypeD::NEG_INF = TypeD::make(-pos_dinf()); | |
TypeInt::MINUS_1 = TypeInt::make(-1); // -1 | |
TypeInt::ZERO = TypeInt::make( 0); // 0 | |
@@ -1087,6 +1103,8 @@ | |
// Convenience common pre-built types. | |
const TypeF *TypeF::ZERO; // Floating point zero | |
const TypeF *TypeF::ONE; // Floating point one | |
+const TypeF *TypeF::POS_INF; // Floating point positive infinity | |
+const TypeF *TypeF::NEG_INF; // Floating point negative infinity | |
//------------------------------make------------------------------------------- | |
// Create a float constant | |
@@ -1195,6 +1213,8 @@ | |
// Convenience common pre-built types. | |
const TypeD *TypeD::ZERO; // Floating point zero | |
const TypeD *TypeD::ONE; // Floating point one | |
+const TypeD *TypeD::POS_INF; // Floating point positive infinity | |
+const TypeD *TypeD::NEG_INF; // Floating point negative infinity | |
//------------------------------make------------------------------------------- | |
const TypeD *TypeD::make(double d) { | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/opto/type.hpp | |
--- a/src/hotspot/share/opto/type.hpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/opto/type.hpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -483,6 +483,8 @@ | |
// Convenience common pre-built types. | |
static const TypeF *ZERO; // positive zero only | |
static const TypeF *ONE; | |
+ static const TypeF *POS_INF; | |
+ static const TypeF *NEG_INF; | |
#ifndef PRODUCT | |
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; | |
#endif | |
@@ -510,6 +512,8 @@ | |
// Convenience common pre-built types. | |
static const TypeD *ZERO; // positive zero only | |
static const TypeD *ONE; | |
+ static const TypeD *POS_INF; | |
+ static const TypeD *NEG_INF; | |
#ifndef PRODUCT | |
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; | |
#endif | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/hotspot/share/runtime/vmStructs.cpp | |
--- a/src/hotspot/share/runtime/vmStructs.cpp Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/hotspot/share/runtime/vmStructs.cpp Tue Dec 18 16:50:35 2018 +0000 | |
@@ -1516,6 +1516,10 @@ | |
declare_c2_type(MaxNode, AddNode) \ | |
declare_c2_type(MaxINode, MaxNode) \ | |
declare_c2_type(MinINode, MaxNode) \ | |
+ declare_c2_type(MaxFNode, MaxNode) \ | |
+ declare_c2_type(MinFNode, MaxNode) \ | |
+ declare_c2_type(MaxDNode, MaxNode) \ | |
+ declare_c2_type(MinDNode, MaxNode) \ | |
declare_c2_type(StartNode, MultiNode) \ | |
declare_c2_type(StartOSRNode, StartNode) \ | |
declare_c2_type(ParmNode, ProjNode) \ | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/java.base/share/classes/java/lang/Math.java | |
--- a/src/java.base/share/classes/java/lang/Math.java Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/java.base/share/classes/java/lang/Math.java Tue Dec 18 16:50:35 2018 +0000 | |
@@ -1460,6 +1460,7 @@ | |
* @param b another argument. | |
* @return the larger of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static float max(float a, float b) { | |
if (a != a) | |
return a; // a is NaN | |
@@ -1486,6 +1487,7 @@ | |
* @param b another argument. | |
* @return the larger of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static double max(double a, double b) { | |
if (a != a) | |
return a; // a is NaN | |
@@ -1541,6 +1543,7 @@ | |
* @param b another argument. | |
* @return the smaller of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static float min(float a, float b) { | |
if (a != a) | |
return a; // a is NaN | |
@@ -1567,6 +1570,7 @@ | |
* @param b another argument. | |
* @return the smaller of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static double min(double a, double b) { | |
if (a != a) | |
return a; // a is NaN | |
diff -r 6aeb6a23fb83 -r f15af1e2c683 src/java.base/share/classes/java/lang/StrictMath.java | |
--- a/src/java.base/share/classes/java/lang/StrictMath.java Tue Dec 18 16:22:46 2018 -0500 | |
+++ b/src/java.base/share/classes/java/lang/StrictMath.java Tue Dec 18 16:50:35 2018 +0000 | |
@@ -1154,6 +1154,7 @@ | |
* @param b another argument. | |
* @return the larger of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static float max(float a, float b) { | |
return Math.max(a, b); | |
} | |
@@ -1172,6 +1173,7 @@ | |
* @param b another argument. | |
* @return the larger of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static double max(double a, double b) { | |
return Math.max(a, b); | |
} | |
@@ -1219,6 +1221,7 @@ | |
* @param b another argument. | |
* @return the smaller of {@code a} and {@code b.} | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static float min(float a, float b) { | |
return Math.min(a, b); | |
} | |
@@ -1237,6 +1240,7 @@ | |
* @param b another argument. | |
* @return the smaller of {@code a} and {@code b}. | |
*/ | |
+ @HotSpotIntrinsicCandidate | |
public static double min(double a, double b) { | |
return Math.min(a, b); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment