1*134bec27SJames Molloy //===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
2*134bec27SJames Molloy //
3*134bec27SJames Molloy //                     The LLVM Compiler Infrastructure
4*134bec27SJames Molloy //
5*134bec27SJames Molloy // This file is distributed under the University of Illinois Open Source
6*134bec27SJames Molloy // License. See LICENSE.TXT for details.
7*134bec27SJames Molloy //
8*134bec27SJames Molloy //===----------------------------------------------------------------------===//
9*134bec27SJames Molloy 
10*134bec27SJames Molloy #include "llvm/Analysis/ValueTracking.h"
11*134bec27SJames Molloy #include "llvm/AsmParser/Parser.h"
12*134bec27SJames Molloy #include "llvm/IR/Function.h"
13*134bec27SJames Molloy #include "llvm/IR/InstIterator.h"
14*134bec27SJames Molloy #include "llvm/IR/LLVMContext.h"
15*134bec27SJames Molloy #include "llvm/IR/Module.h"
16*134bec27SJames Molloy #include "llvm/Support/ErrorHandling.h"
17*134bec27SJames Molloy #include "llvm/Support/SourceMgr.h"
18*134bec27SJames Molloy #include "gtest/gtest.h"
19*134bec27SJames Molloy 
20*134bec27SJames Molloy using namespace llvm;
21*134bec27SJames Molloy 
22*134bec27SJames Molloy namespace {
23*134bec27SJames Molloy 
24*134bec27SJames Molloy class MatchSelectPatternTest : public testing::Test {
25*134bec27SJames Molloy protected:
26*134bec27SJames Molloy   void parseAssembly(const char *Assembly) {
27*134bec27SJames Molloy     SMDiagnostic Error;
28*134bec27SJames Molloy     M = parseAssemblyString(Assembly, Error, getGlobalContext());
29*134bec27SJames Molloy 
30*134bec27SJames Molloy     std::string errMsg;
31*134bec27SJames Molloy     raw_string_ostream os(errMsg);
32*134bec27SJames Molloy     Error.print("", os);
33*134bec27SJames Molloy 
34*134bec27SJames Molloy     // A failure here means that the test itself is buggy.
35*134bec27SJames Molloy     if (!M)
36*134bec27SJames Molloy       report_fatal_error(os.str());
37*134bec27SJames Molloy 
38*134bec27SJames Molloy     Function *F = M->getFunction("test");
39*134bec27SJames Molloy     if (F == nullptr)
40*134bec27SJames Molloy       report_fatal_error("Test must have a function named @test");
41*134bec27SJames Molloy 
42*134bec27SJames Molloy     A = nullptr;
43*134bec27SJames Molloy     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
44*134bec27SJames Molloy       if (I->hasName()) {
45*134bec27SJames Molloy         if (I->getName() == "A")
46*134bec27SJames Molloy           A = &*I;
47*134bec27SJames Molloy       }
48*134bec27SJames Molloy     }
49*134bec27SJames Molloy     if (A == nullptr)
50*134bec27SJames Molloy       report_fatal_error("@test must have an instruction %A");
51*134bec27SJames Molloy   }
52*134bec27SJames Molloy 
53*134bec27SJames Molloy   void expectPattern(const SelectPatternResult &P) {
54*134bec27SJames Molloy     Value *LHS, *RHS;
55*134bec27SJames Molloy     Instruction::CastOps CastOp;
56*134bec27SJames Molloy     SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
57*134bec27SJames Molloy     EXPECT_EQ(P.Flavor, R.Flavor);
58*134bec27SJames Molloy     EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
59*134bec27SJames Molloy     EXPECT_EQ(P.Ordered, R.Ordered);
60*134bec27SJames Molloy   }
61*134bec27SJames Molloy 
62*134bec27SJames Molloy   std::unique_ptr<Module> M;
63*134bec27SJames Molloy   Instruction *A, *B;
64*134bec27SJames Molloy };
65*134bec27SJames Molloy 
66*134bec27SJames Molloy }
67*134bec27SJames Molloy 
68*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMin) {
69*134bec27SJames Molloy   parseAssembly(
70*134bec27SJames Molloy       "define float @test(float %a) {\n"
71*134bec27SJames Molloy       "  %1 = fcmp ult float %a, 5.0\n"
72*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 5.0\n"
73*134bec27SJames Molloy       "  ret float %A\n"
74*134bec27SJames Molloy       "}\n");
75*134bec27SJames Molloy   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
76*134bec27SJames Molloy }
77*134bec27SJames Molloy 
78*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMax) {
79*134bec27SJames Molloy   parseAssembly(
80*134bec27SJames Molloy       "define float @test(float %a) {\n"
81*134bec27SJames Molloy       "  %1 = fcmp ogt float %a, 5.0\n"
82*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 5.0\n"
83*134bec27SJames Molloy       "  ret float %A\n"
84*134bec27SJames Molloy       "}\n");
85*134bec27SJames Molloy   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
86*134bec27SJames Molloy }
87*134bec27SJames Molloy 
88*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax) {
89*134bec27SJames Molloy   parseAssembly(
90*134bec27SJames Molloy       "define float @test(float %a) {\n"
91*134bec27SJames Molloy       "  %1 = fcmp olt float 5.0, %a\n"
92*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 5.0\n"
93*134bec27SJames Molloy       "  ret float %A\n"
94*134bec27SJames Molloy       "}\n");
95*134bec27SJames Molloy   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
96*134bec27SJames Molloy }
97*134bec27SJames Molloy 
98*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax2) {
99*134bec27SJames Molloy   parseAssembly(
100*134bec27SJames Molloy       "define float @test(float %a) {\n"
101*134bec27SJames Molloy       "  %1 = fcmp olt float %a, 5.0\n"
102*134bec27SJames Molloy       "  %A = select i1 %1, float 5.0, float %a\n"
103*134bec27SJames Molloy       "  ret float %A\n"
104*134bec27SJames Molloy       "}\n");
105*134bec27SJames Molloy   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
106*134bec27SJames Molloy }
107*134bec27SJames Molloy 
108*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax3) {
109*134bec27SJames Molloy   parseAssembly(
110*134bec27SJames Molloy       "define float @test(float %a) {\n"
111*134bec27SJames Molloy       "  %1 = fcmp ult float %a, 5.0\n"
112*134bec27SJames Molloy       "  %A = select i1 %1, float 5.0, float %a\n"
113*134bec27SJames Molloy       "  ret float %A\n"
114*134bec27SJames Molloy       "}\n");
115*134bec27SJames Molloy   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
116*134bec27SJames Molloy }
117*134bec27SJames Molloy 
118*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FastFMin) {
119*134bec27SJames Molloy   parseAssembly(
120*134bec27SJames Molloy       "define float @test(float %a) {\n"
121*134bec27SJames Molloy       "  %1 = fcmp nnan olt float %a, 5.0\n"
122*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 5.0\n"
123*134bec27SJames Molloy       "  ret float %A\n"
124*134bec27SJames Molloy       "}\n");
125*134bec27SJames Molloy   expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
126*134bec27SJames Molloy }
127*134bec27SJames Molloy 
128*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZero) {
129*134bec27SJames Molloy   parseAssembly(
130*134bec27SJames Molloy       "define float @test(float %a) {\n"
131*134bec27SJames Molloy       "  %1 = fcmp ole float %a, 0.0\n"
132*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 0.0\n"
133*134bec27SJames Molloy       "  ret float %A\n"
134*134bec27SJames Molloy       "}\n");
135*134bec27SJames Molloy   // This shouldn't be matched, as %a could be -0.0.
136*134bec27SJames Molloy   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
137*134bec27SJames Molloy }
138*134bec27SJames Molloy 
139*134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
140*134bec27SJames Molloy   parseAssembly(
141*134bec27SJames Molloy       "define float @test(float %a) {\n"
142*134bec27SJames Molloy       "  %1 = fcmp nsz ole float %a, 0.0\n"
143*134bec27SJames Molloy       "  %A = select i1 %1, float %a, float 0.0\n"
144*134bec27SJames Molloy       "  ret float %A\n"
145*134bec27SJames Molloy       "}\n");
146*134bec27SJames Molloy   // But this should be, because we've ignored signed zeroes.
147*134bec27SJames Molloy   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
148*134bec27SJames Molloy }
149