[llvm-branch-commits] [llvm] [mlir] [IR] Make @llvm.memset prototype byte width dependent (PR #106537)
Sergei Barannikov via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 6 20:53:51 PDT 2026
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/106537
>From 1bfc7935d750fcdf1ad24a4b77bdc4b460699725 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Thu, 1 Aug 2024 23:47:25 +0300
Subject: [PATCH] [IR] Make @llvm.memset prototype byte width dependent
This patch changes the type of the value argument of @llvm.memset and
similar intrinsics from i8 to iN, where N is the byte width specified
in data layout string.
Note that the argument still has fixed type (not overloaded), but type
checker will complain if the type does not match the byte width.
Ideally, the type of the argument would be dependent on the address
space of the pointer argument. It is easy to do this (and I did it
downstream as a PoC), but since data layout string doesn't currently
allow different byte widths for different address spaces, I refrained
from doing it now.
---
llvm/bindings/ocaml/llvm/llvm.ml | 2 +-
llvm/bindings/ocaml/llvm/llvm.mli | 2 +-
llvm/bindings/ocaml/llvm/llvm_ocaml.c | 6 +-
llvm/include/llvm-c/Core.h | 2 +-
llvm/include/llvm/IR/Intrinsics.h | 10 ++-
llvm/include/llvm/IR/Intrinsics.td | 12 ++-
llvm/lib/AsmParser/LLParser.cpp | 3 +-
llvm/lib/IR/AutoUpgrade.cpp | 8 +-
llvm/lib/IR/Core.cpp | 4 +-
llvm/lib/IR/Function.cpp | 7 +-
llvm/lib/IR/IRBuilder.cpp | 3 +-
llvm/lib/IR/Intrinsics.cpp | 75 +++++++++++--------
llvm/lib/IR/Verifier.cpp | 2 +-
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 3 +-
.../NumericalStabilitySanitizer.cpp | 2 +-
llvm/test/Bindings/OCaml/core.ml | 2 +-
.../LLVMIR/LLVMToLLVMIRTranslation.cpp | 3 +-
17 files changed, 90 insertions(+), 56 deletions(-)
diff --git a/llvm/bindings/ocaml/llvm/llvm.ml b/llvm/bindings/ocaml/llvm/llvm.ml
index 574fa149a47c6b9..9fa54d57bb8e68d 100644
--- a/llvm/bindings/ocaml/llvm/llvm.ml
+++ b/llvm/bindings/ocaml/llvm/llvm.ml
@@ -844,7 +844,7 @@ external intrinsic_id : llvalue -> int = "llvm_intrinsic_id"
let is_intrinsic v = intrinsic_id v <> 0
external intrinsic_declaration : llmodule -> int -> lltype array -> llvalue
= "llvm_intrinsic_declaration"
-external intrinsic_type : llcontext -> int -> lltype array -> lltype
+external intrinsic_type : llmodule -> int -> lltype array -> lltype
= "llvm_intrinsic_type"
external intrinsic_name : int -> string = "llvm_intrinsic_name"
external intrinsic_overloaded_name : llmodule -> int -> lltype array -> string
diff --git a/llvm/bindings/ocaml/llvm/llvm.mli b/llvm/bindings/ocaml/llvm/llvm.mli
index ca525043caf3fc9..b51ca2183ac5a0b 100644
--- a/llvm/bindings/ocaml/llvm/llvm.mli
+++ b/llvm/bindings/ocaml/llvm/llvm.mli
@@ -1572,7 +1572,7 @@ val intrinsic_declaration : llmodule -> int -> lltype array -> llvalue
(** [intrinsic_type c id overload_types] returns the type of intrinsic [id] in
context [c]. For overloaded intrinsics, types must be provided to uniquely
identify an overload. See the method [llvm::Intrinsic::getType]. *)
-val intrinsic_type : llcontext -> int -> lltype array -> lltype
+val intrinsic_type : llmodule -> int -> lltype array -> lltype
(** [intrinsic_name id] returns the name of intrinsic [id]. See the method
[llvm::Intrinsic::getName()]. *)
diff --git a/llvm/bindings/ocaml/llvm/llvm_ocaml.c b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
index 75ae700de70edc0..596ef35dffa2011 100644
--- a/llvm/bindings/ocaml/llvm/llvm_ocaml.c
+++ b/llvm/bindings/ocaml/llvm/llvm_ocaml.c
@@ -1602,12 +1602,12 @@ value llvm_intrinsic_declaration(value M, value ID, value OverloadTypes) {
return to_val(Intrinsic);
}
-/* llcontext -> int -> lltype array -> lltype */
-value llvm_intrinsic_type(value C, value ID, value OverloadTypes) {
+/* llmodule -> int -> lltype array -> lltype */
+value llvm_intrinsic_type(value M, value ID, value OverloadTypes) {
mlsize_t Length = Wosize_val(OverloadTypes);
LLVMTypeRef *Temp = from_val_array(OverloadTypes);
LLVMTypeRef Type =
- LLVMIntrinsicGetType(Context_val(C), Int_val(ID), Temp, Length);
+ LLVMIntrinsicGetType(Module_val(M), Int_val(ID), Temp, Length);
free(Temp);
return to_val(Type);
}
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 8d55f33e553aed1..3296c427aa5cecf 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -3196,7 +3196,7 @@ LLVM_C_ABI LLVMValueRef LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod,
*
* @see llvm::Intrinsic::getType()
*/
-LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID,
+LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMModuleRef Mod, unsigned ID,
LLVMTypeRef *OverloadTypes,
size_t OverloadCount);
diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h
index 7cf28682c83e1df..c760524d605eac0 100644
--- a/llvm/include/llvm/IR/Intrinsics.h
+++ b/llvm/include/llvm/IR/Intrinsics.h
@@ -29,6 +29,7 @@ class APInt;
class AttributeList;
class AttributeSet;
class Constant;
+class DataLayout;
class Function;
class FunctionType;
class LLVMContext;
@@ -82,7 +83,7 @@ LLVM_ABI std::string getName(ID Id, ArrayRef<Type *> OverloadTys, Module *M,
LLVM_ABI std::string getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> OverloadTys);
/// Return the function type for an intrinsic.
-LLVM_ABI FunctionType *getType(LLVMContext &Context, ID id,
+LLVM_ABI FunctionType *getType(const Module *M, ID id,
ArrayRef<Type *> OverloadTys = {});
/// Returns true if the intrinsic can be overloaded.
@@ -175,6 +176,7 @@ struct IITDescriptor {
enum IITDescriptorKind {
// Concrete types. Additional qualifiers listed in comments.
Void,
+ Byte,
VarArg,
MMX,
Token,
@@ -300,7 +302,8 @@ getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
/// Returns false if the given ID and function type combination is not a
/// valid intrinsic call. Also prints the error message to indicate the reason
/// of the mismatch to \p OS.
-LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT,
+LLVM_ABI bool isSignatureValid(const DataLayout &DL, Intrinsic::ID ID,
+ FunctionType *FT,
SmallVectorImpl<Type *> &OverloadTys,
raw_ostream &OS = nulls());
@@ -312,7 +315,8 @@ LLVM_ABI bool isSignatureValid(Function *F,
/// Same as previous, but \p FT may omit exactly \p NumMissingTrailingParams
/// trailing parameters. The omitted parameters must have concrete integer type
/// so that all overload types can be resolved from the provided signature.
-LLVM_ABI bool isSignatureValid(Intrinsic::ID ID, FunctionType *FT,
+LLVM_ABI bool isSignatureValid(const DataLayout &DL, Intrinsic::ID ID,
+ FunctionType *FT,
SmallVectorImpl<Type *> &OverloadTys,
unsigned NumMissingTrailingParams,
raw_ostream &OS = nulls());
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 52be391132b7e87..d1e71b8dfa846d1 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -402,6 +402,7 @@ 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>;
+def IIT_BYTE : IIT_Base<54>;
}
defvar IIT_all_FixedTypes = !filter(iit, IIT_all,
@@ -440,6 +441,10 @@ class LLVMType<ValueType vt> {
!foreach(iit, IITs, iit.Number));
}
+class LLVMByteType : LLVMType<OtherVT> {
+ let Sig = [IIT_BYTE.Number];
+}
+
class LLVMAnyType<ValueType vt, int VecKind, int ElemKind> : LLVMType<vt> {
let Sig = [
IIT_ANY.Number,
@@ -587,6 +592,7 @@ class LLVMVectorOfAnyPointersToElt<int oidx>
def llvm_void_ty : LLVMType<isVoid>;
+def llvm_byte_ty : LLVMByteType;
// Unconstrained overloaded type.
def llvm_any_ty : LLVMAnyType<Any,
@@ -1195,7 +1201,7 @@ def int_memmove : DefaultAttrsIntrinsic<[],
WriteOnly<ArgIndex<0>>, ReadOnly<ArgIndex<1>>,
ImmArg<ArgIndex<3>>]>;
def int_memset : DefaultAttrsIntrinsic<[],
- [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty,
+ [llvm_anyptr_ty, llvm_byte_ty, llvm_anyint_ty,
llvm_i1_ty],
[IntrWriteMem, IntrArgMemOnly,
NoCapture<ArgIndex<0>>, WriteOnly<ArgIndex<0>>,
@@ -1206,7 +1212,7 @@ def int_memset : DefaultAttrsIntrinsic<[],
// external function.
def int_memset_inline
: DefaultAttrsIntrinsic<[],
- [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i1_ty],
+ [llvm_anyptr_ty, llvm_byte_ty, llvm_anyint_ty, llvm_i1_ty],
[IntrWriteMem, IntrArgMemOnly,
NoCapture<ArgIndex<0>>, WriteOnly<ArgIndex<0>>,
ImmArg<ArgIndex<3>>]>;
@@ -2616,7 +2622,7 @@ def int_memmove_element_unordered_atomic
// @llvm.memset.element.unordered.atomic.*(dest, value, length, elementsize)
def int_memset_element_unordered_atomic
: DefaultAttrsIntrinsic<
- [], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty],
+ [], [llvm_anyptr_ty, llvm_byte_ty, llvm_anyint_ty, llvm_i32_ty],
[IntrWriteMem, IntrArgMemOnly, NoCapture<ArgIndex<0>>,
WriteOnly<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>;
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 30e8aeea508ab32..3004c19d7e90ba4 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -458,7 +458,8 @@ bool LLParser::validateEndOfModule(bool UpgradeDebugInfo) {
SmallVector<Type *> OverloadTys;
if (IID != Intrinsic::not_intrinsic &&
- Intrinsic::isSignatureValid(IID, CB->getFunctionType(), OverloadTys,
+ Intrinsic::isSignatureValid(M->getDataLayout(), IID,
+ CB->getFunctionType(), OverloadTys,
ErrorOS)) {
U.set(Intrinsic::getOrInsertDeclaration(M, IID, OverloadTys));
} else {
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 2765934ee02d99b..3d3d41f0373bb1e 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -1506,7 +1506,7 @@ static Intrinsic::ID shouldUpgradeNVPTXBF16Intrinsic(StringRef Name) {
}
static bool isLegacyNVPTXBF16IntSignature(Function *F, Intrinsic::ID IID) {
- FunctionType *NewFnTy = Intrinsic::getType(F->getContext(), IID);
+ FunctionType *NewFnTy = Intrinsic::getType(F->getParent(), IID);
FunctionType *OldFnTy = F->getFunctionType();
auto IsOldBF16StorageTy = [](Type *OldTy, Type *NewTy) {
return OldTy->getScalarType()->isIntegerTy() &&
@@ -1685,7 +1685,8 @@ getFullArgCountForDefaultArgUpgrade(Function *F, Intrinsic::ID IID,
return 0;
unsigned NumMissingTrailingParams = FullArgCount - F->arg_size();
- if (!Intrinsic::isSignatureValid(IID, F->getFunctionType(), OverloadTys,
+ if (!Intrinsic::isSignatureValid(F->getDataLayout(), IID,
+ F->getFunctionType(), OverloadTys,
NumMissingTrailingParams))
return 0;
@@ -2480,7 +2481,8 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn,
if (Intrinsic::ID id = F->getIntrinsicID()) {
// Only do this if the intrinsic signature is valid.
SmallVector<Type *> OverloadTys;
- if (Intrinsic::isSignatureValid(id, F->getFunctionType(), OverloadTys))
+ if (Intrinsic::isSignatureValid(F->getDataLayout(), id,
+ F->getFunctionType(), OverloadTys))
F->setAttributes(
Intrinsic::getAttributes(F->getContext(), id, F->getFunctionType()));
}
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 3aab78bdf2d2a4f..dcd6a9f6c3a33eb 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -2612,12 +2612,12 @@ const char *LLVMIntrinsicGetName(unsigned ID, size_t *NameLength) {
return Str.data();
}
-LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID,
+LLVMTypeRef LLVMIntrinsicGetType(LLVMModuleRef Mod, unsigned ID,
LLVMTypeRef *OverloadTypes,
size_t OverloadCount) {
auto IID = llvm_map_to_intrinsic_id(ID);
ArrayRef<Type *> OverloadTys(unwrap(OverloadTypes), OverloadCount);
- return wrap(llvm::Intrinsic::getType(*unwrap(Ctx), IID, OverloadTys));
+ return wrap(llvm::Intrinsic::getType(unwrap(Mod), IID, OverloadTys));
}
char *LLVMIntrinsicCopyOverloadedName(unsigned ID, LLVMTypeRef *OverloadTypes,
diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 678dd93c96fe9f4..6d3df0698d0bf29 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -510,7 +510,12 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace,
// Don't set the attributes if the intrinsic signature is invalid. This
// case will either be auto-upgraded or fail verification.
SmallVector<Type *> OverloadTys;
- if (!Intrinsic::isSignatureValid(IntID, Ty, OverloadTys))
+ // DirectX backend is the only place where intrinsics are created unattached
+ // to a module. They have invalid signatures though, so skip the check.
+ if (!ParentModule)
+ return;
+ if (!Intrinsic::isSignatureValid(ParentModule->getDataLayout(), IntID, Ty,
+ OverloadTys))
return;
setAttributes(Intrinsic::getAttributes(getContext(), IntID, Ty));
diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp
index 07125506e6094a7..d513a958af502ab 100644
--- a/llvm/lib/IR/IRBuilder.cpp
+++ b/llvm/lib/IR/IRBuilder.cpp
@@ -978,7 +978,8 @@ Value *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID,
FMFSource FMFSource, const Twine &Name,
ArrayRef<OperandBundleDef> OpBundles,
function_ref<void(CallInst *)> SetFn) {
- Type *RetTy = Intrinsic::getType(Context, ID, OverloadTypes)->getReturnType();
+ Module *M = BB->getModule();
+ Type *RetTy = Intrinsic::getType(M, ID, OverloadTypes)->getReturnType();
if (Value *V = Folder.FoldIntrinsic(ID, Args, RetTy, FMFSource.get(FMF),
GetInsertBlock()->getParent()))
return V;
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index b4131903c5dddf8..c315eaca612c6b1 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -39,7 +39,7 @@
using namespace llvm;
// Forward declaration of static functions.
-static bool isSignatureValid(FunctionType *FTy,
+static bool isSignatureValid(const DataLayout &DL, FunctionType *FTy,
ArrayRef<Intrinsic::IITDescriptor> &Infos,
unsigned NumArgs, bool IsVarArg,
SmallVectorImpl<Type *> &OverloadTys,
@@ -191,9 +191,9 @@ static std::string getIntrinsicNameImpl(Intrinsic::ID Id,
if (HasUnnamedType) {
assert(M && "unnamed types need a module");
if (!FT)
- FT = Intrinsic::getType(M->getContext(), Id, OverloadTys);
+ FT = Intrinsic::getType(M, Id, OverloadTys);
else
- assert(FT == Intrinsic::getType(M->getContext(), Id, OverloadTys) &&
+ assert(FT == Intrinsic::getType(M, Id, OverloadTys) &&
"Provided FunctionType must match arguments");
return M->getUniqueIntrinsicName(Result, Id, FT);
}
@@ -242,6 +242,9 @@ DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
case IIT_Done:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
return;
+ case IIT_BYTE:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::Byte, 0));
+ return;
case IIT_VARARG:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));
return;
@@ -536,8 +539,8 @@ Intrinsic::getIntrinsicInfoTableEntries(ID id,
}
static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
- ArrayRef<Type *> OverloadTys,
- LLVMContext &Context) {
+ ArrayRef<Type *> OverloadTys, LLVMContext &Context,
+ const DataLayout &DL) {
using namespace Intrinsic;
IITDescriptor D = Infos.consume_front();
@@ -545,6 +548,8 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
switch (D.Kind) {
case IITDescriptor::Void:
return Type::getVoidTy(Context);
+ case IITDescriptor::Byte:
+ return Type::getIntNTy(Context, DL.getByteWidth());
case IITDescriptor::MMX:
return llvm::FixedVectorType::get(llvm::IntegerType::get(Context, 64), 1);
case IITDescriptor::AMX:
@@ -574,14 +579,14 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
case IITDescriptor::Integer:
return IntegerType::get(Context, D.IntegerWidth);
case IITDescriptor::Vector:
- return VectorType::get(DecodeFixedType(Infos, OverloadTys, Context),
+ return VectorType::get(DecodeFixedType(Infos, OverloadTys, Context, DL),
D.VectorWidth);
case IITDescriptor::Pointer:
return PointerType::get(Context, D.PointerAddressSpace);
case IITDescriptor::Struct: {
SmallVector<Type *, 8> Elts;
for (unsigned i = 0, e = D.StructNumElements; i != e; ++i)
- Elts.push_back(DecodeFixedType(Infos, OverloadTys, Context));
+ Elts.push_back(DecodeFixedType(Infos, OverloadTys, Context, DL));
return StructType::get(Context, Elts);
}
// For any overload type or partially dependent type, substitute it with the
@@ -608,7 +613,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
cast<VectorType>(OverloadTys[D.getOverloadIndex()]),
D.getVectorDivisor());
case IITDescriptor::SameVecWidth: {
- Type *EltTy = DecodeFixedType(Infos, OverloadTys, Context);
+ Type *EltTy = DecodeFixedType(Infos, OverloadTys, Context, DL);
Type *Ty = OverloadTys[D.getOverloadIndex()];
if (auto *VTy = dyn_cast<VectorType>(Ty))
return VectorType::get(EltTy, VTy->getElementCount());
@@ -634,16 +639,18 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
llvm_unreachable("unhandled");
}
-FunctionType *Intrinsic::getType(LLVMContext &Context, ID id,
+FunctionType *Intrinsic::getType(const Module *M, ID id,
ArrayRef<Type *> OverloadTys) {
SmallVector<IITDescriptor, 8> Table;
auto [TableRef, _, IsVarArg] = getIntrinsicInfoTableEntries(id, Table);
- Type *ResultTy = DecodeFixedType(TableRef, OverloadTys, Context);
+ Type *ResultTy = DecodeFixedType(TableRef, OverloadTys, M->getContext(),
+ M->getDataLayout());
SmallVector<Type *, 8> ArgTys;
while (!TableRef.empty())
- ArgTys.push_back(DecodeFixedType(TableRef, OverloadTys, Context));
+ ArgTys.push_back(DecodeFixedType(TableRef, OverloadTys, M->getContext(),
+ M->getDataLayout()));
return FunctionType::get(ResultTy, ArgTys, IsVarArg);
}
@@ -803,7 +810,7 @@ Function *Intrinsic::getOrInsertDeclaration(Module *M, ID id,
ArrayRef<Type *> OverloadTys) {
// There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type.
- FunctionType *FT = getType(M->getContext(), id, OverloadTys);
+ FunctionType *FT = getType(M, id, OverloadTys);
return getOrInsertIntrinsicDeclarationImpl(M, id, OverloadTys, FT);
}
@@ -820,8 +827,9 @@ Function *Intrinsic::getOrInsertDeclaration(Module *M, ID id, Type *RetTy,
// Automatically determine the overloaded types.
SmallVector<Type *, 4> OverloadTys;
- [[maybe_unused]] bool IsValid = ::isSignatureValid(
- FTy, TableRef, NumArgs, IsVarArg, OverloadTys, nulls());
+ [[maybe_unused]] bool IsValid =
+ ::isSignatureValid(M->getDataLayout(), FTy, TableRef, NumArgs, IsVarArg,
+ OverloadTys, nulls());
assert(IsValid && "intrinsic signature mismatch");
return getOrInsertIntrinsicDeclarationImpl(M, id, OverloadTys, FTy);
}
@@ -941,7 +949,8 @@ using DeferredIntrinsicMatchInfo =
std::tuple<Type *, ArrayRef<Intrinsic::IITDescriptor>, MatchPosition>;
static bool
-matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
+matchIntrinsicType(const DataLayout &DL, Type *Ty,
+ ArrayRef<Intrinsic::IITDescriptor> &Infos,
MatchPosition Position, SmallVectorImpl<Type *> &OverloadTys,
SmallVectorImpl<DeferredIntrinsicMatchInfo> &DeferredChecks,
bool IsDeferredCheck, raw_ostream &OS) {
@@ -1012,6 +1021,8 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
assert(Position.IsRet && Position.NumIndices == 0 &&
"void descriptor expected only for return type");
return PrintMsg(Ty->isVoidTy(), "void");
+ case IITDescriptor::Byte:
+ return PrintMsg(Ty->isIntegerTy(DL.getByteWidth()), "byte-sized integer");
case IITDescriptor::MMX: {
FixedVectorType *VT = dyn_cast<FixedVectorType>(Ty);
return PrintMsg(VT && VT->getNumElements() == 1 &&
@@ -1061,7 +1072,7 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
if (HasError)
return true;
Position.push_vector_element();
- return matchIntrinsicType(VT->getElementType(), Infos, Position,
+ return matchIntrinsicType(DL, VT->getElementType(), Infos, Position,
OverloadTys, DeferredChecks, IsDeferredCheck, OS);
}
case IITDescriptor::Pointer: {
@@ -1084,8 +1095,8 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
for (const auto &[Idx, ETy] : llvm::enumerate(ST->elements())) {
Position.push_struct_element(Idx);
- if (matchIntrinsicType(ETy, Infos, Position, OverloadTys, DeferredChecks,
- IsDeferredCheck, OS))
+ if (matchIntrinsicType(DL, ETy, Infos, Position, OverloadTys,
+ DeferredChecks, IsDeferredCheck, OS))
return true;
Position.pop_index();
}
@@ -1239,7 +1250,7 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
EltTy = ThisArgVecType->getElementType();
Position.push_vector_element();
}
- return matchIntrinsicType(EltTy, Infos, Position, OverloadTys,
+ return matchIntrinsicType(DL, EltTy, Infos, Position, OverloadTys,
DeferredChecks, IsDeferredCheck, OS);
}
case IITDescriptor::VecOfAnyPtrsToElt: {
@@ -1345,7 +1356,7 @@ matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
///
/// If the type is not valid, returns false and prints an error message to
/// \p OS.
-static bool isSignatureValid(FunctionType *FTy,
+static bool isSignatureValid(const DataLayout &DL, FunctionType *FTy,
ArrayRef<Intrinsic::IITDescriptor> &Infos,
unsigned NumArgs, bool IsVarArg,
SmallVectorImpl<Type *> &OverloadTys,
@@ -1359,7 +1370,7 @@ static bool isSignatureValid(FunctionType *FTy,
Pos.IsRet = true;
Pos.Num = 0;
- if (matchIntrinsicType(FTy->getReturnType(), Infos, Pos, OverloadTys,
+ if (matchIntrinsicType(DL, FTy->getReturnType(), Infos, Pos, OverloadTys,
DeferredChecks, false, OS))
return false;
@@ -1373,14 +1384,14 @@ static bool isSignatureValid(FunctionType *FTy,
Pos.IsRet = false;
for (const auto &[Idx, Ty] : llvm::enumerate(FTy->params())) {
Pos.Num = Idx;
- if (matchIntrinsicType(Ty, Infos, Pos, OverloadTys, DeferredChecks, false,
- OS))
+ if (matchIntrinsicType(DL, Ty, Infos, Pos, OverloadTys, DeferredChecks,
+ false, OS))
return false;
}
for (unsigned I = 0, E = DeferredChecks.size(); I != E; ++I) {
auto &[DefTy, DefInfos, DefPosition] = DeferredChecks[I];
- if (matchIntrinsicType(DefTy, DefInfos, DefPosition, OverloadTys,
+ if (matchIntrinsicType(DL, DefTy, DefInfos, DefPosition, OverloadTys,
DeferredChecks, true, OS))
return false;
}
@@ -1420,14 +1431,16 @@ bool Intrinsic::hasStructReturnType(ID id) {
return !Table.empty() && Table[0].Kind == IITDescriptor::Struct;
}
-bool Intrinsic::isSignatureValid(Intrinsic::ID ID, FunctionType *FT,
+bool Intrinsic::isSignatureValid(const DataLayout &DL, Intrinsic::ID ID,
+ FunctionType *FT,
SmallVectorImpl<Type *> &OverloadTys,
raw_ostream &OS) {
- return isSignatureValid(ID, FT, OverloadTys,
+ return isSignatureValid(DL, ID, FT, OverloadTys,
/*NumMissingTrailingParams=*/0, OS);
}
-bool Intrinsic::isSignatureValid(Intrinsic::ID ID, FunctionType *FT,
+bool Intrinsic::isSignatureValid(const DataLayout &DL, Intrinsic::ID ID,
+ FunctionType *FT,
SmallVectorImpl<Type *> &OverloadTys,
unsigned NumMissingTrailingParams,
raw_ostream &OS) {
@@ -1437,15 +1450,15 @@ bool Intrinsic::isSignatureValid(Intrinsic::ID ID, FunctionType *FT,
SmallVector<Intrinsic::IITDescriptor, 8> Table;
auto [TableRef, NumArgs, IsVarArg] = getIntrinsicInfoTableEntries(ID, Table);
- return ::isSignatureValid(FT, TableRef, NumArgs, IsVarArg, OverloadTys, OS,
- NumMissingTrailingParams);
+ return ::isSignatureValid(DL, FT, TableRef, NumArgs, IsVarArg, OverloadTys,
+ OS, NumMissingTrailingParams);
}
bool Intrinsic::isSignatureValid(Function *F,
SmallVectorImpl<Type *> &OverloadTys,
raw_ostream &OS) {
- return isSignatureValid(F->getIntrinsicID(), F->getFunctionType(),
- OverloadTys, OS);
+ return isSignatureValid(F->getDataLayout(), F->getIntrinsicID(),
+ F->getFunctionType(), OverloadTys, OS);
}
std::optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 27149e3ad1c4ff0..57aca85c870b891 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3496,7 +3496,7 @@ void Verifier::visitFunction(const Function &F) {
std::string ErrMsg;
raw_string_ostream ErrOS(ErrMsg);
SmallVector<Type *, 4> OverloadTys;
- bool IsValid = Intrinsic::isSignatureValid(IID, FT, OverloadTys, ErrOS);
+ bool IsValid = Intrinsic::isSignatureValid(DL, IID, FT, OverloadTys, ErrOS);
Printable PrintDecl([&F](raw_ostream &OS) { F.print(OS); });
Check(IsValid, ErrMsg, PrintDecl);
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 2915d7a50074cb8..d23d89ed91d91b5 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -20639,8 +20639,9 @@ Align SITargetLowering::computeKnownAlignForTargetInstr(
// site specifies a lower alignment?
Intrinsic::ID IID = GI->getIntrinsicID();
LLVMContext &Ctx = VT.getMachineFunction().getFunction().getContext();
+ const Module *M = VT.getMachineFunction().getFunction().getParent();
AttributeList Attrs =
- Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(Ctx, IID));
+ Intrinsic::getAttributes(Ctx, IID, Intrinsic::getType(M, IID));
if (MaybeAlign RetAlign = Attrs.getRetAlignment())
return *RetAlign;
}
diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
index cb41f1bb35c06a8..44a986ab6a9814c 100644
--- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp
@@ -1579,7 +1579,7 @@ Value *NumericalStabilitySanitizer::maybeHandleKnownCallBase(
// Check that the widened intrinsic is valid.
SmallVector<Type *, 4> OverloadTys;
[[maybe_unused]] bool IsValid =
- Intrinsic::isSignatureValid(WidenedId, WidenedFnTy, OverloadTys);
+ Intrinsic::isSignatureValid(DL, WidenedId, WidenedFnTy, OverloadTys);
assert(IsValid && "invalid widened intrinsic");
// For known intrinsic functions, we create a second call to the same
// intrinsic with a different type.
diff --git a/llvm/test/Bindings/OCaml/core.ml b/llvm/test/Bindings/OCaml/core.ml
index 31e5dd8ae87aedc..9c09320be91bc6f 100644
--- a/llvm/test/Bindings/OCaml/core.ml
+++ b/llvm/test/Bindings/OCaml/core.ml
@@ -700,7 +700,7 @@ let test_functions () =
let abs_decl = intrinsic_declaration m abs_id [|i32_type|] in
insist ("llvm.abs.i8" = intrinsic_overloaded_name m abs_id [|i8_type|]);
insist ("llvm.abs.i32" = intrinsic_overloaded_name m abs_id [|i32_type|]);
- let abs_i8_type = intrinsic_type context abs_id [|i8_type|] in
+ let abs_i8_type = intrinsic_type m abs_id [|i8_type|] in
insist (TypeKind.Function = classify_type abs_i8_type);
insist (is_intrinsic abs_decl);
insist (intrinsic_is_overloaded abs_id);
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index be36d08930eebb8..32fda06fb38942e 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -97,7 +97,8 @@ getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id,
std::string errorMsg;
llvm::raw_string_ostream errorOS(errorMsg);
SmallVector<llvm::Type *, 8> overloadedTys;
- if (!llvm::Intrinsic::isSignatureValid(id, ft, overloadedTys, errorOS)) {
+ if (!llvm::Intrinsic::isSignatureValid(module->getDataLayout(), id, ft,
+ overloadedTys, errorOS)) {
return mlir::emitError(op.getLoc(), "call intrinsic signature ")
<< diagStr(ft) << " to overloaded intrinsic " << op.getIntrinAttr()
<< " does not match any of the overloads: " << errorMsg;
More information about the llvm-branch-commits
mailing list