forked from OSchip/llvm-project
[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
This commit is contained in:
parent
63d00b19e5
commit
cb238de456
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/InstrTypes.h"
|
||||
|
@ -1812,6 +1813,57 @@ template <typename Val_t> inline Signum_match<Val_t> m_Signum(const Val_t &V) {
|
|||
return Signum_match<Val_t>(V);
|
||||
}
|
||||
|
||||
/// \brief LibFunc matchers.
|
||||
struct LibFunc_match {
|
||||
LibFunc F;
|
||||
TargetLibraryInfo TLI;
|
||||
|
||||
LibFunc_match(LibFunc Func, TargetLibraryInfo TargetLI)
|
||||
: F(Func), TLI(TargetLI) {}
|
||||
|
||||
template <typename OpTy> bool match(OpTy *V) {
|
||||
LibFunc LF;
|
||||
if (const auto *CI = dyn_cast<CallInst>(V))
|
||||
if (!CI->isNoBuiltin() && CI->getCalledFunction() &&
|
||||
TLI.getLibFunc(*CI->getCalledFunction(), LF) &&
|
||||
LF == F && TLI.has(LF))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/// LibFunc matches are combinations of Name matchers, and argument
|
||||
/// matchers.
|
||||
template <typename T0 = void, typename T1 = void, typename T2 = void>
|
||||
struct m_LibFunc_Ty;
|
||||
template <typename T0> struct m_LibFunc_Ty<T0> {
|
||||
using Ty = match_combine_and<LibFunc_match, Argument_match<T0>>;
|
||||
};
|
||||
template <typename T0, typename T1> struct m_LibFunc_Ty<T0, T1> {
|
||||
using Ty =
|
||||
match_combine_and<typename m_LibFunc_Ty<T0>::Ty,
|
||||
Argument_match<T1>>;
|
||||
};
|
||||
|
||||
/// \brief Match LibFunc calls like this:
|
||||
/// m_LibFunc<LibFunc_tan>(m_Value(X))
|
||||
template <LibFunc F>
|
||||
inline LibFunc_match m_LibFunc(TargetLibraryInfo TLI) {
|
||||
return LibFunc_match(F, TLI);
|
||||
}
|
||||
|
||||
template <LibFunc F, typename T0>
|
||||
inline typename m_LibFunc_Ty<T0>::Ty
|
||||
m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0) {
|
||||
return m_CombineAnd(m_LibFunc<F>(TLI), m_Argument<0>(Op0));
|
||||
}
|
||||
|
||||
template <LibFunc F, typename T0, typename T1>
|
||||
inline typename m_LibFunc_Ty<T0, T1>::Ty
|
||||
m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0, const T1 &Op1) {
|
||||
return m_CombineAnd(m_LibFunc<F>(TLI, Op0), m_Argument<1>(Op1));
|
||||
}
|
||||
|
||||
} // end namespace PatternMatch
|
||||
} // end namespace llvm
|
||||
|
||||
|
|
|
@ -35,13 +35,15 @@ struct PatternMatchTest : ::testing::Test {
|
|||
Function *F;
|
||||
BasicBlock *BB;
|
||||
IRBuilder<NoFolder> IRB;
|
||||
TargetLibraryInfoImpl TLII;
|
||||
TargetLibraryInfo TLI;
|
||||
|
||||
PatternMatchTest()
|
||||
: M(new Module("PatternMatchTestModule", Ctx)),
|
||||
F(Function::Create(
|
||||
FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
|
||||
Function::ExternalLinkage, "f", M.get())),
|
||||
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
|
||||
BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB), TLI(TLII) {}
|
||||
};
|
||||
|
||||
TEST_F(PatternMatchTest, OneUse) {
|
||||
|
@ -1008,6 +1010,40 @@ TEST_F(PatternMatchTest, FloatingPointFNeg) {
|
|||
EXPECT_FALSE(match(V3, m_FNeg(m_Value(Match))));
|
||||
}
|
||||
|
||||
TEST_F(PatternMatchTest, LibFunc) {
|
||||
Type *FltTy = IRB.getFloatTy();
|
||||
Value *One = ConstantFP::get(FltTy, 1.0);
|
||||
Value *Two = ConstantFP::get(FltTy, 2.0);
|
||||
Value *MatchOne, *MatchTwo;
|
||||
|
||||
StringRef TanName = TLI.getName(LibFunc_tan);
|
||||
FunctionCallee TanCallee = M->getOrInsertFunction(TanName, FltTy, FltTy);
|
||||
CallInst *Tan = IRB.CreateCall(TanCallee, One, TanName);
|
||||
|
||||
StringRef PowName = TLI.getName(LibFunc_pow);
|
||||
FunctionCallee PowCallee = M->getOrInsertFunction(PowName, FltTy, FltTy, FltTy);
|
||||
CallInst *Pow = IRB.CreateCall(PowCallee, {One, Two}, PowName);
|
||||
|
||||
EXPECT_TRUE(match(Tan, m_LibFunc<LibFunc_tan>(TLI)));
|
||||
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_pow>(TLI)));
|
||||
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_tan>(TLI)));
|
||||
|
||||
EXPECT_TRUE(match(Tan, m_LibFunc<LibFunc_tan>(TLI, m_Value(MatchOne))));
|
||||
EXPECT_EQ(One, MatchOne);
|
||||
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_sin>(TLI, m_Value())));
|
||||
|
||||
EXPECT_TRUE(match(Pow, m_LibFunc<LibFunc_pow>(TLI, m_Value(MatchOne),
|
||||
m_Value(MatchTwo))));
|
||||
EXPECT_EQ(One, MatchOne);
|
||||
EXPECT_EQ(Two, MatchTwo);
|
||||
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_fminf>(TLI, m_Value(), m_Value())));
|
||||
|
||||
TLII.disableAllFunctions();
|
||||
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_tan>(TLI)));
|
||||
EXPECT_FALSE(match(Tan, m_LibFunc<LibFunc_tan>(TLI, m_Value())));
|
||||
EXPECT_FALSE(match(Pow, m_LibFunc<LibFunc_pow>(TLI, m_Value(), m_Value())));
|
||||
}
|
||||
|
||||
template <typename T> struct MutableConstTest : PatternMatchTest { };
|
||||
|
||||
typedef ::testing::Types<std::tuple<Value*, Instruction*>,
|
||||
|
|
Loading…
Reference in New Issue