Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for LLVM 14.x #68719

Merged
merged 4 commits into from
Apr 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/mono/mono/mini/llvm-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ INTRINS(PEXT_I32, x86_bmi_pext_32, X86)
INTRINS(PEXT_I64, x86_bmi_pext_64, X86)
INTRINS(PDEP_I32, x86_bmi_pdep_32, X86)
INTRINS(PDEP_I64, x86_bmi_pdep_64, X86)

#if LLVM_API_VERSION >= 1400
INTRINS_OVR_TAG(ROUNDEVEN, roundeven, Generic, Scalar | V64 | V128 | R4 | R8)
#endif

#if defined(TARGET_AMD64) || defined(TARGET_X86)
INTRINS(SSE_PMOVMSKB, x86_sse2_pmovmskb_128, X86)
INTRINS(SSE_MOVMSK_PS, x86_sse_movmsk_ps, X86)
Expand Down Expand Up @@ -256,6 +261,7 @@ INTRINS_OVR(WASM_ANYTRUE_V2, wasm_anytrue, Wasm, sse_i8_t)
#if defined(TARGET_ARM64)
INTRINS_OVR(BITREVERSE_I32, bitreverse, Generic, LLVMInt32Type ())
INTRINS_OVR(BITREVERSE_I64, bitreverse, Generic, LLVMInt64Type ())
INTRINS_OVR_TAG(BITREVERSE, bitreverse, Generic, V64 | V128 | I1 | I2 | I4 | I8)
INTRINS(AARCH64_CRC32B, aarch64_crc32b, Arm64)
INTRINS(AARCH64_CRC32H, aarch64_crc32h, Arm64)
INTRINS(AARCH64_CRC32W, aarch64_crc32w, Arm64)
Expand Down Expand Up @@ -394,10 +400,14 @@ INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRSQRTE, aarch64_neon_frsqrte, Arm64, Scalar |
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRSQRTS, aarch64_neon_frsqrts, Arm64, Scalar | V64 | V128 | R4 | R8)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRECPS, aarch64_neon_frecps, Arm64, Scalar | V64 | V128 | R4 | R8)

#if LLVM_API_VERSION < 1400
vargaz marked this conversation as resolved.
Show resolved Hide resolved
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_RBIT, aarch64_neon_rbit, Arm64, V64 | V128 | I1)
#endif

INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTA, round, Generic, Scalar | V64 | V128 | R4 | R8)
#if LLVM_API_VERSION < 1400
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTN, aarch64_neon_frintn, Arm64, Scalar | V64 | V128 | R4 | R8)
fanyang-mono marked this conversation as resolved.
Show resolved Hide resolved
#endif
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTM, floor, Generic, Scalar | V64 | V128 | R4 | R8)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTP, ceil, Generic, Scalar | V64 | V128 | R4 | R8)
INTRINS_OVR_TAG(AARCH64_ADV_SIMD_FRINTZ, trunc, Generic, Scalar | V64 | V128 | R4 | R8)
Expand Down
41 changes: 31 additions & 10 deletions src/mono/mono/mini/mini-llvm-cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty, LLVMValueRef Arr
}

LLVMValueRef
mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMTypeRef Type, LLVMValueRef PointerVal,
const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier)
{
LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
LoadInst *ins = unwrap(builder)->CreateLoad(unwrap(Type), unwrap(PointerVal), is_volatile, Name);

ins->setAlignment (to_align (alignment));
switch (barrier) {
Expand All @@ -129,12 +129,12 @@ mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
}

LLVMValueRef
mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMTypeRef Type, LLVMValueRef PointerVal,
const char *Name, gboolean is_volatile, int alignment)
{
LoadInst *ins;

ins = unwrap(builder)->CreateLoad(unwrap(PointerVal), is_volatile, Name);
ins = unwrap(builder)->CreateLoad(unwrap(Type), unwrap(PointerVal), is_volatile, Name);
ins->setAlignment (to_align (alignment));

return wrap(ins);
Expand Down Expand Up @@ -320,12 +320,22 @@ mono_llvm_set_call_nonnull_arg (LLVMValueRef wrapped_calli, int argNo)
dyn_cast<CallBase>(calli)->addParamAttr (argNo, Attribute::NonNull);
}

void
mono_llvm_set_call_nonnull_ret (LLVMValueRef wrapped_calli)
static void
add_ret_attr (LLVMValueRef wrapped_calli, Attribute::AttrKind Kind)
{
Instruction *calli = unwrap<Instruction> (wrapped_calli);

dyn_cast<CallBase>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NonNull);
#if LLVM_API_VERSION >= 1400
dyn_cast<CallBase>(calli)->addRetAttr (Kind);
#else
dyn_cast<CallBase>(calli)->addAttribute (AttributeList::ReturnIndex, Kind);
#endif
}

