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);
%}
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,
rFlagsReg cr)
%{

View File

@ -140,6 +140,7 @@ class methodHandle;
do_name(incrementExact_name,"incrementExact") \
do_name(multiplyExact_name,"multiplyExact") \
do_name(multiplyHigh_name,"multiplyHigh") \
do_name(unsignedMultiplyHigh_name,"unsignedMultiplyHigh") \
do_name(negateExact_name,"negateExact") \
do_name(subtractExact_name,"subtractExact") \
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(_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(_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(_negateExactL, java_lang_Math, negateExact_name, long_long_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:
if (!Matcher::match_rule_supported(Op_MulHiL)) return false;
break;
case vmIntrinsics::_unsignedMultiplyHigh:
if (!Matcher::match_rule_supported(Op_UMulHiL)) return false;
break;
case vmIntrinsics::_getCallerClass:
if (vmClasses::reflect_CallerSensitive_klass() == NULL) return false;
break;

View File

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

View File

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

View File

@ -210,6 +210,7 @@ class LibraryCallKit : public GraphKit {
bool inline_math_multiplyExactI();
bool inline_math_multiplyExactL();
bool inline_math_multiplyHigh();
bool inline_math_unsignedMultiplyHigh();
bool inline_math_negateExactI();
bool inline_math_negateExactL();
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------------------------------------------
const Type* MulHiLNode::Value(PhaseGVN* phase) const {
// Either input is TOP ==> the result is TOP
const Type *t1 = phase->type( in(1) );
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( t2 == Type::TOP ) return Type::TOP;
// Either input is BOTTOM ==> the result is the local BOTTOM
const Type *bot = bottom_type();
if( (t1 == bot) || (t2 == bot) ||
(t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) )
return bot;

View File

@ -154,6 +154,8 @@ public:
};
//-------------------------------MulHiLNode------------------------------------
const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot);
// Upper 64 bits of a 64 bit by 64 bit multiply
class MulHiLNode : public Node {
public:
@ -162,6 +164,18 @@ public:
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);
};
// 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---------------------------------------

View File

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

View File

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

View File

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