• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
parseAssembly(const char * Assembly)26    void parseAssembly(const char *Assembly) {
27      SMDiagnostic Error;
28      M = parseAssemblyString(Assembly, Error, getGlobalContext());
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  
expectPattern(const SelectPatternResult & P)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    std::unique_ptr<Module> M;
63    Instruction *A, *B;
64  };
65  
66  }
67  
TEST_F(MatchSelectPatternTest,SimpleFMin)68  TEST_F(MatchSelectPatternTest, SimpleFMin) {
69    parseAssembly(
70        "define float @test(float %a) {\n"
71        "  %1 = fcmp ult float %a, 5.0\n"
72        "  %A = select i1 %1, float %a, float 5.0\n"
73        "  ret float %A\n"
74        "}\n");
75    expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
76  }
77  
TEST_F(MatchSelectPatternTest,SimpleFMax)78  TEST_F(MatchSelectPatternTest, SimpleFMax) {
79    parseAssembly(
80        "define float @test(float %a) {\n"
81        "  %1 = fcmp ogt float %a, 5.0\n"
82        "  %A = select i1 %1, float %a, float 5.0\n"
83        "  ret float %A\n"
84        "}\n");
85    expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
86  }
87  
TEST_F(MatchSelectPatternTest,SwappedFMax)88  TEST_F(MatchSelectPatternTest, SwappedFMax) {
89    parseAssembly(
90        "define float @test(float %a) {\n"
91        "  %1 = fcmp olt float 5.0, %a\n"
92        "  %A = select i1 %1, float %a, float 5.0\n"
93        "  ret float %A\n"
94        "}\n");
95    expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
96  }
97  
TEST_F(MatchSelectPatternTest,SwappedFMax2)98  TEST_F(MatchSelectPatternTest, SwappedFMax2) {
99    parseAssembly(
100        "define float @test(float %a) {\n"
101        "  %1 = fcmp olt float %a, 5.0\n"
102        "  %A = select i1 %1, float 5.0, float %a\n"
103        "  ret float %A\n"
104        "}\n");
105    expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
106  }
107  
TEST_F(MatchSelectPatternTest,SwappedFMax3)108  TEST_F(MatchSelectPatternTest, SwappedFMax3) {
109    parseAssembly(
110        "define float @test(float %a) {\n"
111        "  %1 = fcmp ult float %a, 5.0\n"
112        "  %A = select i1 %1, float 5.0, float %a\n"
113        "  ret float %A\n"
114        "}\n");
115    expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
116  }
117  
TEST_F(MatchSelectPatternTest,FastFMin)118  TEST_F(MatchSelectPatternTest, FastFMin) {
119    parseAssembly(
120        "define float @test(float %a) {\n"
121        "  %1 = fcmp nnan olt float %a, 5.0\n"
122        "  %A = select i1 %1, float %a, float 5.0\n"
123        "  ret float %A\n"
124        "}\n");
125    expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
126  }
127  
TEST_F(MatchSelectPatternTest,FMinConstantZero)128  TEST_F(MatchSelectPatternTest, FMinConstantZero) {
129    parseAssembly(
130        "define float @test(float %a) {\n"
131        "  %1 = fcmp ole float %a, 0.0\n"
132        "  %A = select i1 %1, float %a, float 0.0\n"
133        "  ret float %A\n"
134        "}\n");
135    // This shouldn't be matched, as %a could be -0.0.
136    expectPattern({SPF_UNKNOWN, SPNB_NA, false});
137  }
138  
TEST_F(MatchSelectPatternTest,FMinConstantZeroNsz)139  TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
140    parseAssembly(
141        "define float @test(float %a) {\n"
142        "  %1 = fcmp nsz ole float %a, 0.0\n"
143        "  %A = select i1 %1, float %a, float 0.0\n"
144        "  ret float %A\n"
145        "}\n");
146    // But this should be, because we've ignored signed zeroes.
147    expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
148  }
149  
TEST_F(MatchSelectPatternTest,DoubleCastU)150  TEST_F(MatchSelectPatternTest, DoubleCastU) {
151    parseAssembly(
152        "define i32 @test(i8 %a, i8 %b) {\n"
153        "  %1 = icmp ult i8 %a, %b\n"
154        "  %2 = zext i8 %a to i32\n"
155        "  %3 = zext i8 %b to i32\n"
156        "  %A = select i1 %1, i32 %2, i32 %3\n"
157        "  ret i32 %A\n"
158        "}\n");
159    // We should be able to look through the situation where we cast both operands
160    // to the select.
161    expectPattern({SPF_UMIN, SPNB_NA, false});
162  }
163  
TEST_F(MatchSelectPatternTest,DoubleCastS)164  TEST_F(MatchSelectPatternTest, DoubleCastS) {
165    parseAssembly(
166        "define i32 @test(i8 %a, i8 %b) {\n"
167        "  %1 = icmp slt i8 %a, %b\n"
168        "  %2 = sext i8 %a to i32\n"
169        "  %3 = sext i8 %b to i32\n"
170        "  %A = select i1 %1, i32 %2, i32 %3\n"
171        "  ret i32 %A\n"
172        "}\n");
173    // We should be able to look through the situation where we cast both operands
174    // to the select.
175    expectPattern({SPF_SMIN, SPNB_NA, false});
176  }
177  
TEST_F(MatchSelectPatternTest,DoubleCastBad)178  TEST_F(MatchSelectPatternTest, DoubleCastBad) {
179    parseAssembly(
180        "define i32 @test(i8 %a, i8 %b) {\n"
181        "  %1 = icmp ult i8 %a, %b\n"
182        "  %2 = zext i8 %a to i32\n"
183        "  %3 = sext i8 %b to i32\n"
184        "  %A = select i1 %1, i32 %2, i32 %3\n"
185        "  ret i32 %A\n"
186        "}\n");
187    // The cast types here aren't the same, so we cannot match an UMIN.
188    expectPattern({SPF_UNKNOWN, SPNB_NA, false});
189  }
190