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 15203da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero1) { 15303da6e6aSSanjay Patel parseAssembly( 15403da6e6aSSanjay Patel "define float @test(float %a) {\n" 15503da6e6aSSanjay Patel " %1 = fcmp olt float -0.0, %a\n" 15603da6e6aSSanjay Patel " %A = select i1 %1, float 0.0, float %a\n" 15703da6e6aSSanjay Patel " ret float %A\n" 15803da6e6aSSanjay Patel "}\n"); 159*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 160*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true}); 16103da6e6aSSanjay Patel } 16203da6e6aSSanjay Patel 16303da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero2) { 16403da6e6aSSanjay Patel parseAssembly( 16503da6e6aSSanjay Patel "define float @test(float %a) {\n" 16603da6e6aSSanjay Patel " %1 = fcmp ogt float %a, -0.0\n" 16703da6e6aSSanjay Patel " %A = select i1 %1, float 0.0, float %a\n" 16803da6e6aSSanjay Patel " ret float %A\n" 16903da6e6aSSanjay Patel "}\n"); 170*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 171*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 17203da6e6aSSanjay Patel } 17303da6e6aSSanjay Patel 17403da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero3) { 17503da6e6aSSanjay Patel parseAssembly( 17603da6e6aSSanjay Patel "define float @test(float %a) {\n" 17703da6e6aSSanjay Patel " %1 = fcmp olt float 0.0, %a\n" 17803da6e6aSSanjay Patel " %A = select i1 %1, float -0.0, float %a\n" 17903da6e6aSSanjay Patel " ret float %A\n" 18003da6e6aSSanjay Patel "}\n"); 181*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 182*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, true}); 18303da6e6aSSanjay Patel } 18403da6e6aSSanjay Patel 18503da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero4) { 18603da6e6aSSanjay Patel parseAssembly( 18703da6e6aSSanjay Patel "define float @test(float %a) {\n" 18803da6e6aSSanjay Patel " %1 = fcmp ogt float %a, 0.0\n" 18903da6e6aSSanjay Patel " %A = select i1 %1, float -0.0, float %a\n" 19003da6e6aSSanjay Patel " ret float %A\n" 19103da6e6aSSanjay Patel "}\n"); 192*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 193*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 19403da6e6aSSanjay Patel } 19503da6e6aSSanjay Patel 19603da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero5) { 19703da6e6aSSanjay Patel parseAssembly( 19803da6e6aSSanjay Patel "define float @test(float %a) {\n" 19903da6e6aSSanjay Patel " %1 = fcmp ogt float -0.0, %a\n" 20003da6e6aSSanjay Patel " %A = select i1 %1, float %a, float 0.0\n" 20103da6e6aSSanjay Patel " ret float %A\n" 20203da6e6aSSanjay Patel "}\n"); 203*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 204*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false}); 20503da6e6aSSanjay Patel } 20603da6e6aSSanjay Patel 20703da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero6) { 20803da6e6aSSanjay Patel parseAssembly( 20903da6e6aSSanjay Patel "define float @test(float %a) {\n" 21003da6e6aSSanjay Patel " %1 = fcmp olt float %a, -0.0\n" 21103da6e6aSSanjay Patel " %A = select i1 %1, float %a, float 0.0\n" 21203da6e6aSSanjay Patel " ret float %A\n" 21303da6e6aSSanjay Patel "}\n"); 214*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 215*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 21603da6e6aSSanjay Patel } 21703da6e6aSSanjay Patel 21803da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero7) { 21903da6e6aSSanjay Patel parseAssembly( 22003da6e6aSSanjay Patel "define float @test(float %a) {\n" 22103da6e6aSSanjay Patel " %1 = fcmp ogt float 0.0, %a\n" 22203da6e6aSSanjay Patel " %A = select i1 %1, float %a, float -0.0\n" 22303da6e6aSSanjay Patel " ret float %A\n" 22403da6e6aSSanjay Patel "}\n"); 225*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 226*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, false}); 22703da6e6aSSanjay Patel } 22803da6e6aSSanjay Patel 22903da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZero8) { 23003da6e6aSSanjay Patel parseAssembly( 23103da6e6aSSanjay Patel "define float @test(float %a) {\n" 23203da6e6aSSanjay Patel " %1 = fcmp olt float %a, 0.0\n" 23303da6e6aSSanjay Patel " %A = select i1 %1, float %a, float -0.0\n" 23403da6e6aSSanjay Patel " ret float %A\n" 23503da6e6aSSanjay Patel "}\n"); 236*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 237*e7c94ef1SSanjay Patel expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 23803da6e6aSSanjay Patel } 23903da6e6aSSanjay Patel 24003da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero1) { 24103da6e6aSSanjay Patel parseAssembly( 24203da6e6aSSanjay Patel "define float @test(float %a) {\n" 24303da6e6aSSanjay Patel " %1 = fcmp ogt float -0.0, %a\n" 24403da6e6aSSanjay Patel " %A = select i1 %1, float 0.0, float %a\n" 24503da6e6aSSanjay Patel " ret float %A\n" 24603da6e6aSSanjay Patel "}\n"); 247*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 248*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true}); 24903da6e6aSSanjay Patel } 25003da6e6aSSanjay Patel 25103da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero2) { 25203da6e6aSSanjay Patel parseAssembly( 25303da6e6aSSanjay Patel "define float @test(float %a) {\n" 25403da6e6aSSanjay Patel " %1 = fcmp olt float %a, -0.0\n" 25503da6e6aSSanjay Patel " %A = select i1 %1, float 0.0, float %a\n" 25603da6e6aSSanjay Patel " ret float %A\n" 25703da6e6aSSanjay Patel "}\n"); 258*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 259*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); 26003da6e6aSSanjay Patel } 26103da6e6aSSanjay Patel 26203da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero3) { 26303da6e6aSSanjay Patel parseAssembly( 26403da6e6aSSanjay Patel "define float @test(float %a) {\n" 26503da6e6aSSanjay Patel " %1 = fcmp ogt float 0.0, %a\n" 26603da6e6aSSanjay Patel " %A = select i1 %1, float -0.0, float %a\n" 26703da6e6aSSanjay Patel " ret float %A\n" 26803da6e6aSSanjay Patel "}\n"); 269*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 270*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, true}); 27103da6e6aSSanjay Patel } 27203da6e6aSSanjay Patel 27303da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero4) { 27403da6e6aSSanjay Patel parseAssembly( 27503da6e6aSSanjay Patel "define float @test(float %a) {\n" 27603da6e6aSSanjay Patel " %1 = fcmp olt float %a, 0.0\n" 27703da6e6aSSanjay Patel " %A = select i1 %1, float -0.0, float %a\n" 27803da6e6aSSanjay Patel " ret float %A\n" 27903da6e6aSSanjay Patel "}\n"); 280*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 281*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false}); 28203da6e6aSSanjay Patel } 28303da6e6aSSanjay Patel 28403da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero5) { 28503da6e6aSSanjay Patel parseAssembly( 28603da6e6aSSanjay Patel "define float @test(float %a) {\n" 28703da6e6aSSanjay Patel " %1 = fcmp olt float -0.0, %a\n" 28803da6e6aSSanjay Patel " %A = select i1 %1, float %a, float 0.0\n" 28903da6e6aSSanjay Patel " ret float %A\n" 29003da6e6aSSanjay Patel "}\n"); 291*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 292*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); 29303da6e6aSSanjay Patel } 29403da6e6aSSanjay Patel 29503da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero6) { 29603da6e6aSSanjay Patel parseAssembly( 29703da6e6aSSanjay Patel "define float @test(float %a) {\n" 29803da6e6aSSanjay Patel " %1 = fcmp ogt float %a, -0.0\n" 29903da6e6aSSanjay Patel " %A = select i1 %1, float %a, float 0.0\n" 30003da6e6aSSanjay Patel " ret float %A\n" 30103da6e6aSSanjay Patel "}\n"); 302*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 303*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 30403da6e6aSSanjay Patel } 30503da6e6aSSanjay Patel 30603da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero7) { 30703da6e6aSSanjay Patel parseAssembly( 30803da6e6aSSanjay Patel "define float @test(float %a) {\n" 30903da6e6aSSanjay Patel " %1 = fcmp olt float 0.0, %a\n" 31003da6e6aSSanjay Patel " %A = select i1 %1, float %a, float -0.0\n" 31103da6e6aSSanjay Patel " ret float %A\n" 31203da6e6aSSanjay Patel "}\n"); 313*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 314*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false}); 31503da6e6aSSanjay Patel } 31603da6e6aSSanjay Patel 31703da6e6aSSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZero8) { 31803da6e6aSSanjay Patel parseAssembly( 31903da6e6aSSanjay Patel "define float @test(float %a) {\n" 32003da6e6aSSanjay Patel " %1 = fcmp ogt float %a, 0.0\n" 32103da6e6aSSanjay Patel " %A = select i1 %1, float %a, float -0.0\n" 32203da6e6aSSanjay Patel " ret float %A\n" 32303da6e6aSSanjay Patel "}\n"); 324*e7c94ef1SSanjay Patel // The sign of zero doesn't matter in fcmp. 325*e7c94ef1SSanjay Patel expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true}); 326*e7c94ef1SSanjay Patel } 327*e7c94ef1SSanjay Patel 328*e7c94ef1SSanjay Patel TEST_F(MatchSelectPatternTest, FMinMismatchConstantZeroVecUndef) { 329*e7c94ef1SSanjay Patel parseAssembly( 330*e7c94ef1SSanjay Patel "define <2 x float> @test(<2 x float> %a) {\n" 331*e7c94ef1SSanjay Patel " %1 = fcmp ogt <2 x float> %a, <float -0.0, float -0.0>\n" 332*e7c94ef1SSanjay Patel " %A = select <2 x i1> %1, <2 x float> <float undef, float 0.0>, <2 x float> %a\n" 333*e7c94ef1SSanjay Patel " ret <2 x float> %A\n" 334*e7c94ef1SSanjay Patel "}\n"); 335*e7c94ef1SSanjay Patel // An undef in a vector constant can not be back-propagated for this analysis. 336*e7c94ef1SSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 337*e7c94ef1SSanjay Patel } 338*e7c94ef1SSanjay Patel 339*e7c94ef1SSanjay Patel TEST_F(MatchSelectPatternTest, FMaxMismatchConstantZeroVecUndef) { 340*e7c94ef1SSanjay Patel parseAssembly( 341*e7c94ef1SSanjay Patel "define <2 x float> @test(<2 x float> %a) {\n" 342*e7c94ef1SSanjay Patel " %1 = fcmp ogt <2 x float> %a, zeroinitializer\n" 343*e7c94ef1SSanjay Patel " %A = select <2 x i1> %1, <2 x float> %a, <2 x float> <float -0.0, float undef>\n" 344*e7c94ef1SSanjay Patel " ret <2 x float> %A\n" 345*e7c94ef1SSanjay Patel "}\n"); 346*e7c94ef1SSanjay Patel // An undef in a vector constant can not be back-propagated for this analysis. 34703da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 34803da6e6aSSanjay Patel } 34903da6e6aSSanjay Patel 35030f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinimum) { 351d47b5c7bSThomas Lively parseAssembly( 352d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 353d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 354d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 355d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 356d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 357d47b5c7bSThomas Lively " ret <4 x float> %A\n" 358d47b5c7bSThomas Lively "}\n"); 359d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 360d47b5c7bSThomas Lively // unordered pattern. 361d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 362d47b5c7bSThomas Lively } 363d47b5c7bSThomas Lively 364d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) { 365d47b5c7bSThomas Lively parseAssembly( 366d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 367d47b5c7bSThomas Lively " %1 = fcmp ole <4 x float> %a, \n" 368d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 369d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 370d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 371d47b5c7bSThomas Lively " ret <4 x float> %A\n" 372d47b5c7bSThomas Lively "}\n"); 373d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 374d47b5c7bSThomas Lively // ordered pattern. 375d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 376d47b5c7bSThomas Lively } 377d47b5c7bSThomas Lively 37830f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinimum) { 379d47b5c7bSThomas Lively parseAssembly( 380d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 381d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 382d47b5c7bSThomas Lively " <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n" 383d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 384d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float " 385d47b5c7bSThomas Lively "5.0>\n" 386d47b5c7bSThomas Lively " ret <4 x float> %A\n" 387d47b5c7bSThomas Lively "}\n"); 388d47b5c7bSThomas Lively // The lane that contains a NaN (0x7ff80...) behaves like a 389d47b5c7bSThomas Lively // non-NaN-propagating min and the other lines behave like a NaN-propagating 390d47b5c7bSThomas Lively // min, so check that neither is returned. 391d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 392d47b5c7bSThomas Lively } 393d47b5c7bSThomas Lively 394d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinZero) { 395d47b5c7bSThomas Lively parseAssembly( 396d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 397d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 398d47b5c7bSThomas Lively " <float 5.0, float -0.0, float 5.0, float 5.0>\n" 399d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 400d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n" 401d47b5c7bSThomas Lively " ret <4 x float> %A\n" 402d47b5c7bSThomas Lively "}\n"); 403d47b5c7bSThomas Lively // Always selects the second lane of %a if it is positive or negative zero, so 404d47b5c7bSThomas Lively // this is stricter than a min. 405d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 406d47b5c7bSThomas Lively } 407d47b5c7bSThomas Lively 408569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastU) { 409569cea65SJames Molloy parseAssembly( 410569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 411569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 412569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 413569cea65SJames Molloy " %3 = zext i8 %b to i32\n" 414569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 415569cea65SJames Molloy " ret i32 %A\n" 416569cea65SJames Molloy "}\n"); 417569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 418569cea65SJames Molloy // to the select. 419569cea65SJames Molloy expectPattern({SPF_UMIN, SPNB_NA, false}); 420569cea65SJames Molloy } 421569cea65SJames Molloy 422569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastS) { 423569cea65SJames Molloy parseAssembly( 424569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 425569cea65SJames Molloy " %1 = icmp slt i8 %a, %b\n" 426569cea65SJames Molloy " %2 = sext i8 %a to i32\n" 427569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 428569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 429569cea65SJames Molloy " ret i32 %A\n" 430569cea65SJames Molloy "}\n"); 431569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 432569cea65SJames Molloy // to the select. 433569cea65SJames Molloy expectPattern({SPF_SMIN, SPNB_NA, false}); 434569cea65SJames Molloy } 435569cea65SJames Molloy 436569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastBad) { 437569cea65SJames Molloy parseAssembly( 438569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 439569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 440569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 441569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 442569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 443569cea65SJames Molloy " ret i32 %A\n" 444569cea65SJames Molloy "}\n"); 445687a8448SJames Molloy // The cast types here aren't the same, so we cannot match an UMIN. 446569cea65SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 447569cea65SJames Molloy } 4483bb2dbd6SSanjoy Das 4493bb2dbd6SSanjoy Das TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { 4503bb2dbd6SSanjoy Das StringRef Assembly = 4513bb2dbd6SSanjoy Das "declare void @nounwind_readonly(i32*) nounwind readonly " 4523bb2dbd6SSanjoy Das "declare void @nounwind_argmemonly(i32*) nounwind argmemonly " 4533bb2dbd6SSanjoy Das "declare void @throws_but_readonly(i32*) readonly " 4543bb2dbd6SSanjoy Das "declare void @throws_but_argmemonly(i32*) argmemonly " 4553bb2dbd6SSanjoy Das " " 4563bb2dbd6SSanjoy Das "declare void @unknown(i32*) " 4573bb2dbd6SSanjoy Das " " 4583bb2dbd6SSanjoy Das "define void @f(i32* %p) { " 4593bb2dbd6SSanjoy Das " call void @nounwind_readonly(i32* %p) " 4603bb2dbd6SSanjoy Das " call void @nounwind_argmemonly(i32* %p) " 4613bb2dbd6SSanjoy Das " call void @throws_but_readonly(i32* %p) " 4623bb2dbd6SSanjoy Das " call void @throws_but_argmemonly(i32* %p) " 4633bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind readonly " 4643bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind argmemonly " 4653bb2dbd6SSanjoy Das " call void @unknown(i32* %p) readonly " 4663bb2dbd6SSanjoy Das " call void @unknown(i32* %p) argmemonly " 4673bb2dbd6SSanjoy Das " ret void " 4683bb2dbd6SSanjoy Das "} "; 4693bb2dbd6SSanjoy Das 4703bb2dbd6SSanjoy Das LLVMContext Context; 4713bb2dbd6SSanjoy Das SMDiagnostic Error; 4723bb2dbd6SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 4733bb2dbd6SSanjoy Das assert(M && "Bad assembly?"); 4743bb2dbd6SSanjoy Das 4753bb2dbd6SSanjoy Das auto *F = M->getFunction("f"); 4763bb2dbd6SSanjoy Das assert(F && "Bad assembly?"); 4773bb2dbd6SSanjoy Das 4783bb2dbd6SSanjoy Das auto &BB = F->getEntryBlock(); 4798580cd4eSCraig Topper bool ExpectedAnswers[] = { 4803bb2dbd6SSanjoy Das true, // call void @nounwind_readonly(i32* %p) 4813bb2dbd6SSanjoy Das true, // call void @nounwind_argmemonly(i32* %p) 4823bb2dbd6SSanjoy Das false, // call void @throws_but_readonly(i32* %p) 4833bb2dbd6SSanjoy Das false, // call void @throws_but_argmemonly(i32* %p) 4843bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind readonly 4853bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind argmemonly 4863bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) readonly 4873bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) argmemonly 4883bb2dbd6SSanjoy Das false, // ret void 4893bb2dbd6SSanjoy Das }; 4903bb2dbd6SSanjoy Das 4913bb2dbd6SSanjoy Das int Index = 0; 4923bb2dbd6SSanjoy Das for (auto &I : BB) { 4933bb2dbd6SSanjoy Das EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I), 4943bb2dbd6SSanjoy Das ExpectedAnswers[Index]) 4953bb2dbd6SSanjoy Das << "Incorrect answer at instruction " << Index << " = " << I; 4963bb2dbd6SSanjoy Das Index++; 4973bb2dbd6SSanjoy Das } 4983bb2dbd6SSanjoy Das } 49939a684d1SSanjoy Das 50039a684d1SSanjoy Das TEST(ValueTracking, ComputeNumSignBits_PR32045) { 50139a684d1SSanjoy Das StringRef Assembly = "define i32 @f(i32 %a) { " 50239a684d1SSanjoy Das " %val = ashr i32 %a, -1 " 50339a684d1SSanjoy Das " ret i32 %val " 50439a684d1SSanjoy Das "} "; 50539a684d1SSanjoy Das 50639a684d1SSanjoy Das LLVMContext Context; 50739a684d1SSanjoy Das SMDiagnostic Error; 50839a684d1SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 50939a684d1SSanjoy Das assert(M && "Bad assembly?"); 51039a684d1SSanjoy Das 51139a684d1SSanjoy Das auto *F = M->getFunction("f"); 51239a684d1SSanjoy Das assert(F && "Bad assembly?"); 51339a684d1SSanjoy Das 51439a684d1SSanjoy Das auto *RVal = 51539a684d1SSanjoy Das cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 5164897cea4SSanjoy Das EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 51739a684d1SSanjoy Das } 51870dbd5fbSSimon Dardis 519a68096c7SSanjay Patel // No guarantees for canonical IR in this analysis, so this just bails out. 520a68096c7SSanjay Patel TEST(ValueTracking, ComputeNumSignBits_Shuffle) { 521a68096c7SSanjay Patel StringRef Assembly = "define <2 x i32> @f() { " 522a68096c7SSanjay Patel " %val = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0> " 523a68096c7SSanjay Patel " ret <2 x i32> %val " 524a68096c7SSanjay Patel "} "; 525a68096c7SSanjay Patel 526a68096c7SSanjay Patel LLVMContext Context; 527a68096c7SSanjay Patel SMDiagnostic Error; 528a68096c7SSanjay Patel auto M = parseAssemblyString(Assembly, Error, Context); 529a68096c7SSanjay Patel assert(M && "Bad assembly?"); 530a68096c7SSanjay Patel 531a68096c7SSanjay Patel auto *F = M->getFunction("f"); 532a68096c7SSanjay Patel assert(F && "Bad assembly?"); 533a68096c7SSanjay Patel 534a68096c7SSanjay Patel auto *RVal = 535a68096c7SSanjay Patel cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 536a68096c7SSanjay Patel EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 537a68096c7SSanjay Patel } 538a68096c7SSanjay Patel 53945a148deSSanjay Patel // No guarantees for canonical IR in this analysis, so a shuffle element that 54045a148deSSanjay Patel // references an undef value means this can't return any extra information. 54145a148deSSanjay Patel TEST(ValueTracking, ComputeNumSignBits_Shuffle2) { 54245a148deSSanjay Patel StringRef Assembly = "define <2 x i32> @f(<2 x i1> %x) { " 54345a148deSSanjay Patel " %sext = sext <2 x i1> %x to <2 x i32> " 54445a148deSSanjay Patel " %val = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2> " 54545a148deSSanjay Patel " ret <2 x i32> %val " 54645a148deSSanjay Patel "} "; 54745a148deSSanjay Patel 54845a148deSSanjay Patel LLVMContext Context; 54945a148deSSanjay Patel SMDiagnostic Error; 55045a148deSSanjay Patel auto M = parseAssemblyString(Assembly, Error, Context); 55145a148deSSanjay Patel assert(M && "Bad assembly?"); 55245a148deSSanjay Patel 55345a148deSSanjay Patel auto *F = M->getFunction("f"); 55445a148deSSanjay Patel assert(F && "Bad assembly?"); 55545a148deSSanjay Patel 55645a148deSSanjay Patel auto *RVal = 55745a148deSSanjay Patel cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 558cac28b45SSanjay Patel EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 55945a148deSSanjay Patel } 56045a148deSSanjay Patel 56170dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownBits) { 56270dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 56370dbd5fbSSimon Dardis " %ash = mul i32 %a, 8 " 56470dbd5fbSSimon Dardis " %aad = add i32 %ash, 7 " 56570dbd5fbSSimon Dardis " %aan = and i32 %aad, 4095 " 56670dbd5fbSSimon Dardis " %bsh = shl i32 %b, 4 " 56770dbd5fbSSimon Dardis " %bad = or i32 %bsh, 6 " 56870dbd5fbSSimon Dardis " %ban = and i32 %bad, 4095 " 56970dbd5fbSSimon Dardis " %mul = mul i32 %aan, %ban " 57070dbd5fbSSimon Dardis " ret i32 %mul " 57170dbd5fbSSimon Dardis "} "; 57270dbd5fbSSimon Dardis 57370dbd5fbSSimon Dardis LLVMContext Context; 57470dbd5fbSSimon Dardis SMDiagnostic Error; 57570dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 57670dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 57770dbd5fbSSimon Dardis 57870dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 57970dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 58070dbd5fbSSimon Dardis 58170dbd5fbSSimon Dardis auto *RVal = 58270dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 58370dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 58470dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 58570dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 10u); 58670dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 4278190085u); 58770dbd5fbSSimon Dardis } 58870dbd5fbSSimon Dardis 58970dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownMulBits) { 59070dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 59170dbd5fbSSimon Dardis " %aa = shl i32 %a, 5 " 59270dbd5fbSSimon Dardis " %bb = shl i32 %b, 5 " 59370dbd5fbSSimon Dardis " %aaa = or i32 %aa, 24 " 59470dbd5fbSSimon Dardis " %bbb = or i32 %bb, 28 " 59570dbd5fbSSimon Dardis " %mul = mul i32 %aaa, %bbb " 59670dbd5fbSSimon Dardis " ret i32 %mul " 59770dbd5fbSSimon Dardis "} "; 59870dbd5fbSSimon Dardis 59970dbd5fbSSimon Dardis LLVMContext Context; 60070dbd5fbSSimon Dardis SMDiagnostic Error; 60170dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 60270dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 60370dbd5fbSSimon Dardis 60470dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 60570dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 60670dbd5fbSSimon Dardis 60770dbd5fbSSimon Dardis auto *RVal = 60870dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 60970dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 61070dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 61170dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 32u); 61270dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 95u); 61370dbd5fbSSimon Dardis } 614