[llvm] [TLI] Add getLibFunc in TLI API that accepts an Instruction. (PR #75919)

Paschalis Mpeis via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 19 10:03:06 PST 2023


https://github.com/paschalis-mpeis updated https://github.com/llvm/llvm-project/pull/75919

>From f00bc4e59dd4ec90b9eff78b9e4eecdc30b3dd92 Mon Sep 17 00:00:00 2001
From: Paschalis Mpeis <Paschalis.Mpeis at arm.com>
Date: Tue, 19 Dec 2023 09:58:57 +0000
Subject: [PATCH 1/3] [TLI] Add getLibFunc in API that accepts an Instruction.

It sets a LibFunc similarly with the other two getLibFunc methods.
Currently, it supports only the FRem Instruction.

Add tests for FRem.
---
 .../include/llvm/Analysis/TargetLibraryInfo.h | 10 +++
 llvm/lib/Analysis/TargetLibraryInfo.cpp       | 16 +++++
 .../Analysis/TargetLibraryInfoTest.cpp        | 61 +++++++++++++++++++
 3 files changed, 87 insertions(+)

diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.h b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
index 2ffd4d4b714394..bd77d1e8285626 100644
--- a/llvm/include/llvm/Analysis/TargetLibraryInfo.h
+++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.h
@@ -156,6 +156,10 @@ class TargetLibraryInfoImpl {
   /// FDecl is assumed to have a parent Module when using this function.
   bool getLibFunc(const Function &FDecl, LibFunc &F) const;
 
+  /// Searches for a function name using the opcode of \p I. Currently, only the
+  /// frem instruction is supported.
+  bool getLibFunc(const Instruction &I, LibFunc &F) const;
+
   /// Forces a function to be marked as unavailable.
   void setUnavailable(LibFunc F) {
     setState(F, Unavailable);
@@ -360,6 +364,12 @@ class TargetLibraryInfo {
            getLibFunc(*(CB.getCalledFunction()), F);
   }
 
+  /// Searches for a function name using the opcode of \p I. Currently, only the
+  /// frem instruction is supported.
+  bool getLibFunc(const Instruction &I, LibFunc &F) const {
+    return Impl->getLibFunc(I, F);
+  }
+
   /// Disables all builtins.
   ///
   /// This can be used for options like -fno-builtin.
diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 20959cf6948f65..4bc9db2db54258 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -1149,6 +1149,22 @@ bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl,
   return isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M);
 }
 
+bool TargetLibraryInfoImpl::getLibFunc(const Instruction &I, LibFunc &F) const {
+  if (I.getOpcode() != Instruction::FRem)
+    return false;
+
+  Type *ScalarTy = I.getType()->getScalarType();
+  if (ScalarTy->isDoubleTy())
+    F = LibFunc_fmod;
+  else if (ScalarTy->isFloatTy())
+    F = LibFunc_fmodf;
+  else if (ScalarTy->isFP128Ty())
+    F = LibFunc_fmodl;
+  else
+    return false;
+  return true;
+}
+
 void TargetLibraryInfoImpl::disableAllFunctions() {
   memset(AvailableArray, 0, sizeof(AvailableArray));
 }
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index 292b5cade9509b..d4285092a58d3c 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
@@ -621,3 +622,63 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
     EXPECT_TRUE(isLibFunc(F, LF));
   }
 }
