[llvm] Make `IntrinsicLowering` external function call lowering configurable (PR #102148)

Thomas Symalla via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 6 07:03:02 PDT 2024


https://github.com/tsymalla created https://github.com/llvm/llvm-project/pull/102148

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.

>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] 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 0b327a34ca098..703b7b2d99568 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 45fba4341ad00..89078179e686d 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: {



More information about the llvm-commits mailing list