Skip to content

Commit f00bc4e

Browse files
[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.
1 parent 6294129 commit f00bc4e

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

llvm/include/llvm/Analysis/TargetLibraryInfo.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ class TargetLibraryInfoImpl {
156156
/// FDecl is assumed to have a parent Module when using this function.
157157
bool getLibFunc(const Function &FDecl, LibFunc &F) const;
158158

159+
/// Searches for a function name using the opcode of \p I. Currently, only the
160+
/// frem instruction is supported.
161+
bool getLibFunc(const Instruction &I, LibFunc &F) const;
162+
159163
/// Forces a function to be marked as unavailable.
160164
void setUnavailable(LibFunc F) {
161165
setState(F, Unavailable);
@@ -360,6 +364,12 @@ class TargetLibraryInfo {
360364
getLibFunc(*(CB.getCalledFunction()), F);
361365
}
362366

367+
/// Searches for a function name using the opcode of \p I. Currently, only the
368+
/// frem instruction is supported.
369+
bool getLibFunc(const Instruction &I, LibFunc &F) const {
370+
return Impl->getLibFunc(I, F);
371+
}
372+
363373
/// Disables all builtins.
364374
///
365375
/// This can be used for options like -fno-builtin.

llvm/lib/Analysis/TargetLibraryInfo.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,22 @@ bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl,
11491149
return isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M);
11501150
}
11511151

1152+
bool TargetLibraryInfoImpl::getLibFunc(const Instruction &I, LibFunc &F) const {
1153+
if (I.getOpcode() != Instruction::FRem)
1154+
return false;
1155+
1156+
Type *ScalarTy = I.getType()->getScalarType();
1157+
if (ScalarTy->isDoubleTy())
1158+
F = LibFunc_fmod;
1159+
else if (ScalarTy->isFloatTy())
1160+
F = LibFunc_fmodf;
1161+
else if (ScalarTy->isFP128Ty())
1162+
F = LibFunc_fmodl;
1163+
else
1164+
return false;
1165+
return true;
1166+
}
1167+
11521168
void TargetLibraryInfoImpl::disableAllFunctions() {
11531169
memset(AvailableArray, 0, sizeof(AvailableArray));
11541170
}

llvm/unittests/Analysis/TargetLibraryInfoTest.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "llvm/Analysis/TargetLibraryInfo.h"
1010
#include "llvm/AsmParser/Parser.h"
11+
#include "llvm/IR/IRBuilder.h"
1112
#include "llvm/IR/LLVMContext.h"
1213
#include "llvm/IR/Module.h"
1314
#include "llvm/Support/SourceMgr.h"
@@ -621,3 +622,63 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
621622
EXPECT_TRUE(isLibFunc(F, LF));
622623
}
623624
}
625+
626+
namespace {
627+
628+
// Creates TLI for AArch64 and VecLibrary ARmPL, and uses it to get the TLI
629+
// names for different FRem Instructions.
630+
class TLITestAarch64ArmPl : public ::testing::Test {
631+
private:
632+
SMDiagnostic Err;
633+
const Triple TargetTriple;
634+
const TargetLibraryInfoImpl::VectorLibrary VecLib;
635+
636+
protected:
637+
LLVMContext Ctx;
638+
std::unique_ptr<Module> M;
639+
std::unique_ptr<TargetLibraryInfoImpl> TLII;
640+
std::unique_ptr<TargetLibraryInfo> TLI;
641+
642+
/// Create TLI for AArch64 with VecLib ArmPL.
643+
TLITestAarch64ArmPl()
644+
: TargetTriple(Triple("aarch64-unknown-linux-gnu")),
645+
VecLib(TargetLibraryInfoImpl::ArmPL) {
646+
TLII = std::make_unique<TargetLibraryInfoImpl>(
647+
TargetLibraryInfoImpl(TargetTriple));
648+
TLII->addVectorizableFunctionsFromVecLib(VecLib, TargetTriple);
649+
TLI = std::make_unique<TargetLibraryInfo>(TargetLibraryInfo(*TLII));
650+
// Create a dummy module needed for tests.
651+
M = parseAssemblyString("declare void @dummy()", Err, Ctx);
652+
EXPECT_NE(M.get(), nullptr)
653+
<< "Loading an invalid module.\n " << Err.getMessage() << "\n";
654+
}
655+
656+
/// Creates an FRem Instruction of Type \p Ty, and uses it to get the TLI
657+
/// function name.
658+
StringRef getFremScalarName(Type *Ty) {
659+
// Use a dummy function and a BB to create an FRem Instruction.
660+
FunctionType *FTy = FunctionType::get(Ty, {Ty, Ty}, false);
661+
Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", *M);
662+
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
663+
IRBuilder<> Builder(BB);
664+
Builder.SetInsertPoint(BB);
665+
auto *FRem =
666+
dyn_cast<Instruction>(Builder.CreateFRem(F->getArg(0), F->getArg(1)));
667+
668+
// Use TLI to get LibFunc and then the TLI name.
669+
LibFunc Func;
670+
if (!TLI->getLibFunc(*FRem, Func))
671+
return "";
672+
auto FuncName = TLI->getName(Func);
673+
// Erase tmp function to prepare for the next test.
674+
F->eraseFromParent();
675+
return FuncName;
676+
}
677+
};
678+
} // end anonymous namespace
679+
680+
TEST_F(TLITestAarch64ArmPl, TestFrem) {
681+
EXPECT_EQ(getFremScalarName(Type::getDoubleTy(Ctx)), "fmod");
682+
EXPECT_EQ(getFremScalarName(Type::getFloatTy(Ctx)), "fmodf");
683+
EXPECT_EQ(getFremScalarName(Type::getFP128Ty(Ctx)), "fmodl");
684+
}

0 commit comments

Comments
 (0)