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
20using namespace llvm;
21
22namespace {
23
24class MatchSelectPatternTest : public testing::Test {
25protected:
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
69TEST_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
79TEST_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
89TEST_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
99TEST_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
109TEST_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
119TEST_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
129TEST_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
140TEST_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
151TEST_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
165TEST_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
179TEST_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