Home | History | Annotate | Download | only in Analysis
      1 //===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/Analysis/ValueTracking.h"
     11 #include "llvm/AsmParser/Parser.h"
     12 #include "llvm/IR/Function.h"
     13 #include "llvm/IR/InstIterator.h"
     14 #include "llvm/IR/LLVMContext.h"
     15 #include "llvm/IR/Module.h"
     16 #include "llvm/Support/ErrorHandling.h"
     17 #include "llvm/Support/SourceMgr.h"
     18 #include "gtest/gtest.h"
     19 
     20 using namespace llvm;
     21 
     22 namespace {
     23 
     24 class MatchSelectPatternTest : public testing::Test {
     25 protected:
     26   void parseAssembly(const char *Assembly) {
     27     SMDiagnostic Error;
     28     M = parseAssemblyString(Assembly, Error, Context);
     29 
     30     std::string errMsg;
     31     raw_string_ostream os(errMsg);
     32     Error.print("", os);
     33 
     34     // A failure here means that the test itself is buggy.
     35     if (!M)
     36       report_fatal_error(os.str());
     37 
     38     Function *F = M->getFunction("test");
     39     if (F == nullptr)
     40       report_fatal_error("Test must have a function named @test");
     41 
     42     A = nullptr;
     43     for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
     44       if (I->hasName()) {
     45         if (I->getName() == "A")
     46           A = &*I;
     47       }
     48     }
     49     if (A == nullptr)
     50       report_fatal_error("@test must have an instruction %A");
     51   }
     52 
     53   void expectPattern(const SelectPatternResult &P) {
     54     Value *LHS, *RHS;
     55     Instruction::CastOps CastOp;
     56     SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
     57     EXPECT_EQ(P.Flavor, R.Flavor);
     58     EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
     59     EXPECT_EQ(P.Ordered, R.Ordered);
     60   }
     61 
     62   LLVMContext Context;
     63   std::unique_ptr<Module> M;
     64   Instruction *A, *B;
     65 };
     66 
     67 }
     68 
     69 TEST_F(MatchSelectPatternTest, SimpleFMin) {
     70   parseAssembly(
     71       "define float @test(float %a) {\n"
     72       "  %1 = fcmp ult float %a, 5.0\n"
     73       "  %A = select i1 %1, float %a, float 5.0\n"
     74       "  ret float %A\n"
     75       "}\n");
     76   expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
     77 }
     78 
     79 TEST_F(MatchSelectPatternTest, SimpleFMax) {
     80   parseAssembly(
     81       "define float @test(float %a) {\n"
     82       "  %1 = fcmp ogt float %a, 5.0\n"
     83       "  %A = select i1 %1, float %a, float 5.0\n"
     84       "  ret float %A\n"
     85       "}\n");
     86   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
     87 }
     88 
     89 TEST_F(MatchSelectPatternTest, SwappedFMax) {
     90   parseAssembly(
     91       "define float @test(float %a) {\n"
     92       "  %1 = fcmp olt float 5.0, %a\n"
     93       "  %A = select i1 %1, float %a, float 5.0\n"
     94       "  ret float %A\n"
     95       "}\n");
     96   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
     97 }
     98 
     99 TEST_F(MatchSelectPatternTest, SwappedFMax2) {
    100   parseAssembly(
    101       "define float @test(float %a) {\n"
    102       "  %1 = fcmp olt float %a, 5.0\n"
    103       "  %A = select i1 %1, float 5.0, float %a\n"
    104       "  ret float %A\n"
    105       "}\n");
    106   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
    107 }
    108 
    109 TEST_F(MatchSelectPatternTest, SwappedFMax3) {
    110   parseAssembly(
    111       "define float @test(float %a) {\n"
    112       "  %1 = fcmp ult float %a, 5.0\n"
    113       "  %A = select i1 %1, float 5.0, float %a\n"
    114       "  ret float %A\n"
    115       "}\n");
    116   expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
    117 }
    118 
    119 TEST_F(MatchSelectPatternTest, FastFMin) {
    120   parseAssembly(
    121       "define float @test(float %a) {\n"
    122       "  %1 = fcmp nnan olt float %a, 5.0\n"
    123       "  %A = select i1 %1, float %a, float 5.0\n"
    124       "  ret float %A\n"
    125       "}\n");
    126   expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
    127 }
    128 
    129 TEST_F(MatchSelectPatternTest, FMinConstantZero) {
    130   parseAssembly(
    131       "define float @test(float %a) {\n"
    132       "  %1 = fcmp ole float %a, 0.0\n"
    133       "  %A = select i1 %1, float %a, float 0.0\n"
    134       "  ret float %A\n"
    135       "}\n");
    136   // This shouldn't be matched, as %a could be -0.0.
    137   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
    138 }
    139 
    140 TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
    141   parseAssembly(
    142       "define float @test(float %a) {\n"
    143       "  %1 = fcmp nsz ole float %a, 0.0\n"
    144       "  %A = select i1 %1, float %a, float 0.0\n"
    145       "  ret float %A\n"
    146       "}\n");
    147   // But this should be, because we've ignored signed zeroes.
    148   expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
    149 }
    150 
    151 TEST_F(MatchSelectPatternTest, DoubleCastU) {
    152   parseAssembly(
    153       "define i32 @test(i8 %a, i8 %b) {\n"
    154       "  %1 = icmp ult i8 %a, %b\n"
    155       "  %2 = zext i8 %a to i32\n"
    156       "  %3 = zext i8 %b to i32\n"
    157       "  %A = select i1 %1, i32 %2, i32 %3\n"
    158       "  ret i32 %A\n"
    159       "}\n");
    160   // We should be able to look through the situation where we cast both operands
    161   // to the select.
    162   expectPattern({SPF_UMIN, SPNB_NA, false});
    163 }
    164 
    165 TEST_F(MatchSelectPatternTest, DoubleCastS) {
    166   parseAssembly(
    167       "define i32 @test(i8 %a, i8 %b) {\n"
    168       "  %1 = icmp slt i8 %a, %b\n"
    169       "  %2 = sext i8 %a to i32\n"
    170       "  %3 = sext i8 %b to i32\n"
    171       "  %A = select i1 %1, i32 %2, i32 %3\n"
    172       "  ret i32 %A\n"
    173       "}\n");
    174   // We should be able to look through the situation where we cast both operands
    175   // to the select.
    176   expectPattern({SPF_SMIN, SPNB_NA, false});
    177 }
    178 
    179 TEST_F(MatchSelectPatternTest, DoubleCastBad) {
    180   parseAssembly(
    181       "define i32 @test(i8 %a, i8 %b) {\n"
    182       "  %1 = icmp ult i8 %a, %b\n"
    183       "  %2 = zext i8 %a to i32\n"
    184       "  %3 = sext i8 %b to i32\n"
    185       "  %A = select i1 %1, i32 %2, i32 %3\n"
    186       "  ret i32 %A\n"
    187       "}\n");
    188   // The cast types here aren't the same, so we cannot match an UMIN.
    189   expectPattern({SPF_UNKNOWN, SPNB_NA, false});
    190 }
    191