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" 18134bec27SJames Molloy #include "gtest/gtest.h" 19134bec27SJames Molloy 20134bec27SJames Molloy using namespace llvm; 21134bec27SJames Molloy 22134bec27SJames Molloy namespace { 23134bec27SJames Molloy 24134bec27SJames Molloy class MatchSelectPatternTest : public testing::Test { 25134bec27SJames Molloy protected: 26134bec27SJames Molloy void parseAssembly(const char *Assembly) { 27134bec27SJames Molloy SMDiagnostic Error; 2803b42e41SMehdi Amini M = parseAssemblyString(Assembly, Error, Context); 29134bec27SJames Molloy 30134bec27SJames Molloy std::string errMsg; 31134bec27SJames Molloy raw_string_ostream os(errMsg); 32134bec27SJames Molloy Error.print("", os); 33134bec27SJames Molloy 34134bec27SJames Molloy // A failure here means that the test itself is buggy. 35134bec27SJames Molloy if (!M) 36134bec27SJames Molloy report_fatal_error(os.str()); 37134bec27SJames Molloy 38134bec27SJames Molloy Function *F = M->getFunction("test"); 39134bec27SJames Molloy if (F == nullptr) 40134bec27SJames Molloy report_fatal_error("Test must have a function named @test"); 41134bec27SJames Molloy 42134bec27SJames Molloy A = nullptr; 43134bec27SJames Molloy for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) { 44134bec27SJames Molloy if (I->hasName()) { 45134bec27SJames Molloy if (I->getName() == "A") 46134bec27SJames Molloy A = &*I; 47134bec27SJames Molloy } 48134bec27SJames Molloy } 49134bec27SJames Molloy if (A == nullptr) 50134bec27SJames Molloy report_fatal_error("@test must have an instruction %A"); 51134bec27SJames Molloy } 52134bec27SJames Molloy 53134bec27SJames Molloy void expectPattern(const SelectPatternResult &P) { 54134bec27SJames Molloy Value *LHS, *RHS; 55134bec27SJames Molloy Instruction::CastOps CastOp; 56134bec27SJames Molloy SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp); 57134bec27SJames Molloy EXPECT_EQ(P.Flavor, R.Flavor); 58134bec27SJames Molloy EXPECT_EQ(P.NaNBehavior, R.NaNBehavior); 59134bec27SJames Molloy EXPECT_EQ(P.Ordered, R.Ordered); 60134bec27SJames Molloy } 61134bec27SJames Molloy 6203b42e41SMehdi Amini LLVMContext Context; 63134bec27SJames Molloy std::unique_ptr<Module> M; 64134bec27SJames Molloy Instruction *A, *B; 65134bec27SJames Molloy }; 66134bec27SJames Molloy 67134bec27SJames Molloy } 68134bec27SJames Molloy 69134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMin) { 70134bec27SJames Molloy parseAssembly( 71134bec27SJames Molloy "define float @test(float %a) {\n" 72134bec27SJames Molloy " %1 = fcmp ult float %a, 5.0\n" 73134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 74134bec27SJames Molloy " ret float %A\n" 75134bec27SJames Molloy "}\n"); 76134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 77134bec27SJames Molloy } 78134bec27SJames Molloy 79134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SimpleFMax) { 80134bec27SJames Molloy parseAssembly( 81134bec27SJames Molloy "define float @test(float %a) {\n" 82134bec27SJames Molloy " %1 = fcmp ogt float %a, 5.0\n" 83134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 84134bec27SJames Molloy " ret float %A\n" 85134bec27SJames Molloy "}\n"); 86134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 87134bec27SJames Molloy } 88134bec27SJames Molloy 89134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax) { 90134bec27SJames Molloy parseAssembly( 91134bec27SJames Molloy "define float @test(float %a) {\n" 92134bec27SJames Molloy " %1 = fcmp olt float 5.0, %a\n" 93134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 94134bec27SJames Molloy " ret float %A\n" 95134bec27SJames Molloy "}\n"); 96134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); 97134bec27SJames Molloy } 98134bec27SJames Molloy 99134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax2) { 100134bec27SJames Molloy parseAssembly( 101134bec27SJames Molloy "define float @test(float %a) {\n" 102134bec27SJames Molloy " %1 = fcmp olt float %a, 5.0\n" 103134bec27SJames Molloy " %A = select i1 %1, float 5.0, float %a\n" 104134bec27SJames Molloy " ret float %A\n" 105134bec27SJames Molloy "}\n"); 106134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); 107134bec27SJames Molloy } 108134bec27SJames Molloy 109134bec27SJames Molloy TEST_F(MatchSelectPatternTest, SwappedFMax3) { 110134bec27SJames Molloy parseAssembly( 111134bec27SJames Molloy "define float @test(float %a) {\n" 112134bec27SJames Molloy " %1 = fcmp ult float %a, 5.0\n" 113134bec27SJames Molloy " %A = select i1 %1, float 5.0, float %a\n" 114134bec27SJames Molloy " ret float %A\n" 115134bec27SJames Molloy "}\n"); 116134bec27SJames Molloy expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 117134bec27SJames Molloy } 118134bec27SJames Molloy 119134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FastFMin) { 120134bec27SJames Molloy parseAssembly( 121134bec27SJames Molloy "define float @test(float %a) {\n" 122134bec27SJames Molloy " %1 = fcmp nnan olt float %a, 5.0\n" 123134bec27SJames Molloy " %A = select i1 %1, float %a, float 5.0\n" 124134bec27SJames Molloy " ret float %A\n" 125134bec27SJames Molloy "}\n"); 126134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false}); 127134bec27SJames Molloy } 128134bec27SJames Molloy 129134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZero) { 130134bec27SJames Molloy parseAssembly( 131134bec27SJames Molloy "define float @test(float %a) {\n" 132134bec27SJames Molloy " %1 = fcmp ole float %a, 0.0\n" 133134bec27SJames Molloy " %A = select i1 %1, float %a, float 0.0\n" 134134bec27SJames Molloy " ret float %A\n" 135134bec27SJames Molloy "}\n"); 136134bec27SJames Molloy // This shouldn't be matched, as %a could be -0.0. 137134bec27SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 138134bec27SJames Molloy } 139134bec27SJames Molloy 140134bec27SJames Molloy TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) { 141134bec27SJames Molloy parseAssembly( 142134bec27SJames Molloy "define float @test(float %a) {\n" 143134bec27SJames Molloy " %1 = fcmp nsz ole float %a, 0.0\n" 144134bec27SJames Molloy " %A = select i1 %1, float %a, float 0.0\n" 145134bec27SJames Molloy " ret float %A\n" 146134bec27SJames Molloy "}\n"); 147134bec27SJames Molloy // But this should be, because we've ignored signed zeroes. 148134bec27SJames Molloy expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 149134bec27SJames Molloy } 150569cea65SJames Molloy 151569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastU) { 152569cea65SJames Molloy parseAssembly( 153569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 154569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 155569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 156569cea65SJames Molloy " %3 = zext i8 %b to i32\n" 157569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 158569cea65SJames Molloy " ret i32 %A\n" 159569cea65SJames Molloy "}\n"); 160569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 161569cea65SJames Molloy // to the select. 162569cea65SJames Molloy expectPattern({SPF_UMIN, SPNB_NA, false}); 163569cea65SJames Molloy } 164569cea65SJames Molloy 165569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastS) { 166569cea65SJames Molloy parseAssembly( 167569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 168569cea65SJames Molloy " %1 = icmp slt i8 %a, %b\n" 169569cea65SJames Molloy " %2 = sext i8 %a to i32\n" 170569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 171569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 172569cea65SJames Molloy " ret i32 %A\n" 173569cea65SJames Molloy "}\n"); 174569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 175569cea65SJames Molloy // to the select. 176569cea65SJames Molloy expectPattern({SPF_SMIN, SPNB_NA, false}); 177569cea65SJames Molloy } 178569cea65SJames Molloy 179569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastBad) { 180569cea65SJames Molloy parseAssembly( 181569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 182569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 183569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 184569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 185569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 186569cea65SJames Molloy " ret i32 %A\n" 187569cea65SJames Molloy "}\n"); 188687a8448SJames Molloy // The cast types here aren't the same, so we cannot match an UMIN. 189569cea65SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 190569cea65SJames Molloy } 1913bb2dbd6SSanjoy Das 1923bb2dbd6SSanjoy Das TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { 1933bb2dbd6SSanjoy Das StringRef Assembly = 1943bb2dbd6SSanjoy Das "declare void @nounwind_readonly(i32*) nounwind readonly " 1953bb2dbd6SSanjoy Das "declare void @nounwind_argmemonly(i32*) nounwind argmemonly " 1963bb2dbd6SSanjoy Das "declare void @throws_but_readonly(i32*) readonly " 1973bb2dbd6SSanjoy Das "declare void @throws_but_argmemonly(i32*) argmemonly " 1983bb2dbd6SSanjoy Das " " 1993bb2dbd6SSanjoy Das "declare void @unknown(i32*) " 2003bb2dbd6SSanjoy Das " " 2013bb2dbd6SSanjoy Das "define void @f(i32* %p) { " 2023bb2dbd6SSanjoy Das " call void @nounwind_readonly(i32* %p) " 2033bb2dbd6SSanjoy Das " call void @nounwind_argmemonly(i32* %p) " 2043bb2dbd6SSanjoy Das " call void @throws_but_readonly(i32* %p) " 2053bb2dbd6SSanjoy Das " call void @throws_but_argmemonly(i32* %p) " 2063bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind readonly " 2073bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind argmemonly " 2083bb2dbd6SSanjoy Das " call void @unknown(i32* %p) readonly " 2093bb2dbd6SSanjoy Das " call void @unknown(i32* %p) argmemonly " 2103bb2dbd6SSanjoy Das " ret void " 2113bb2dbd6SSanjoy Das "} "; 2123bb2dbd6SSanjoy Das 2133bb2dbd6SSanjoy Das LLVMContext Context; 2143bb2dbd6SSanjoy Das SMDiagnostic Error; 2153bb2dbd6SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 2163bb2dbd6SSanjoy Das assert(M && "Bad assembly?"); 2173bb2dbd6SSanjoy Das 2183bb2dbd6SSanjoy Das auto *F = M->getFunction("f"); 2193bb2dbd6SSanjoy Das assert(F && "Bad assembly?"); 2203bb2dbd6SSanjoy Das 2213bb2dbd6SSanjoy Das auto &BB = F->getEntryBlock(); 2223bb2dbd6SSanjoy Das ArrayRef<bool> ExpectedAnswers = { 2233bb2dbd6SSanjoy Das true, // call void @nounwind_readonly(i32* %p) 2243bb2dbd6SSanjoy Das true, // call void @nounwind_argmemonly(i32* %p) 2253bb2dbd6SSanjoy Das false, // call void @throws_but_readonly(i32* %p) 2263bb2dbd6SSanjoy Das false, // call void @throws_but_argmemonly(i32* %p) 2273bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind readonly 2283bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind argmemonly 2293bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) readonly 2303bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) argmemonly 2313bb2dbd6SSanjoy Das false, // ret void 2323bb2dbd6SSanjoy Das }; 2333bb2dbd6SSanjoy Das 2343bb2dbd6SSanjoy Das int Index = 0; 2353bb2dbd6SSanjoy Das for (auto &I : BB) { 2363bb2dbd6SSanjoy Das EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I), 2373bb2dbd6SSanjoy Das ExpectedAnswers[Index]) 2383bb2dbd6SSanjoy Das << "Incorrect answer at instruction " << Index << " = " << I; 2393bb2dbd6SSanjoy Das Index++; 2403bb2dbd6SSanjoy Das } 2413bb2dbd6SSanjoy Das } 242*39a684d1SSanjoy Das 243*39a684d1SSanjoy Das TEST(ValueTracking, ComputeNumSignBits_PR32045) { 244*39a684d1SSanjoy Das StringRef Assembly = "define i32 @f(i32 %a) { " 245*39a684d1SSanjoy Das " %val = ashr i32 %a, -1 " 246*39a684d1SSanjoy Das " ret i32 %val " 247*39a684d1SSanjoy Das "} "; 248*39a684d1SSanjoy Das 249*39a684d1SSanjoy Das LLVMContext Context; 250*39a684d1SSanjoy Das SMDiagnostic Error; 251*39a684d1SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 252*39a684d1SSanjoy Das assert(M && "Bad assembly?"); 253*39a684d1SSanjoy Das 254*39a684d1SSanjoy Das auto *F = M->getFunction("f"); 255*39a684d1SSanjoy Das assert(F && "Bad assembly?"); 256*39a684d1SSanjoy Das 257*39a684d1SSanjoy Das auto *RVal = 258*39a684d1SSanjoy Das cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 259*39a684d1SSanjoy Das EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1); 260*39a684d1SSanjoy Das } 261