8275167: x86 intrinsic for unsignedMultiplyHigh

Reviewed-by: kvn, sviswanathan
This commit is contained in:
vamsi-parasa 2021-10-20 22:40:51 +00:00 committed by Sandhya Viswanathan
parent cea3f01046
commit af7c56b85b
11 changed files with 61 additions and 2 deletions

View File

@ -8527,6 +8527,19 @@ instruct mulHiL_rReg(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr)
ins_pipe(ialu_reg_reg_alu0); ins_pipe(ialu_reg_reg_alu0);
%} %}
instruct umulHiL_rReg(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr)
%{
match(Set dst (UMulHiL src rax));
effect(USE_KILL rax, KILL cr);
ins_cost(300);
format %{ "mulq RDX:RAX, RAX, $src\t# umulhi" %}
ins_encode %{
__ mulq($src$$Register);
%}
ins_pipe(ialu_reg_reg_alu0);
%}
instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
rFlagsReg cr) rFlagsReg cr)
%{ %{

View File

@ -140,6 +140,7 @@ class methodHandle;
do_name(incrementExact_name,"incrementExact") \ do_name(incrementExact_name,"incrementExact") \
do_name(multiplyExact_name,"multiplyExact") \ do_name(multiplyExact_name,"multiplyExact") \
do_name(multiplyHigh_name,"multiplyHigh") \ do_name(multiplyHigh_name,"multiplyHigh") \
do_name(unsignedMultiplyHigh_name,"unsignedMultiplyHigh") \
do_name(negateExact_name,"negateExact") \ do_name(negateExact_name,"negateExact") \
do_name(subtractExact_name,"subtractExact") \ do_name(subtractExact_name,"subtractExact") \
do_name(fma_name, "fma") \ do_name(fma_name, "fma") \
@ -173,6 +174,7 @@ class methodHandle;
do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \ do_intrinsic(_multiplyExactI, java_lang_Math, multiplyExact_name, int2_int_signature, F_S) \
do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \ do_intrinsic(_multiplyExactL, java_lang_Math, multiplyExact_name, long2_long_signature, F_S) \
do_intrinsic(_multiplyHigh, java_lang_Math, multiplyHigh_name, long2_long_signature, F_S) \ do_intrinsic(_multiplyHigh, java_lang_Math, multiplyHigh_name, long2_long_signature, F_S) \
do_intrinsic(_unsignedMultiplyHigh, java_lang_Math, unsignedMultiplyHigh_name, long2_long_signature, F_S) \
do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \ do_intrinsic(_negateExactI, java_lang_Math, negateExact_name, int_int_signature, F_S) \
do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \ do_intrinsic(_negateExactL, java_lang_Math, negateExact_name, long_long_signature, F_S) \
do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \ do_intrinsic(_subtractExactI, java_lang_Math, subtractExact_name, int2_int_signature, F_S) \

View File

@ -426,6 +426,9 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_multiplyHigh: case vmIntrinsics::_multiplyHigh:
if (!Matcher::match_rule_supported(Op_MulHiL)) return false; if (!Matcher::match_rule_supported(Op_MulHiL)) return false;
break; break;
case vmIntrinsics::_unsignedMultiplyHigh:
if (!Matcher::match_rule_supported(Op_UMulHiL)) return false;
break;
case vmIntrinsics::_getCallerClass: case vmIntrinsics::_getCallerClass:
if (vmClasses::reflect_CallerSensitive_klass() == NULL) return false; if (vmClasses::reflect_CallerSensitive_klass() == NULL) return false;
break; break;

View File

@ -238,6 +238,7 @@ macro(MoveD2L)
macro(MulD) macro(MulD)
macro(MulF) macro(MulF)
macro(MulHiL) macro(MulHiL)
macro(UMulHiL)
macro(MulI) macro(MulI)
macro(MulL) macro(MulL)
macro(Multi) macro(Multi)

View File

@ -286,6 +286,7 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_multiplyExactI: return inline_math_multiplyExactI(); case vmIntrinsics::_multiplyExactI: return inline_math_multiplyExactI();
case vmIntrinsics::_multiplyExactL: return inline_math_multiplyExactL(); case vmIntrinsics::_multiplyExactL: return inline_math_multiplyExactL();
case vmIntrinsics::_multiplyHigh: return inline_math_multiplyHigh(); case vmIntrinsics::_multiplyHigh: return inline_math_multiplyHigh();
case vmIntrinsics::_unsignedMultiplyHigh: return inline_math_unsignedMultiplyHigh();
case vmIntrinsics::_negateExactI: return inline_math_negateExactI(); case vmIntrinsics::_negateExactI: return inline_math_negateExactI();
case vmIntrinsics::_negateExactL: return inline_math_negateExactL(); case vmIntrinsics::_negateExactL: return inline_math_negateExactL();
case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */); case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */);
@ -1867,6 +1868,11 @@ bool LibraryCallKit::inline_math_multiplyHigh() {
return true; return true;
} }
bool LibraryCallKit::inline_math_unsignedMultiplyHigh() {
set_result(_gvn.transform(new UMulHiLNode(argument(0), argument(2))));
return true;
}
Node* Node*
LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) { LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) {
// These are the candidate return value: // These are the candidate return value:

View File

@ -210,6 +210,7 @@ class LibraryCallKit : public GraphKit {
bool inline_math_multiplyExactI(); bool inline_math_multiplyExactI();
bool inline_math_multiplyExactL(); bool inline_math_multiplyExactL();
bool inline_math_multiplyHigh(); bool inline_math_multiplyHigh();
bool inline_math_unsignedMultiplyHigh();
bool inline_math_negateExactI(); bool inline_math_negateExactI();
bool inline_math_negateExactL(); bool inline_math_negateExactL();
bool inline_math_subtractExactI(bool is_decrement); bool inline_math_subtractExactI(bool is_decrement);

View File

@ -432,14 +432,26 @@ const Type *MulDNode::mul_ring(const Type *t0, const Type *t1) const {
//============================================================================= //=============================================================================
//------------------------------Value------------------------------------------ //------------------------------Value------------------------------------------
const Type* MulHiLNode::Value(PhaseGVN* phase) const { const Type* MulHiLNode::Value(PhaseGVN* phase) const {
// Either input is TOP ==> the result is TOP
const Type *t1 = phase->type( in(1) ); const Type *t1 = phase->type( in(1) );
const Type *t2 = phase->type( in(2) ); const Type *t2 = phase->type( in(2) );
const Type *bot = bottom_type();
return MulHiValue(t1, t2, bot);
}
const Type* UMulHiLNode::Value(PhaseGVN* phase) const {
const Type *t1 = phase->type( in(1) );
const Type *t2 = phase->type( in(2) );
const Type *bot = bottom_type();
return MulHiValue(t1, t2, bot);
}
// A common routine used by UMulHiLNode and MulHiLNode
const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot) {
// Either input is TOP ==> the result is TOP
if( t1 == Type::TOP ) return Type::TOP; if( t1 == Type::TOP ) return Type::TOP;
if( t2 == Type::TOP ) return Type::TOP; if( t2 == Type::TOP ) return Type::TOP;
// Either input is BOTTOM ==> the result is the local BOTTOM // Either input is BOTTOM ==> the result is the local BOTTOM
const Type *bot = bottom_type();
if( (t1 == bot) || (t2 == bot) || if( (t1 == bot) || (t2 == bot) ||
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
return bot; return bot;

View File

@ -154,6 +154,8 @@ public:
}; };
//-------------------------------MulHiLNode------------------------------------ //-------------------------------MulHiLNode------------------------------------
const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot);
// Upper 64 bits of a 64 bit by 64 bit multiply // Upper 64 bits of a 64 bit by 64 bit multiply
class MulHiLNode : public Node { class MulHiLNode : public Node {
public: public:
@ -162,6 +164,18 @@ public:
virtual const Type* Value(PhaseGVN* phase) const; virtual const Type* Value(PhaseGVN* phase) const;
const Type *bottom_type() const { return TypeLong::LONG; } const Type *bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; } virtual uint ideal_reg() const { return Op_RegL; }
friend const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot);
};
// Upper 64 bits of a 64 bit by 64 bit unsigned multiply
class UMulHiLNode : public Node {
public:
UMulHiLNode( Node *in1, Node *in2 ) : Node(0,in1,in2) {}
virtual int Opcode() const;
virtual const Type* Value(PhaseGVN* phase) const;
const Type *bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
friend const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot);
}; };
//------------------------------AndINode--------------------------------------- //------------------------------AndINode---------------------------------------

