1134bec27SJames Molloy //===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===// 2134bec27SJames Molloy // 3134bec27SJames Molloy // The LLVM Compiler Infrastructure 4134bec27SJames Molloy // 5134bec27SJames Molloy // This file is distributed under the University of Illinois Open Source 6134bec27SJames Molloy // License. See LICENSE.TXT for details. 7134bec27SJames Molloy // 8134bec27SJames Molloy //===----------------------------------------------------------------------===// 9134bec27SJames Molloy 10134bec27SJames Molloy #include "llvm/Analysis/ValueTracking.h" 11134bec27SJames Molloy #include "llvm/AsmParser/Parser.h" 12134bec27SJames Molloy #include "llvm/IR/Function.h" 13134bec27SJames Molloy #include "llvm/IR/InstIterator.h" 14134bec27SJames Molloy #include "llvm/IR/LLVMContext.h" 15134bec27SJames Molloy #include "llvm/IR/Module.h" 16134bec27SJames Molloy #include "llvm/Support/ErrorHandling.h" 17134bec27SJames Molloy #include "llvm/Support/SourceMgr.h" 1870dbd5fbSSimon Dardis #include "llvm/Support/KnownBits.h" 19134bec27SJames Molloy #include "gtest/gtest.h" 20134bec27SJames Molloy 21134bec27SJames Molloy using namespace llvm; 22134bec27SJames Molloy 23134bec27SJames Molloy namespace { 24134bec27SJames Molloy 25134bec27SJames Molloy class MatchSelectPatternTest : public testing::Test { 26134bec27SJames Molloy protected: 27134bec27SJames Molloy void parseAssembly(const char *Assembly) { 28134bec27SJames Molloy SMDiagnostic Error; 2903b42e41SMehdi Amini M = parseAssemblyString(Assembly, Error, Context); 30134bec27SJames Molloy 31134bec27SJames Molloy std::string errMsg; 32134bec27SJames Molloy raw_string_ostream os(errMsg); 33134bec27SJames Molloy Error.print("", os); 34134bec27SJames Molloy 35134bec27SJames Molloy // A failure here means that the test itself is buggy. 36134bec27SJames Molloy if (!M) 37134bec27SJames Molloy report_fatal_error(os.str()); 38134bec27SJames Molloy 39134bec27SJames Molloy Function *F = M->getFunction("test"); 40134bec27SJames Molloy if (F == nullptr) 41134bec27SJames Molloy report_fatal_error("Test must have a function named @test"); 42134bec27SJames Molloy 43134bec27SJames Molloy A = nullptr; 44134bec27SJames Molloy for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 45134bec27SJames Molloy if (I->hasName()) { 46134bec27SJames Molloy if (I->getName() == "A") 47134bec27SJames Molloy A = &*I; 48134bec27SJames Molloy } 49134bec27SJames Molloy } 50134bec27SJames Molloy if (A == nullptr) 51134bec27SJames Molloy report_fatal_error("@test must have an instruction %A"); 52134bec27SJames Molloy } 53134bec27SJames Molloy 54134bec27SJames Molloy void expectPattern(const SelectPatternResult &P) { 55134bec27SJames Molloy Value *LHS, *RHS; 56134bec27SJames Molloy Instruction::CastOps CastOp; 57134bec27SJames Molloy SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp); 58134bec27SJames Molloy EXPECT_EQ(P.Flavor, R.Flavor); 59134bec27SJames Molloy EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); 60134bec27SJames Molloy EXPECT_EQ(P.Ordered, R.Ordered); 61134bec27SJames Molloy } 62134bec27SJames Molloy 6303b42e41SMehdi Amini LLVMContext Context; 64134bec27SJames Molloy std::unique_ptr<Module> M; 65134bec27SJames Molloy Instruction *A, *B; 66134bec27SJames Molloy }; 67134bec27SJames Molloy 68134bec27SJames Molloy } 69134bec27SJames Molloy 70134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMin) { 71134bec27SJames Molloy parseAssembly( 72134bec27SJames Molloy "define float @test(float %a) {\n" 73134bec27SJames Molloy " %1 = fcmp ult float %a, 5.0\n" 74134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 75134bec27SJames Molloy " ret float %A\n" 76134bec27SJames Molloy "}\n"); 77134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 78134bec27SJames Molloy } 79134bec27SJames Molloy 80134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMax) { 81134bec27SJames Molloy parseAssembly( 82134bec27SJames Molloy "define float @test(float %a) {\n" 83134bec27SJames Molloy " %1 = fcmp ogt float %a, 5.0\n" 84134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 85134bec27SJames Molloy " ret float %A\n" 86134bec27SJames Molloy "}\n"); 87134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 88134bec27SJames Molloy } 89134bec27SJames Molloy 90134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax) { 91134bec27SJames Molloy parseAssembly( 92134bec27SJames Molloy "define float @test(float %a) {\n" 93134bec27SJames Molloy " %1 = fcmp olt float 5.0, %a\n" 94134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 95134bec27SJames Molloy " ret float %A\n" 96134bec27SJames Molloy "}\n"); 97134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); 98134bec27SJames Molloy } 99134bec27SJames Molloy 100134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax2) { 101134bec27SJames Molloy parseAssembly( 102134bec27SJames Molloy "define float @test(float %a) {\n" 103134bec27SJames Molloy " %1 = fcmp olt float %a, 5.0\n" 104134bec27SJames Molloy " %A = select i1 %1, float 5.0, float %a\n" 105134bec27SJames Molloy " ret float %A\n" 106134bec27SJames Molloy "}\n"); 107134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); 108134bec27SJames Molloy } 109134bec27SJames Molloy 110134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax3) { 111134bec27SJames Molloy parseAssembly( 112134bec27SJames Molloy "define float @test(float %a) {\n" 113134bec27SJames Molloy " %1 = fcmp ult float %a, 5.0\n" 114134bec27SJames Molloy " %A = select i1 %1, float 5.0, float %a\n" 115134bec27SJames Molloy " ret float %A\n" 116134bec27SJames Molloy "}\n"); 117134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 118134bec27SJames Molloy } 119134bec27SJames Molloy 120134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FastFMin) { 121134bec27SJames Molloy parseAssembly( 122134bec27SJames Molloy "define float @test(float %a) {\n" 123134bec27SJames Molloy " %1 = fcmp nnan olt float %a, 5.0\n" 124134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 125134bec27SJames Molloy " ret float %A\n" 126134bec27SJames Molloy "}\n"); 127134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false}); 128134bec27SJames Molloy } 129134bec27SJames Molloy 130134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZero) { 131134bec27SJames Molloy parseAssembly( 132134bec27SJames Molloy "define float @test(float %a) {\n" 133134bec27SJames Molloy " %1 = fcmp ole float %a, 0.0\n" 134134bec27SJames Molloy " %A = select i1 %1, float %a, float 0.0\n" 135134bec27SJames Molloy " ret float %A\n" 136134bec27SJames Molloy "}\n"); 137134bec27SJames Molloy // This shouldn't be matched, as %a could be -0.0. 138134bec27SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 139134bec27SJames Molloy } 140134bec27SJames Molloy 141134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) { 142134bec27SJames Molloy parseAssembly( 143134bec27SJames Molloy "define float @test(float %a) {\n" 144134bec27SJames Molloy " %1 = fcmp nsz ole float %a, 0.0\n" 145134bec27SJames Molloy " %A = select i1 %1, float %a, float 0.0\n" 146134bec27SJames Molloy " ret float %A\n" 147134bec27SJames Molloy "}\n"); 148134bec27SJames Molloy // But this should be, because we've ignored signed zeroes. 149134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 150134bec27SJames Molloy } 151569cea65SJames Molloy 152*30f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinimum) { 153d47b5c7bSThomas Lively parseAssembly( 154d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 155d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 156d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 157d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 158d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 159d47b5c7bSThomas Lively " ret <4 x float> %A\n" 160d47b5c7bSThomas Lively "}\n"); 161d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 162d47b5c7bSThomas Lively // unordered pattern. 163d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 164d47b5c7bSThomas Lively } 165d47b5c7bSThomas Lively 166d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) { 167d47b5c7bSThomas Lively parseAssembly( 168d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 169d47b5c7bSThomas Lively " %1 = fcmp ole <4 x float> %a, \n" 170d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 171d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 172d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 173d47b5c7bSThomas Lively " ret <4 x float> %A\n" 174d47b5c7bSThomas Lively "}\n"); 175d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 176d47b5c7bSThomas Lively // ordered pattern. 177d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 178d47b5c7bSThomas Lively } 179d47b5c7bSThomas Lively 180*30f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinimum) { 181d47b5c7bSThomas Lively parseAssembly( 182d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 183d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 184d47b5c7bSThomas Lively " <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n" 185d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 186d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float " 187d47b5c7bSThomas Lively "5.0>\n" 188d47b5c7bSThomas Lively " ret <4 x float> %A\n" 189d47b5c7bSThomas Lively "}\n"); 190d47b5c7bSThomas Lively // The lane that contains a NaN (0x7ff80...) behaves like a 191d47b5c7bSThomas Lively // non-NaN-propagating min and the other lines behave like a NaN-propagating 192d47b5c7bSThomas Lively // min, so check that neither is returned. 193d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 194d47b5c7bSThomas Lively } 195d47b5c7bSThomas Lively 196d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinZero) { 197d47b5c7bSThomas Lively parseAssembly( 198d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 199d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 200d47b5c7bSThomas Lively " <float 5.0, float -0.0, float 5.0, float 5.0>\n" 201d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 202d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n" 203d47b5c7bSThomas Lively " ret <4 x float> %A\n" 204d47b5c7bSThomas Lively "}\n"); 205d47b5c7bSThomas Lively // Always selects the second lane of %a if it is positive or negative zero, so 206d47b5c7bSThomas Lively // this is stricter than a min. 207d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 208d47b5c7bSThomas Lively } 209d47b5c7bSThomas Lively 210569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastU) { 211569cea65SJames Molloy parseAssembly( 212569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 213569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 214569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 215569cea65SJames Molloy " %3 = zext i8 %b to i32\n" 216569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 217569cea65SJames Molloy " ret i32 %A\n" 218569cea65SJames Molloy "}\n"); 219569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 220569cea65SJames Molloy // to the select. 221569cea65SJames Molloy expectPattern({SPF_UMIN, SPNB_NA, false}); 222569cea65SJames Molloy } 223569cea65SJames Molloy 224569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastS) { 225569cea65SJames Molloy parseAssembly( 226569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 227569cea65SJames Molloy " %1 = icmp slt i8 %a, %b\n" 228569cea65SJames Molloy " %2 = sext i8 %a to i32\n" 229569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 230569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 231569cea65SJames Molloy " ret i32 %A\n" 232569cea65SJames Molloy "}\n"); 233569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 234569cea65SJames Molloy // to the select. 235569cea65SJames Molloy expectPattern({SPF_SMIN, SPNB_NA, false}); 236569cea65SJames Molloy } 237569cea65SJames Molloy 238569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastBad) { 239569cea65SJames Molloy parseAssembly( 240569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 241569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 242569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 243569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 244569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 245569cea65SJames Molloy " ret i32 %A\n" 246569cea65SJames Molloy "}\n"); 247687a8448SJames Molloy // The cast types here aren't the same, so we cannot match an UMIN. 248569cea65SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 249569cea65SJames Molloy } 2503bb2dbd6SSanjoy Das 2513bb2dbd6SSanjoy Das TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { 2523bb2dbd6SSanjoy Das StringRef Assembly = 2533bb2dbd6SSanjoy Das "declare void @nounwind_readonly(i32*) nounwind readonly " 2543bb2dbd6SSanjoy Das "declare void @nounwind_argmemonly(i32*) nounwind argmemonly " 2553bb2dbd6SSanjoy Das "declare void @throws_but_readonly(i32*) readonly " 2563bb2dbd6SSanjoy Das "declare void @throws_but_argmemonly(i32*) argmemonly " 2573bb2dbd6SSanjoy Das " " 2583bb2dbd6SSanjoy Das "declare void @unknown(i32*) " 2593bb2dbd6SSanjoy Das " " 2603bb2dbd6SSanjoy Das "define void @f(i32* %p) { " 2613bb2dbd6SSanjoy Das " call void @nounwind_readonly(i32* %p) " 2623bb2dbd6SSanjoy Das " call void @nounwind_argmemonly(i32* %p) " 2633bb2dbd6SSanjoy Das " call void @throws_but_readonly(i32* %p) " 2643bb2dbd6SSanjoy Das " call void @throws_but_argmemonly(i32* %p) " 2653bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind readonly " 2663bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind argmemonly " 2673bb2dbd6SSanjoy Das " call void @unknown(i32* %p) readonly " 2683bb2dbd6SSanjoy Das " call void @unknown(i32* %p) argmemonly " 2693bb2dbd6SSanjoy Das " ret void " 2703bb2dbd6SSanjoy Das "} "; 2713bb2dbd6SSanjoy Das 2723bb2dbd6SSanjoy Das LLVMContext Context; 2733bb2dbd6SSanjoy Das SMDiagnostic Error; 2743bb2dbd6SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 2753bb2dbd6SSanjoy Das assert(M && "Bad assembly?"); 2763bb2dbd6SSanjoy Das 2773bb2dbd6SSanjoy Das auto *F = M->getFunction("f"); 2783bb2dbd6SSanjoy Das assert(F && "Bad assembly?"); 2793bb2dbd6SSanjoy Das 2803bb2dbd6SSanjoy Das auto &BB = F->getEntryBlock(); 2818580cd4eSCraig Topper bool ExpectedAnswers[] = { 2823bb2dbd6SSanjoy Das true, // call void @nounwind_readonly(i32* %p) 2833bb2dbd6SSanjoy Das true, // call void @nounwind_argmemonly(i32* %p) 2843bb2dbd6SSanjoy Das false, // call void @throws_but_readonly(i32* %p) 2853bb2dbd6SSanjoy Das false, // call void @throws_but_argmemonly(i32* %p) 2863bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind readonly 2873bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind argmemonly 2883bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) readonly 2893bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) argmemonly 2903bb2dbd6SSanjoy Das false, // ret void 2913bb2dbd6SSanjoy Das }; 2923bb2dbd6SSanjoy Das 2933bb2dbd6SSanjoy Das int Index = 0; 2943bb2dbd6SSanjoy Das for (auto &I : BB) { 2953bb2dbd6SSanjoy Das EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I), 2963bb2dbd6SSanjoy Das ExpectedAnswers[Index]) 2973bb2dbd6SSanjoy Das << "Incorrect answer at instruction " << Index << " = " << I; 2983bb2dbd6SSanjoy Das Index++; 2993bb2dbd6SSanjoy Das } 3003bb2dbd6SSanjoy Das } 30139a684d1SSanjoy Das 30239a684d1SSanjoy Das TEST(ValueTracking, ComputeNumSignBits_PR32045) { 30339a684d1SSanjoy Das StringRef Assembly = "define i32 @f(i32 %a) { " 30439a684d1SSanjoy Das " %val = ashr i32 %a, -1 " 30539a684d1SSanjoy Das " ret i32 %val " 30639a684d1SSanjoy Das "} "; 30739a684d1SSanjoy Das 30839a684d1SSanjoy Das LLVMContext Context; 30939a684d1SSanjoy Das SMDiagnostic Error; 31039a684d1SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 31139a684d1SSanjoy Das assert(M && "Bad assembly?"); 31239a684d1SSanjoy Das 31339a684d1SSanjoy Das auto *F = M->getFunction("f"); 31439a684d1SSanjoy Das assert(F && "Bad assembly?"); 31539a684d1SSanjoy Das 31639a684d1SSanjoy Das auto *RVal = 31739a684d1SSanjoy Das cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 3184897cea4SSanjoy Das EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 31939a684d1SSanjoy Das } 32070dbd5fbSSimon Dardis 32170dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownBits) { 32270dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 32370dbd5fbSSimon Dardis " %ash = mul i32 %a, 8 " 32470dbd5fbSSimon Dardis " %aad = add i32 %ash, 7 " 32570dbd5fbSSimon Dardis " %aan = and i32 %aad, 4095 " 32670dbd5fbSSimon Dardis " %bsh = shl i32 %b, 4 " 32770dbd5fbSSimon Dardis " %bad = or i32 %bsh, 6 " 32870dbd5fbSSimon Dardis " %ban = and i32 %bad, 4095 " 32970dbd5fbSSimon Dardis " %mul = mul i32 %aan, %ban " 33070dbd5fbSSimon Dardis " ret i32 %mul " 33170dbd5fbSSimon Dardis "} "; 33270dbd5fbSSimon Dardis 33370dbd5fbSSimon Dardis LLVMContext Context; 33470dbd5fbSSimon Dardis SMDiagnostic Error; 33570dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 33670dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 33770dbd5fbSSimon Dardis 33870dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 33970dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 34070dbd5fbSSimon Dardis 34170dbd5fbSSimon Dardis auto *RVal = 34270dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 34370dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 34470dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 34570dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 10u); 34670dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 4278190085u); 34770dbd5fbSSimon Dardis } 34870dbd5fbSSimon Dardis 34970dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownMulBits) { 35070dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 35170dbd5fbSSimon Dardis " %aa = shl i32 %a, 5 " 35270dbd5fbSSimon Dardis " %bb = shl i32 %b, 5 " 35370dbd5fbSSimon Dardis " %aaa = or i32 %aa, 24 " 35470dbd5fbSSimon Dardis " %bbb = or i32 %bb, 28 " 35570dbd5fbSSimon Dardis " %mul = mul i32 %aaa, %bbb " 35670dbd5fbSSimon Dardis " ret i32 %mul " 35770dbd5fbSSimon Dardis "} "; 35870dbd5fbSSimon Dardis 35970dbd5fbSSimon Dardis LLVMContext Context; 36070dbd5fbSSimon Dardis SMDiagnostic Error; 36170dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 36270dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 36370dbd5fbSSimon Dardis 36470dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 36570dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 36670dbd5fbSSimon Dardis 36770dbd5fbSSimon Dardis auto *RVal = 36870dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 36970dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 37070dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 37170dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 32u); 37270dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 95u); 37370dbd5fbSSimon Dardis } 374