Skip to content

Commit

Permalink
[mono][jit] ArmBase methods are now intrinsic. (#85458)
Browse files Browse the repository at this point in the history
* ArmBase methods are now intrinsic.

* Arm.Yield maps to a NOP.

* Adding hint operation for arm64's yield.
  • Loading branch information
jandupej authored May 2, 2023
1 parent 08ba40d commit 18e3bbf
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 1 deletion.
22 changes: 22 additions & 0 deletions src/mono/mono/arch/arm64/arm64-codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ typedef enum {
ARMSIZE_X = 0x3
} ARMSize;

typedef enum {
ARMHINT_NOP = 0x0,
ARMHINT_YIELD = 0x1,
ARMHINT_WFE = 0x2,
ARMHINT_WFI = 0x3,
ARMHINT_SEV = 0x4,
ARMHINT_SEVL = 0x5
} ARMHint;

#define arm_emit(p, ins) do { *(guint32*)(p) = (ins); (p) += 4; } while (0)

/* Overwrite bits [offset,offset+nbits] with value */
Expand Down Expand Up @@ -703,6 +712,19 @@ arm_encode_arith_imm (int imm, guint32 *shift)
#define arm_mulw(p, rd, rn, rm) arm_maddw ((p), (rd), (rn), (rm), ARMREG_RZR)

/* FIXME: Missing multiple opcodes */
#define arm_format_clx(p, sf, op, rd, rn) arm_emit ((p), 0b01011010110000000001000000000000 | (sf) << 31 | (op) << 10 | (rn) << 5 | (rd))
#define arm_clsw(p, rd, rn) arm_format_clx ((p), 0, 1, (rd), (rn))
#define arm_clsx(p, rd, rn) arm_format_clx ((p), 1, 1, (rd), (rn))
#define arm_clzw(p, rd, rn) arm_format_clx ((p), 0, 0, (rd), (rn))
#define arm_clzx(p, rd, rn) arm_format_clx ((p), 1, 0, (rd), (rn))

#define arm_format_mulh(p, u, rd, rn, rm) arm_emit ((p), 0b10011011010000000111110000000000 | (u) << 23 | (rm) << 16 | (rn) << 5 | (rd))
#define arm_smulh(p, rd, rn, rm) arm_format_mulh ((p), 0, (rd), (rn), (rm))
#define arm_umulh(p, rd, rn, rm) arm_format_mulh ((p), 1, (rd), (rn), (rm))

#define arm_format_rbit(p, sf, rd, rn) arm_emit ((p), 0b01011010110000000000000000000000 | (sf) << 31 | (rn) << 5 | (rd))
#define arm_rbitw(p, rd, rn) arm_format_rbit ((p), 0, (rd), (rn))
#define arm_rbitx(p, rd, rn) arm_format_rbit ((p), 1, (rd), (rn))

/* Division */
#define arm_format_div(p, sf, o1, rd, rn, rm) arm_emit ((p), ((sf) << 31) | (0xd6 << 21) | ((rm) << 16) | (0x1 << 11) | ((o1) << 10) | ((rn) << 5) | ((rd) << 0))
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/mini/cpu-arm64.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,15 @@ arm64_cbzw: src1:i len:16
arm64_cbzx: src1:i len:16
arm64_cbnzw: src1:i len:16
arm64_cbnzx: src1:i len:16
lzcnt32: dest:i src1:i len:4
lzcnt64: dest:i src1:i len:4
lscnt32: dest:i src1:i len:4
lscnt64: dest:i src1:i len:4
xop_i8_i8: dest:i src1:i len:4
xop_i4_i4: dest:i src1:i len:4
arm64_smulh: dest:i src1:i src2:i len:4
arm64_umulh: dest:i src1:i src2:i len:4
arm64_hint: len:4

atomic_add_i4: dest:i src1:i src2:i len:32
atomic_add_i8: dest:i src1:i src2:i len:32
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/llvm-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ INTRINS(AARCH64_SHA256SU1, aarch64_crypto_sha256su1, Arm64)
INTRINS(AARCH64_SHA256H, aarch64_crypto_sha256h, Arm64)
INTRINS(AARCH64_SHA256H2, aarch64_crypto_sha256h2, Arm64)
INTRINS(AARCH64_PMULL64, aarch64_neon_pmull64, Arm64)
INTRINS(AARCH64_HINT, aarch64_hint, Arm64)

INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_FACGE, aarch64_neon_facge, Arm64, Ftoi, Scalar | V64 | V128 | I4 | I8)
INTRINS_OVR_TAG_KIND(AARCH64_ADV_SIMD_FACGT, aarch64_neon_facgt, Arm64, Ftoi, Scalar | V64 | V128 | I4 | I8)
Expand Down
40 changes: 40 additions & 0 deletions src/mono/mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -5337,6 +5337,46 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
arm_strx (code, i, ins->sreg1, MONO_STRUCT_OFFSET (MonoContext, regs) + i * sizeof (target_mgreg_t));
break;

