Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8275167: x86 intrinsic for unsignedMultiplyHigh
Reviewed-by: kvn, sviswanathan
  • Loading branch information
vamsi-parasa authored and Sandhya Viswanathan committed Oct 20, 2021
1 parent cea3f01 commit af7c56b
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/hotspot/cpu/x86/x86_64.ad
Expand Up @@ -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)
%{
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/vmIntrinsics.hpp
Expand Up @@ -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") \
Expand Down Expand Up @@ -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) \
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/opto/c2compiler.cpp
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/classes.hpp
Expand Up @@ -238,6 +238,7 @@ macro(MoveD2L)
macro(MulD)
macro(MulF)
macro(MulHiL)
macro(UMulHiL)
macro(MulI)
macro(MulL)
macro(Multi)
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/share/opto/library_call.cpp
Expand Up @@ -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 */);
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/library_call.hpp
Expand Up @@ -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);
Expand Down
16 changes: 14 additions & 2 deletions src/hotspot/share/opto/mulnode.cpp
Expand Up @@ -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;
Expand Down
14 changes: 14 additions & 0 deletions src/hotspot/share/opto/mulnode.hpp
Expand Up @@ -154,6 +154,8 @@ class MulDNode : public MulNode {
};

//-------------------------------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:
Expand All @@ -162,6 +164,18 @@ class MulHiLNode : public Node {
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---------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/vmStructs.cpp
Expand Up @@ -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) \
Expand Down
1 change: 1 addition & 0 deletions src/java.base/share/classes/java/lang/Math.java
Expand Up @@ -1390,6 +1390,7 @@ public static long multiplyHigh(long x, long y) {
* @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);
Expand Down
5 changes: 5 additions & 0 deletions test/micro/org/openjdk/bench/java/lang/MathBench.java
Expand Up @@ -540,4 +540,9 @@ public double ulpFloat() {
return Math.ulp(float7);
}

@Benchmark
public long unsignedMultiplyHighLongLong() {
return Math.unsignedMultiplyHigh(long747, long13);
}

}

1 comment on commit af7c56b

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.