+
+namespace {
+
+// Creates TLI for AArch64 and VecLibrary ARmPL, and uses it to get the TLI
+// names for different FRem Instructions.
+class TLITestAarch64ArmPl : public ::testing::Test {
+private:
+  SMDiagnostic Err;
+  const Triple TargetTriple;
+  const TargetLibraryInfoImpl::VectorLibrary VecLib;
+
+protected:
+  LLVMContext Ctx;
+  std::unique_ptr<Module> M;
+  std::unique_ptr<TargetLibraryInfoImpl> TLII;
+  std::unique_ptr<TargetLibraryInfo> TLI;
+
+  /// Create TLI for AArch64 with VecLib ArmPL.
+  TLITestAarch64ArmPl()
+      : TargetTriple(Triple("aarch64-unknown-linux-gnu")),
+        VecLib(TargetLibraryInfoImpl::ArmPL) {
+    TLII = std::make_unique<TargetLibraryInfoImpl>(
+        TargetLibraryInfoImpl(TargetTriple));
+    TLII->addVectorizableFunctionsFromVecLib(VecLib, TargetTriple);
+    TLI = std::make_unique<TargetLibraryInfo>(TargetLibraryInfo(*TLII));
+    // Create a dummy module needed for tests.
+    M = parseAssemblyString("declare void @dummy()", Err, Ctx);
+    EXPECT_NE(M.get(), nullptr)
+        << "Loading an invalid module.\n " << Err.getMessage() << "\n";
+  }
+
+  /// Creates an FRem Instruction of Type \p Ty, and uses it to get the TLI
+  /// function name.
+  StringRef getFremScalarName(Type *Ty) {
+    // Use a dummy function and a BB to create an FRem Instruction.
+    FunctionType *FTy = FunctionType::get(Ty, {Ty, Ty}, false);
+    Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", *M);
+    BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
+    IRBuilder<> Builder(BB);
+    Builder.SetInsertPoint(BB);
+    auto *FRem =
+        dyn_cast<Instruction>(Builder.CreateFRem(F->getArg(0), F->getArg(1)));
+
+    // Use TLI to get LibFunc and then the TLI name.
+    LibFunc Func;
+    if (!TLI->getLibFunc(*FRem, Func))
+      return "";
+    auto FuncName = TLI->getName(Func);
+    // Erase tmp function to prepare for the next test.
+    F->eraseFromParent();
+    return FuncName;
+  }
+};
+} // end anonymous namespace
+
+TEST_F(TLITestAarch64ArmPl, TestFrem) {
+  EXPECT_EQ(getFremScalarName(Type::getDoubleTy(Ctx)), "fmod");
+  EXPECT_EQ(getFremScalarName(Type::getFloatTy(Ctx)), "fmodf");
+  EXPECT_EQ(getFremScalarName(Type::getFP128Ty(Ctx)), "fmodl");
+}
\ No newline at end of file

>From 89aa0341ac27250b043fe6972e08b02e36ecff64 Mon Sep 17 00:00:00 2001
From: Paschalis Mpeis <Paschalis.Mpeis at arm.com>
Date: Tue, 19 Dec 2023 11:51:13 +0000
Subject: [PATCH 2/3] Dropping FP128 as they are target specific.

---
 llvm/lib/Analysis/TargetLibraryInfo.cpp           | 2 --
 llvm/unittests/Analysis/TargetLibraryInfoTest.cpp | 1 -
 2 files changed, 3 deletions(-)

diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index 4bc9db2db54258..bd238d29b689c4 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -1158,8 +1158,6 @@ bool TargetLibraryInfoImpl::getLibFunc(const Instruction &I, LibFunc &F) const {
     F = LibFunc_fmod;
   else if (ScalarTy->isFloatTy())
     F = LibFunc_fmodf;
-  else if (ScalarTy->isFP128Ty())
-    F = LibFunc_fmodl;
   else
     return false;
   return true;
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index d4285092a58d3c..993556420e41ff 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -680,5 +680,4 @@ class TLITestAarch64ArmPl : public ::testing::Test {
 TEST_F(TLITestAarch64ArmPl, TestFrem) {
   EXPECT_EQ(getFremScalarName(Type::getDoubleTy(Ctx)), "fmod");
   EXPECT_EQ(getFremScalarName(Type::getFloatTy(Ctx)), "fmodf");
-  EXPECT_EQ(getFremScalarName(Type::getFP128Ty(Ctx)), "fmodl");
 }
\ No newline at end of file

>From b3718544febbf7d854353f124358946bb828cafb Mon Sep 17 00:00:00 2001
From: Paschalis Mpeis <Paschalis.Mpeis at arm.com>
Date: Tue, 19 Dec 2023 17:52:22 +0000
Subject: [PATCH 3/3] Simplified code.

Test class:
- no longer using IRBuilder to create FRem instructions
- no need to use ArmPL vector library
---
 llvm/lib/Analysis/TargetLibraryInfo.cpp       |  8 ++--
 .../Analysis/TargetLibraryInfoTest.cpp        | 43 ++++++-------------
 2 files changed, 15 insertions(+), 36 deletions(-)

diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp
index bd238d29b689c4..b4e7a7e00be80c 100644
--- a/llvm/lib/Analysis/TargetLibraryInfo.cpp
+++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp
@@ -1154,12 +1154,10 @@ bool TargetLibraryInfoImpl::getLibFunc(const Instruction &I, LibFunc &F) const {
     return false;
 
   Type *ScalarTy = I.getType()->getScalarType();
-  if (ScalarTy->isDoubleTy())
-    F = LibFunc_fmod;
-  else if (ScalarTy->isFloatTy())
-    F = LibFunc_fmodf;
-  else
+  if (!ScalarTy->isDoubleTy() && !ScalarTy->isFloatTy())
     return false;
+
+  F = ScalarTy->isDoubleTy() ? LibFunc_fmod : LibFunc_fmodf;
   return true;
 }
 
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index 993556420e41ff..2e33ce0c1123c8 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -8,7 +8,6 @@
 
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/AsmParser/Parser.h"
-#include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/SourceMgr.h"
@@ -625,59 +624,41 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
 
 namespace {
 
-// Creates TLI for AArch64 and VecLibrary ARmPL, and uses it to get the TLI
-// names for different FRem Instructions.
-class TLITestAarch64ArmPl : public ::testing::Test {
+/// Creates TLI for AArch64 and uses it to get the LibFunc names for the FRem
+/// Instruction.
+class TLITestAarch64 : public ::testing::Test {
 private:
-  SMDiagnostic Err;
   const Triple TargetTriple;
-  const TargetLibraryInfoImpl::VectorLibrary VecLib;
 
 protected:
   LLVMContext Ctx;
-  std::unique_ptr<Module> M;
   std::unique_ptr<TargetLibraryInfoImpl> TLII;
   std::unique_ptr<TargetLibraryInfo> TLI;
 
-  /// Create TLI for AArch64 with VecLib ArmPL.
-  TLITestAarch64ArmPl()
-      : TargetTriple(Triple("aarch64-unknown-linux-gnu")),
-        VecLib(TargetLibraryInfoImpl::ArmPL) {
+  /// Create TLI for AArch64
+  TLITestAarch64() : TargetTriple(Triple("aarch64-unknown-linux-gnu")) {
     TLII = std::make_unique<TargetLibraryInfoImpl>(
         TargetLibraryInfoImpl(TargetTriple));
-    TLII->addVectorizableFunctionsFromVecLib(VecLib, TargetTriple);
+    TLII->addVectorizableFunctionsFromVecLib(TargetLibraryInfoImpl::NoLibrary,
+                                             TargetTriple);
     TLI = std::make_unique<TargetLibraryInfo>(TargetLibraryInfo(*TLII));
-    // Create a dummy module needed for tests.
-    M = parseAssemblyString("declare void @dummy()", Err, Ctx);
-    EXPECT_NE(M.get(), nullptr)
-        << "Loading an invalid module.\n " << Err.getMessage() << "\n";
   }
 
   /// Creates an FRem Instruction of Type \p Ty, and uses it to get the TLI
   /// function name.
   StringRef getFremScalarName(Type *Ty) {
-    // Use a dummy function and a BB to create an FRem Instruction.
-    FunctionType *FTy = FunctionType::get(Ty, {Ty, Ty}, false);
-    Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", *M);
-    BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
-    IRBuilder<> Builder(BB);
-    Builder.SetInsertPoint(BB);
-    auto *FRem =
-        dyn_cast<Instruction>(Builder.CreateFRem(F->getArg(0), F->getArg(1)));
-
-    // Use TLI to get LibFunc and then the TLI name.
+    Value *V = Constant::getNullValue(Ty);
+    Instruction *FRem = BinaryOperator::Create(Instruction::FRem, V, V);
     LibFunc Func;
     if (!TLI->getLibFunc(*FRem, Func))
       return "";
-    auto FuncName = TLI->getName(Func);
-    // Erase tmp function to prepare for the next test.
-    F->eraseFromParent();
-    return FuncName;
+    FRem->deleteValue();
+    return TLI->getName(Func);
   }
 };
 } // end anonymous namespace
 
-TEST_F(TLITestAarch64ArmPl, TestFrem) {
+TEST_F(TLITestAarch64, TestFrem) {
   EXPECT_EQ(getFremScalarName(Type::getDoubleTy(Ctx)), "fmod");
   EXPECT_EQ(getFremScalarName(Type::getFloatTy(Ctx)), "fmodf");
 }
\ No newline at end of file



More information about the llvm-commits mailing list