/**** Arm.ArmBase ****/
case OP_LZCNT32:
arm_clzw (code, dreg, sreg1);
break;

case OP_LSCNT32:
arm_clsw (code, dreg, sreg1);
break;

case OP_LZCNT64:
arm_clzx (code, dreg, sreg1);
break;

case OP_LSCNT64:
arm_clsx (code, dreg, sreg1);
break;

case OP_ARM64_SMULH:
arm_smulh (code, dreg, sreg1, sreg2);
break;

case OP_ARM64_UMULH:
arm_umulh (code, dreg, sreg1, sreg2);
break;

case OP_XOP_I8_I8:
g_assert (ins->inst_c0 == INTRINS_BITREVERSE_I64);
arm_rbitx (code, dreg, sreg1);
break;

case OP_XOP_I4_I4:
g_assert (ins->inst_c0 == INTRINS_BITREVERSE_I32);
arm_rbitw (code, dreg, sreg1);
break;

case OP_ARM64_HINT:
g_assert (ins->inst_c0 <= ARMHINT_SEVL);
arm_hint (code, ins->inst_c0);
break;

default:
g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
g_assert_not_reached ();
Expand Down
7 changes: 7 additions & 0 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -10271,6 +10271,13 @@ MONO_RESTORE_WARNING
values [ins->dreg] = LLVMBuildSExt (builder, result, ret_t, "");
break;
}
case OP_ARM64_HINT: {
g_assert (ins->inst_c0 <= ARMHINT_SEVL);
LLVMValueRef hintid = LLVMConstInt (LLVMInt32Type (), ins->inst_c0, FALSE);
LLVMValueRef args [] = { hintid };
call_intrins (ctx, INTRINS_AARCH64_HINT, args, "");
break;
}
case OP_ARM64_EXT: {
LLVMTypeRef ret_t = LLVMTypeOf (lhs);
unsigned int elems = LLVMGetVectorSize (ret_t);
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/mini-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1465,6 +1465,7 @@ MINI_OP(OP_ARM64_CBZX, "arm64_cbzx", NONE, IREG, NONE)
/* Branch if sreg1 != 0 */
MINI_OP(OP_ARM64_CBNZW, "arm64_cbnzw", NONE, IREG, NONE)
MINI_OP(OP_ARM64_CBNZX, "arm64_cbnzx", NONE, IREG, NONE)
MINI_OP(OP_ARM64_HINT, "arm64_hint", NONE, NONE, NONE)
#endif

/* Same as OUTARG_VT, but has a dreg */
Expand Down
11 changes: 10 additions & 1 deletion src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -3119,6 +3119,7 @@ static SimdIntrinsic armbase_methods [] = {
{SN_LeadingZeroCount},
{SN_MultiplyHigh},
{SN_ReverseElementBits},
{SN_Yield},
{SN_get_IsSupported},
};

Expand Down Expand Up @@ -3562,7 +3563,7 @@ static const SimdIntrinsic dp_methods [] = {
static const IntrinGroup supported_arm_intrinsics [] = {
{ "AdvSimd", MONO_CPU_ARM64_NEON, advsimd_methods, sizeof (advsimd_methods) },
{ "Aes", MONO_CPU_ARM64_CRYPTO, crypto_aes_methods, sizeof (crypto_aes_methods) },
{ "ArmBase", MONO_CPU_ARM64_BASE, armbase_methods, sizeof (armbase_methods) },
{ "ArmBase", MONO_CPU_ARM64_BASE, armbase_methods, sizeof (armbase_methods), TRUE },
{ "Crc32", MONO_CPU_ARM64_CRC, crc32_methods, sizeof (crc32_methods) },
{ "Dp", MONO_CPU_ARM64_DP, dp_methods, sizeof (dp_methods) },
{ "Rdm", MONO_CPU_ARM64_RDM, rdm_methods, sizeof (rdm_methods) },
Expand Down Expand Up @@ -3598,6 +3599,14 @@ emit_arm64_intrinsics (
(is_64bit ? OP_XOP_I8_I8 : OP_XOP_I4_I4),
(is_64bit ? INTRINS_BITREVERSE_I64 : INTRINS_BITREVERSE_I32),
arg0_type, fsig, args);
case SN_Yield: {
MonoInst* ins;
MONO_INST_NEW (cfg, ins, OP_ARM64_HINT);
ins->inst_c0 = ARMHINT_YIELD;
MONO_ADD_INS (cfg->cbb, ins);
return ins;
}

default:
g_assert_not_reached (); // if a new API is added we need to either implement it or change IsSupported to false
}
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/mini/simd-methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ METHOD(CarrylessMultiply)
// ArmBase
METHOD(LeadingSignCount)
METHOD(ReverseElementBits)
METHOD(Yield)
// Crc32
METHOD(ComputeCrc32)
METHOD(ComputeCrc32C)
Expand Down

0 comments on commit 18e3bbf

Please sign in to comment.