-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[TLI] Add getLibFunc that accepts an Opcode and scalar Type. #75919
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TLI] Add getLibFunc that accepts an Opcode and scalar Type. #75919
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Paschalis Mpeis (paschalis-mpeis) ChangesIt sets a LibFunc similarly with the other two getLibFunc methods. Currently, it supports only the FRem Instruction. Add tests for FRem. Full diff: https://github.com/llvm/llvm-project/pull/75919.diff 3 Files Affected:
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
|
What's the motivation for this? |
@nikic, almost all libm functions are represented in LLVM as intrinsics with the exception of fmod that is transformed into the FREM instruction. This difference means existing code to map scalar calls to vector functions (as used by LoopVectorize and ReplaceWithVecLib) does not work and so first we want to map the instruction back to it’s representative scalar function. Given variants of getLibFunc exist to map an intrinsic to such functions it seems reasonable to have a variant for instructions as well. |
It sets a LibFunc similarly with the other two getLibFunc methods. Currently, it supports only the FRem Instruction. Add tests for FRem.
Test class: - no longer using IRBuilder to create FRem instructions - no need to use ArmPL vector library
b371854
to
24617b5
Compare
Addressed review with 24617b5 and rebased to main. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of minor things but otherwise looks good to me.
In test no longer creating an FRem instruction.
It sets a LibFunc similarly with the other two getLibFunc methods. Currently, it supports only the FRem Instruction.
Add tests for FRem.
Motivation:
Almost all libm functions are represented in LLVM as intrinsics with the exception of
fmod
that is transformed into theFREM
Instruction. This difference means existing code to map scalar calls to vector functions (as used byLoopVectorize
andReplaceWithVecLib
) does not work and so first we want to map the instruction back to it’s representative scalar function.Given variants of getLibFunc exist to map an intrinsic to such functions it seems reasonable to have a variant for instructions as well.