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"); 15903da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 16003da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 17003da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 17103da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 18103da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 18203da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 19203da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 19303da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 20303da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 20403da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 21403da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 21503da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 22503da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 22603da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 23603da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 23703da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 24703da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 24803da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 25803da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 25903da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 26903da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 27003da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 28003da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 28103da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 29103da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 29203da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 30203da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 30303da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 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"); 31303da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 31403da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, 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"); 32403da6e6aSSanjay Patel // FIXME: The sign of zero doesn't matter in fcmp. 32503da6e6aSSanjay Patel expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 32603da6e6aSSanjay Patel } 32703da6e6aSSanjay Patel 32830f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinimum) { 329d47b5c7bSThomas Lively parseAssembly( 330d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 331d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 332d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 333d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 334d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 335d47b5c7bSThomas Lively " ret <4 x float> %A\n" 336d47b5c7bSThomas Lively "}\n"); 337d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 338d47b5c7bSThomas Lively // unordered pattern. 339d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false}); 340d47b5c7bSThomas Lively } 341d47b5c7bSThomas Lively 342d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorFMinOtherOrdered) { 343d47b5c7bSThomas Lively parseAssembly( 344d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 345d47b5c7bSThomas Lively " %1 = fcmp ole <4 x float> %a, \n" 346d47b5c7bSThomas Lively " <float 5.0, float 5.0, float 5.0, float 5.0>\n" 347d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 348d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 5.0, float 5.0, float 5.0>\n" 349d47b5c7bSThomas Lively " ret <4 x float> %A\n" 350d47b5c7bSThomas Lively "}\n"); 351d47b5c7bSThomas Lively // Check that pattern matching works on vectors where each lane has the same 352d47b5c7bSThomas Lively // ordered pattern. 353d47b5c7bSThomas Lively expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true}); 354d47b5c7bSThomas Lively } 355d47b5c7bSThomas Lively 35630f1d691SThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinimum) { 357d47b5c7bSThomas Lively parseAssembly( 358d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 359d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 360d47b5c7bSThomas Lively " <float 5.0, float 0x7ff8000000000000, float 5.0, float 5.0>\n" 361d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 362d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0x7ff8000000000000, float 5.0, float " 363d47b5c7bSThomas Lively "5.0>\n" 364d47b5c7bSThomas Lively " ret <4 x float> %A\n" 365d47b5c7bSThomas Lively "}\n"); 366d47b5c7bSThomas Lively // The lane that contains a NaN (0x7ff80...) behaves like a 367d47b5c7bSThomas Lively // non-NaN-propagating min and the other lines behave like a NaN-propagating 368d47b5c7bSThomas Lively // min, so check that neither is returned. 369d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 370d47b5c7bSThomas Lively } 371d47b5c7bSThomas Lively 372d47b5c7bSThomas Lively TEST_F(MatchSelectPatternTest, VectorNotFMinZero) { 373d47b5c7bSThomas Lively parseAssembly( 374d47b5c7bSThomas Lively "define <4 x float> @test(<4 x float> %a) {\n" 375d47b5c7bSThomas Lively " %1 = fcmp ule <4 x float> %a, \n" 376d47b5c7bSThomas Lively " <float 5.0, float -0.0, float 5.0, float 5.0>\n" 377d47b5c7bSThomas Lively " %A = select <4 x i1> %1, <4 x float> %a,\n" 378d47b5c7bSThomas Lively " <4 x float> <float 5.0, float 0.0, float 5.0, float 5.0>\n" 379d47b5c7bSThomas Lively " ret <4 x float> %A\n" 380d47b5c7bSThomas Lively "}\n"); 381d47b5c7bSThomas Lively // Always selects the second lane of %a if it is positive or negative zero, so 382d47b5c7bSThomas Lively // this is stricter than a min. 383d47b5c7bSThomas Lively expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 384d47b5c7bSThomas Lively } 385d47b5c7bSThomas Lively 386569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastU) { 387569cea65SJames Molloy parseAssembly( 388569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 389569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 390569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 391569cea65SJames Molloy " %3 = zext i8 %b to i32\n" 392569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 393569cea65SJames Molloy " ret i32 %A\n" 394569cea65SJames Molloy "}\n"); 395569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 396569cea65SJames Molloy // to the select. 397569cea65SJames Molloy expectPattern({SPF_UMIN, SPNB_NA, false}); 398569cea65SJames Molloy } 399569cea65SJames Molloy 400569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastS) { 401569cea65SJames Molloy parseAssembly( 402569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 403569cea65SJames Molloy " %1 = icmp slt i8 %a, %b\n" 404569cea65SJames Molloy " %2 = sext i8 %a to i32\n" 405569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 406569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 407569cea65SJames Molloy " ret i32 %A\n" 408569cea65SJames Molloy "}\n"); 409569cea65SJames Molloy // We should be able to look through the situation where we cast both operands 410569cea65SJames Molloy // to the select. 411569cea65SJames Molloy expectPattern({SPF_SMIN, SPNB_NA, false}); 412569cea65SJames Molloy } 413569cea65SJames Molloy 414569cea65SJames Molloy TEST_F(MatchSelectPatternTest, DoubleCastBad) { 415569cea65SJames Molloy parseAssembly( 416569cea65SJames Molloy "define i32 @test(i8 %a, i8 %b) {\n" 417569cea65SJames Molloy " %1 = icmp ult i8 %a, %b\n" 418569cea65SJames Molloy " %2 = zext i8 %a to i32\n" 419569cea65SJames Molloy " %3 = sext i8 %b to i32\n" 420569cea65SJames Molloy " %A = select i1 %1, i32 %2, i32 %3\n" 421569cea65SJames Molloy " ret i32 %A\n" 422569cea65SJames Molloy "}\n"); 423687a8448SJames Molloy // The cast types here aren't the same, so we cannot match an UMIN. 424569cea65SJames Molloy expectPattern({SPF_UNKNOWN, SPNB_NA, false}); 425569cea65SJames Molloy } 4263bb2dbd6SSanjoy Das 4273bb2dbd6SSanjoy Das TEST(ValueTracking, GuaranteedToTransferExecutionToSuccessor) { 4283bb2dbd6SSanjoy Das StringRef Assembly = 4293bb2dbd6SSanjoy Das "declare void @nounwind_readonly(i32*) nounwind readonly " 4303bb2dbd6SSanjoy Das "declare void @nounwind_argmemonly(i32*) nounwind argmemonly " 4313bb2dbd6SSanjoy Das "declare void @throws_but_readonly(i32*) readonly " 4323bb2dbd6SSanjoy Das "declare void @throws_but_argmemonly(i32*) argmemonly " 4333bb2dbd6SSanjoy Das " " 4343bb2dbd6SSanjoy Das "declare void @unknown(i32*) " 4353bb2dbd6SSanjoy Das " " 4363bb2dbd6SSanjoy Das "define void @f(i32* %p) { " 4373bb2dbd6SSanjoy Das " call void @nounwind_readonly(i32* %p) " 4383bb2dbd6SSanjoy Das " call void @nounwind_argmemonly(i32* %p) " 4393bb2dbd6SSanjoy Das " call void @throws_but_readonly(i32* %p) " 4403bb2dbd6SSanjoy Das " call void @throws_but_argmemonly(i32* %p) " 4413bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind readonly " 4423bb2dbd6SSanjoy Das " call void @unknown(i32* %p) nounwind argmemonly " 4433bb2dbd6SSanjoy Das " call void @unknown(i32* %p) readonly " 4443bb2dbd6SSanjoy Das " call void @unknown(i32* %p) argmemonly " 4453bb2dbd6SSanjoy Das " ret void " 4463bb2dbd6SSanjoy Das "} "; 4473bb2dbd6SSanjoy Das 4483bb2dbd6SSanjoy Das LLVMContext Context; 4493bb2dbd6SSanjoy Das SMDiagnostic Error; 4503bb2dbd6SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 4513bb2dbd6SSanjoy Das assert(M && "Bad assembly?"); 4523bb2dbd6SSanjoy Das 4533bb2dbd6SSanjoy Das auto *F = M->getFunction("f"); 4543bb2dbd6SSanjoy Das assert(F && "Bad assembly?"); 4553bb2dbd6SSanjoy Das 4563bb2dbd6SSanjoy Das auto &BB = F->getEntryBlock(); 4578580cd4eSCraig Topper bool ExpectedAnswers[] = { 4583bb2dbd6SSanjoy Das true, // call void @nounwind_readonly(i32* %p) 4593bb2dbd6SSanjoy Das true, // call void @nounwind_argmemonly(i32* %p) 4603bb2dbd6SSanjoy Das false, // call void @throws_but_readonly(i32* %p) 4613bb2dbd6SSanjoy Das false, // call void @throws_but_argmemonly(i32* %p) 4623bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind readonly 4633bb2dbd6SSanjoy Das true, // call void @unknown(i32* %p) nounwind argmemonly 4643bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) readonly 4653bb2dbd6SSanjoy Das false, // call void @unknown(i32* %p) argmemonly 4663bb2dbd6SSanjoy Das false, // ret void 4673bb2dbd6SSanjoy Das }; 4683bb2dbd6SSanjoy Das 4693bb2dbd6SSanjoy Das int Index = 0; 4703bb2dbd6SSanjoy Das for (auto &I : BB) { 4713bb2dbd6SSanjoy Das EXPECT_EQ(isGuaranteedToTransferExecutionToSuccessor(&I), 4723bb2dbd6SSanjoy Das ExpectedAnswers[Index]) 4733bb2dbd6SSanjoy Das << "Incorrect answer at instruction " << Index << " = " << I; 4743bb2dbd6SSanjoy Das Index++; 4753bb2dbd6SSanjoy Das } 4763bb2dbd6SSanjoy Das } 47739a684d1SSanjoy Das 47839a684d1SSanjoy Das TEST(ValueTracking, ComputeNumSignBits_PR32045) { 47939a684d1SSanjoy Das StringRef Assembly = "define i32 @f(i32 %a) { " 48039a684d1SSanjoy Das " %val = ashr i32 %a, -1 " 48139a684d1SSanjoy Das " ret i32 %val " 48239a684d1SSanjoy Das "} "; 48339a684d1SSanjoy Das 48439a684d1SSanjoy Das LLVMContext Context; 48539a684d1SSanjoy Das SMDiagnostic Error; 48639a684d1SSanjoy Das auto M = parseAssemblyString(Assembly, Error, Context); 48739a684d1SSanjoy Das assert(M && "Bad assembly?"); 48839a684d1SSanjoy Das 48939a684d1SSanjoy Das auto *F = M->getFunction("f"); 49039a684d1SSanjoy Das assert(F && "Bad assembly?"); 49139a684d1SSanjoy Das 49239a684d1SSanjoy Das auto *RVal = 49339a684d1SSanjoy Das cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 4944897cea4SSanjoy Das EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 49539a684d1SSanjoy Das } 49670dbd5fbSSimon Dardis 497a68096c7SSanjay Patel // No guarantees for canonical IR in this analysis, so this just bails out. 498a68096c7SSanjay Patel TEST(ValueTracking, ComputeNumSignBits_Shuffle) { 499a68096c7SSanjay Patel StringRef Assembly = "define <2 x i32> @f() { " 500a68096c7SSanjay Patel " %val = shufflevector <2 x i32> undef, <2 x i32> undef, <2 x i32> <i32 0, i32 0> " 501a68096c7SSanjay Patel " ret <2 x i32> %val " 502a68096c7SSanjay Patel "} "; 503a68096c7SSanjay Patel 504a68096c7SSanjay Patel LLVMContext Context; 505a68096c7SSanjay Patel SMDiagnostic Error; 506a68096c7SSanjay Patel auto M = parseAssemblyString(Assembly, Error, Context); 507a68096c7SSanjay Patel assert(M && "Bad assembly?"); 508a68096c7SSanjay Patel 509a68096c7SSanjay Patel auto *F = M->getFunction("f"); 510a68096c7SSanjay Patel assert(F && "Bad assembly?"); 511a68096c7SSanjay Patel 512a68096c7SSanjay Patel auto *RVal = 513a68096c7SSanjay Patel cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 514a68096c7SSanjay Patel EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 1u); 515a68096c7SSanjay Patel } 516a68096c7SSanjay Patel 517*45a148deSSanjay Patel // FIXME: 518*45a148deSSanjay Patel // No guarantees for canonical IR in this analysis, so a shuffle element that 519*45a148deSSanjay Patel // references an undef value means this can't return any extra information. 520*45a148deSSanjay Patel TEST(ValueTracking, ComputeNumSignBits_Shuffle2) { 521*45a148deSSanjay Patel StringRef Assembly = "define <2 x i32> @f(<2 x i1> %x) { " 522*45a148deSSanjay Patel " %sext = sext <2 x i1> %x to <2 x i32> " 523*45a148deSSanjay Patel " %val = shufflevector <2 x i32> %sext, <2 x i32> undef, <2 x i32> <i32 0, i32 2> " 524*45a148deSSanjay Patel " ret <2 x i32> %val " 525*45a148deSSanjay Patel "} "; 526*45a148deSSanjay Patel 527*45a148deSSanjay Patel LLVMContext Context; 528*45a148deSSanjay Patel SMDiagnostic Error; 529*45a148deSSanjay Patel auto M = parseAssemblyString(Assembly, Error, Context); 530*45a148deSSanjay Patel assert(M && "Bad assembly?"); 531*45a148deSSanjay Patel 532*45a148deSSanjay Patel auto *F = M->getFunction("f"); 533*45a148deSSanjay Patel assert(F && "Bad assembly?"); 534*45a148deSSanjay Patel 535*45a148deSSanjay Patel auto *RVal = 536*45a148deSSanjay Patel cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 537*45a148deSSanjay Patel EXPECT_EQ(ComputeNumSignBits(RVal, M->getDataLayout()), 32u); 538*45a148deSSanjay Patel } 539*45a148deSSanjay Patel 54070dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownBits) { 54170dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 54270dbd5fbSSimon Dardis " %ash = mul i32 %a, 8 " 54370dbd5fbSSimon Dardis " %aad = add i32 %ash, 7 " 54470dbd5fbSSimon Dardis " %aan = and i32 %aad, 4095 " 54570dbd5fbSSimon Dardis " %bsh = shl i32 %b, 4 " 54670dbd5fbSSimon Dardis " %bad = or i32 %bsh, 6 " 54770dbd5fbSSimon Dardis " %ban = and i32 %bad, 4095 " 54870dbd5fbSSimon Dardis " %mul = mul i32 %aan, %ban " 54970dbd5fbSSimon Dardis " ret i32 %mul " 55070dbd5fbSSimon Dardis "} "; 55170dbd5fbSSimon Dardis 55270dbd5fbSSimon Dardis LLVMContext Context; 55370dbd5fbSSimon Dardis SMDiagnostic Error; 55470dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 55570dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 55670dbd5fbSSimon Dardis 55770dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 55870dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 55970dbd5fbSSimon Dardis 56070dbd5fbSSimon Dardis auto *RVal = 56170dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 56270dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 56370dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 56470dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 10u); 56570dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 4278190085u); 56670dbd5fbSSimon Dardis } 56770dbd5fbSSimon Dardis 56870dbd5fbSSimon Dardis TEST(ValueTracking, ComputeKnownMulBits) { 56970dbd5fbSSimon Dardis StringRef Assembly = "define i32 @f(i32 %a, i32 %b) { " 57070dbd5fbSSimon Dardis " %aa = shl i32 %a, 5 " 57170dbd5fbSSimon Dardis " %bb = shl i32 %b, 5 " 57270dbd5fbSSimon Dardis " %aaa = or i32 %aa, 24 " 57370dbd5fbSSimon Dardis " %bbb = or i32 %bb, 28 " 57470dbd5fbSSimon Dardis " %mul = mul i32 %aaa, %bbb " 57570dbd5fbSSimon Dardis " ret i32 %mul " 57670dbd5fbSSimon Dardis "} "; 57770dbd5fbSSimon Dardis 57870dbd5fbSSimon Dardis LLVMContext Context; 57970dbd5fbSSimon Dardis SMDiagnostic Error; 58070dbd5fbSSimon Dardis auto M = parseAssemblyString(Assembly, Error, Context); 58170dbd5fbSSimon Dardis assert(M && "Bad assembly?"); 58270dbd5fbSSimon Dardis 58370dbd5fbSSimon Dardis auto *F = M->getFunction("f"); 58470dbd5fbSSimon Dardis assert(F && "Bad assembly?"); 58570dbd5fbSSimon Dardis 58670dbd5fbSSimon Dardis auto *RVal = 58770dbd5fbSSimon Dardis cast<ReturnInst>(F->getEntryBlock().getTerminator())->getOperand(0); 58870dbd5fbSSimon Dardis auto Known = computeKnownBits(RVal, M->getDataLayout()); 58970dbd5fbSSimon Dardis ASSERT_FALSE(Known.hasConflict()); 59070dbd5fbSSimon Dardis EXPECT_EQ(Known.One.getZExtValue(), 32u); 59170dbd5fbSSimon Dardis EXPECT_EQ(Known.Zero.getZExtValue(), 95u); 59270dbd5fbSSimon Dardis } 593