Index: llvm/trunk/include/llvm/IR/PatternMatch.h =================================================================== --- llvm/trunk/include/llvm/IR/PatternMatch.h +++ llvm/trunk/include/llvm/IR/PatternMatch.h @@ -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 @@ return Signum_match(V); } +/// \brief LibFunc matchers. +struct LibFunc_match { + LibFunc F; + TargetLibraryInfo TLI; + + LibFunc_match(LibFunc Func, TargetLibraryInfo TargetLI) + : F(Func), TLI(TargetLI) {} + + template bool match(OpTy *V) { + LibFunc LF; + if (const auto *CI = dyn_cast(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 +struct m_LibFunc_Ty; +template struct m_LibFunc_Ty { + using Ty = match_combine_and>; +}; +template struct m_LibFunc_Ty { + using Ty = + match_combine_and::Ty, + Argument_match>; +}; + +/// \brief Match LibFunc calls like this: +/// m_LibFunc(m_Value(X)) +template +inline LibFunc_match m_LibFunc(TargetLibraryInfo TLI) { + return LibFunc_match(F, TLI); +} + +template +inline typename m_LibFunc_Ty::Ty +m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0) { + return m_CombineAnd(m_LibFunc(TLI), m_Argument<0>(Op0)); +} + +template +inline typename m_LibFunc_Ty::Ty +m_LibFunc(const TargetLibraryInfo TLI, const T0 &Op0, const T1 &Op1) { + return m_CombineAnd(m_LibFunc(TLI, Op0), m_Argument<1>(Op1)); +} + } // end namespace PatternMatch } // end namespace llvm Index: llvm/trunk/unittests/IR/PatternMatch.cpp =================================================================== --- llvm/trunk/unittests/IR/PatternMatch.cpp +++ llvm/trunk/unittests/IR/PatternMatch.cpp @@ -35,13 +35,15 @@ Function *F; BasicBlock *BB; IRBuilder 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 @@ 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(TLI))); + EXPECT_FALSE(match(Tan, m_LibFunc(TLI))); + EXPECT_FALSE(match(Pow, m_LibFunc(TLI))); + + EXPECT_TRUE(match(Tan, m_LibFunc(TLI, m_Value(MatchOne)))); + EXPECT_EQ(One, MatchOne); + EXPECT_FALSE(match(Tan, m_LibFunc(TLI, m_Value()))); + + EXPECT_TRUE(match(Pow, m_LibFunc(TLI, m_Value(MatchOne), + m_Value(MatchTwo)))); + EXPECT_EQ(One, MatchOne); + EXPECT_EQ(Two, MatchTwo); + EXPECT_FALSE(match(Pow, m_LibFunc(TLI, m_Value(), m_Value()))); + + TLII.disableAllFunctions(); + EXPECT_FALSE(match(Tan, m_LibFunc(TLI))); + EXPECT_FALSE(match(Tan, m_LibFunc(TLI, m_Value()))); + EXPECT_FALSE(match(Pow, m_LibFunc(TLI, m_Value(), m_Value()))); +} + template struct MutableConstTest : PatternMatchTest { }; typedef ::testing::Types,