Skip to content

Commit cb238de

Browse files
committed
[PatternMatch] Implement matching code for LibFunc
Summary: Provides m_LibFunc pattern that can be used to match LibFuncs. Reviewers: spatel, hfinkel, efriedma, lebedev.ri Reviewed By: lebedev.ri Subscribers: lebedev.ri, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D42047 llvm-svn: 366069
1 parent 63d00b1 commit cb238de

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

llvm/include/llvm/IR/PatternMatch.h

+52
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
#include "llvm/ADT/APFloat.h"
3232
#include "llvm/ADT/APInt.h"
33+
#include "llvm/Analysis/TargetLibraryInfo.h"
3334
#include "llvm/IR/Constant.h"
3435
#include "llvm/IR/Constants.h"
3536
#include "llvm/IR/InstrTypes.h"
@@ -1812,6 +1813,57 @@ template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
18121813
return Signum_match<Val_t>(V);
18131814
}
18141815

1816+
/// \brief LibFunc matchers.
1817+
struct LibFunc_match {
1818+
LibFunc F;
1819+
TargetLibraryInfo TLI;
1820+
1821+
LibFunc_match(LibFunc Func, TargetLibraryInfo TargetLI)
1822+
: F(Func), TLI(TargetLI) {}
1823+
1824+
template <typename OpTy> bool match(OpTy *V) {
1825+
LibFunc LF;
1826+
if (const auto *CI = dyn_cast<CallInst>(V))
1827+
if (!CI->isNoBuiltin() && CI->getCalledFunction() &&
1828+
TLI.getLibFunc(*CI->getCalledFunction(), LF) &&
1829+
LF == F && TLI.has(LF))
1830+
return true;
1831+
return false;
1832+
}
1833+
};
1834+
1835+
/// LibFunc matches are combinations of Name matchers, and argument
1836+
/// matchers.
1837+
template <typename T0 = void, typename T1 = void, typename T2 = void>
1838+
struct m_LibFunc_Ty;
1839+
template <typename T0> struct m_LibFunc_Ty<T0> {
1840+
using Ty = match_combine_and<LibFunc_match, Argument_match<T0>>;
1841+
};
1842+
template <typename T0, typename T1> struct m_LibFunc_Ty<T0, T1> {
1843+
using Ty =
1844+
match_combine_and<typename m_LibFunc_Ty<T0>::Ty,
1845+
Argument_match<T1>>;
1846+
};
1847+
1848+
/// \brief Match LibFunc calls like this:
1849+
/// m_LibFunc<LibFunc_tan>(m_Value(X))
1850+
template <LibFunc F>
1851+
inline LibFunc_match m_LibFunc(TargetLibraryInfo TLI) {
1852+
return LibFunc_match(F, TLI);
1853+
}
1854+
1855+
template <LibFunc F, typename T0>
1856+
inline typename m_LibFunc_Ty<T0>::Ty
1857+
m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0) {
1858+
return m_CombineAnd(m_LibFunc<F>(TLI), m_Argument<0>(Op0));
1859+
}
1860+
1861+
template <LibFunc F, typename T0, typename T1>
1862+
inline typename m_LibFunc_Ty<T0, T1>::Ty
1863+
m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0, const T1 &Op1) {
1864+
return m_CombineAnd(m_LibFunc<F>(TLI, Op0), m_Argument<1>(Op1));
1865+
}
1866+
18151867
} // end namespace PatternMatch
18161868
} // end namespace llvm
18171869

llvm/unittests/IR/PatternMatch.cpp

+37-1
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ struct PatternMatchTest : ::testing::Test {
3535
Function *F;
3636
BasicBlock *BB;
3737
IRBuilder<NoFolder> IRB;
38+
TargetLibraryInfoImpl TLII;
39+
TargetLibraryInfo TLI;
3840

3941
PatternMatchTest()
4042
: M(new Module("PatternMatchTestModule", Ctx)),
4143
F(Function::Create(
4244
FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
4345
Function::ExternalLinkage, "f", M.get())),
44-
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
46+
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB), TLI(TLII) {}
4547
};
4648

4749
TEST_F(PatternMatchTest, OneUse) {
@@ -1008,6 +1010,40 @@ TEST_F(PatternMatchTest, FloatingPointFNeg) {
10081010
EXPECT_FALSE(match(V3, m_FNeg(m_Value(Match))));
10091011
}
10101012

1013+
TEST_F(PatternMatchTest, LibFunc) {
1014+
Type *FltTy = IRB.getFloatTy();
1015+
Value *One = ConstantFP::get(FltTy, 1.0);
1016+
Value *Two = ConstantFP::get(FltTy, 2.0);
1017+
Value *MatchOne, *MatchTwo;
1018+
1019+
StringRef TanName = TLI.getName(LibFunc_tan);
1020+
FunctionCallee TanCallee = M->getOrInsertFunction(TanName, FltTy, FltTy);
1021+
CallInst *Tan = IRB.CreateCall(TanCallee, One, TanName);
1022+
1023+
StringRef PowName = TLI.getName(LibFunc_pow);
1024+
FunctionCallee PowCallee = M->getOrInsertFunction(PowName, FltTy, FltTy, FltTy);
1025+
CallInst *Pow = IRB.CreateCall(PowCallee, {One, Two}, PowName);
1026+
1027+
EXPECT_TRUE(match(Tan, m_LibFunc<LibFunc_tan>(TLI)));
1028+
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_pow>(TLI)));
1029+
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_tan>(TLI)));
1030+
1031+
EXPECT_TRUE(match(Tan, m_LibFunc<LibFunc_tan>(TLI, m_Value(MatchOne))));
1032+
EXPECT_EQ(One, MatchOne);
1033+
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_sin>(TLI, m_Value())));
1034+
1035+
EXPECT_TRUE(match(Pow, m_LibFunc<LibFunc_pow>(TLI, m_Value(MatchOne),
1036+
m_Value(MatchTwo))));
1037+
EXPECT_EQ(One, MatchOne);
1038+
EXPECT_EQ(Two, MatchTwo);
1039+
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_fminf>(TLI, m_Value(), m_Value())));
1040+
1041+
TLII.disableAllFunctions();
1042+
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_tan>(TLI)));
1043+
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_tan>(TLI, m_Value())));
1044+
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_pow>(TLI, m_Value(), m_Value())));
1045+
}
1046+
10111047
template <typename T> struct MutableConstTest : PatternMatchTest { };
10121048

10131049
typedef ::testing::Types<std::tuple<Value*, Instruction*>,

0 commit comments

Comments
 (0)