• 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 "llvm/Support/KnownBits.h"
19 #include "gtest/gtest.h"
20 
21 using namespace llvm;
22 
23 namespace {
24 
25 class MatchSelectPatternTest : public testing::Test {
26 protected:
parseAssembly(const char * Assembly)27   void parseAssembly(const char *Assembly) {
28     SMDiagnostic Error;
29     M = parseAssemblyString(Assembly, Error, Context);
30 
31     std::string errMsg;
32     raw_string_ostream os(errMsg);
33     Error.print("", os);
34 
35     // A failure here means that the test itself is buggy.
36     if (!M)
37       report_fatal_error(os.str());
38 
39     Function *F = M->getFunction("test");
40     if (F == nullptr)
41       report_fatal_error("Test must have a function named @test");
42 
43     A = nullptr;
44     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
45       if (I->hasName()) {
46         if (I->getName() == "A")
47           A = &*I;
48       }
49     }
50     if (A == nullptr)
51       report_fatal_error("@test must have an instruction %A");
52   }
53 
expectPattern(const SelectPatternResult & P)54   void expectPattern(const SelectPatternResult &P) {
55     Value *LHS, *RHS;
56     Instruction::CastOps CastOp;
57     SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
58     EXPECT_EQ(P.Flavor, R.Flavor);
59     EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
60     EXPECT_EQ(P.Ordered, R.Ordered);
61   }
62 
63   LLVMContext Context;
64   std::unique_ptr<Module> M;
65   Instruction *A, *B;
66 };
67 
68 }
69 
TEST_F(MatchSelectPatternTest,SimpleFMin)70 TEST_F(MatchSelectPatternTest, SimpleFMin) {
71   parseAssembly(
72       "define float @test(float %a) {\n"
73       "  %1 = fcmp ult float %a, 5.0\n"
74       "  %A = select i1 %1, float %a, float 5.0\n"
75       "  ret float %A\n"
76       "}\n");
77   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
78 }
79 
TEST_F(MatchSelectPatternTest,SimpleFMax)80 TEST_F(MatchSelectPatternTest, SimpleFMax) {
81   parseAssembly(
82       "define float @test(float %a) {\n"
83       "  %1 = fcmp ogt float %a, 5.0\n"
84       "  %A = select i1 %1, float %a, float 5.0\n"
85       "  ret float %A\n"
86       "}\n");
87   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
88 }
89 
TEST_F(MatchSelectPatternTest,SwappedFMax)90 TEST_F(MatchSelectPatternTest, SwappedFMax) {
91   parseAssembly(
92       "define float @test(float %a) {\n"
93       "  %1 = fcmp olt float 5.0, %a\n"
94       "  %A = select i1 %1, float %a, float 5.0\n"
95       "  ret float %A\n"
96       "}\n");
97   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
98 }
99 
TEST_F(MatchSelectPatternTest,SwappedFMax2)100 TEST_F(MatchSelectPatternTest, SwappedFMax2) {
101   parseAssembly(
102       "define float @test(float %a) {\n"
103       "  %1 = fcmp olt float %a, 5.0\n"
104       "  %A = select i1 %1, float 5.0, float %a\n"
105       "  ret float %A\n"
106       "}\n");
107   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
108 }
109 
TEST_F(MatchSelectPatternTest,SwappedFMax3)110 TEST_F(MatchSelectPatternTest, SwappedFMax3) {
111   parseAssembly(
112       "define float @test(float %a) {\n"
113       "  %1 = fcmp ult float %a, 5.0\n"
114       "  %A = select i1 %1, float 5.0, float %a\n"
115       "  ret float %A\n"
116       "}\n");
117   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
118 }
119 
TEST_F(MatchSelectPatternTest,FastFMin)120 TEST_F(MatchSelectPatternTest, FastFMin) {
121   parseAssembly(
122       "define float @test(float %a) {\n"
123       "  %1 = fcmp nnan olt float %a, 5.0\n"
124       "  %A = select i1 %1, float %a, float 5.0\n"
125       "  ret float %A\n"
126       "}\n");
127   expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
128 }
129 
TEST_F(MatchSelectPatternTest,FMinConstantZero)130 TEST_F(MatchSelectPatternTest, FMinConstantZero) {
131   parseAssembly(
132       "define float @test(float %a) {\n"
133       "  %1 = fcmp ole float %a, 0.0\n"
134       "  %A = select i1 %1, float %a, float 0.0\n"
135       "  ret float %A\n"
136       "}\n");
137   // This shouldn't be matched, as %a could be -0.0.
138   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
139 }
140 
TEST_F(MatchSelectPatternTest,FMinConstantZeroNsz)141 TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
142   parseAssembly(
143       "define float @test(float %a) {\n"
144       "  %1 = fcmp nsz ole float %a, 0.0\n"
145       "  %A = select i1 %1, float %a, float 0.0\n"
146       "  ret float %A\n"
147       "}\n");
148   // But this should be, because we've ignored signed zeroes.
149   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
150 }
151 
TEST_F(MatchSelectPatternTest,DoubleCastU)152 TEST_F(MatchSelectPatternTest, DoubleCastU) {
153   parseAssembly(
154       "define i32 @test(i8 %a, i8 %b) {\n"
155       "  %1 = icmp ult i8 %a, %b\n"
156       "  %2 = zext i8 %a to i32\n"
157       "  %3 = zext i8 %b to i32\n"
158       "  %A = select i1 %1, i32 %2, i32 %3\n"
159       "  ret i32 %A\n"
160       "}\n");
161   // We should be able to look through the situation where we cast both operands
162   // to the select.
163   expectPattern({SPF_UMIN, SPNB_NA, false});
164 }
165 
TEST_F(MatchSelectPatternTest,DoubleCastS)166 TEST_F(MatchSelectPatternTest, DoubleCastS) {
167   parseAssembly(
168       "define i32 @test(i8 %a, i8 %b) {\n"
169       "  %1 = icmp slt i8 %a, %b\n"
170       "  %2 = sext i8 %a to i32\n"
171       "  %3 = sext i8 %b to i32\n"
172       "  %A = select i1 %1, i32 %2, i32 %3\n"
173       "  ret i32 %A\n"
174       "}\n");
175   // We should be able to look through the situation where we cast both operands
176   // to the select.
177   expectPattern({SPF_SMIN, SPNB_NA, false});
178 }
179 
TEST_F(MatchSelectPatternTest,DoubleCastBad)180 TEST_F(MatchSelectPatternTest, DoubleCastBad) {
181   parseAssembly(
182       "define i32 @test(i8 %a, i8 %b) {\n"
183       "  %1 = icmp ult i8 %a, %b\n"
184       "  %2 = zext i8 %a to i32\n"
185       "  %3 = sext i8 %b to i32\n"
186       "  %A = select i1 %1, i32 %2, i32 %3\n"
187       "  ret i32 %A\n"
188       "}\n");
189   // The cast types here aren't the same, so we cannot match an UMIN.
190   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
191 }
192 
TEST(ValueTracking,GuaranteedToTransferExecutionToSuccessor)193 TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) {
194   StringRef Assembly =
195       "declare void @nounwind_readonly(i32*) nounwind readonly "
196       "declare void @nounwind_argmemonly(i32*) nounwind argmemonly "
197       "declare void @throws_but_readonly(i32*) readonly "
198       "declare void @throws_but_argmemonly(i32*) argmemonly "
199       " "
200       "declare void @unknown(i32*) "
201       " "
202       "define void @f(i32* %p) { "
203       "  call void @nounwind_readonly(i32* %p) "
204       "  call void @nounwind_argmemonly(i32* %p) "
205       "  call void @throws_but_readonly(i32* %p) "
206       "  call void @throws_but_argmemonly(i32* %p) "
207       "  call void @unknown(i32* %p) nounwind readonly "
208       "  call void @unknown(i32* %p) nounwind argmemonly "
209       "  call void @unknown(i32* %p) readonly "
210       "  call void @unknown(i32* %p) argmemonly "
211       "  ret void "
212       "} ";
213 
214   LLVMContext Context;
215   SMDiagnostic Error;
216   auto M = parseAssemblyString(Assembly, Error, Context);
217   assert(M && "Bad assembly?");
218 
219   auto *F = M->getFunction("f");
220   assert(F && "Bad assembly?");
221 
222   auto &BB = F->getEntryBlock();
223   bool ExpectedAnswers[] = {
224       true,  // call void @nounwind_readonly(i32* %p)
225       true,  // call void @nounwind_argmemonly(i32* %p)
226       false, // call void @throws_but_readonly(i32* %p)
227       false, // call void @throws_but_argmemonly(i32* %p)
228       true,  // call void @unknown(i32* %p) nounwind readonly
229       true,  // call void @unknown(i32* %p) nounwind argmemonly
230       false, // call void @unknown(i32* %p) readonly
231       false, // call void @unknown(i32* %p) argmemonly
232       false, // ret void
233   };
234 
235   int Index = 0;
236   for (auto &I : BB) {
237     EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I),
238               ExpectedAnswers[Index])
239         << "Incorrect answer at instruction " << Index << " = " << I;
240     Index++;
241   }
242 }
243 
TEST(ValueTracking,ComputeNumSignBits_PR32045)244 TEST(ValueTracking, ComputeNumSignBits_PR32045) {
245   StringRef Assembly = "define i32 @f(i32 %a) { "
246                        "  %val = ashr i32 %a, -1 "
247                        "  ret i32 %val "
248                        "} ";
249 
250   LLVMContext Context;
251   SMDiagnostic Error;
252   auto M = parseAssemblyString(Assembly, Error, Context);
253   assert(M && "Bad assembly?");
254 
255   auto *F = M->getFunction("f");
256   assert(F && "Bad assembly?");
257 
258   auto *RVal =
259       cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
260   EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u);
261 }
262 
TEST(ValueTracking,ComputeKnownBits)263 TEST(ValueTracking, ComputeKnownBits) {
264   StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { "
265                        "  %ash = mul i32 %a, 8 "
266                        "  %aad = add i32 %ash, 7 "
267                        "  %aan = and i32 %aad, 4095 "
268                        "  %bsh = shl i32 %b, 4 "
269                        "  %bad = or i32 %bsh, 6 "
270                        "  %ban = and i32 %bad, 4095 "
271                        "  %mul = mul i32 %aan, %ban "
272                        "  ret i32 %mul "
273                        "} ";
274 
275   LLVMContext Context;
276   SMDiagnostic Error;
277   auto M = parseAssemblyString(Assembly, Error, Context);
278   assert(M && "Bad assembly?");
279 
280   auto *F = M->getFunction("f");
281   assert(F && "Bad assembly?");
282 
283   auto *RVal =
284       cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
285   auto Known = computeKnownBits(RVal, M->getDataLayout());
286   ASSERT_FALSE(Known.hasConflict());
287   EXPECT_EQ(Known.One.getZExtValue(), 10u);
288   EXPECT_EQ(Known.Zero.getZExtValue(), 4278190085u);
289 }
290 
TEST(ValueTracking,ComputeKnownMulBits)291 TEST(ValueTracking, ComputeKnownMulBits) {
292   StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { "
293                        "  %aa = shl i32 %a, 5 "
294                        "  %bb = shl i32 %b, 5 "
295                        "  %aaa = or i32 %aa, 24 "
296                        "  %bbb = or i32 %bb, 28 "
297                        "  %mul = mul i32 %aaa, %bbb "
298                        "  ret i32 %mul "
299                        "} ";
300 
301   LLVMContext Context;
302   SMDiagnostic Error;
303   auto M = parseAssemblyString(Assembly, Error, Context);
304   assert(M && "Bad assembly?");
305 
306   auto *F = M->getFunction("f");
307   assert(F && "Bad assembly?");
308 
309   auto *RVal =
310       cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0);
311   auto Known = computeKnownBits(RVal, M->getDataLayout());
312   ASSERT_FALSE(Known.hasConflict());
313   EXPECT_EQ(Known.One.getZExtValue(), 32u);
314   EXPECT_EQ(Known.Zero.getZExtValue(), 95u);
315 }
316