diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -886,7 +886,7 @@ Instruction *FMFSource = nullptr, const Twine &Name = ""); - /// Create a call to intrinsic \p ID with \p args, mangled using \p Types. If + /// Create a call to intrinsic \p ID with \p Args, mangled using \p Types. If /// \p FMFSource is provided, copy fast-math-flags from that instruction to /// the intrinsic. CallInst *CreateIntrinsic(Intrinsic::ID ID, ArrayRef Types, @@ -894,6 +894,14 @@ Instruction *FMFSource = nullptr, const Twine &Name = ""); + /// Create a call to intrinsic \p ID with \p RetTy and \p Args. If + /// \p FMFSource is provided, copy fast-math-flags from that instruction to + /// the intrinsic. + CallInst *CreateIntrinsic(Type *RetTy, Intrinsic::ID ID, + ArrayRef Args, + Instruction *FMFSource = nullptr, + const Twine &Name = ""); + /// Create call to the minnum intrinsic. CallInst *CreateMinNum(Value *LHS, Value *RHS, const Twine &Name = "") { return CreateBinaryIntrinsic(Intrinsic::minnum, LHS, RHS, nullptr, Name); diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -898,6 +898,33 @@ return createCallHelper(Fn, Args, Name, FMFSource); } +CallInst *IRBuilderBase::CreateIntrinsic(Type *RetTy, Intrinsic::ID ID, + ArrayRef Args, + Instruction *FMFSource, + const Twine &Name) { + Module *M = BB->getModule(); + + SmallVector Table; + Intrinsic::getIntrinsicInfoTableEntries(ID, Table); + ArrayRef TableRef(Table); + + SmallVector ArgTys; + ArgTys.reserve(Args.size()); + for (auto &I : Args) + ArgTys.push_back(I->getType()); + FunctionType *FTy = FunctionType::get(RetTy, ArgTys, false); + SmallVector OverloadTys; + Intrinsic::MatchIntrinsicTypesResult Res = + matchIntrinsicSignature(FTy, TableRef, OverloadTys); + (void)Res; + assert(Res == Intrinsic::MatchIntrinsicTypes_Match && TableRef.empty() && + "Wrong types for intrinsic!"); + // TODO: Handle varargs intrinsics. + + Function *Fn = Intrinsic::getDeclaration(M, ID, OverloadTys); + return createCallHelper(Fn, Args, Name, FMFSource); +} + CallInst *IRBuilderBase::CreateConstrainedFPBinOp( Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource, const Twine &Name, MDNode *FPMathTag, diff --git a/llvm/unittests/IR/IRBuilderTest.cpp b/llvm/unittests/IR/IRBuilderTest.cpp --- a/llvm/unittests/IR/IRBuilderTest.cpp +++ b/llvm/unittests/IR/IRBuilderTest.cpp @@ -137,6 +137,29 @@ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::set_rounding); } +TEST_F(IRBuilderTest, IntrinsicMangling) { + IRBuilder<> Builder(BB); + Type *VoidTy = Builder.getVoidTy(); + Type *Int64Ty = Builder.getInt64Ty(); + Value *Int64Val = Builder.getInt64(0); + Value *DoubleVal = PoisonValue::get(Builder.getDoubleTy()); + CallInst *Call; + + // Mangled return type, no arguments. + Call = Builder.CreateIntrinsic(Int64Ty, Intrinsic::coro_size, {}); + EXPECT_EQ(Call->getCalledFunction()->getName(), "llvm.coro.size.i64"); + + // Void return type, mangled argument type. + Call = + Builder.CreateIntrinsic(VoidTy, Intrinsic::set_loop_iterations, Int64Val); + EXPECT_EQ(Call->getCalledFunction()->getName(), + "llvm.set.loop.iterations.i64"); + + // Mangled return type and argument type. + Call = Builder.CreateIntrinsic(Int64Ty, Intrinsic::lround, DoubleVal); + EXPECT_EQ(Call->getCalledFunction()->getName(), "llvm.lround.i64.f64"); +} + TEST_F(IRBuilderTest, IntrinsicsWithScalableVectors) { IRBuilder<> Builder(BB); CallInst *Call;