8187964: [s390][ppc]: Intrinsify Math.multiplyHigh(long, long)
Reviewed-by: mdoerr
--- a/src/hotspot/cpu/s390/assembler_s390.hpp Mon Oct 09 08:15:25 2017 +0000
+++ b/src/hotspot/cpu/s390/assembler_s390.hpp Mon Oct 09 11:43:42 2017 +0200
@@ -1437,10 +1437,18 @@
// unsigned arithmetic calculation instructions
// Mask bit#0 is not used by these instructions.
// There is no indication of overflow for these instr.
- bcondLogZero = 2,
- bcondLogNotZero = 5,
+ bcondLogZero_NoCarry = 8,
+ bcondLogZero_Carry = 2,
+ // bcondLogZero_Borrow = 8, // This CC is never generated.
+ bcondLogZero_NoBorrow = 2,
+ bcondLogZero = bcondLogZero_Carry | bcondLogZero_NoCarry,
+ bcondLogNotZero_NoCarry = 4,
+ bcondLogNotZero_Carry = 1,
bcondLogNotZero_Borrow = 4,
bcondLogNotZero_NoBorrow = 1,
+ bcondLogNotZero = bcondLogNotZero_Carry | bcondLogNotZero_NoCarry,
+ bcondLogCarry = bcondLogZero_Carry | bcondLogNotZero_Carry,
+ bcondLogBorrow = /* bcondLogZero_Borrow | */ bcondLogNotZero_Borrow,
// string search instructions
bcondFound = 4,
bcondNotFound = 2,
@@ -2117,13 +2125,16 @@
inline void z_alsi( const Address& d, int64_t i2); // add logical *(d) += i2_imm8 ; uint32 -- z10
inline void z_algsi(const Address& d, int64_t i2); // add logical *(d) += i2_imm8 ; uint64 -- z10
- // negate
+ // sign adjustment
inline void z_lcr( Register r1, Register r2 = noreg); // neg r1 = -r2 ; int32
inline void z_lcgr( Register r1, Register r2 = noreg); // neg r1 = -r2 ; int64
inline void z_lcgfr(Register r1, Register r2); // neg r1 = -r2 ; int64 <- int32
inline void z_lnr( Register r1, Register r2 = noreg); // neg r1 = -|r2| ; int32
inline void z_lngr( Register r1, Register r2 = noreg); // neg r1 = -|r2| ; int64
inline void z_lngfr(Register r1, Register r2); // neg r1 = -|r2| ; int64 <- int32
+ inline void z_lpr( Register r1, Register r2 = noreg); // r1 = |r2| ; int32
+ inline void z_lpgr( Register r1, Register r2 = noreg); // r1 = |r2| ; int64
+ inline void z_lpgfr(Register r1, Register r2); // r1 = |r2| ; int64 <- int32
// subtract intstructions
// sub registers
--- a/src/hotspot/cpu/s390/assembler_s390.inline.hpp Mon Oct 09 08:15:25 2017 +0000
+++ b/src/hotspot/cpu/s390/assembler_s390.inline.hpp Mon Oct 09 11:43:42 2017 +0200
@@ -309,6 +309,9 @@
inline void Assembler::z_lnr( Register r1, Register r2) { emit_16( LNR_ZOPC | regt( r1, 8, 16) | reg((r2 == noreg) ? r1:r2, 12, 16)); }
inline void Assembler::z_lngr( Register r1, Register r2) { emit_32( LNGR_ZOPC | regt( r1, 24, 32) | reg((r2 == noreg) ? r1:r2, 28, 32)); }
inline void Assembler::z_lngfr(Register r1, Register r2) { emit_32( LNGFR_ZOPC | regt( r1, 24, 32) | reg((r2 == noreg) ? r1:r2, 28, 32)); }
+inline void Assembler::z_lpr( Register r1, Register r2) { emit_16( LPR_ZOPC | regt( r1, 8, 16) | reg((r2 == noreg) ? r1:r2, 12, 16)); }
+inline void Assembler::z_lpgr( Register r1, Register r2) { emit_32( LPGR_ZOPC | regt( r1, 24, 32) | reg((r2 == noreg) ? r1:r2, 28, 32)); }
+inline void Assembler::z_lpgfr(Register r1, Register r2) { emit_32( LPGFR_ZOPC | regt( r1, 24, 32) | reg((r2 == noreg) ? r1:r2, 28, 32)); }
inline void Assembler::z_lrvr( Register r1, Register r2) { emit_32( LRVR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }
inline void Assembler::z_lrvgr(Register r1, Register r2) { emit_32( LRVGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }
--- a/src/hotspot/cpu/s390/s390.ad Mon Oct 09 08:15:25 2017 +0000
+++ b/src/hotspot/cpu/s390/s390.ad Mon Oct 09 11:43:42 2017 +0200
@@ -3149,7 +3149,7 @@
interface(REG_INTER);
%}
-// Revenregi and roddRegI constitute and even-odd-pair.
+// revenRegI and roddRegI constitute and even-odd-pair.
operand revenRegI() %{
constraint(ALLOC_IN_RC(z_rarg3_int_reg));
match(iRegI);
@@ -3157,7 +3157,7 @@
interface(REG_INTER);
%}
-// Revenregi and roddRegI constitute and even-odd-pair.
+// revenRegI and roddRegI constitute and even-odd-pair.
operand roddRegI() %{
constraint(ALLOC_IN_RC(z_rarg4_int_reg));
match(iRegI);
@@ -3283,7 +3283,7 @@
interface(REG_INTER);
%}
-// Revenregp and roddRegP constitute and even-odd-pair.
+// revenRegP and roddRegP constitute and even-odd-pair.
operand revenRegP() %{
constraint(ALLOC_IN_RC(z_rarg3_ptr_reg));
match(iRegP);
@@ -3291,7 +3291,7 @@
interface(REG_INTER);
%}
-// Revenregl and roddRegL constitute and even-odd-pair.
+// revenRegP and roddRegP constitute and even-odd-pair.
operand roddRegP() %{
constraint(ALLOC_IN_RC(z_rarg4_ptr_reg));
match(iRegP);
@@ -3380,7 +3380,7 @@
interface(REG_INTER);
%}
-// Revenregl and roddRegL constitute and even-odd-pair.
+// revenRegL and roddRegL constitute and even-odd-pair.
operand revenRegL() %{
constraint(ALLOC_IN_RC(z_rarg3_long_reg));
match(iRegL);
@@ -3388,7 +3388,7 @@
interface(REG_INTER);
%}
-// Revenregl and roddRegL constitute and even-odd-pair.
+// revenRegL and roddRegL constitute and even-odd-pair.
operand roddRegL() %{
constraint(ALLOC_IN_RC(z_rarg4_long_reg));
match(iRegL);
@@ -6443,6 +6443,32 @@
ins_pipe(pipe_class_dummy);
%}
+instruct mulHiL_reg_reg(revenRegL Rdst, roddRegL Rsrc1, iRegL Rsrc2, iRegL Rtmp1, flagsReg cr)%{
+ match(Set Rdst (MulHiL Rsrc1 Rsrc2));
+ effect(TEMP_DEF Rdst, USE_KILL Rsrc1, TEMP Rtmp1, KILL cr);
+ ins_cost(7*DEFAULT_COST);
+ // TODO: s390 port size(VARIABLE_SIZE);
+ format %{ "MulHiL $Rdst, $Rsrc1, $Rsrc2\t # Multiply High Long" %}
+ ins_encode%{
+ Register dst = $Rdst$$Register;
+ Register src1 = $Rsrc1$$Register;
+ Register src2 = $Rsrc2$$Register;
+ Register tmp1 = $Rtmp1$$Register;
+ Register tmp2 = $Rdst$$Register;
+ // z/Architecture has only unsigned multiply (64 * 64 -> 128).
+ // implementing mulhs(a,b) = mulhu(a,b) – (a & (b>>63)) – (b & (a>>63))
+ __ z_srag(tmp2, src1, 63); // a>>63
+ __ z_srag(tmp1, src2, 63); // b>>63
+ __ z_ngr(tmp2, src2); // b & (a>>63)
+ __ z_ngr(tmp1, src1); // a & (b>>63)
+ __ z_agr(tmp1, tmp2); // ((a & (b>>63)) + (b & (a>>63)))
+ __ z_mlgr(dst, src2); // tricky: 128-bit product is written to even/odd pair (dst,src1),
+ // multiplicand is taken from oddReg (src1), multiplier in src2.
+ __ z_sgr(dst, tmp1);
+ %}
+ ins_pipe(pipe_class_dummy);
+%}
+
// DIV
// Integer DIVMOD with Register, both quotient and mod results