View File

@ -1670,6 +1670,7 @@
declare_c2_type(MulFNode, MulNode) \ declare_c2_type(MulFNode, MulNode) \
declare_c2_type(MulDNode, MulNode) \ declare_c2_type(MulDNode, MulNode) \
declare_c2_type(MulHiLNode, Node) \ declare_c2_type(MulHiLNode, Node) \
declare_c2_type(UMulHiLNode, Node) \
declare_c2_type(AndINode, MulINode) \ declare_c2_type(AndINode, MulINode) \
declare_c2_type(AndLNode, MulLNode) \ declare_c2_type(AndLNode, MulLNode) \
declare_c2_type(LShiftINode, Node) \ declare_c2_type(LShiftINode, Node) \

View File

@ -1390,6 +1390,7 @@ public final class Math {
* @see #multiplyHigh * @see #multiplyHigh
* @since 18 * @since 18
*/ */
@IntrinsicCandidate
public static long unsignedMultiplyHigh(long x, long y) { public static long unsignedMultiplyHigh(long x, long y) {
// Compute via multiplyHigh() to leverage the intrinsic // Compute via multiplyHigh() to leverage the intrinsic
long result = Math.multiplyHigh(x, y); long result = Math.multiplyHigh(x, y);

View File

@ -540,4 +540,9 @@ public class MathBench {
return Math.ulp(float7); return Math.ulp(float7);
} }
@Benchmark
public long unsignedMultiplyHighLongLong() {
return Math.unsignedMultiplyHigh(long747, long13);
}
} }