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