8187964: [s390][ppc]: Intrinsify Math.multiplyHigh(long, long)

Reviewed-by: mdoerr
This commit is contained in:
Lutz Schmidt 2017-10-09 11:43:42 +02:00
parent b8a270598e
commit 75a4bdf218
3 changed files with 49 additions and 9 deletions

View file

@ -1437,10 +1437,18 @@ class Assembler : public AbstractAssembler {
// unsigned arithmetic calculation instructions // unsigned arithmetic calculation instructions
// Mask bit#0 is not used by these instructions. // Mask bit#0 is not used by these instructions.
// There is no indication of overflow for these instr. // There is no indication of overflow for these instr.
bcondLogZero = 2, bcondLogZero_NoCarry = 8,
bcondLogNotZero = 5, 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_Borrow = 4,
bcondLogNotZero_NoBorrow = 1, bcondLogNotZero_NoBorrow = 1,
bcondLogNotZero = bcondLogNotZero_Carry | bcondLogNotZero_NoCarry,
bcondLogCarry = bcondLogZero_Carry | bcondLogNotZero_Carry,
bcondLogBorrow = /* bcondLogZero_Borrow | */ bcondLogNotZero_Borrow,
// string search instructions // string search instructions
bcondFound = 4, bcondFound = 4,
bcondNotFound = 2, bcondNotFound = 2,
@ -2117,13 +2125,16 @@ class Assembler : public AbstractAssembler {
inline void z_alsi( const Address& d, int64_t i2); // add logical *(d) += i2_imm8 ; uint32 -- z10 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 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_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_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_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_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_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_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 // subtract intstructions
// sub registers // sub registers

View file

@ -309,6 +309,9 @@ inline void Assembler::z_lcgfr(Register r1, Register r2) { emit_32( LCGFR_ZOPC |
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_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_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_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_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)); } inline void Assembler::z_lrvgr(Register r1, Register r2) { emit_32( LRVGR_ZOPC | regt(r1, 24, 32) | reg(r2, 28, 32)); }

View file

@ -3149,7 +3149,7 @@ operand noArg_iRegI() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregi and roddRegI constitute and even-odd-pair. // revenRegI and roddRegI constitute and even-odd-pair.
operand revenRegI() %{ operand revenRegI() %{
constraint(ALLOC_IN_RC(z_rarg3_int_reg)); constraint(ALLOC_IN_RC(z_rarg3_int_reg));
match(iRegI); match(iRegI);
@ -3157,7 +3157,7 @@ operand revenRegI() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregi and roddRegI constitute and even-odd-pair. // revenRegI and roddRegI constitute and even-odd-pair.
operand roddRegI() %{ operand roddRegI() %{
constraint(ALLOC_IN_RC(z_rarg4_int_reg)); constraint(ALLOC_IN_RC(z_rarg4_int_reg));
match(iRegI); match(iRegI);
@ -3283,7 +3283,7 @@ operand memoryRegP() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregp and roddRegP constitute and even-odd-pair. // revenRegP and roddRegP constitute and even-odd-pair.
operand revenRegP() %{ operand revenRegP() %{
constraint(ALLOC_IN_RC(z_rarg3_ptr_reg)); constraint(ALLOC_IN_RC(z_rarg3_ptr_reg));
match(iRegP); match(iRegP);
@ -3291,7 +3291,7 @@ operand revenRegP() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregl and roddRegL constitute and even-odd-pair. // revenRegP and roddRegP constitute and even-odd-pair.
operand roddRegP() %{ operand roddRegP() %{
constraint(ALLOC_IN_RC(z_rarg4_ptr_reg)); constraint(ALLOC_IN_RC(z_rarg4_ptr_reg));
match(iRegP); match(iRegP);
@ -3380,7 +3380,7 @@ operand iRegL() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregl and roddRegL constitute and even-odd-pair. // revenRegL and roddRegL constitute and even-odd-pair.
operand revenRegL() %{ operand revenRegL() %{
constraint(ALLOC_IN_RC(z_rarg3_long_reg)); constraint(ALLOC_IN_RC(z_rarg3_long_reg));
match(iRegL); match(iRegL);
@ -3388,7 +3388,7 @@ operand revenRegL() %{
interface(REG_INTER); interface(REG_INTER);
%} %}
// Revenregl and roddRegL constitute and even-odd-pair. // revenRegL and roddRegL constitute and even-odd-pair.
operand roddRegL() %{ operand roddRegL() %{
constraint(ALLOC_IN_RC(z_rarg4_long_reg)); constraint(ALLOC_IN_RC(z_rarg4_long_reg));
match(iRegL); match(iRegL);
@ -6443,6 +6443,32 @@ instruct mulL_Reg_mem(iRegL dst, memory src)%{
ins_pipe(pipe_class_dummy); 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 // DIV
// Integer DIVMOD with Register, both quotient and mod results // Integer DIVMOD with Register, both quotient and mod results