void
mono_llvm_set_call_nonnull_ret (LLVMValueRef wrapped_calli)
{
add_ret_attr (wrapped_calli, Attribute::NonNull);
}

void
Expand Down Expand Up @@ -423,17 +433,20 @@ mono_llvm_set_call_notailcall (LLVMValueRef func)
void
mono_llvm_set_call_noalias_ret (LLVMValueRef wrapped_calli)
{
Instruction *calli = unwrap<Instruction> (wrapped_calli);

dyn_cast<CallBase>(calli)->addAttribute (AttributeList::ReturnIndex, Attribute::NoAlias);
add_ret_attr (wrapped_calli, Attribute::NoAlias);
}

void
mono_llvm_set_alignment_ret (LLVMValueRef call, int alignment)
{
Instruction *ins = unwrap<Instruction> (call);
auto &ctx = ins->getContext ();

#if LLVM_API_VERSION >= 1400
dyn_cast<CallBase>(ins)->addRetAttr (Attribute::getWithAlignment(ctx, to_align (alignment)));
#else
dyn_cast<CallBase>(ins)->addAttribute (AttributeList::ReturnIndex, Attribute::getWithAlignment(ctx, to_align (alignment)));
#endif
}

static Attribute::AttrKind
Expand Down Expand Up @@ -495,13 +508,21 @@ mono_llvm_add_param_byval_attr (LLVMValueRef param, LLVMTypeRef type)
void
mono_llvm_add_instr_attr (LLVMValueRef val, int index, AttrKind kind)
{
#if LLVM_API_VERSION >= 1400
unwrap<CallBase> (val)->addParamAttr (index - 1, convert_attr (kind));
#else
unwrap<CallBase> (val)->addAttribute (index, convert_attr (kind));
#endif
}

void
mono_llvm_add_instr_byval_attr (LLVMValueRef val, int index, LLVMTypeRef type)
{
#if LLVM_API_VERSION >= 1400
unwrap<CallBase> (val)->addParamAttr (index - 1, Attribute::getWithByValType (*unwrap (LLVMGetGlobalContext ()), unwrap (type)));
#else
unwrap<CallBase> (val)->addAttribute (index, Attribute::getWithByValType (*unwrap (LLVMGetGlobalContext ()), unwrap (type)));
#endif
}

void*
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/mini/mini-llvm-cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,11 @@ mono_llvm_build_alloca (LLVMBuilderRef builder, LLVMTypeRef Ty,
int alignment, const char *Name);

LLVMValueRef
mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
mono_llvm_build_atomic_load (LLVMBuilderRef builder, LLVMTypeRef Type, LLVMValueRef PointerVal,
const char *Name, gboolean is_volatile, int alignment, BarrierKind barrier);

LLVMValueRef
mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMValueRef PointerVal,
mono_llvm_build_aligned_load (LLVMBuilderRef builder, LLVMTypeRef Type, LLVMValueRef PointerVal,
const char *Name, gboolean is_volatile, int alignment);

LLVMValueRef
Expand Down
32 changes: 20 additions & 12 deletions src/mono/mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -6605,7 +6605,7 @@ MONO_RESTORE_WARNING
addr = convert (ctx, addr, LLVMPointerType (t, 0));

if (is_unaligned)
values [ins->dreg] = mono_llvm_build_aligned_load (builder, addr, dname, is_volatile, 1);
values [ins->dreg] = mono_llvm_build_aligned_load (builder, t, addr, dname, is_volatile, 1);
else
values [ins->dreg] = emit_load (builder, t, addr, dname, is_volatile);

Expand Down Expand Up @@ -7172,7 +7172,7 @@ MONO_RESTORE_WARNING
addr = convert (ctx, addr, LLVMPointerType (t, 0));

ARM64_ATOMIC_FENCE_FIX;
values [ins->dreg] = mono_llvm_build_atomic_load (builder, addr, dname, is_volatile, size, barrier);
values [ins->dreg] = mono_llvm_build_atomic_load (builder, t, addr, dname, is_volatile, size, barrier);
ARM64_ATOMIC_FENCE_FIX;

if (sext)
Expand Down Expand Up @@ -7511,7 +7511,11 @@ MONO_RESTORE_WARNING

