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