1 //===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Analysis/ValueTracking.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/InstIterator.h"
13 #include "llvm/IR/LLVMContext.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/KnownBits.h"
18 #include "gtest/gtest.h"
19 
20 using namespace llvm;
21 
22 namespace {
23 
24 class ValueTrackingTest : public testing::Test {
25 protected:
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 
53   LLVMContext Context;
54   std::unique_ptr<Module> M;
55   Instruction *A;
56 };
57 
58 class MatchSelectPatternTest : public ValueTrackingTest {
59 protected:
60   void expectPattern(const SelectPatternResult &P) {
61     Value *LHS, *RHS;
62     Instruction::CastOps CastOp;
63     SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
64     EXPECT_EQ(P.Flavor, R.Flavor);
65     EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
66     EXPECT_EQ(P.Ordered, R.Ordered);
67   }
68 };
69 
70 class ComputeKnownBitsTest : public ValueTrackingTest {
71 protected:
72   void expectKnownBits(uint64_t Zero, uint64_t One) {
73     auto Known = computeKnownBits(A, M->getDataLayout());
74     ASSERT_FALSE(Known.hasConflict());
75     EXPECT_EQ(Known.One.getZExtValue(), One);
76     EXPECT_EQ(Known.Zero.getZExtValue(), Zero);
77   }
78 };
79 
80 }
81 
82 TEST_F(MatchSelectPatternTest, SimpleFMin) {
83   parseAssembly(
84       "define float @test(float %a) {\n"
85       "  %1 = fcmp ult float %a, 5.0\n"
86       "  %A = select i1 %1, float %a, float 5.0\n"
87       "  ret float %A\n"
88       "}\n");
89   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
90 }
91 
92 TEST_F(MatchSelectPatternTest, SimpleFMax) {
93   parseAssembly(
94       "define float @test(float %a) {\n"
95       "  %1 = fcmp ogt float %a, 5.0\n"
96       "  %A = select i1 %1, float %a, float 5.0\n"
97       "  ret float %A\n"
98       "}\n");
99   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
100 }
101 
102 TEST_F(MatchSelectPatternTest, SwappedFMax) {
103   parseAssembly(
104       "define float @test(float %a) {\n"
105       "  %1 = fcmp olt float 5.0, %a\n"
106       "  %A = select i1 %1, float %a, float 5.0\n"
107       "  ret float %A\n"
108       "}\n");
109   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
110 }
111 
112 TEST_F(MatchSelectPatternTest, SwappedFMax2) {
113   parseAssembly(
114       "define float @test(float %a) {\n"
115       "  %1 = fcmp olt float %a, 5.0\n"
116       "  %A = select i1 %1, float 5.0, float %a\n"
117       "  ret float %A\n"
118       "}\n");
119   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
120 }
121 
122 TEST_F(MatchSelectPatternTest, SwappedFMax3) {
123   parseAssembly(
124       "define float @test(float %a) {\n"
125       "  %1 = fcmp ult float %a, 5.0\n"
126       "  %A = select i1 %1, float 5.0, float %a\n"
127       "  ret float %A\n"
128       "}\n");
129   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
130 }
131 
132 TEST_F(MatchSelectPatternTest, FastFMin) {
133   parseAssembly(
134       "define float @test(float %a) {\n"
135       "  %1 = fcmp nnan olt float %a, 5.0\n"
136       "  %A = select i1 %1, float %a, float 5.0\n"
137       "  ret float %A\n"
138       "}\n");
139   expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
140 }
141 
142 TEST_F(MatchSelectPatternTest, FMinConstantZero) {
143   parseAssembly(
144       "define float @test(float %a) {\n"
145       "  %1 = fcmp ole float %a, 0.0\n"
146       "  %A = select i1 %1, float %a, float 0.0\n"
147       "  ret float %A\n"
148       "}\n");
149   // This shouldn't be matched, as %a could be -0.0.
150   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
151 }
152 
153 TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
154   parseAssembly(
155       "define float @test(float %a) {\n"
156       "  %1 = fcmp nsz ole float %a, 0.0\n"
157       "  %A = select i1 %1, float %a, float 0.0\n"
158       "  ret float %A\n"
159       "}\n");
160   // But this should be, because we've ignored signed zeroes.
161   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
162 }
163 
164 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero1) {
165   parseAssembly(
166       "define float @test(float %a) {\n"
167       "  %1 = fcmp olt float -0.0, %a\n"
168       "  %A = select i1 %1, float 0.0, float %a\n"
169       "  ret float %A\n"
170       "}\n");
171   // The sign of zero doesn't matter in fcmp.
172   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
173 }
174 
175 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) {
176   parseAssembly(
177       "define float @test(float %a) {\n"
178       "  %1 = fcmp ogt float %a, -0.0\n"
179       "  %A = select i1 %1, float 0.0, float %a\n"
180       "  ret float %A\n"
181       "}\n");
182   // The sign of zero doesn't matter in fcmp.
183   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
184 }
185 
186 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) {
187   parseAssembly(
188       "define float @test(float %a) {\n"
189       "  %1 = fcmp olt float 0.0, %a\n"
190       "  %A = select i1 %1, float -0.0, float %a\n"
191       "  ret float %A\n"
192       "}\n");
193   // The sign of zero doesn't matter in fcmp.
194   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true});
195 }
196 
197 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) {
198   parseAssembly(
199       "define float @test(float %a) {\n"
200       "  %1 = fcmp ogt float %a, 0.0\n"
201       "  %A = select i1 %1, float -0.0, float %a\n"
202       "  ret float %A\n"
203       "}\n");
204   // The sign of zero doesn't matter in fcmp.
205   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
206 }
207 
208 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) {
209   parseAssembly(
210       "define float @test(float %a) {\n"
211       "  %1 = fcmp ogt float -0.0, %a\n"
212       "  %A = select i1 %1, float %a, float 0.0\n"
213       "  ret float %A\n"
214       "}\n");
215   // The sign of zero doesn't matter in fcmp.
216   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
217 }
218 
219 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) {
220   parseAssembly(
221       "define float @test(float %a) {\n"
222       "  %1 = fcmp olt float %a, -0.0\n"
223       "  %A = select i1 %1, float %a, float 0.0\n"
224       "  ret float %A\n"
225       "}\n");
226   // The sign of zero doesn't matter in fcmp.
227   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
228 }
229 
230 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) {
231   parseAssembly(
232       "define float @test(float %a) {\n"
233       "  %1 = fcmp ogt float 0.0, %a\n"
234       "  %A = select i1 %1, float %a, float -0.0\n"
235       "  ret float %A\n"
236       "}\n");
237   // The sign of zero doesn't matter in fcmp.
238   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false});
239 }
240 
241 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) {
242   parseAssembly(
243       "define float @test(float %a) {\n"
244       "  %1 = fcmp olt float %a, 0.0\n"
245       "  %A = select i1 %1, float %a, float -0.0\n"
246       "  ret float %A\n"
247       "}\n");
248   // The sign of zero doesn't matter in fcmp.
249   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
250 }
251 
252 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) {
253   parseAssembly(
254       "define float @test(float %a) {\n"
255       "  %1 = fcmp ogt float -0.0, %a\n"
256       "  %A = select i1 %1, float 0.0, float %a\n"
257       "  ret float %A\n"
258       "}\n");
259   // The sign of zero doesn't matter in fcmp.
260   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
261 }
262 
263 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) {
264   parseAssembly(
265       "define float @test(float %a) {\n"
266       "  %1 = fcmp olt float %a, -0.0\n"
267       "  %A = select i1 %1, float 0.0, float %a\n"
268       "  ret float %A\n"
269       "}\n");
270   // The sign of zero doesn't matter in fcmp.
271   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
272 }
273 
274 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) {
275   parseAssembly(
276       "define float @test(float %a) {\n"
277       "  %1 = fcmp ogt float 0.0, %a\n"
278       "  %A = select i1 %1, float -0.0, float %a\n"
279       "  ret float %A\n"
280       "}\n");
281   // The sign of zero doesn't matter in fcmp.
282   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true});
283 }
284 
285 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) {
286   parseAssembly(
287       "define float @test(float %a) {\n"
288       "  %1 = fcmp olt float %a, 0.0\n"
289       "  %A = select i1 %1, float -0.0, float %a\n"
290       "  ret float %A\n"
291       "}\n");
292   // The sign of zero doesn't matter in fcmp.
293   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
294 }
295 
296 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) {
297   parseAssembly(
298       "define float @test(float %a) {\n"
299       "  %1 = fcmp olt float -0.0, %a\n"
300       "  %A = select i1 %1, float %a, float 0.0\n"
301       "  ret float %A\n"
302       "}\n");
303   // The sign of zero doesn't matter in fcmp.
304   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
305 }
306 
307 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) {
308   parseAssembly(
309       "define float @test(float %a) {\n"
310       "  %1 = fcmp ogt float %a, -0.0\n"
311       "  %A = select i1 %1, float %a, float 0.0\n"
312       "  ret float %A\n"
313       "}\n");
314   // The sign of zero doesn't matter in fcmp.
315   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
316 }
317 
318 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) {
319   parseAssembly(
320       "define float @test(float %a) {\n"
321       "  %1 = fcmp olt float 0.0, %a\n"
322       "  %A = select i1 %1, float %a, float -0.0\n"
323       "  ret float %A\n"
324       "}\n");
325   // The sign of zero doesn't matter in fcmp.
326   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
327 }
328 
329 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) {
330   parseAssembly(
331       "define float @test(float %a) {\n"
332       "  %1 = fcmp ogt float %a, 0.0\n"
333       "  %A = select i1 %1, float %a, float -0.0\n"
334       "  ret float %A\n"
335       "}\n");
336   // The sign of zero doesn't matter in fcmp.
337   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
338 }
339 
340 TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) {
341   parseAssembly(
342       "define <2 x float> @test(<2 x float> %a) {\n"
343       "  %1 = fcmp ogt <2 x float> %a, <float -0.0, float -0.0>\n"
344       "  %A = select <2 x i1> %1, <2 x float> <float undef, float 0.0>, <2 x float> %a\n"
345       "  ret <2 x float> %A\n"
346       "}\n");
347   // An undef in a vector constant can not be back-propagated for this analysis.
348   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
349 }
350 
351 TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) {
352   parseAssembly(
353       "define <2 x float> @test(<2 x float> %a) {\n"
354       "  %1 = fcmp ogt <2 x float> %a, zeroinitializer\n"
355       "  %A = select <2 x i1> %1, <2 x float> %a, <2 x float> <float -0.0, float undef>\n"
356       "  ret <2 x float> %A\n"
357       "}\n");
358   // An undef in a vector constant can not be back-propagated for this analysis.
359   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
360 }
361 
362 TEST_F(MatchSelectPatternTest, VectorFMinimum) {
363   parseAssembly(
364       "define <4 x float> @test(<4 x float> %a) {\n"
365       "  %1 = fcmp ule <4 x float> %a, \n"
366       "    <float 5.0, float 5.0, float 5.0, float 5.0>\n"
367       "  %A = select <4 x i1> %1, <4 x float> %a,\n"
368       "     <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n"
369       "  ret <4 x float> %A\n"
370       "}\n");
371   // Check that pattern matching works on vectors where each lane has the same
372   // unordered pattern.
373   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
374 }
375 
376 TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) {
377   parseAssembly(
378       "define <4 x float> @test(<4 x float> %a) {\n"
379       "  %1 = fcmp ole <4 x float> %a, \n"
380       "    <float 5.0, float 5.0, float 5.0, float 5.0>\n"
381       "  %A = select <4 x i1> %1, <4 x float> %a,\n"
382       "     <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n"
383       "  ret <4 x float> %A\n"
384       "}\n");
385   // Check that pattern matching works on vectors where each lane has the same
386   // ordered pattern.
387   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
388 }
389 
390 TEST_F(MatchSelectPatternTest, VectorNotFMinimum) {
391   parseAssembly(
392       "define <4 x float> @test(<4 x float> %a) {\n"
393       "  %1 = fcmp ule <4 x float> %a, \n"
394       "    <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n"
395       "  %A = select <4 x i1> %1, <4 x float> %a,\n"
396       "     <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float "
397       "5.0>\n"
398       "  ret <4 x float> %A\n"
399       "}\n");
400   // The lane that contains a NaN (0x7ff80...) behaves like a
401   // non-NaN-propagating min and the other lines behave like a NaN-propagating
402   // min, so check that neither is returned.
403   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
404 }
405 
406 TEST_F(MatchSelectPatternTest, VectorNotFMinZero) {
407   parseAssembly(
408       "define <4 x float> @test(<4 x float> %a) {\n"
409       "  %1 = fcmp ule <4 x float> %a, \n"
410       "    <float 5.0, float -0.0, float 5.0, float 5.0>\n"
411       "  %A = select <4 x i1> %1, <4 x float> %a,\n"
412       "     <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n"
413       "  ret <4 x float> %A\n"
414       "}\n");
415   // Always selects the second lane of %a if it is positive or negative zero, so
416   // this is stricter than a min.
417   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
418 }
419 
420 TEST_F(MatchSelectPatternTest, DoubleCastU) {
421   parseAssembly(
422       "define i32 @test(i8 %a, i8 %b) {\n"
423       "  %1 = icmp ult i8 %a, %b\n"
424       "  %2 = zext i8 %a to i32\n"
425       "  %3 = zext i8 %b to i32\n"
426       "  %A = select i1 %1, i32 %2, i32 %3\n"
427       "  ret i32 %A\n"
428       "}\n");
429   // We should be able to look through the situation where we cast both operands
430   // to the select.
431   expectPattern({SPF_UMIN, SPNB_NA, false});
432 }
433 
434 TEST_F(MatchSelectPatternTest, DoubleCastS) {
435   parseAssembly(
436       "define i32 @test(i8 %a, i8 %b) {\n"
437       "  %1 = icmp slt i8 %a, %b\n"
438       "  %2 = sext i8 %a to i32\n"
439       "  %3 = sext i8 %b to i32\n"
440       "  %A = select i1 %1, i32 %2, i32 %3\n"
441       "  ret i32 %A\n"
442       "}\n");
443   // We should be able to look through the situation where we cast both operands
444   // to the select.
445   expectPattern({SPF_SMIN, SPNB_NA, false});
446 }
447 
448 TEST_F(MatchSelectPatternTest, DoubleCastBad) {
449   parseAssembly(
450       "define i32 @test(i8 %a, i8 %b) {\n"
451       "  %1 = icmp ult i8 %a, %b\n"
452       "  %2 = zext i8 %a to i32\n"
453       "  %3 = sext i8 %b to i32\n"
454       "  %A = select i1 %1, i32 %2, i32 %3\n"
455       "  ret i32 %A\n"
456       "}\n");
457   // The cast types here aren't the same, so we cannot match an UMIN.
458   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
459 }
460 
461 TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) {
462   StringRef Assembly =
463       "declare void @nounwind_readonly(i32*) nounwind readonly "
464       "declare void @nounwind_argmemonly(i32*) nounwind argmemonly "
465       "declare void @throws_but_readonly(i32*) readonly "
466       "declare void @throws_but_argmemonly(i32*) argmemonly "
467       " "
468       "declare void @unknown(i32*) "
469       " "
470       "define void @f(i32* %p) { "
471       "  call void @nounwind_readonly(i32* %p) "
472       "  call void @nounwind_argmemonly(i32* %p) "
473       "  call void @throws_but_readonly(i32* %p) "
474       "  call void @throws_but_argmemonly(i32* %p) "
475       "  call void @unknown(i32* %p) nounwind readonly "
476       "  call void @unknown(i32* %p) nounwind argmemonly "
477       "  call void @unknown(i32* %p) readonly "
478       "  call void @unknown(i32* %p) argmemonly "
479       "  ret void "
480       "} ";
481 
482   LLVMContext Context;
483   SMDiagnostic Error;
484   auto M = parseAssemblyString(Assembly, Error, Context);
485   assert(M && "Bad assembly?");
486 
487   auto *F = M->getFunction("f");
488   assert(F && "Bad assembly?");
489 
490   auto &BB = F->getEntryBlock();
491   bool ExpectedAnswers[] = {
492       true,  // call void @nounwind_readonly(i32* %p)
493       true,  // call void @nounwind_argmemonly(i32* %p)
494       false, // call void @throws_but_readonly(i32* %p)
495       false, // call void @throws_but_argmemonly(i32* %p)
496       true,  // call void @unknown(i32* %p) nounwind readonly
497       true,  // call void @unknown(i32* %p) nounwind argmemonly
498       false, // call void @unknown(i32* %p) readonly
499       false, // call void @unknown(i32* %p) argmemonly
500       false, // ret void
501   };
502 
503   int Index = 0;
504   for (auto &I : BB) {
505     EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I),
506               ExpectedAnswers[Index])
507         << "Incorrect answer at instruction " << Index << " = " << I;
508     Index++;
509   }
510 }
511 
512 TEST_F(ValueTrackingTest, ComputeNumSignBits_PR32045) {
513   parseAssembly(
514       "define i32 @test(i32 %a) {\n"
515       "  %A = ashr i32 %a, -1\n"
516       "  ret i32 %A\n"
517       "}\n");
518   EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
519 }
520 
521 // No guarantees for canonical IR in this analysis, so this just bails out.
522 TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle) {
523   parseAssembly(
524       "define <2 x i32> @test() {\n"
525       "  %A = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0>\n"
526       "  ret <2 x i32> %A\n"
527       "}\n");
528   EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
529 }
530 
531 // No guarantees for canonical IR in this analysis, so a shuffle element that
532 // references an undef value means this can't return any extra information.
533 TEST_F(ValueTrackingTest, ComputeNumSignBits_Shuffle2) {
534   parseAssembly(
535       "define <2 x i32> @test(<2 x i1> %x) {\n"
536       "  %sext = sext <2 x i1> %x to <2 x i32>\n"
537       "  %A = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2>\n"
538       "  ret <2 x i32> %A\n"
539       "}\n");
540   EXPECT_EQ(ComputeNumSignBits(A, M->getDataLayout()), 1u);
541 }
542 
543 TEST_F(ComputeKnownBitsTest, ComputeKnownBits) {
544   parseAssembly(
545       "define i32 @test(i32 %a, i32 %b) {\n"
546       "  %ash = mul i32 %a, 8\n"
547       "  %aad = add i32 %ash, 7\n"
548       "  %aan = and i32 %aad, 4095\n"
549       "  %bsh = shl i32 %b, 4\n"
550       "  %bad = or i32 %bsh, 6\n"
551       "  %ban = and i32 %bad, 4095\n"
552       "  %A = mul i32 %aan, %ban\n"
553       "  ret i32 %A\n"
554       "}\n");
555   expectKnownBits(/*zero*/ 4278190085u, /*one*/ 10u);
556 }
557 
558 TEST_F(ComputeKnownBitsTest, ComputeKnownMulBits) {
559   parseAssembly(
560       "define i32 @test(i32 %a, i32 %b) {\n"
561       "  %aa = shl i32 %a, 5\n"
562       "  %bb = shl i32 %b, 5\n"
563       "  %aaa = or i32 %aa, 24\n"
564       "  %bbb = or i32 %bb, 28\n"
565       "  %A = mul i32 %aaa, %bbb\n"
566       "  ret i32 %A\n"
567       "}\n");
568   expectKnownBits(/*zero*/ 95u, /*one*/ 32u);
569 }
570 
571 TEST_F(ComputeKnownBitsTest, ComputeKnownFshl) {
572   // fshl(....1111....0000, 00..1111........, 6)
573   // = 11....000000..11
574   parseAssembly(
575       "define i16 @test(i16 %a, i16 %b) {\n"
576       "  %aa = shl i16 %a, 4\n"
577       "  %bb = lshr i16 %b, 2\n"
578       "  %aaa = or i16 %aa, 3840\n"
579       "  %bbb = or i16 %bb, 3840\n"
580       "  %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 6)\n"
581       "  ret i16 %A\n"
582       "}\n"
583       "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");
584   expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);
585 }
586 
587 TEST_F(ComputeKnownBitsTest, ComputeKnownFshr) {
588   // fshr(....1111....0000, 00..1111........, 26)
589   // = 11....000000..11
590   parseAssembly(
591       "define i16 @test(i16 %a, i16 %b) {\n"
592       "  %aa = shl i16 %a, 4\n"
593       "  %bb = lshr i16 %b, 2\n"
594       "  %aaa = or i16 %aa, 3840\n"
595       "  %bbb = or i16 %bb, 3840\n"
596       "  %A = call i16 @llvm.fshr.i16(i16 %aaa, i16 %bbb, i16 26)\n"
597       "  ret i16 %A\n"
598       "}\n"
599       "declare i16 @llvm.fshr.i16(i16, i16, i16)\n");
600   expectKnownBits(/*zero*/ 1008u, /*one*/ 49155u);
601 }
602 
603 TEST_F(ComputeKnownBitsTest, ComputeKnownFshlZero) {
604   // fshl(....1111....0000, 00..1111........, 0)
605   // = ....1111....0000
606   parseAssembly(
607       "define i16 @test(i16 %a, i16 %b) {\n"
608       "  %aa = shl i16 %a, 4\n"
609       "  %bb = lshr i16 %b, 2\n"
610       "  %aaa = or i16 %aa, 3840\n"
611       "  %bbb = or i16 %bb, 3840\n"
612       "  %A = call i16 @llvm.fshl.i16(i16 %aaa, i16 %bbb, i16 0)\n"
613       "  ret i16 %A\n"
614       "}\n"
615       "declare i16 @llvm.fshl.i16(i16, i16, i16)\n");
616   expectKnownBits(/*zero*/ 15u, /*one*/ 3840u);
617 }
618 
619 TEST_F(ComputeKnownBitsTest, ComputeKnownUAddSatLeadingOnes) {
620   // uadd.sat(1111...1, ........)
621   // = 1111....
622   parseAssembly(
623       "define i8 @test(i8 %a, i8 %b) {\n"
624       "  %aa = or i8 %a, 241\n"
625       "  %A = call i8 @llvm.uadd.sat.i8(i8 %aa, i8 %b)\n"
626       "  ret i8 %A\n"
627       "}\n"
628       "declare i8 @llvm.uadd.sat.i8(i8, i8)\n");
629   expectKnownBits(/*zero*/ 0u, /*one*/ 240u);
630 }
631 
632 TEST_F(ComputeKnownBitsTest, ComputeKnownUAddSatOnesPreserved) {
633   // uadd.sat(00...011, .1...110)
634   // = .......1
635   parseAssembly(
636       "define i8 @test(i8 %a, i8 %b) {\n"
637       "  %aa = or i8 %a, 3\n"
638       "  %aaa = and i8 %aa, 59\n"
639       "  %bb = or i8 %b, 70\n"
640       "  %bbb = and i8 %bb, 254\n"
641       "  %A = call i8 @llvm.uadd.sat.i8(i8 %aaa, i8 %bbb)\n"
642       "  ret i8 %A\n"
643       "}\n"
644       "declare i8 @llvm.uadd.sat.i8(i8, i8)\n");
645   expectKnownBits(/*zero*/ 0u, /*one*/ 1u);
646 }
647 
648 TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatLHSLeadingZeros) {
649   // usub.sat(0000...0, ........)
650   // = 0000....
651   parseAssembly(
652       "define i8 @test(i8 %a, i8 %b) {\n"
653       "  %aa = and i8 %a, 14\n"
654       "  %A = call i8 @llvm.usub.sat.i8(i8 %aa, i8 %b)\n"
655       "  ret i8 %A\n"
656       "}\n"
657       "declare i8 @llvm.usub.sat.i8(i8, i8)\n");
658   expectKnownBits(/*zero*/ 240u, /*one*/ 0u);
659 }
660 
661 TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatRHSLeadingOnes) {
662   // usub.sat(........, 1111...1)
663   // = 0000....
664   parseAssembly(
665       "define i8 @test(i8 %a, i8 %b) {\n"
666       "  %bb = or i8 %a, 241\n"
667       "  %A = call i8 @llvm.usub.sat.i8(i8 %a, i8 %bb)\n"
668       "  ret i8 %A\n"
669       "}\n"
670       "declare i8 @llvm.usub.sat.i8(i8, i8)\n");
671   expectKnownBits(/*zero*/ 240u, /*one*/ 0u);
672 }
673 
674 TEST_F(ComputeKnownBitsTest, ComputeKnownUSubSatZerosPreserved) {
675   // usub.sat(11...011, .1...110)
676   // = ......0.
677   parseAssembly(
678       "define i8 @test(i8 %a, i8 %b) {\n"
679       "  %aa = or i8 %a, 195\n"
680       "  %aaa = and i8 %aa, 251\n"
681       "  %bb = or i8 %b, 70\n"
682       "  %bbb = and i8 %bb, 254\n"
683       "  %A = call i8 @llvm.usub.sat.i8(i8 %aaa, i8 %bbb)\n"
684       "  ret i8 %A\n"
685       "}\n"
686       "declare i8 @llvm.usub.sat.i8(i8, i8)\n");
687   expectKnownBits(/*zero*/ 2u, /*one*/ 0u);
688 }
689