indexes [0] = const_int32 (0);
indexes [1] = const_int32 (0);
#if LLVM_API_VERSION >= 1400
LLVMSetInitializer (ref_var, LLVMConstGEP2 (var_type, name_var, indexes, 2));
#else
LLVMSetInitializer (ref_var, LLVMConstGEP (name_var, indexes, 2));
#endif
LLVMSetLinkage (ref_var, LLVMPrivateLinkage);
LLVMSetExternallyInitialized (ref_var, TRUE);
LLVMSetSection (ref_var, "__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
Expand Down Expand Up @@ -7626,7 +7630,7 @@ MONO_RESTORE_WARNING
LLVMValueRef src;

src = convert (ctx, LLVMBuildAdd (builder, convert (ctx, values [ins->inst_basereg], IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_offset, FALSE), ""), LLVMPointerType (t, 0));
values [ins->dreg] = mono_llvm_build_aligned_load (builder, src, "", FALSE, 1);
values [ins->dreg] = mono_llvm_build_aligned_load (builder, t, src, "", FALSE, 1);
break;
}
case OP_STOREX_MEMBASE: {
Expand Down Expand Up @@ -8439,8 +8443,9 @@ MONO_RESTORE_WARNING

case OP_SSE_LOADU: {
LLVMValueRef dst_ptr = convert (ctx, lhs, LLVMPointerType (primitive_type_to_llvm_type (inst_c1_type (ins)), 0));
LLVMValueRef dst_vec = LLVMBuildBitCast (builder, dst_ptr, LLVMPointerType (type_to_sse_type (ins->inst_c1), 0), "");
values [ins->dreg] = mono_llvm_build_aligned_load (builder, dst_vec, "", FALSE, ins->inst_c0); // inst_c0 is alignment
LLVMTypeRef etype = type_to_sse_type (ins->inst_c1);
LLVMValueRef dst_vec = LLVMBuildBitCast (builder, dst_ptr, LLVMPointerType (etype, 0), "");
Copy link
Member

Choose a reason for hiding this comment

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

one of the motivations for opaque pointer types in the LLVM docs is that it allows them to get rid of a lot of pointer-to-pointer bitcasts that are just changing the element type.

I'm guessing they probably have a pass that will remove these pretty early on.

Do you think we should try to avoid emitting them at all?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are still using the non-opaque mode since the opaque mode is experimental afaik in llvm 11.x. So we can remove those after switching to llvm 14.x.

values [ins->dreg] = mono_llvm_build_aligned_load (builder, etype, dst_vec, "", FALSE, ins->inst_c0); // inst_c0 is alignment
break;
}
case OP_SSE_MOVSS: {
Expand All @@ -8467,7 +8472,7 @@ MONO_RESTORE_WARNING
LLVMTypeRef srcty = LLVMGetElementType (rty);
LLVMValueRef zero = LLVMConstNull (rty);
LLVMValueRef addr = convert (ctx, lhs, LLVMPointerType (srcty, 0));
LLVMValueRef val = mono_llvm_build_aligned_load (builder, addr, "", FALSE, 1);
LLVMValueRef val = mono_llvm_build_aligned_load (builder, srcty, addr, "", FALSE, 1);
values [ins->dreg] = LLVMBuildInsertElement (builder, zero, val, const_int32 (0), dname);
break;
}
Expand Down Expand Up @@ -9097,7 +9102,7 @@ MONO_RESTORE_WARNING
case OP_SSE3_MOVDDUP_MEM: {
LLVMValueRef undef = LLVMGetUndef (v128_r8_t);
LLVMValueRef addr = convert (ctx, lhs, LLVMPointerType (r8_t, 0));
LLVMValueRef elem = mono_llvm_build_aligned_load (builder, addr, "sse3_movddup_mem", FALSE, 1);
LLVMValueRef elem = mono_llvm_build_aligned_load (builder, r8_t, addr, "sse3_movddup_mem", FALSE, 1);
LLVMValueRef val = LLVMBuildInsertElement (builder, undef, elem, const_int32 (0), "sse3_movddup_mem");
values [ins->dreg] = LLVMBuildShuffleVector (builder, val, undef, LLVMConstNull (LLVMVectorType (i4_t, 2)), "sse3_movddup_mem");
break;
Expand Down Expand Up @@ -9322,7 +9327,7 @@ MONO_RESTORE_WARNING
LLVMValueRef value;
if (LLVMGetTypeKind (LLVMTypeOf (lhs)) != LLVMVectorTypeKind) {
LLVMValueRef bitcasted = LLVMBuildBitCast (ctx->builder, lhs, LLVMPointerType (vec_type, 0), "");
value = mono_llvm_build_aligned_load (builder, bitcasted, "", FALSE, 1);
value = mono_llvm_build_aligned_load (builder, vec_type, bitcasted, "", FALSE, 1);
} else {
value = LLVMBuildBitCast (ctx->builder, lhs, vec_type, "");
}
Expand Down Expand Up @@ -9353,8 +9358,9 @@ MONO_RESTORE_WARNING

case OP_SSE41_LOADANT: {
LLVMValueRef dst_ptr = convert (ctx, lhs, LLVMPointerType (primitive_type_to_llvm_type (inst_c1_type (ins)), 0));
LLVMValueRef dst_vec = LLVMBuildBitCast (builder, dst_ptr, LLVMPointerType (type_to_sse_type (ins->inst_c1), 0), "");
LLVMValueRef load = mono_llvm_build_aligned_load (builder, dst_vec, "", FALSE, 16);
LLVMTypeRef etype = type_to_sse_type (ins->inst_c1);
LLVMValueRef dst_vec = LLVMBuildBitCast (builder, dst_ptr, LLVMPointerType (etype, 0), "");
LLVMValueRef load = mono_llvm_build_aligned_load (builder, etype, dst_vec, "", FALSE, 16);
set_nontemporal_flag (load);
values [ins->dreg] = load;
break;
Expand Down Expand Up @@ -10641,7 +10647,7 @@ MONO_RESTORE_WARNING
LLVMTypeRef elem_t = LLVMGetElementType (ret_t);
LLVMValueRef address = convert (ctx, arg3, LLVMPointerType (elem_t, 0));
unsigned int alignment = mono_llvm_get_prim_size_bits (ret_t) / 8;
LLVMValueRef result = mono_llvm_build_aligned_load (builder, address, "arm64_ld1_insert", FALSE, alignment);
LLVMValueRef result = mono_llvm_build_aligned_load (builder, elem_t, address, "arm64_ld1_insert", FALSE, alignment);
result = LLVMBuildInsertElement (builder, lhs, result, rhs, "arm64_ld1_insert");
values [ins->dreg] = result;
break;
Expand All @@ -10652,13 +10658,15 @@ MONO_RESTORE_WARNING
LLVMTypeRef ret_t = simd_class_to_llvm_type (ctx, ins->klass);
unsigned int alignment = mono_llvm_get_prim_size_bits (ret_t) / 8;
LLVMValueRef address = lhs;
LLVMTypeRef etype = ret_t;
LLVMTypeRef address_t = LLVMPointerType (ret_t, 0);
if (replicate) {
LLVMTypeRef elem_t = LLVMGetElementType (ret_t);
etype = elem_t;
address_t = LLVMPointerType (elem_t, 0);
}
address = convert (ctx, address, address_t);
LLVMValueRef result = mono_llvm_build_aligned_load (builder, address, "arm64_ld1", FALSE, alignment);
LLVMValueRef result = mono_llvm_build_aligned_load (builder, etype, address, "arm64_ld1", FALSE, alignment);
if (replicate) {
unsigned int elems = LLVMGetVectorSize (ret_t);
result = broadcast_element (ctx, result, elems);
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/mini/simd-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -2517,11 +2517,20 @@ static SimdIntrinsic advsimd_methods [] = {
{SN_ReverseElement16, OP_ARM64_REVN, 16},
{SN_ReverseElement32, OP_ARM64_REVN, 32},
{SN_ReverseElement8, OP_ARM64_REVN, 8},
#if LLVM_API_VERSION >= 1400
{SN_ReverseElementBits, OP_XOP_OVR_X_X, INTRINS_BITREVERSE},
#else
{SN_ReverseElementBits, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_RBIT},
#endif
{SN_RoundAwayFromZero, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTA},
{SN_RoundAwayFromZeroScalar, OP_XOP_OVR_SCALAR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTA},
#if LLVM_API_VERSION >= 1400
{SN_RoundToNearest, OP_XOP_OVR_X_X, INTRINS_ROUNDEVEN},
{SN_RoundToNearestScalar, OP_XOP_OVR_SCALAR_X_X, INTRINS_ROUNDEVEN},
#else
{SN_RoundToNearest, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTN},
{SN_RoundToNearestScalar, OP_XOP_OVR_SCALAR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTN},
#endif
{SN_RoundToNegativeInfinity, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTM},
{SN_RoundToNegativeInfinityScalar, OP_XOP_OVR_SCALAR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTM},
{SN_RoundToPositiveInfinity, OP_XOP_OVR_X_X, INTRINS_AARCH64_ADV_SIMD_FRINTP},
Expand Down