diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4485,7 +4485,7 @@ Assert(UseCall != nullptr, "Uses of llvm.call.preallocated.setup must be calls"); const Function *Fn = UseCall->getCalledFunction(); - if (Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { + if (Fn && Fn->getIntrinsicID() == Intrinsic::call_preallocated_arg) { auto *AllocArgIndex = dyn_cast(UseCall->getArgOperand(1)); Assert(AllocArgIndex != nullptr, "llvm.call.preallocated.alloc arg index must be a constant"); @@ -4500,8 +4500,8 @@ "llvm.call.preallocated.setup"); FoundCall = true; size_t NumPreallocatedArgs = 0; - for (auto &Arg : Fn->args()) { - if (Arg.hasAttribute(Attribute::Preallocated)) { + for (unsigned i = 0; i < UseCall->getNumArgOperands(); i++) { + if (UseCall->paramHasAttr(i, Attribute::Preallocated)) { ++NumPreallocatedArgs; } } diff --git a/llvm/test/Verifier/preallocated-valid.ll b/llvm/test/Verifier/preallocated-valid.ll --- a/llvm/test/Verifier/preallocated-valid.ll +++ b/llvm/test/Verifier/preallocated-valid.ll @@ -14,6 +14,14 @@ ret void } +define void @preallocated_indirect(void (i32*)* %f) { + %cs = call token @llvm.call.preallocated.setup(i32 1) + %x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32) + %y = bitcast i8* %x to i32* + call void %f(i32* preallocated(i32) %y) ["preallocated"(token %cs)] + ret void +} + define void @preallocated_setup_without_call() { %cs = call token @llvm.call.preallocated.setup(i32 1) %a0 = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32)