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