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