[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
diff --git a/llvm/unittests/IR/PatternMatch.cpp b/llvm/unittests/IR/PatternMatch.cpp
index 600494f..3f8e691 100644
--- a/llvm/unittests/IR/PatternMatch.cpp
+++ b/llvm/unittests/IR/PatternMatch.cpp
@@ -35,13 +35,15 @@
   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 @@
   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*>,