//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines properties of all LLVM intrinsics. // //===----------------------------------------------------------------------===// include "llvm/CodeGen/ValueTypes.td" include "llvm/CodeGen/SDNodeProperties.td" //===----------------------------------------------------------------------===// // Properties we keep track of for intrinsics. //===----------------------------------------------------------------------===// class IntrinsicProperty { bit IsDefault = is_default; } // Intr*Mem - Memory properties. If no property is set, the worst case // is assumed (it may read and write any memory it can get access to and it may // have other side effects). // IntrNoMem - The intrinsic does not access memory or have any other side // effects. It may be CSE'd deleted if dead, etc. def IntrNoMem : IntrinsicProperty; // IntrReadMem - This intrinsic only reads from memory. It does not write to // memory and has no other side effects. Therefore, it cannot be moved across // potentially aliasing stores. However, it can be reordered otherwise and can // be deleted if dead. def IntrReadMem : IntrinsicProperty; // IntrWriteMem - This intrinsic only writes to memory, but does not read from // memory, and has no other side effects. This means dead stores before calls // to this intrinsics may be removed. def IntrWriteMem : IntrinsicProperty; // IntrArgMemOnly - This intrinsic only accesses memory that its pointer-typed // argument(s) points to, but may access an unspecified amount. Other than // reads from and (possibly volatile) writes to memory, it has no side effects. def IntrArgMemOnly : IntrinsicProperty; // IntrInaccessibleMemOnly -- This intrinsic only accesses memory that is not // accessible by the module being compiled. This is a weaker form of IntrNoMem. def IntrInaccessibleMemOnly : IntrinsicProperty; // IntrInaccessibleMemOrArgMemOnly -- This intrinsic only accesses memory that // its pointer-typed arguments point to or memory that is not accessible // by the module being compiled. This is a weaker form of IntrArgMemOnly. def IntrInaccessibleMemOrArgMemOnly : IntrinsicProperty; // Tablegen representation of IRMemLocation. class IntrinsicMemoryLocation; // TODO: Populate with all IRMemLocation enum values and update // getValueAsIRMemLocation accordingly. def ArgMem : IntrinsicMemoryLocation; def InaccessibleMem : IntrinsicMemoryLocation; def TargetMem0 : IntrinsicMemoryLocation; def TargetMem1 : IntrinsicMemoryLocation; // The list of IRMemoryLocations that are read from. class IntrRead idx> : IntrinsicProperty { list MemLoc=idx; } // The list of IRMemoryLocations that are write to. class IntrWrite idx> : IntrinsicProperty { list MemLoc=idx; } // Commutative - This intrinsic is commutative: X op Y == Y op X. def Commutative : IntrinsicProperty; // Throws - This intrinsic can throw. def Throws : IntrinsicProperty; // Attribute index needs to match `AttrIndex` defined `Attributes.h`. class AttrIndex { int Value = idx; } def RetIndex : AttrIndex<0>; class ArgIndex : AttrIndex; // Note: Properties that are applicable either to arguments or return values // use AttrIndex. Properties applicable only to arguments use ArgIndex. Please // refer to Attributes.td. // NoCapture - The specified argument pointer is not captured by the intrinsic. class NoCapture : IntrinsicProperty { int ArgNo = idx.Value; } // NoAlias - The return value or the specified argument pointer is not aliasing // other "noalias" pointer arguments of the intrinsic wrt. the intrinsic scope. class NoAlias : IntrinsicProperty { int ArgNo = idx.Value; } // NoUndef - The return value or specified argument is neither undef nor poison. class NoUndef : IntrinsicProperty { int ArgNo = idx.Value; } // NonNull - The return value or specified argument is not null. class NonNull : IntrinsicProperty { int ArgNo = idx.Value; } // Align - Alignment for return value or the specified argument. class Align : IntrinsicProperty { int ArgNo = idx.Value; int Align = align; } // Dereferenceable -- Return value or the specified argument is dereferenceable // upto `bytes` bytes in size. class Dereferenceable : IntrinsicProperty { int ArgNo = idx.Value; int Bytes = bytes; } // Returned - The specified argument is always the return value of the // intrinsic. class Returned : IntrinsicProperty { int ArgNo = idx.Value; } // ImmArg - The specified argument must be an immediate. class ImmArg : IntrinsicProperty { int ArgNo = idx.Value; } // ReadOnly - The specified argument pointer is not written to through the // pointer by the intrinsic. class ReadOnly : IntrinsicProperty { int ArgNo = idx.Value; } // WriteOnly - The intrinsic does not read memory through the specified // argument pointer. class WriteOnly : IntrinsicProperty { int ArgNo = idx.Value; } // ReadNone - The specified argument pointer is not dereferenced by the // intrinsic. class ReadNone : IntrinsicProperty { int ArgNo = idx.Value; } // The return value or argument is in the range [lower, upper), // where lower and upper are interpreted as signed integers. class Range : IntrinsicProperty { int ArgNo = idx.Value; int Lower = lower; int Upper = upper; } // ArgProperty - Base class for argument properties that can be specified in // ArgInfo. class ArgProperty; // ArgName - Specifies the name of an argument for pretty-printing. class ArgName : ArgProperty { string Name = name; } // ImmArgPrinter - Specifies a custom printer function for immediate arguments. class ImmArgPrinter : ArgProperty { string FuncName = funcname; } // ArgInfo - The specified argument has properties defined by a list of // ArgProperty objects. class ArgInfo properties> : IntrinsicProperty { int ArgNo = idx.Value; list Properties = properties; } def IntrNoReturn : IntrinsicProperty; // Applied by default. def IntrNoCallback : IntrinsicProperty<1>; // IntrNoSync - Threads executing the intrinsic will not synchronize using // memory or other means. Applied by default. def IntrNoSync : IntrinsicProperty<1>; // Applied by default. def IntrNoFree : IntrinsicProperty<1>; // Applied by default. def IntrWillReturn : IntrinsicProperty<1>; // IntrCold - Calls to this intrinsic are cold. // Parallels the cold attribute on LLVM IR functions. def IntrCold : IntrinsicProperty; // IntrNoDuplicate - Calls to this intrinsic cannot be duplicated. // Parallels the noduplicate attribute on LLVM IR functions. def IntrNoDuplicate : IntrinsicProperty; // IntrNoMerge - Calls to this intrinsic cannot be merged // Parallels the nomerge attribute on LLVM IR functions. def IntrNoMerge : IntrinsicProperty; // IntrConvergent - Calls to this intrinsic are convergent and may not be made // control-dependent on any additional values. // Parallels the convergent attribute on LLVM IR functions. def IntrConvergent : IntrinsicProperty; // This property indicates that the intrinsic is safe to speculate. def IntrSpeculatable : IntrinsicProperty; // This property can be used to override the 'has no other side effects' // language of the IntrNoMem, IntrReadMem, IntrWriteMem, and IntrArgMemOnly // intrinsic properties. By default, intrinsics are assumed to have side // effects, so this property is only necessary if you have defined one of // the memory properties listed above. // For this property, 'side effects' has the same meaning as 'side effects' // defined by the hasSideEffects property of the TableGen Instruction class. def IntrHasSideEffects : IntrinsicProperty; // Result will not be undef or poison if all arguments are not undef and not // poison. def IntrNoCreateUndefOrPoison : IntrinsicProperty; // This property indicates that the intrinsic is trivially scalarizable. def IntrTriviallyScalarizable : IntrinsicProperty; //===----------------------------------------------------------------------===// // IIT constants and utils //===----------------------------------------------------------------------===// // llvm::Intrinsic::IITDescriptor::AnyKindVectorConstraint::VC_% def AnyKindVectorConstraint { int None = 0; int Vector = 1; int Scalar = 2; } // llvm::Intrinsic::IITDescriptor::AnyKindElementConstraint::EC_% def AnyKindElementConstraint { int None = 0; int Integer = 1; int Float = 2; int Pointer = 3; } // Placeholder to encode the overload index of the current type. We encode a // value > 255 to indicate that this entry needs to be patched up with the // overload index (to prevent conflict with any valid not-to-be-patched IIT // encoding byte, whose value will be <= 255). Note that this is just a // transient representation till it gets processed by `PatchOverloadIndex` // below, so this is *not* the encoding of the final type signature. defvar OverloadIndexPlaceholder = 0x100; // This class verifies that the overload index is valid for the final IIT table // encoding. Overload index has a single byte assigned in the IIT encoding, so // verify that its >= 0 and <= 255. class VerifyOverloadIndex { assert !ge(OverloadIndex, 0), "overload index must be >= 0"; assert !lt(OverloadIndex, 256), "cannot support more than 256 overload types"; int ret = OverloadIndex; } // This class handles the actual patching of the overload index into a component // value `Sig` in the type signature. If the value is > 255, it's a placeholder // value generated by OverloadIndexPlaceholder and patching is needed, else the // value is left unchanged. class PatchOverloadIndex { // If the value is equal to `OverloadIndexPlaceholder`, it indicates that // patching is needed by replacing it with this type's overload index. int ret = !if(!eq(Sig, OverloadIndexPlaceholder), VerifyOverloadIndex.ret, Sig); } //===----------------------------------------------------------------------===// // IIT_Info //===----------------------------------------------------------------------===// class IIT_Base { int Number = num; list VTs = ?; } class IIT_VT : IIT_Base { let VTs = [vt]; } class IIT_Int : IIT_Base { let VTs = !filter(vti, ValueTypes, !and(vti.isInteger, !eq(vti.Size, size))); } class IIT_Vec : IIT_Base { let VTs = !filter(vti, ValueTypes, !and(vti.isVector, !eq(vti.nElem, nelem))); } defset list IIT_all = { def IIT_Done : IIT_Base< 0>; def IIT_I1 : IIT_Int<1, 1>; def IIT_I8 : IIT_Int<8, 2>; def IIT_I16 : IIT_Int<16, 3>; def IIT_I32 : IIT_Int<32, 4>; def IIT_I64 : IIT_Int<64, 5>; def IIT_F16 : IIT_VT; def IIT_F32 : IIT_VT; def IIT_F64 : IIT_VT; def IIT_V2 : IIT_Vec<2, 9>; def IIT_V4 : IIT_Vec<4, 10>; def IIT_V8 : IIT_Vec<8, 11>; def IIT_V16 : IIT_Vec<16, 12>; def IIT_V32 : IIT_Vec<32, 13>; def IIT_PTR : IIT_Base< 14>; // pointer with address space 0. def IIT_ANY : IIT_Base< 15>; def IIT_V64 : IIT_Vec<64, 16>; def IIT_MMX : IIT_VT; def IIT_TOKEN : IIT_VT; def IIT_METADATA : IIT_VT; def IIT_MATCH : IIT_Base<20>; def IIT_STRUCT : IIT_Base<21>; def IIT_EXTEND_ARG : IIT_Base<22>; def IIT_TRUNC_ARG : IIT_Base<23>; def IIT_PTR_AS : IIT_Base<24>; // Pointer with address space. def IIT_V1 : IIT_Vec<1, 25>; def IIT_VARARG : IIT_VT; def IIT_ONE_NTH_ELTS_VEC_ARG : IIT_Base<27>; def IIT_SAME_VEC_WIDTH_ARG : IIT_Base<28>; def IIT_VEC_OF_ANYPTRS_TO_ELT : IIT_Base<29>; def IIT_I128 : IIT_Int<128, 30>; def IIT_V512 : IIT_Vec<512, 31>; def IIT_V1024 : IIT_Vec<1024, 32>; def IIT_F128 : IIT_VT; def IIT_VEC_ELEMENT : IIT_Base<34>; def IIT_SCALABLE_VEC : IIT_Base<35>; def IIT_SUBDIVIDE2_ARG : IIT_Base<36>; def IIT_SUBDIVIDE4_ARG : IIT_Base<37>; def IIT_VEC_OF_BITCASTS_TO_INT : IIT_Base<38>; def IIT_V128 : IIT_Vec<128, 39>; def IIT_BF16 : IIT_VT; def IIT_V256 : IIT_Vec<256, 41>; def IIT_AMX : IIT_VT; def IIT_PPCF128 : IIT_VT; def IIT_V3 : IIT_Vec<3, 44>; def IIT_EXTERNREF : IIT_VT; def IIT_FUNCREF : IIT_VT; def IIT_I2 : IIT_Int<2, 47>; def IIT_I4 : IIT_Int<4, 48>; def IIT_AARCH64_SVCOUNT : IIT_VT; def IIT_V6 : IIT_Vec<6, 50>; def IIT_V10 : IIT_Vec<10, 51>; def IIT_V2048 : IIT_Vec<2048, 52>; def IIT_V4096 : IIT_Vec<4096, 53>; } defvar IIT_all_FixedTypes = !filter(iit, IIT_all, !or(!isa(iit), !isa(iit))); defvar IIT_all_VectorTypes = !filter(iit, IIT_all, !isa(iit)); //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// class LLVMType { ValueType VT = vt; list IITs = !filter(iit, IIT_all_FixedTypes, !not(!empty(!filter(iit_vt, iit.VTs, !eq(iit_vt, !if(vt.isVector, vt.ElementType, vt)))))); assert !le(!size(IITs), 1), "Duplicate type"; list IIT_Vecs = !if(vt.isVector, !filter(iit, IIT_all_VectorTypes, !not(!empty(!filter(iit_vt, iit.VTs, !and( !eq(iit_vt.ElementType, vt.ElementType), !eq(iit_vt.nElem, vt.nElem)))))), []); assert !le(!size(IIT_Vecs), 1), "Duplicate type"; // For vector types, assert that the IIT_Vecs list is not empty. assert !or(!not(vt.isVector), !not(!empty(IIT_Vecs))), "Invalid IIT encoding for vector type v" # vt.nElem # vt.ElementType; list Sig = !listconcat( !foreach(iit, IIT_Vecs, iit.Number), !if(vt.isScalable, [IIT_SCALABLE_VEC.Number], []), !foreach(iit, IITs, iit.Number)); } class LLVMAnyType : LLVMType { let Sig = [ IIT_ANY.Number, // The first byte of the IIT_ANY payload is the overload index of this type. // Here we use `OverloadIndexPlaceholder` which will be updated to the // overload index in `PatchOverloadIndex`. OverloadIndexPlaceholder, // The second byte of IIT_ANY payload is the packed AnyKindVectorConstraint // and AnyKindElementConstraint. !or(!shl(VecKind, 4), ElemKind) ]; assert VT.isOverloaded, "LLVMAnyType.VT should have isOverloaded"; } class LLVMQualPointerType : LLVMType { assert !and(!le(0, addrspace), !le(addrspace, 255)), "Address space exceeds 255"; let Sig = !if(addrspace, [ IIT_PTR_AS.Number, addrspace, ], [ IIT_PTR.Number, ]); } // Dependent types: These are types that depend on another LLVMAnyType overload // type. There are 2 subclasses of dependent types: // 1. Fully dependent types: dependent type can be completely derived from // another overload type. // 2. Partially dependent types: dependent type is constrained by another // overload type, but cannot be fully derived from it. Such types get // assigned an overload index and are a part of the overloaded types for an // intrinsics. class LLVMDependentType : LLVMType { // Overload index of the overload type that this dependent type is dependent // on. int OverloadIndex = oidx; } class LLVMFullyDependentType : LLVMDependentType { // For fully dependent overload types, the type signature is just the IIT code // followed by the overload index of the overload type it depends on. let Sig = [ IIT_Info.Number, VerifyOverloadIndex.ret ]; } class LLVMPartiallyDependentType : LLVMDependentType { // For partially dependent type, the type signature is the IIT code, followed // by this type's oveerload index, followed by the overload index of the // overload type its depends on. let Sig = [ IIT_Info.Number, // This types overload index. OverloadIndexPlaceholder, // Overload index of the reference overload type. VerifyOverloadIndex.ret, ]; } // ---------------------------------------------------------------------------- // Various sub-classes of fully dependent types. // Match the type of another intrinsic parameter. `oidx` is the overload index // of the overloaded type that this type is dependent on. Overload types are // either LLVMAnyType or LLVMPartiallyDependentType. // // Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyfloat_ty, LLVMMatchType<0>]> // // has one overloaded type, the 2nd argument. LLVMMatchType<0> refers to this // first overloaded type, which is the 2nd argument. As another example, // // Intrinsic<[llvm_anyint_ty], // [llvm_anyfloat_ty, LLVMMatchType<0>, llvm_anyfloat_ty, LLVMMatchType<2>]> // // has 3 overloaded types: // overload index 0 = return type // overload index 1 = first argument // overload index 2 = third argument // // LLVMMatchType<0> therefore will match the return type, and // LLVMMatchType<2> will match the 3rd argument. class LLVMMatchType : LLVMFullyDependentType; // Match the type of another intrinsic parameter that is expected to be based on // an integral type (i.e. either iN or ), but change the scalar size to // be twice as wide or half as wide as the other type. This is only useful when // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType : LLVMFullyDependentType; class LLVMTruncatedType : LLVMFullyDependentType; // Match the scalar/vector of another intrinsic parameter but with a different // element type. Either both are scalars or both are vectors with the same // number of elements. class LLVMScalarOrSameVectorWidth : LLVMFullyDependentType { let Sig = !listconcat([ IIT_SAME_VEC_WIDTH_ARG.Number, // Overload index of the reference overload type. VerifyOverloadIndex.ret, ], elty.Sig); } class LLVMVectorElementType : LLVMFullyDependentType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be 1/n of it. class LLVMOneNthElementsVectorType : LLVMFullyDependentType { let Sig = [ IIT_ONE_NTH_ELTS_VEC_ARG.Number, VerifyOverloadIndex.ret, n, ]; } // Match the type of another intrinsic parameter that is expected to be a // vector type (i.e. ) but with each element subdivided to // form a vector with more elements that are smaller than the original. class LLVMSubdivide2VectorType : LLVMFullyDependentType; class LLVMSubdivide4VectorType : LLVMFullyDependentType; // Match the element count and bit width of another intrinsic parameter, but // change the element type to an integer. class LLVMVectorOfBitcastsToInt : LLVMFullyDependentType; // ---------------------------------------------------------------------------- // Various sub-classes of partially dependent types. class LLVMVectorOfAnyPointersToElt : LLVMPartiallyDependentType; def llvm_void_ty : LLVMType; // Unconstrained overloaded type. def llvm_any_ty : LLVMAnyType; // Integer overloaded types. def llvm_anyint_ty : LLVMAnyType; def llvm_any_vector_int_ty : LLVMAnyType; def llvm_any_scalar_int_ty : LLVMAnyType; // FP overloaded types. def llvm_anyfloat_ty : LLVMAnyType; def llvm_any_vector_float_ty : LLVMAnyType; def llvm_any_scalar_float_ty : LLVMAnyType; // Other overloaded types. def llvm_anyvector_ty : LLVMAnyType; // Note: CodeGenIntrinsics.cpp seems to check this class to check pointers. class LLVMAnyPointerType : LLVMAnyType; def llvm_anyptr_ty : LLVMAnyPointerType; // ptr addrspace(N) def llvm_i1_ty : LLVMType; def llvm_i8_ty : LLVMType; def llvm_i16_ty : LLVMType; def llvm_i32_ty : LLVMType; def llvm_i64_ty : LLVMType; def llvm_i128_ty : LLVMType; def llvm_half_ty : LLVMType; def llvm_bfloat_ty : LLVMType; def llvm_float_ty : LLVMType; def llvm_double_ty : LLVMType; def llvm_f80_ty : LLVMType; def llvm_f128_ty : LLVMType; def llvm_ppcf128_ty : LLVMType; def llvm_ptr_ty : LLVMQualPointerType<0>; // ptr def llvm_empty_ty : LLVMType; // { } def llvm_metadata_ty : LLVMType; // !{...} def llvm_token_ty : LLVMType; // token def llvm_x86mmx_ty : LLVMType; def llvm_aarch64_svcount_ty : LLVMType; def llvm_x86amx_ty : LLVMType; def llvm_v2i1_ty : LLVMType; // 2 x i1 def llvm_v4i1_ty : LLVMType; // 4 x i1 def llvm_v8i1_ty : LLVMType; // 8 x i1 def llvm_v16i1_ty : LLVMType; // 16 x i1 def llvm_v32i1_ty : LLVMType; // 32 x i1 def llvm_v64i1_ty : LLVMType; // 64 x i1 def llvm_v128i1_ty : LLVMType; // 128 x i1 def llvm_v256i1_ty : LLVMType; // 256 x i1 def llvm_v512i1_ty : LLVMType; // 512 x i1 def llvm_v1024i1_ty : LLVMType; //1024 x i1 def llvm_v2048i1_ty : LLVMType; //2048 x i1 def llvm_v4096i1_ty : LLVMType; //4096 x i1 def llvm_v1i8_ty : LLVMType; // 1 x i8 def llvm_v2i8_ty : LLVMType; // 2 x i8 def llvm_v3i8_ty : LLVMType; // 3 x i8 def llvm_v4i8_ty : LLVMType; // 4 x i8 def llvm_v8i8_ty : LLVMType; // 8 x i8 def llvm_v16i8_ty : LLVMType; // 16 x i8 def llvm_v32i8_ty : LLVMType; // 32 x i8 def llvm_v64i8_ty : LLVMType; // 64 x i8 def llvm_v128i8_ty : LLVMType; //128 x i8 def llvm_v256i8_ty : LLVMType; //256 x i8 def llvm_v1i16_ty : LLVMType; // 1 x i16 def llvm_v2i16_ty : LLVMType; // 2 x i16 def llvm_v4i16_ty : LLVMType; // 4 x i16 def llvm_v8i16_ty : LLVMType; // 8 x i16 def llvm_v16i16_ty : LLVMType; // 16 x i16 def llvm_v32i16_ty : LLVMType; // 32 x i16 def llvm_v64i16_ty : LLVMType; // 64 x i16 def llvm_v128i16_ty : LLVMType; // 128 x i16 def llvm_v4096i16_ty : LLVMType; // 4096 x i16 def llvm_v1i32_ty : LLVMType; // 1 x i32 def llvm_v2i32_ty : LLVMType; // 2 x i32 def llvm_v3i32_ty : LLVMType; // 3 x i32 def llvm_v4i32_ty : LLVMType; // 4 x i32 def llvm_v6i32_ty : LLVMType; // 6 x i32 def llvm_v8i32_ty : LLVMType; // 8 x i32 def llvm_v10i32_ty : LLVMType; // 10 x i32 def llvm_v16i32_ty : LLVMType; // 16 x i32 def llvm_v32i32_ty : LLVMType; // 32 x i32 def llvm_v64i32_ty : LLVMType; // 64 x i32 def llvm_v128i32_ty : LLVMType; // 128 x i32 def llvm_v256i32_ty : LLVMType; // 256 x i32 def llvm_v2048i32_ty : LLVMType; // 2048 x i32 def llvm_v4096i32_ty : LLVMType; // 4096 x i32 def llvm_v1i64_ty : LLVMType; // 1 x i64 def llvm_v2i64_ty : LLVMType; // 2 x i64 def llvm_v4i64_ty : LLVMType; // 4 x i64 def llvm_v8i64_ty : LLVMType; // 8 x i64 def llvm_v16i64_ty : LLVMType; // 16 x i64 def llvm_v32i64_ty : LLVMType; // 32 x i64 def llvm_v1i128_ty : LLVMType; // 1 x i128 def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) def llvm_v16f16_ty : LLVMType; // 16 x half (__fp16) def llvm_v32f16_ty : LLVMType; // 32 x half (__fp16) def llvm_v4096f16_ty : LLVMType; // 4096 x half (__fp16) def llvm_v2bf16_ty : LLVMType; // 2 x bfloat (__bf16) def llvm_v4bf16_ty : LLVMType; // 4 x bfloat (__bf16) def llvm_v8bf16_ty : LLVMType; // 8 x bfloat (__bf16) def llvm_v16bf16_ty : LLVMType; // 16 x bfloat (__bf16) def llvm_v32bf16_ty : LLVMType; // 32 x bfloat (__bf16) def llvm_v4096bf16_ty : LLVMType; // 4096 x bfloat (__bf16) def llvm_v1f32_ty : LLVMType; // 1 x float def llvm_v2f32_ty : LLVMType; // 2 x float def llvm_v3f32_ty : LLVMType; // 3 x float def llvm_v4f32_ty : LLVMType; // 4 x float def llvm_v8f32_ty : LLVMType; // 8 x float def llvm_v10f32_ty : LLVMType; // 10 x float def llvm_v16f32_ty : LLVMType; // 16 x float def llvm_v32f32_ty : LLVMType; // 32 x float def llvm_v2048f32_ty : LLVMType; // 2048 x float def llvm_v1f64_ty : LLVMType; // 1 x double def llvm_v2f64_ty : LLVMType; // 2 x double def llvm_v4f64_ty : LLVMType; // 4 x double def llvm_v8f64_ty : LLVMType; // 8 x double def llvm_v16f64_ty : LLVMType; // 16 x double def llvm_vararg_ty : LLVMType; // this means vararg here def llvm_externref_ty : LLVMType; def llvm_funcref_ty : LLVMType; def llvm_exnref_ty : LLVMType; //===----------------------------------------------------------------------===// // Computes the overload index for overloaded types used by an intrinsic. // Input `IsOverloadedType` is a list of booleans, one for each type in the // intrinsic's type signature. A 0 value indicate that that type is not an // overloaded type, and 1 indicates that its an overloaded type. // // Assigns overload index by essentially computing a prefix sum on this list. // The output list `ret` has value ? for non-overload types and the overload // index for overloaded types. class AssignOverloadIndex IsOverloadedType> { list PrefixSum = !foreach(i, !range(IsOverloadedType), !if(IsOverloadedType[i], !foldl(0, !range(0, i), m, j, !add(m, IsOverloadedType[j])), -1)); // Assign ? if the entry was -1, else its the expected prefix sum. list ret = !foreach(a, PrefixSum, !if(!ge(a, 0), a, ?)); } class TypeInfoGen RetTypes, list ParamTypes> { list AllTypes = !listconcat(RetTypes, ParamTypes); // Assign overload index for all overloaded types // (LLVMAnyType or LLVMPartiallyDependentType). list OverloadIdxs = AssignOverloadIndex< !foreach(ty, AllTypes, !or(!isa(ty), !isa(ty)))>.ret; // List of all overloaded types, in their overload-index order. list OverloadTypes = !filter(ty, AllTypes, !or(!isa(ty), !isa(ty))); bit isOverloaded = !not(!empty(OverloadTypes)); list TypeSig = !listflatten(!listconcat( [!cond( !eq(!size(RetTypes), 0): [IIT_Done.Number], !eq(!size(RetTypes), 1): [], true: [IIT_STRUCT.Number, !sub(!size(RetTypes), 2)])], !foreach(i, !range(AllTypes), !foreach(a, AllTypes[i].Sig, PatchOverloadIndex.ret)))); } //===----------------------------------------------------------------------===// // Intrinsic Definitions. //===----------------------------------------------------------------------===// // Intrinsic class - This is used to define one LLVM intrinsic. The name of the // intrinsic definition should start with "int_", then match the LLVM intrinsic // name with the "llvm." prefix removed, and all "."s turned into "_"s. For // example, llvm.bswap.i16 -> int_bswap_i16. // // * RetTypes is a list containing the return types expected for the // intrinsic. // * ParamTypes is a list containing the parameter types expected for the // intrinsic. // * Properties can be set to describe the behavior of the intrinsic. // class Intrinsic ret_types, list param_types = [], list intr_properties = [], string name = "", list sd_properties = [], bit disable_default_attributes = true> : SDPatternOperator { string LLVMName = name; string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. list RetTypes = ret_types; list ParamTypes = param_types; list IntrProperties = intr_properties; let Properties = sd_properties; // Disable applying IntrinsicProperties that are marked default with // IntrinsicProperty<1> bit DisableDefaultAttributes = disable_default_attributes; TypeInfoGen TypeInfo = TypeInfoGen; } // Intrinsic with default attributes (disable_default_attributes = false). class DefaultAttrsIntrinsic ret_types, list param_types = [], list intr_properties = [], string name = "", list sd_properties = []> : Intrinsic {} /// ClangBuiltin - If this intrinsic exactly corresponds to a Clang builtin, /// this specifies the name of the builtin. This provides automatic CBE and CFE /// support. class ClangBuiltin { string ClangBuiltinName = name; } class MSBuiltin { string MSBuiltinName = name; } /// Utility class for intrinsics that /// 1. Don't touch memory or any hidden state /// 2. Can be freely speculated, and /// 3. Will not create undef or poison on defined inputs. class PureIntrinsic ret_types, list param_types = [], list intr_properties = [], string name = "", list sd_properties = []> : DefaultAttrsIntrinsic; #ifndef TEST_INTRINSICS_SUPPRESS_DEFS //===--------------- Variable Argument Handling Intrinsics ----------------===// // def int_vastart : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty], [], "llvm.va_start">; def int_vacopy : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, LLVMMatchType<0>], [], "llvm.va_copy">; def int_vaend : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty], [], "llvm.va_end">; //===------------------- Garbage Collection Intrinsics --------------------===// // def int_gcroot : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_gcread : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>; def int_gcwrite : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [IntrArgMemOnly, NoCapture>, NoCapture>]>; //===------------------- ObjC ARC runtime Intrinsics --------------------===// // // Note these are to support the Objective-C ARC optimizer which wants to // eliminate retain and releases where possible. def int_objc_autorelease : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_autoreleasePoolPop : Intrinsic<[], [llvm_ptr_ty]>; def int_objc_autoreleasePoolPush : Intrinsic<[llvm_ptr_ty], []>; def int_objc_autoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_copyWeak : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_destroyWeak : Intrinsic<[], [llvm_ptr_ty]>; def int_objc_initWeak : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_loadWeak : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_loadWeakRetained : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_moveWeak : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_release : Intrinsic<[], [llvm_ptr_ty]>; def int_objc_retain : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_retainAutorelease : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_retainAutoreleaseReturnValue : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_retainAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_unsafeClaimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_claimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_retainBlock : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_storeStrong : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_storeWeak : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_clang_arc_use : Intrinsic<[], [llvm_vararg_ty]>; def int_objc_clang_arc_noop_use : DefaultAttrsIntrinsic<[], [llvm_vararg_ty], [IntrInaccessibleMemOnly]>; def int_objc_retainedObject : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_unretainedObject : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_unretainedPointer : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty]>; def int_objc_retain_autorelease : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [Returned>]>; def int_objc_sync_enter : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_objc_sync_exit : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_objc_arc_annotation_topdown_bbstart : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_arc_annotation_topdown_bbend : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_arc_annotation_bottomup_bbstart : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_objc_arc_annotation_bottomup_bbend : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; //===--------------- Swift asynchronous context intrinsics ----------------===// // Returns the location of the Swift asynchronous context (usually stored just // before the frame pointer), and triggers the creation of a null context if it // would otherwise be unneeded. def int_swift_async_context_addr : Intrinsic<[llvm_ptr_ty], [], []>; //===--------------------- Code Generator Intrinsics ----------------------===// // def int_returnaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_addressofreturnaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>; def int_frameaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_sponentry : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrNoMem]>; def int_stackaddress : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], []>; def int_read_register : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrReadMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [IntrNoCallback], "llvm.write_register">; def int_write_volatile_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [], "llvm.write_volatile_register">; def int_read_volatile_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrHasSideEffects], "llvm.read_volatile_register">; // Gets the address of the local variable area. This is typically a copy of the // stack, frame, or base pointer depending on the type of prologue. def int_localaddress : DefaultAttrsIntrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; // Escapes local variables to allow access from other functions. def int_localescape : DefaultAttrsIntrinsic<[], [llvm_vararg_ty]>; // Given a function and the localaddress of a parent frame, returns a pointer // to an escaped allocation indicated by the index. def int_localrecover : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; // Given the frame pointer passed into an SEH filter function, returns a // pointer to the local variable area suitable for use with llvm.localrecover. def int_eh_recoverfp : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], [IntrNoMem]>; // To mark the beginning/end of a try-scope for Windows SEH -EHa // calls/invokes to these intrinsics are placed to model control flows // caused by HW exceptions under option -EHa. // calls/invokes to these intrinsics will be discarded during a codegen pass // after EH tables are generated def int_seh_try_begin : Intrinsic<[], [], [IntrWriteMem, IntrWillReturn]>; def int_seh_try_end : Intrinsic<[], [], [IntrWriteMem, IntrWillReturn]>; def int_seh_scope_begin : Intrinsic<[], [], [IntrNoMem]>; def int_seh_scope_end : Intrinsic<[], [], [IntrNoMem]>; // Note: we treat stacksave/stackrestore as writemem because we don't otherwise // model their dependencies on allocas. def int_stacksave : DefaultAttrsIntrinsic<[llvm_anyptr_ty]>, ClangBuiltin<"__builtin_stack_save">; def int_stackrestore : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty]>, ClangBuiltin<"__builtin_stack_restore">; def int_get_dynamic_area_offset : DefaultAttrsIntrinsic<[llvm_anyint_ty]>; def int_thread_pointer : DefaultAttrsIntrinsic< [llvm_anyptr_ty], [], [IntrNoMem]>, ClangBuiltin<"__builtin_thread_pointer">; // IntrInaccessibleMemOrArgMemOnly is a little more pessimistic than strictly // necessary for prefetch, however it does conveniently prevent the prefetch // from being reordered overly much with respect to nearby access to the same // memory while not impeding optimization. def int_prefetch : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrInaccessibleMemOrArgMemOnly, ReadOnly>, NoCapture>, ImmArg>, ImmArg>, ImmArg>]>; def int_pcmarker : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>; def int_readcyclecounter : DefaultAttrsIntrinsic<[llvm_i64_ty]>; def int_readsteadycounter : DefaultAttrsIntrinsic<[llvm_i64_ty]>; // The assume intrinsic is marked InaccessibleMemOnly so that proper control // dependencies will be maintained. def int_assume : DefaultAttrsIntrinsic<[], [llvm_i1_ty], [IntrWriteMem, IntrInaccessibleMemOnly, NoUndef>]>; // 'llvm.experimental.noalias.scope.decl' intrinsic: Inserted at the location of // noalias scope declaration. Makes it possible to identify that a noalias scope // is only valid inside the body of a loop. // // Purpose of the different arguments: // - arg0: id.scope: metadata representing the scope declaration. def int_experimental_noalias_scope_decl : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], [IntrInaccessibleMemOnly]>; // blocks LICM and some more // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. def int_stackprotector : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_ptr_ty]>; def int_stackguard : DefaultAttrsIntrinsic<[llvm_ptr_ty], []>; // A cover for instrumentation based profiling. def int_instrprof_cover : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty]>; // A counter increment for instrumentation based profiling. def int_instrprof_increment : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty]>; // A counter increment with step for instrumentation based profiling. def int_instrprof_increment_step : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_i64_ty]>; // Callsite instrumentation for contextual profiling def int_instrprof_callsite : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty]>; // A timestamp for instrumentation based profiling. def int_instrprof_timestamp : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty]>; // A call to profile runtime for value profiling of target expressions // through instrumentation based profiling. def int_instrprof_value_profile : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i32_ty]>; // A parameter configuration for instrumentation based MCDC profiling. def int_instrprof_mcdc_parameters : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty]>; // A test vector bitmap update for instrumentation based MCDC profiling. def int_instrprof_mcdc_tvbitmap_update : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty]>; def int_call_preallocated_setup : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty], [ImmArg>]>; def int_call_preallocated_arg : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_i32_ty], [ImmArg>]>; def int_call_preallocated_teardown : DefaultAttrsIntrinsic<[], [llvm_token_ty]>; // This intrinsic is intentionally undocumented and users shouldn't call it; // it's produced then quickly consumed during codegen. def int_callbr_landingpad : Intrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMerge]>; def int_structured_gep : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_vararg_ty], [IntrNoMem, IntrSpeculatable]>; def int_structured_alloca : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [], [IntrInaccessibleMemOnly]>; //===------------------- Standard C Library Intrinsics --------------------===// // // The memcpy etc. intrinsics specify willreturn and argmemonly here, and these // then get removed by accessors if the memcpy is volatile. FIXME: Consider // inverting the handling. def int_memcpy : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, NoCapture>, NoCapture>, NoAlias>, NoAlias>, WriteOnly>, ReadOnly>, ImmArg>]>; // Memcpy semantic that is guaranteed to be inlined. // In particular this means that the generated code is not allowed to call any // external function. def int_memcpy_inline : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, NoCapture>, NoCapture>, NoAlias>, NoAlias>, WriteOnly>, ReadOnly>, ImmArg>]>; def int_memmove : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i1_ty], [IntrArgMemOnly, NoCapture>, NoCapture>, WriteOnly>, ReadOnly>, ImmArg>]>; def int_memset : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty], [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>, ImmArg>]>; // Memset version that is guaranteed to be inlined. // In particular this means that the generated code is not allowed to call any // external function. def int_memset_inline : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty], [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>, ImmArg>]>; // Memset variant that writes a given pattern. def int_experimental_memset_pattern : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty, // Destination. llvm_any_ty, // Pattern value. llvm_anyint_ty, // Count (number of times to fill value). llvm_i1_ty], // IsVolatile. [IntrWriteMem, IntrArgMemOnly, NoCapture>, WriteOnly>, ImmArg>]>; // FIXME: Add version of these floating point intrinsics which allow non-default // rounding modes and FP exception handling. let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { def int_fma : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; def int_fmuladd : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; // These functions do not read memory, but are sensitive to the // rounding mode. LLVM purposely does not model changes to the FP // environment so they can be treated as readnone. def int_sqrt : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_powi : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>; def int_sin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_cos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_pow : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_log : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_log10: DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_log2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp10 : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_copysign : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_ceil : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_trunc : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_rint : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_round : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_roundeven : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>]>; // Truncate a floating point number with a specific rounding mode def int_fptrunc_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty ]>; // Convert from native LLVM floating-point to arbitrary FP format // Returns an integer containing the arbitrary FP bits def int_convert_to_arbitrary_fp : DefaultAttrsIntrinsic< [ llvm_anyint_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty, llvm_metadata_ty, llvm_i1_ty ], [ IntrNoMem, IntrSpeculatable, ImmArg> ]>; // Convert from arbitrary FP format to native LLVM floating-point // Takes an integer containing the arbitrary FP bits def int_convert_from_arbitrary_fp : DefaultAttrsIntrinsic< [ llvm_anyfloat_ty ], [ llvm_anyint_ty, llvm_metadata_ty ], [ IntrNoMem, IntrSpeculatable ]>; def int_canonicalize : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; // Arithmetic fence intrinsic. def int_arithmetic_fence : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; // If the value doesn't fit an unspecified value is returned, but this // is not poison so we can still mark these as IntrNoCreateUndefOrPoison. def int_lround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; def int_llround : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; def int_lrint : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; def int_llrint : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; // TODO: int operand should be constrained to same number of elements as the // result. def int_ldexp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_anyint_ty]>; // TODO: Should constrain all element counts to match. def int_frexp : DefaultAttrsIntrinsic<[llvm_anyfloat_ty, llvm_anyint_ty], [LLVMMatchType<0>]>; } // TODO: Move all of these into the IntrNoCreateUndefOrPoison case above. let IntrProperties = [IntrNoMem, IntrSpeculatable] in { // These functions do not read memory, but are sensitive to the // rounding mode. LLVM purposely does not model changes to the FP // environment so they can be treated as readnone. def int_asin : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_acos : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_atan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_atan2 : DefaultAttrsIntrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_tan : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_sinh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_cosh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_tanh : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_sincos : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], [llvm_anyfloat_ty]>; def int_sincospi : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], [llvm_anyfloat_ty]>; def int_modf : DefaultAttrsIntrinsic<[LLVMMatchType<0>, LLVMMatchType<0>], [llvm_anyfloat_ty]>; } def int_minnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; def int_maxnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; def int_minimum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; def int_maximum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; def int_minimumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; def int_maximumnum : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, Commutative, IntrNoCreateUndefOrPoison] >; // Internal interface for object size checking def int_objectsize : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, llvm_i1_ty, llvm_i1_ty, llvm_i1_ty], [IntrNoMem, IntrSpeculatable, ImmArg>, ImmArg>, ImmArg>]>, ClangBuiltin<"__builtin_object_size">; //===--------------- Access to Floating Point Environment -----------------===// // let IntrProperties = [IntrInaccessibleMemOnly] in { def int_get_rounding : DefaultAttrsIntrinsic<[llvm_i32_ty], []>; def int_set_rounding : DefaultAttrsIntrinsic<[], [llvm_i32_ty]>; def int_get_fpenv : DefaultAttrsIntrinsic<[llvm_anyint_ty], []>; def int_set_fpenv : DefaultAttrsIntrinsic<[], [llvm_anyint_ty]>; def int_reset_fpenv : DefaultAttrsIntrinsic<[], []>; def int_get_fpmode : DefaultAttrsIntrinsic<[llvm_anyint_ty], []>; def int_set_fpmode : DefaultAttrsIntrinsic<[], [llvm_anyint_ty]>; def int_reset_fpmode : DefaultAttrsIntrinsic<[], []>; } //===--------------- Floating Point Properties ----------------------------===// // def int_is_fpclass : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, ImmArg>]>; //===--------------- Constrained Floating Point Intrinsics ----------------===// // /// IntrStrictFP - The intrinsic is allowed to be used in an alternate /// floating point environment. def IntrStrictFP : IntrinsicProperty; let IntrProperties = [IntrInaccessibleMemOnly, IntrStrictFP] in { def int_experimental_constrained_fadd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fsub : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fmul : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fdiv : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_frem : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fma : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fmuladd : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fptosi : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fptoui : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty ]>; def int_experimental_constrained_sitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ llvm_anyint_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_uitofp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ llvm_anyint_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fptrunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fpext : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ llvm_anyfloat_ty, llvm_metadata_ty ]>; // These intrinsics are sensitive to the rounding mode so we need constrained // versions of each of them. When strict rounding and exception control are // not required the non-constrained versions of these intrinsics should be // used. def int_experimental_constrained_sqrt : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_powi : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_i32_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_ldexp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_anyint_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_asin : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_acos : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_atan : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_atan2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_sin : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_cos : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_tan : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_sinh : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_cosh : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_tanh : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_pow : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_log : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_log10: DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_log2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_exp : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_exp2 : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_rint : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_nearbyint : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_lrint : DefaultAttrsIntrinsic<[ llvm_any_scalar_int_ty ], [ llvm_any_scalar_float_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_llrint : DefaultAttrsIntrinsic<[ llvm_any_scalar_int_ty ], [ llvm_any_scalar_float_ty, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_maxnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_minnum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_maximum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_minimum : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_ceil : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_floor : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_lround : DefaultAttrsIntrinsic<[ llvm_any_scalar_int_ty ], [ llvm_any_scalar_float_ty, llvm_metadata_ty ]>; def int_experimental_constrained_llround : DefaultAttrsIntrinsic<[ llvm_any_scalar_int_ty ], [ llvm_any_scalar_float_ty, llvm_metadata_ty ]>; def int_experimental_constrained_round : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_roundeven : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty ]>; def int_experimental_constrained_trunc : DefaultAttrsIntrinsic<[ llvm_anyfloat_ty ], [ LLVMMatchType<0>, llvm_metadata_ty ]>; // Constrained floating-point comparison (quiet and signaling variants). // Third operand is the predicate represented as a metadata string. def int_experimental_constrained_fcmp : DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], [ llvm_anyfloat_ty, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; def int_experimental_constrained_fcmps : DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], [ llvm_anyfloat_ty, LLVMMatchType<0>, llvm_metadata_ty, llvm_metadata_ty ]>; } // FIXME: Consider maybe adding intrinsics for sitofp, uitofp. //===------------------------- Expect Intrinsics --------------------------===// // def int_expect : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_expect_with_probability : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_double_ty], [IntrNoMem, ImmArg>]>; //===-------------------- Bit Manipulation Intrinsics ---------------------===// // // None of these intrinsics accesses memory at all. let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { def int_bswap: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_ctpop: DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_bitreverse : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>]>; def int_fshl : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; def int_fshr : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>; def int_clmul : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_pext : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_pdep : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; } let IntrProperties = [IntrNoMem, IntrSpeculatable, ImmArg>] in { def int_ctlz : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; def int_cttz : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty]>; } //===------------------------ Debugger Intrinsics -------------------------===// // // None of these intrinsics accesses memory at all...but that doesn't // mean the optimizers can change them aggressively. Special handling // needed in a few places. These synthetic intrinsics have no // side-effects and just mark information about their operands. let IntrProperties = [IntrNoMem, IntrSpeculatable] in { def int_dbg_declare : DefaultAttrsIntrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; def int_dbg_value : DefaultAttrsIntrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; def int_dbg_assign : DefaultAttrsIntrinsic<[], [llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty, llvm_metadata_ty]>; def int_dbg_label : DefaultAttrsIntrinsic<[], [llvm_metadata_ty]>; } //===------------------ Exception Handling Intrinsics----------------------===// // // The result of eh.typeid.for depends on the enclosing function, but inside a // given function it is 'const' and may be CSE'd etc. def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; // eh.exceptionpointer returns the pointer to the exception caught by // the given `catchpad`. def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], [IntrNoMem]>; // Gets the exception code from a catchpad token. Only used on some platforms. def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>; // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. def int_eh_unwind_init: Intrinsic<[]>, ClangBuiltin<"__builtin_unwind_init">; def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>; //===---------------- Generic Variable Attribute Intrinsics----------------===// // def int_var_annotation : DefaultAttrsIntrinsic< [], [llvm_anyptr_ty, llvm_anyptr_ty, LLVMMatchType<1>, llvm_i32_ty, LLVMMatchType<1>], [IntrInaccessibleMemOnly]>; def int_ptr_annotation : DefaultAttrsIntrinsic< [llvm_anyptr_ty], [LLVMMatchType<0>, llvm_anyptr_ty, LLVMMatchType<1>, llvm_i32_ty, LLVMMatchType<1>], [IntrInaccessibleMemOnly]>; def int_annotation : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, llvm_anyptr_ty, LLVMMatchType<1>, llvm_i32_ty], [IntrInaccessibleMemOnly]>; // Annotates the current program point with metadata strings which are emitted // as CodeView debug info records. This is expensive, as it disables inlining // and is modelled as having side effects. def int_codeview_annotation : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], [IntrInaccessibleMemOnly, IntrNoDuplicate]>; //===------------------------ Trampoline Intrinsics -----------------------===// // def int_init_trampoline : DefaultAttrsIntrinsic< [], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [IntrArgMemOnly, NoCapture>, WriteOnly>, ReadNone>, ReadNone>]>, ClangBuiltin<"__builtin_init_trampoline">; def int_adjust_trampoline : DefaultAttrsIntrinsic< [llvm_ptr_ty], [llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly]>, ClangBuiltin<"__builtin_adjust_trampoline">; //===------------------------ Overflow Intrinsics -------------------------===// // // Expose the carry flag from add operations on two integrals. let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { def int_sadd_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_uadd_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_ssub_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_usub_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_smul_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_umul_with_overflow : DefaultAttrsIntrinsic< [llvm_anyint_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [LLVMMatchType<0>, LLVMMatchType<0>]>; } //===------------------ Saturation Arithmetic Intrinsics ------------------===// // def int_sadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Commutative]>; def int_uadd_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Commutative]>; def int_ssub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_usub_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_sshl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; def int_ushl_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; //===------------------- Fixed Point Arithmetic Intrinsics ----------------===// // def int_smul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, Commutative, ImmArg>]>; def int_umul_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, Commutative, ImmArg>]>; def int_sdiv_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_udiv_fix : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, ImmArg>]>; //===------------ Fixed Point Saturation Arithmetic Intrinsics ------------===// // def int_smul_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, Commutative, ImmArg>]>; def int_umul_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, Commutative, ImmArg>]>; def int_sdiv_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_udiv_fix_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, ImmArg>]>; //===------------------ Integer Min/Max/Abs Intrinsics --------------------===// // def int_abs : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, llvm_i1_ty], [IntrNoMem, IntrSpeculatable, ImmArg>]>; def int_smax : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_smin : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_umax : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_umin : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison]>; def int_scmp : DefaultAttrsIntrinsic< [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Range]>; def int_ucmp : DefaultAttrsIntrinsic< [llvm_anyint_ty], [llvm_anyint_ty, LLVMMatchType<1>], [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison, Range]>; //===------------------------- Memory Use Markers -------------------------===// // def int_lifetime_start : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty], [IntrArgMemOnly, NoCapture>]>; def int_lifetime_end : DefaultAttrsIntrinsic<[], [llvm_anyptr_ty], [IntrArgMemOnly, NoCapture>]>; def int_invariant_start : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_i64_ty, llvm_anyptr_ty], [IntrArgMemOnly, NoCapture>, ImmArg>]>; def int_invariant_end : DefaultAttrsIntrinsic<[], [llvm_ptr_ty, llvm_i64_ty, llvm_anyptr_ty], [IntrArgMemOnly, NoCapture>, ImmArg>]>; // launder.invariant.group can't be marked with 'readnone' (IntrNoMem), // because it would cause CSE of two barriers with the same argument. // Inaccessiblememonly says that the barrier doesn't read the argument, // but it changes state not accessible to this module. This way // we can DSE through the barrier because it doesn't read the value // after store. Although the barrier doesn't modify any memory it // can't be marked as readonly, because it would be possible to // CSE 2 barriers with store in between. // The argument also can't be marked with 'returned' attribute, because // it would remove barrier. // Note that it is still experimental, which means that its semantics // might change in the future. def int_launder_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], [IntrInaccessibleMemOnly, IntrSpeculatable]>; def int_strip_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], [IntrSpeculatable, IntrNoMem]>; //===------------------------ Stackmap Intrinsics -------------------------===// // def int_experimental_stackmap : DefaultAttrsIntrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty], [Throws, ImmArg>, ImmArg>]>; def int_experimental_patchpoint_void : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_vararg_ty], [Throws, ImmArg>, ImmArg>, ImmArg>]>; def int_experimental_patchpoint : Intrinsic<[llvm_any_ty], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, llvm_vararg_ty], [Throws, ImmArg>, ImmArg>, ImmArg>]>; //===------------------------ Garbage Collection Intrinsics ---------------===// // These are documented in docs/Statepoint.rst def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty], [llvm_i64_ty, llvm_i32_ty, llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty, llvm_vararg_ty], [Throws, ImmArg>, ImmArg>, ImmArg>, ImmArg>]>; def int_experimental_gc_result : DefaultAttrsIntrinsic< [llvm_any_ty], [llvm_token_ty], [IntrNoMem]>; def int_experimental_gc_relocate : DefaultAttrsIntrinsic< [llvm_any_ty], [llvm_token_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; def int_experimental_gc_get_pointer_base : DefaultAttrsIntrinsic< [llvm_anyptr_ty], [llvm_anyptr_ty], [IntrNoMem, ReadNone>, NoCapture>]>; def int_experimental_gc_get_pointer_offset : DefaultAttrsIntrinsic< [llvm_i64_ty], [llvm_anyptr_ty], [IntrNoMem, ReadNone>, NoCapture>]>; //===------------------------ Coroutine Intrinsics ---------------===// // These are documented in docs/Coroutines.md // Coroutine Structure Intrinsics. def int_coro_id : DefaultAttrsIntrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [IntrArgMemOnly, IntrReadMem, ReadNone>, ReadOnly>, NoCapture>]>; def int_coro_id_retcon : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], []>; def int_coro_id_retcon_once : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], []>; def int_coro_alloc : Intrinsic<[llvm_i1_ty], [llvm_token_ty], []>; def int_coro_id_async : Intrinsic<[llvm_token_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_ptr_ty], []>; def int_coro_async_context_alloc : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_ptr_ty], []>; def int_coro_async_context_dealloc : Intrinsic<[], [llvm_ptr_ty], []>; def int_coro_async_resume : Intrinsic<[llvm_ptr_ty], [], [IntrNoMerge, IntrNoDuplicate]>; def int_coro_async_size_replace : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], []>; def int_coro_suspend_async : Intrinsic<[llvm_any_ty], [llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty], [IntrNoMerge, IntrNoDuplicate]>; def int_coro_prepare_async : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_coro_begin : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], [WriteOnly>]>; def int_coro_begin_custom_abi : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty, llvm_i32_ty], [WriteOnly>]>; def int_coro_free : Intrinsic<[llvm_ptr_ty], [llvm_token_ty, llvm_ptr_ty], [IntrReadMem, IntrArgMemOnly, ReadOnly>, NoCapture>]>; def int_coro_dead : Intrinsic<[], [llvm_ptr_ty], [IntrNoMem]>; def int_coro_end : Intrinsic<[], [llvm_ptr_ty, llvm_i1_ty, llvm_token_ty], []>; def int_coro_end_results : Intrinsic<[llvm_token_ty], [llvm_vararg_ty]>; def int_coro_end_async : Intrinsic<[], [llvm_ptr_ty, llvm_i1_ty, llvm_vararg_ty], []>; def int_coro_frame : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; def int_coro_is_in_ramp : Intrinsic<[llvm_i1_ty], [], [IntrNoMem], "llvm.coro.is_in_ramp">; def int_coro_noop : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; def int_coro_size : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; def int_coro_align : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; def int_coro_save : Intrinsic<[llvm_token_ty], [llvm_ptr_ty], [IntrNoMerge]>; def int_coro_suspend : Intrinsic<[llvm_i8_ty], [llvm_token_ty, llvm_i1_ty], []>; def int_coro_suspend_retcon : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], []>; def int_coro_prepare_retcon : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_coro_alloca_alloc : Intrinsic<[llvm_token_ty], [llvm_anyint_ty, llvm_i32_ty], []>; def int_coro_alloca_get : Intrinsic<[llvm_ptr_ty], [llvm_token_ty], []>; def int_coro_alloca_free : Intrinsic<[], [llvm_token_ty], []>; // Coroutine Manipulation Intrinsics. def int_coro_resume : Intrinsic<[], [llvm_ptr_ty], [Throws]>; def int_coro_destroy : Intrinsic<[], [llvm_ptr_ty], [Throws]>; def int_coro_done : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty], [IntrArgMemOnly, ReadOnly>, NoCapture>]>; def int_coro_promise : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_i1_ty], [IntrNoMem, NoCapture>]>; def int_coro_await_suspend_void : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [Throws]>; def int_coro_await_suspend_bool : Intrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [Throws]>; def int_coro_await_suspend_handle : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty], [Throws]>; // Coroutine Lowering Intrinsics. Used internally by coroutine passes. def int_coro_subfn_addr : DefaultAttrsIntrinsic< [llvm_ptr_ty], [llvm_ptr_ty, llvm_i8_ty], [IntrReadMem, IntrArgMemOnly, ReadOnly>, NoCapture>]>; ///===------------------------- Other Intrinsics --------------------------===// // // TODO: We should introduce a new memory kind fo traps (and other side effects // we only model to keep things alive). def int_trap : Intrinsic<[], [], [IntrNoReturn, IntrCold, IntrInaccessibleMemOnly, IntrWriteMem]>, ClangBuiltin<"__builtin_trap">; def int_debugtrap : Intrinsic<[]>, ClangBuiltin<"__builtin_debugtrap">; def int_ubsantrap : Intrinsic<[], [llvm_i8_ty], [IntrNoReturn, IntrCold, ImmArg>, IntrInaccessibleMemOnly, IntrWriteMem]>; def int_looptrap : Intrinsic<[], [], [IntrNoReturn, IntrCold, IntrInaccessibleMemOnly, IntrWriteMem]>; // Return true if ubsan check is allowed. def int_allow_ubsan_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_i8_ty], [IntrInaccessibleMemOnly, ImmArg>, NoUndef]>; // Return true if runtime check is allowed. def int_allow_runtime_check : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_metadata_ty], [IntrInaccessibleMemOnly, NoUndef]>, ClangBuiltin<"__builtin_allow_runtime_check">; // Return true if the specific sanitizer is enabled for the function. def int_allow_sanitize_address : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrInaccessibleMemOnly, NoUndef]>; def int_allow_sanitize_thread : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrInaccessibleMemOnly, NoUndef]>; def int_allow_sanitize_memory : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrInaccessibleMemOnly, NoUndef]>; def int_allow_sanitize_hwaddress : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrInaccessibleMemOnly, NoUndef]>; // Support for dynamic deoptimization (or de-specialization) def int_experimental_deoptimize : Intrinsic<[llvm_any_ty], [llvm_vararg_ty], [Throws]>; // Support for speculative runtime guards def int_experimental_guard : Intrinsic<[], [llvm_i1_ty, llvm_vararg_ty], [Throws]>; // Supports widenable conditions for guards represented as explicit branches. def int_experimental_widenable_condition : DefaultAttrsIntrinsic<[llvm_i1_ty], [], [IntrInaccessibleMemOnly, IntrSpeculatable, NoUndef]>; // NOP: calls/invokes to this intrinsic are removed by codegen def int_donothing : DefaultAttrsIntrinsic<[], [], [IntrNoMem]>; // This instruction has no actual effect, though it is treated by the optimizer // has having opaque side effects. This may be inserted into loops to ensure // that they are not removed even if they turn out to be empty, for languages // which specify that infinite loops must be preserved. def int_sideeffect : DefaultAttrsIntrinsic<[], [], [IntrInaccessibleMemOnly]>; // The pseudoprobe intrinsic works as a place holder to the block it probes. // Like the sideeffect intrinsic defined above, this intrinsic is treated by the // optimizer as having opaque side effects so that it won't be get rid of or moved // out of the block it probes. def int_pseudoprobe : DefaultAttrsIntrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrInaccessibleMemOnly]>; // Saturating floating point to integer intrinsics let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { def int_fptoui_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; def int_fptosi_sat : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty]>; } // Clear cache intrinsic, default to ignore (ie. emit nothing) // maps to void __clear_cache() on supporting platforms def int_clear_cache : Intrinsic<[], [llvm_anyptr_ty, LLVMMatchType<0>], [], "llvm.clear_cache">; // Intrinsic to detect whether its argument is a constant. def int_is_constant : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem, IntrConvergent]>; // Introduce a use of the argument without generating any code. def int_fake_use : DefaultAttrsIntrinsic<[], [llvm_vararg_ty], [IntrHasSideEffects, IntrInaccessibleMemOnly]>; // Intrinsic to mask out bits of a pointer. // First argument must be pointer or vector of pointer. This is checked by the // verifier. def int_ptrmask: PureIntrinsic<[llvm_any_ty], [LLVMMatchType<0>, llvm_anyint_ty]>; // Intrinsic to wrap a thread local variable. def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>], [NonNull, NonNull>, IntrNoMem, IntrSpeculatable]>; def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], [IntrNoMem, IntrHasSideEffects]>; //===--------------------- Vector Predication Intrinsics ------------------===// // Memory Intrinsics def int_vp_store : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ NoCapture>, IntrWriteMem, IntrArgMemOnly ]>; def int_vp_load : DefaultAttrsIntrinsic<[ llvm_anyvector_ty], [ llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ NoCapture>, IntrReadMem, IntrArgMemOnly ]>; def int_vp_load_ff : DefaultAttrsIntrinsic<[ llvm_anyvector_ty, llvm_i32_ty ], [ llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ NoCapture>, IntrNoSync, IntrReadMem, IntrWillReturn, IntrArgMemOnly ]>; def int_vp_gather: DefaultAttrsIntrinsic<[ llvm_anyvector_ty], [ LLVMVectorOfAnyPointersToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ IntrReadMem]>; def int_vp_scatter: DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], []>; // TODO allow IntrNoCapture for vectors of // pointers. // Experimental strided memory accesses def int_experimental_vp_strided_store : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, llvm_anyptr_ty, llvm_anyint_ty, // Stride in bytes LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ NoCapture>, IntrWriteMem, IntrArgMemOnly ]>; def int_experimental_vp_strided_load : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [ llvm_anyptr_ty, llvm_anyint_ty, // Stride in bytes LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ NoCapture>, IntrReadMem, IntrArgMemOnly ]>; // Experimental histogram def int_experimental_vector_histogram_add : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, // Vector of pointers llvm_anyint_ty, // Increment LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], // Mask [ IntrArgMemOnly ]>; def int_experimental_vector_histogram_uadd_sat : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, // Vector of pointers llvm_anyint_ty, // Increment LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], // Mask [ IntrArgMemOnly ]>; def int_experimental_vector_histogram_umin : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, // Vector of pointers llvm_anyint_ty, // Update value LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], // Mask [ IntrArgMemOnly ]>; def int_experimental_vector_histogram_umax : DefaultAttrsIntrinsic<[], [ llvm_anyvector_ty, // Vector of pointers llvm_anyint_ty, // Update value LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], // Mask [ IntrArgMemOnly ]>; // Experimental match def int_experimental_vector_match : DefaultAttrsIntrinsic< [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], [ llvm_anyvector_ty, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], // Mask [ IntrNoMem, IntrSpeculatable ]>; // Extract based on mask bits def int_experimental_vector_extract_last_active: DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMVectorElementType<0>], [IntrNoMem, IntrSpeculatable]>; // Operators let IntrProperties = [IntrNoMem, IntrSpeculatable] in { // Integer arithmetic def int_vp_add : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_sub : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_mul : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_ashr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_lshr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_shl : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_or : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_and : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_xor : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_abs : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, llvm_i1_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_smin : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_smax : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_umin : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_umax : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_bswap : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_bitreverse : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_ctpop : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fshl : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fshr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_sadd_sat : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_uadd_sat : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_ssub_sat : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_usub_sat : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; // Floating-point arithmetic def int_vp_fadd : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fsub : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fmul : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fdiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_frem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fneg : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fabs : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_sqrt : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fma : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fmuladd : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_minnum : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_maxnum : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_minimum : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_maximum : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_copysign : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_ceil : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_floor : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_round : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_roundeven : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_roundtozero : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_rint : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_nearbyint : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_lrint : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_llrint : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; // Casts def int_vp_trunc : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_zext : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_sext : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fptrunc : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fpext : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fptoui : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_fptosi : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_uitofp : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_sitofp : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_ptrtoint : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_inttoptr : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; // Shuffles def int_vp_select : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty]>; def int_vp_merge : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty]>; // Comparisons def int_vp_fcmp : DefaultAttrsIntrinsic< [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], [ llvm_anyvector_ty, LLVMMatchType<0>, llvm_metadata_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_icmp : DefaultAttrsIntrinsic< [ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty> ], [ llvm_anyvector_ty, LLVMMatchType<0>, llvm_metadata_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; // Reductions def int_vp_reduce_fadd : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_fmul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_add : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_mul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_and : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_or : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_xor : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_smax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_smin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_umax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_umin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_fmax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_fmin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_fmaximum : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_reduce_fminimum : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [ LLVMVectorElementType<0>, llvm_anyvector_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; } // Integer VP division and remainder: not speculatable. def int_vp_sdiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [IntrNoMem]>; def int_vp_udiv : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [IntrNoMem]>; def int_vp_srem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [IntrNoMem]>; def int_vp_urem : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [IntrNoMem]>; let IntrProperties = [IntrNoMem, IntrSpeculatable, ImmArg>] in { def int_vp_ctlz : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, llvm_i1_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_cttz : DefaultAttrsIntrinsic<[ llvm_anyvector_ty ], [ LLVMMatchType<0>, llvm_i1_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty]>; def int_vp_cttz_elts : DefaultAttrsIntrinsic<[ llvm_anyint_ty ], [ llvm_anyvector_ty, llvm_i1_ty, LLVMScalarOrSameVectorWidth<1, llvm_i1_ty>, llvm_i32_ty]>; } def int_loop_dependence_raw_mask: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyint_ty, LLVMMatchType<1>, LLVMMatchType<1>], [IntrNoMem, IntrNoSync, IntrWillReturn, ImmArg>]>; def int_loop_dependence_war_mask: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyint_ty, LLVMMatchType<1>, LLVMMatchType<1>], [IntrNoMem, IntrNoSync, IntrWillReturn, ImmArg>]>; def int_get_active_lane_mask: DefaultAttrsIntrinsic<[llvm_any_vector_int_ty], [llvm_any_scalar_int_ty, LLVMMatchType<1>], [IntrNoMem, IntrSpeculatable]>; def int_experimental_get_vector_length: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], [IntrNoMem, IntrSpeculatable, ImmArg>, ImmArg>]>; def int_experimental_cttz_elts: DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyvector_ty, llvm_i1_ty], [IntrNoMem, IntrSpeculatable, ImmArg>]>; def int_experimental_vp_splice: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, ImmArg>]>; def int_experimental_vp_reverse: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; def int_vp_is_fpclass: DefaultAttrsIntrinsic<[ LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [ llvm_anyvector_ty, llvm_i32_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, llvm_i32_ty], [ IntrNoMem, IntrSpeculatable, ImmArg>]>; //===-------------------------- Masked Intrinsics -------------------------===// // def int_masked_load: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem, IntrArgMemOnly, NoCapture>]>; def int_masked_store: DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrWriteMem, IntrArgMemOnly, NoCapture>]>; def int_masked_gather: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMVectorOfAnyPointersToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem]>; def int_masked_scatter: DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, LLVMVectorOfAnyPointersToElt<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrWriteMem]>; def int_masked_expandload: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrReadMem, NoCapture>]>; def int_masked_compressstore: DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_anyptr_ty, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrWriteMem, IntrArgMemOnly, NoCapture>]>; def int_experimental_vector_compress: DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>, LLVMMatchType<0>], [IntrNoMem]>; def int_masked_udiv: DefaultAttrsIntrinsic<[llvm_any_vector_int_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrNoMem]>; def int_masked_sdiv: DefaultAttrsIntrinsic<[llvm_any_vector_int_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrNoMem]>; def int_masked_urem: DefaultAttrsIntrinsic<[llvm_any_vector_int_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrNoMem]>; def int_masked_srem: DefaultAttrsIntrinsic<[llvm_any_vector_int_ty], [LLVMMatchType<0>, LLVMMatchType<0>, LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>], [IntrNoMem]>; // Test whether a pointer is associated with a type metadata identifier. def int_type_test : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], [IntrNoMem, IntrSpeculatable]>; // Safely loads a function pointer from a virtual table pointer using type // metadata. def int_type_checked_load : DefaultAttrsIntrinsic<[llvm_ptr_ty, llvm_i1_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], [IntrNoMem]>; // Safely loads a relative function pointer from a virtual table pointer using // type metadata. def int_type_checked_load_relative : DefaultAttrsIntrinsic< [llvm_ptr_ty, llvm_i1_ty], [llvm_ptr_ty, llvm_i32_ty, llvm_metadata_ty], [IntrNoMem]>; // Test whether a pointer is associated with a type metadata identifier. Used // for public visibility classes that may later be refined to private // visibility. def int_public_type_test : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_ptr_ty, llvm_metadata_ty], [IntrNoMem, IntrSpeculatable]>; // Create a branch funnel that implements an indirect call to a limited set of // callees. This needs to be a musttail call. def int_icall_branch_funnel : DefaultAttrsIntrinsic<[], [llvm_vararg_ty], []>; def int_load_relative: DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty, llvm_anyint_ty], [IntrReadMem, IntrArgMemOnly]>; def int_asan_check_memaccess : Intrinsic<[],[llvm_ptr_ty, llvm_i32_ty], [ImmArg>]>; // Spin in an infinite loop (using instructions specified by the target) iff the // argument is true. Used to implement efficient conditional traps. def int_cond_loop : Intrinsic<[], [llvm_i1_ty], [IntrNoMem, IntrHasSideEffects]>; // HWASan intrinsics to test whether a pointer is addressable. //===----------------------------------------------------------------------===// // // Variant 1) is the OG memaccess intrinsic // Parameters: Shadow base (passed in a register), pointer to be checked for // validity, AccessInfo (AccessInfo is defined in HWAddressSanitizer.h) def int_hwasan_check_memaccess : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], [ImmArg>]>; // Variant 2) supports short granule checks // Parameters: same as Variant 1 def int_hwasan_check_memaccess_shortgranules : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], [ImmArg>]>; // Variant 3) assumes a fixed shadow offset // Parameters: Pointer to be checked for validity, AccessInfo, Shadow base def int_hwasan_check_memaccess_fixedshadow : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i64_ty], [ImmArg>, ImmArg>]>; // Variant 4) supports short granule checks and assumes a fixed shadow offset // Parameters: same as Variant 3 def int_hwasan_check_memaccess_shortgranules_fixedshadow : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty, llvm_i64_ty], [ImmArg>, ImmArg>]>; // Xray intrinsics //===----------------------------------------------------------------------===// // Custom event logging for x-ray. // Takes a pointer to a string and the length of the string. def int_xray_customevent : Intrinsic<[], [llvm_ptr_ty, llvm_i64_ty], [IntrWriteMem, NoCapture>, ReadOnly>]>; // Typed event logging for x-ray. // Takes a numeric type tag, a pointer to a string and the length of the string. def int_xray_typedevent : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty, llvm_i64_ty], [IntrWriteMem, NoCapture>, ReadOnly>]>; //===----------------------------------------------------------------------===// //===------ Memory intrinsics with element-wise atomicity guarantees ------===// // // @llvm.memcpy.element.unordered.atomic.*(dest, src, length, elementsize) def int_memcpy_element_unordered_atomic : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty], [IntrArgMemOnly, IntrWillReturn, IntrNoSync, NoCapture>, NoCapture>, WriteOnly>, ReadOnly>, ImmArg>]>; // @llvm.memmove.element.unordered.atomic.*(dest, src, length, elementsize) def int_memmove_element_unordered_atomic : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty], [IntrArgMemOnly, IntrWillReturn, IntrNoSync, NoCapture>, NoCapture>, WriteOnly>, ReadOnly>, ImmArg>]>; // @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize) def int_memset_element_unordered_atomic : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty], [IntrWriteMem, IntrArgMemOnly, IntrWillReturn, IntrNoSync, NoCapture>, WriteOnly>, ImmArg>]>; //===------------------------ Reduction Intrinsics ------------------------===// // let IntrProperties = [IntrNoMem, IntrSpeculatable, IntrNoCreateUndefOrPoison] in { def int_vector_reduce_fadd : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [LLVMVectorElementType<0>, llvm_any_vector_float_ty]>; def int_vector_reduce_fmul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [LLVMVectorElementType<0>, llvm_any_vector_float_ty]>; def int_vector_reduce_add : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_mul : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_and : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_or : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_xor : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_smax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_smin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_umax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_umin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_int_ty]>; def int_vector_reduce_fmax : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_float_ty]>; def int_vector_reduce_fmin : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_any_vector_float_ty]>; def int_vector_reduce_fminimum: DefaultAttrsIntrinsic< [LLVMVectorElementType<0>], [llvm_any_vector_float_ty]>; def int_vector_reduce_fmaximum: DefaultAttrsIntrinsic< [LLVMVectorElementType<0>], [llvm_any_vector_float_ty]>; } //===------ Matrix intrinsics ---------------------------------------------===// def int_matrix_transpose : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty], [ IntrNoMem, IntrSpeculatable, ImmArg>, ImmArg>]>; def int_matrix_multiply : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_anyvector_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, IntrSpeculatable, ImmArg>, ImmArg>, ImmArg>]>; def int_matrix_column_major_load : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_ptr_ty, llvm_anyint_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly, IntrReadMem, NoCapture>, ImmArg>, ImmArg>, ImmArg>]>; def int_matrix_column_major_store : DefaultAttrsIntrinsic<[], [llvm_anyvector_ty, llvm_ptr_ty, llvm_anyint_ty, llvm_i1_ty, llvm_i32_ty, llvm_i32_ty], [IntrArgMemOnly, IntrWriteMem, WriteOnly>, NoCapture>, ImmArg>, ImmArg>, ImmArg>]>; //===---------- Intrinsics to control hardware supported loops ----------===// // Specify that the value given is the number of iterations that the next loop // will execute. def int_set_loop_iterations : DefaultAttrsIntrinsic<[], [llvm_anyint_ty], [IntrNoDuplicate]>; // Same as the above, but produces a value (the same as the input operand) to // be fed into the loop. def int_start_loop_iterations : DefaultAttrsIntrinsic< [llvm_anyint_ty], [LLVMMatchType<0>], [IntrNoDuplicate]>; // Specify that the value given is the number of iterations that the next loop // will execute. Also test that the given count is not zero, allowing it to // control entry to a 'while' loop. def int_test_set_loop_iterations : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; // Same as the above, but produces an extra value (the same as the input // operand) to be fed into the loop. def int_test_start_loop_iterations : DefaultAttrsIntrinsic<[llvm_anyint_ty, llvm_i1_ty], [LLVMMatchType<0>], [IntrNoDuplicate]>; // Decrement loop counter by the given argument. Return false if the loop // should exit. def int_loop_decrement : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_anyint_ty], [IntrNoDuplicate]>; // Decrement the first operand (the loop counter) by the second operand (the // maximum number of elements processed in an iteration). Return the remaining // number of iterations still to be executed. This is effectively a sub which // can be used with a phi, icmp and br to control the number of iterations // executed, as usual. Any optimisations are allowed to treat it is a sub, and // it's scevable, so it's the backends responsibility to handle cases where it // may be optimised. def int_loop_decrement_reg : DefaultAttrsIntrinsic<[llvm_anyint_ty], [LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoDuplicate]>; //===----- Intrinsics that are used to provide predicate information -----===// def int_ssa_copy : DefaultAttrsIntrinsic<[llvm_any_ty], [LLVMMatchType<0>], [IntrNoMem, Returned>]>; //===------- Intrinsics that are used to preserve debug information -------===// def int_preserve_array_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; def int_preserve_union_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; def int_preserve_struct_access_index : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_anyptr_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem, ImmArg>, ImmArg>]>; def int_preserve_static_offset : DefaultAttrsIntrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem, IntrSpeculatable, ReadNone >]>; //===------------ Intrinsics to perform common vector shuffles ------------===// def int_vector_reverse : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; def int_vector_splice_left : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; def int_vector_splice_right : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem, IntrSpeculatable]>; //===---------- Intrinsics to query properties of scalable vectors --------===// def int_vscale : DefaultAttrsIntrinsic<[llvm_anyint_ty], [], [IntrNoMem, IntrSpeculatable]>; //===---------- Intrinsics to perform subvector insertion/extraction ------===// def int_vector_insert : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [LLVMMatchType<0>, llvm_anyvector_ty, llvm_i64_ty], [IntrNoMem, IntrSpeculatable, ImmArg>]>; def int_vector_extract : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty, llvm_i64_ty], [IntrNoMem, IntrSpeculatable, ImmArg>]>; foreach n = 2...8 in { def int_vector_interleave#n : DefaultAttrsIntrinsic<[llvm_anyvector_ty], !listsplat(LLVMOneNthElementsVectorType<0, n>, n), [IntrNoMem, IntrSpeculatable]>; def int_vector_deinterleave#n : DefaultAttrsIntrinsic< !listsplat(LLVMOneNthElementsVectorType<0, n>, n), [llvm_anyvector_ty], [IntrNoMem, IntrSpeculatable]>; } //===-------------- Intrinsics to perform partial reduction ---------------===// def int_vector_partial_reduce_add : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyvector_ty, llvm_anyvector_ty], [IntrNoMem, IntrSpeculatable]>; def int_vector_partial_reduce_fadd : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, llvm_anyfloat_ty], [IntrNoMem]>; //===----------------- Pointer Authentication Intrinsics ------------------===// // // Sign an unauthenticated pointer using the specified key and discriminator, // passed in that order. // Returns the first argument, with some known bits replaced with a signature. def int_ptrauth_sign : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrNoMem, ImmArg>]>; // Authenticate a signed pointer, using the specified key and discriminator. // Returns the first argument, with the signature bits removed. // The signature must be valid. def int_ptrauth_auth : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrNoMem,ImmArg>]>; // Authenticate a signed pointer and resign it. // The second (key) and third (discriminator) arguments specify the signing // schema used for authenticating. // The fourth and fifth arguments specify the schema used for signing. // The signature must be valid. // This is a combined form of @llvm.ptrauth.sign and @llvm.ptrauth.auth, with // an additional integrity guarantee on the intermediate value. def int_ptrauth_resign : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrNoMem, ImmArg>, ImmArg>]>; // Authenticate a signed pointer, load 32bit value at offset from pointer, add // both, and sign it. The second (key) and third (discriminator) arguments // specify the signing schema used for authenticating. The fourth and fifth // arguments specify the schema used for signing. The sixth argument is addend // added to pointer to load the relative offset. The signature must be valid. // This is a combined form of int_ptrauth_resign for relative pointers def int_ptrauth_resign_load_relative : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty, llvm_i64_ty], [IntrReadMem, ImmArg>, ImmArg>, ImmArg>]>; // Strip the embedded signature out of a signed pointer. // The second argument specifies the key. // This behaves like @llvm.ptrauth.auth, but doesn't require the signature to // be valid. def int_ptrauth_strip : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty], [IntrNoMem, ImmArg>]>; // Blend a small integer discriminator with an address discriminator, producing // a new discriminator value. def int_ptrauth_blend : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; // Compute the signature of a value, using a given discriminator. // This differs from @llvm.ptrauth.sign in that it doesn't embed the computed // signature in the pointer, but instead returns the signature as a value. // That allows it to be used to sign non-pointer data: in that sense, it is // generic. There is no generic @llvm.ptrauth.auth: instead, the signature // can be computed using @llvm.ptrauth.sign_generic, and compared with icmp. def int_ptrauth_sign_generic : DefaultAttrsIntrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], [IntrNoMem]>; //===----------------- AllocToken Intrinsics ------------------------------===// // Return the token ID for the given !alloc_token metadata. def int_alloc_token_id : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem, NoUndef]>; //===----------------------------------------------------------------------===// //===------- Convergence Intrinsics ---------------------------------------===// def int_experimental_convergence_entry : DefaultAttrsIntrinsic<[llvm_token_ty], [], [IntrNoMem, IntrConvergent]>; def int_experimental_convergence_anchor : DefaultAttrsIntrinsic<[llvm_token_ty], [], [IntrNoMem, IntrConvergent]>; def int_experimental_convergence_loop : DefaultAttrsIntrinsic<[llvm_token_ty], [], [IntrNoMem, IntrConvergent]>; //===----------------- Structure Protection Intrinsics --------------------===// def int_protected_field_ptr : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatchType<0>, llvm_i64_ty, llvm_i1_ty], [IntrNoMem, ImmArg>]>; //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// include "llvm/IR/IntrinsicsPowerPC.td" include "llvm/IR/IntrinsicsX86.td" include "llvm/IR/IntrinsicsARM.td" include "llvm/IR/IntrinsicsAArch64.td" include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsAVR.td" include "llvm/IR/IntrinsicsAMDGPU.td" include "llvm/IR/IntrinsicsBPF.td" include "llvm/IR/IntrinsicsSystemZ.td" include "llvm/IR/IntrinsicsWebAssembly.td" include "llvm/IR/IntrinsicsRISCV.td" include "llvm/IR/IntrinsicsSPIRV.td" include "llvm/IR/IntrinsicsVE.td" include "llvm/IR/IntrinsicsDirectX.td" include "llvm/IR/IntrinsicsLoongArch.td" #endif // TEST_INTRINSICS_SUPPRESS_DEFS