[llvm] Make `IntrinsicLowering` external function call lowering configurable (PR #102148)
Thomas Symalla via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 8 01:42:27 PDT 2024
https://github.com/tsymalla updated https://github.com/llvm/llvm-project/pull/102148
>From d9e5dc9f69bd52804ceedc98a942a3ff84cd4082 Mon Sep 17 00:00:00 2001
From: Thomas Symalla <tsymalla at amd.com>
Date: Tue, 6 Aug 2024 15:58:19 +0200
Subject: [PATCH 1/2] Make `IntrinsicLowering` external function call lowering
configurable
Sometimes a client might want to use `IntrinsicLowering` in its code to
get rid of some intrinsic calls, but does not want to introduce
additional calls to external functions. So, make this functionality
configurable and enable it by default so the behavior is not changed.
---
llvm/include/llvm/CodeGen/IntrinsicLowering.h | 16 +++++-
llvm/lib/CodeGen/IntrinsicLowering.cpp | 50 +++++++++++--------
2 files changed, 44 insertions(+), 22 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/IntrinsicLowering.h b/llvm/include/llvm/CodeGen/IntrinsicLowering.h
index 0b327a34ca098e..703b7b2d99568f 100644
--- a/llvm/include/llvm/CodeGen/IntrinsicLowering.h
+++ b/llvm/include/llvm/CodeGen/IntrinsicLowering.h
@@ -15,17 +15,29 @@
#ifndef LLVM_CODEGEN_INTRINSICLOWERING_H
#define LLVM_CODEGEN_INTRINSICLOWERING_H
+#include "llvm/ADT/ArrayRef.h"
+
namespace llvm {
class CallInst;
class DataLayout;
+class Type;
+class Value;
class IntrinsicLowering {
const DataLayout &DL;
+ bool LowerExternalFunctionCalls;
bool Warned = false;
+ CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
+ ArrayRef<Value *> Args, Type *RetTy);
+ void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname,
+ const char *Dname, const char *LDname);
+
public:
- explicit IntrinsicLowering(const DataLayout &DL) : DL(DL) {}
+ explicit IntrinsicLowering(const DataLayout &DL,
+ bool LowerExternalFunctionCalls = true)
+ : DL(DL), LowerExternalFunctionCalls(LowerExternalFunctionCalls) {}
/// Replace a call to the specified intrinsic function.
/// If an intrinsic function must be implemented by the code generator
@@ -41,6 +53,6 @@ class IntrinsicLowering {
/// false if the call is not a simple integer bswap.
static bool LowerToByteSwap(CallInst *CI);
};
-}
+} // namespace llvm
#endif
diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp
index 45fba4341ad007..89078179e686d8 100644
--- a/llvm/lib/CodeGen/IntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp
@@ -26,23 +26,25 @@ using namespace llvm;
/// an external function. This handles hard cases such as when there was already
/// a prototype for the external function, but that prototype doesn't match the
/// arguments we expect to pass in.
-template <class ArgIt>
-static CallInst *ReplaceCallWith(const char *NewFn, CallInst *CI,
- ArgIt ArgBegin, ArgIt ArgEnd,
- Type *RetTy) {
+CallInst *IntrinsicLowering::ReplaceCallWith(const char *NewFn, CallInst *CI,
+ ArrayRef<Value *> Args,
+ Type *RetTy) {
+ if (!LowerExternalFunctionCalls)
+ return nullptr;
+
// If we haven't already looked up this function, check to see if the
// program already contains a function with this name.
Module *M = CI->getModule();
// Get or insert the definition now.
std::vector<Type *> ParamTys;
- for (ArgIt I = ArgBegin; I != ArgEnd; ++I)
- ParamTys.push_back((*I)->getType());
+ for (auto *I : Args)
+ ParamTys.push_back(I->getType());
FunctionCallee FCache =
M->getOrInsertFunction(NewFn, FunctionType::get(RetTy, ParamTys, false));
IRBuilder<> Builder(CI->getParent(), CI->getIterator());
- SmallVector<Value *, 8> Args(ArgBegin, ArgEnd);
- CallInst *NewCI = Builder.CreateCall(FCache, Args);
+ SmallVector<Value *, 8> ArgVals(Args);
+ CallInst *NewCI = Builder.CreateCall(FCache, ArgVals);
NewCI->setName(CI->getName());
if (!CI->use_empty())
CI->replaceAllUsesWith(NewCI);
@@ -199,24 +201,26 @@ static Value *LowerCTLZ(LLVMContext &Context, Value *V, Instruction *IP) {
return LowerCTPOP(Context, V, IP);
}
-static void ReplaceFPIntrinsicWithCall(CallInst *CI, const char *Fname,
- const char *Dname,
- const char *LDname) {
+void IntrinsicLowering::ReplaceFPIntrinsicWithCall(CallInst *CI,
+ const char *Fname,
+ const char *Dname,
+ const char *LDname) {
+ if (!LowerExternalFunctionCalls)
+ return;
+
+ SmallVector<Value *> Args{CI->args()};
switch (CI->getArgOperand(0)->getType()->getTypeID()) {
default: llvm_unreachable("Invalid type in intrinsic");
case Type::FloatTyID:
- ReplaceCallWith(Fname, CI, CI->arg_begin(), CI->arg_end(),
- Type::getFloatTy(CI->getContext()));
+ ReplaceCallWith(Fname, CI, Args, Type::getFloatTy(CI->getContext()));
break;
case Type::DoubleTyID:
- ReplaceCallWith(Dname, CI, CI->arg_begin(), CI->arg_end(),
- Type::getDoubleTy(CI->getContext()));
+ ReplaceCallWith(Dname, CI, Args, Type::getDoubleTy(CI->getContext()));
break;
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
- ReplaceCallWith(LDname, CI, CI->arg_begin(), CI->arg_end(),
- CI->getArgOperand(0)->getType());
+ ReplaceCallWith(LDname, CI, Args, CI->getArgOperand(0)->getType());
break;
}
}
@@ -352,7 +356,9 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Ops[0] = CI->getArgOperand(0);
Ops[1] = CI->getArgOperand(1);
Ops[2] = Size;
- ReplaceCallWith("memcpy", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
+ SmallVector<Value *> Args;
+ Args.append(Ops, Ops + 3);
+ ReplaceCallWith("memcpy", CI, Args, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::memmove: {
@@ -363,7 +369,9 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Ops[0] = CI->getArgOperand(0);
Ops[1] = CI->getArgOperand(1);
Ops[2] = Size;
- ReplaceCallWith("memmove", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
+ SmallVector<Value *> Args;
+ Args.append(Ops, Ops + 3);
+ ReplaceCallWith("memmove", CI, Args, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::memset: {
@@ -378,7 +386,9 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Type::getInt32Ty(Context),
/* isSigned */ false);
Ops[2] = Size;
- ReplaceCallWith("memset", CI, Ops, Ops+3, CI->getArgOperand(0)->getType());
+ SmallVector<Value *> Args;
+ Args.append(Ops, Ops + 3);
+ ReplaceCallWith("memset", CI, Args, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::sqrt: {
>From c879f2e838fe225e74280f3906ddb5cc69f615d2 Mon Sep 17 00:00:00 2001
From: Thomas Symalla <tsymalla at amd.com>
Date: Thu, 8 Aug 2024 10:42:10 +0200
Subject: [PATCH 2/2] Review comments
---
llvm/include/llvm/CodeGen/IntrinsicLowering.h | 7 ++---
llvm/lib/CodeGen/IntrinsicLowering.cpp | 26 +++++++------------
2 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/IntrinsicLowering.h b/llvm/include/llvm/CodeGen/IntrinsicLowering.h
index 703b7b2d99568f..43f264eb488aba 100644
--- a/llvm/include/llvm/CodeGen/IntrinsicLowering.h
+++ b/llvm/include/llvm/CodeGen/IntrinsicLowering.h
@@ -25,7 +25,8 @@ class Value;
class IntrinsicLowering {
const DataLayout &DL;
- bool LowerExternalFunctionCalls;
+ /// This controls if some intrinsics are lowered to calls to external functions.
+ bool AllowLibraryFunctionCalls;
bool Warned = false;
@@ -36,8 +37,8 @@ class IntrinsicLowering {
public:
explicit IntrinsicLowering(const DataLayout &DL,
- bool LowerExternalFunctionCalls = true)
- : DL(DL), LowerExternalFunctionCalls(LowerExternalFunctionCalls) {}
+ bool AllowLibraryFunctionCalls = true)
+ : DL(DL), AllowLibraryFunctionCalls(AllowLibraryFunctionCalls) {}
/// Replace a call to the specified intrinsic function.
/// If an intrinsic function must be implemented by the code generator
diff --git a/llvm/lib/CodeGen/IntrinsicLowering.cpp b/llvm/lib/CodeGen/IntrinsicLowering.cpp
index 89078179e686d8..0defb731c7d875 100644
--- a/llvm/lib/CodeGen/IntrinsicLowering.cpp
+++ b/llvm/lib/CodeGen/IntrinsicLowering.cpp
@@ -29,8 +29,12 @@ using namespace llvm;
CallInst *IntrinsicLowering::ReplaceCallWith(const char *NewFn, CallInst *CI,
ArrayRef<Value *> Args,
Type *RetTy) {
- if (!LowerExternalFunctionCalls)
- return nullptr;
+ if (!AllowLibraryFunctionCalls) {
+ report_fatal_error(
+ "Trying to lower a call to '" + CI->getCalledFunction()->getName() +
+ "' to a call to an external function '" + NewFn +
+ "', but intrinsic lowering was configured to not allow such lowering.");
+ }
// If we haven't already looked up this function, check to see if the
// program already contains a function with this name.
@@ -43,8 +47,7 @@ CallInst *IntrinsicLowering::ReplaceCallWith(const char *NewFn, CallInst *CI,
M->getOrInsertFunction(NewFn, FunctionType::get(RetTy, ParamTys, false));
IRBuilder<> Builder(CI->getParent(), CI->getIterator());
- SmallVector<Value *, 8> ArgVals(Args);
- CallInst *NewCI = Builder.CreateCall(FCache, ArgVals);
+ CallInst *NewCI = Builder.CreateCall(FCache, Args);
NewCI->setName(CI->getName());
if (!CI->use_empty())
CI->replaceAllUsesWith(NewCI);
@@ -205,9 +208,6 @@ void IntrinsicLowering::ReplaceFPIntrinsicWithCall(CallInst *CI,
const char *Fname,
const char *Dname,
const char *LDname) {
- if (!LowerExternalFunctionCalls)
- return;
-
SmallVector<Value *> Args{CI->args()};
switch (CI->getArgOperand(0)->getType()->getTypeID()) {
default: llvm_unreachable("Invalid type in intrinsic");
@@ -356,9 +356,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Ops[0] = CI->getArgOperand(0);
Ops[1] = CI->getArgOperand(1);
Ops[2] = Size;
- SmallVector<Value *> Args;
- Args.append(Ops, Ops + 3);
- ReplaceCallWith("memcpy", CI, Args, CI->getArgOperand(0)->getType());
+ ReplaceCallWith("memcpy", CI, {Ops, Ops + 3}, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::memmove: {
@@ -369,9 +367,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Ops[0] = CI->getArgOperand(0);
Ops[1] = CI->getArgOperand(1);
Ops[2] = Size;
- SmallVector<Value *> Args;
- Args.append(Ops, Ops + 3);
- ReplaceCallWith("memmove", CI, Args, CI->getArgOperand(0)->getType());
+ ReplaceCallWith("memmove", CI, {Ops, Ops + 3}, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::memset: {
@@ -386,9 +382,7 @@ void IntrinsicLowering::LowerIntrinsicCall(CallInst *CI) {
Type::getInt32Ty(Context),
/* isSigned */ false);
Ops[2] = Size;
- SmallVector<Value *> Args;
- Args.append(Ops, Ops + 3);
- ReplaceCallWith("memset", CI, Args, CI->getArgOperand(0)->getType());
+ ReplaceCallWith("memset", CI, {Ops, Ops + 3}, CI->getArgOperand(0)->getType());
break;
}
case Intrinsic::sqrt: {
More information about the llvm-commits
mailing list