xref: /llvm-project/llvm/unittests/SandboxIR/OperatorTest.cpp (revision a24a420c2b4854598ac24a571a8275bfaa1b9159)
1 //===- OperatorTest.cpp ---------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/SandboxIR/Operator.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/SandboxIR/Context.h"
12 #include "llvm/SandboxIR/Function.h"
13 #include "llvm/SandboxIR/Instruction.h"
14 #include "llvm/SandboxIR/Module.h"
15 #include "llvm/SandboxIR/Value.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gtest/gtest.h"
18 
19 using namespace llvm;
20 
21 struct OperatorTest : public testing::Test {
22   LLVMContext C;
23   std::unique_ptr<Module> M;
24 
25   void parseIR(LLVMContext &C, const char *IR) {
26     SMDiagnostic Err;
27     M = parseAssemblyString(IR, Err, C);
28     if (!M)
29       Err.print("OperatorTest", errs());
30   }
31   BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
32     for (BasicBlock &BB : F)
33       if (BB.getName() == Name)
34         return &BB;
35     llvm_unreachable("Expected to find basic block!");
36   }
37 };
38 
39 TEST_F(OperatorTest, Operator) {
40   parseIR(C, R"IR(
41 define void @foo(i8 %v1) {
42   %add0 = add i8 %v1, 42
43   %add1 = add nuw i8 %v1, 42
44   ret void
45 }
46 )IR");
47   llvm::Function *LLVMF = &*M->getFunction("foo");
48   sandboxir::Context Ctx(C);
49   sandboxir::Function *F = Ctx.createFunction(LLVMF);
50   auto *BB = &*F->begin();
51   auto It = BB->begin();
52   auto *OperatorI0 = cast<sandboxir::Operator>(&*It++);
53   auto *OperatorI1 = cast<sandboxir::Operator>(&*It++);
54   EXPECT_FALSE(OperatorI0->hasPoisonGeneratingFlags());
55   EXPECT_TRUE(OperatorI1->hasPoisonGeneratingFlags());
56 }
57 
58 TEST_F(OperatorTest, OverflowingBinaryOperator) {
59   parseIR(C, R"IR(
60 define void @foo(i8 %v1) {
61   %add = add i8 %v1, 42
62   %addNSW = add nsw i8 %v1, 42
63   %addNUW = add nuw i8 %v1, 42
64   ret void
65 }
66 )IR");
67   llvm::Function *LLVMF = &*M->getFunction("foo");
68   sandboxir::Context Ctx(C);
69   sandboxir::Function *F = Ctx.createFunction(LLVMF);
70   auto *BB = &*F->begin();
71   auto It = BB->begin();
72   auto *Add = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
73   auto *AddNSW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
74   auto *AddNUW = cast<sandboxir::OverflowingBinaryOperator>(&*It++);
75   EXPECT_FALSE(Add->hasNoUnsignedWrap());
76   EXPECT_FALSE(Add->hasNoSignedWrap());
77   EXPECT_EQ(Add->getNoWrapKind(), llvm::OverflowingBinaryOperator::AnyWrap);
78 
79   EXPECT_FALSE(AddNSW->hasNoUnsignedWrap());
80   EXPECT_TRUE(AddNSW->hasNoSignedWrap());
81   EXPECT_EQ(AddNSW->getNoWrapKind(),
82             llvm::OverflowingBinaryOperator::NoSignedWrap);
83 
84   EXPECT_TRUE(AddNUW->hasNoUnsignedWrap());
85   EXPECT_FALSE(AddNUW->hasNoSignedWrap());
86   EXPECT_EQ(AddNUW->getNoWrapKind(),
87             llvm::OverflowingBinaryOperator::NoUnsignedWrap);
88 }
89 
90 TEST_F(OperatorTest, FPMathOperator) {
91   parseIR(C, R"IR(
92 define void @foo(float %v1, double %v2) {
93   %fadd = fadd float %v1, 42.0
94   %Fast = fadd fast float %v1, 42.0
95   %Reassoc = fmul reassoc float %v1, 42.0
96   %NNAN = fmul nnan float %v1, 42.0
97   %NINF = fmul ninf float %v1, 42.0
98   %NSZ = fmul nsz float %v1, 42.0
99   %ARCP = fmul arcp float %v1, 42.0
100   %CONTRACT = fmul contract float %v1, 42.0
101   %AFN = fmul afn double %v2, 42.0
102   ret void
103 }
104 )IR");
105   llvm::Function *LLVMF = &*M->getFunction("foo");
106   auto *LLVMBB = &*LLVMF->begin();
107   auto LLVMIt = LLVMBB->begin();
108 
109   sandboxir::Context Ctx(C);
110   sandboxir::Function *F = Ctx.createFunction(LLVMF);
111   auto *BB = &*F->begin();
112   auto It = BB->begin();
113   auto TermIt = BB->getTerminator()->getIterator();
114   while (It != TermIt) {
115     auto *FPM = cast<sandboxir::FPMathOperator>(&*It++);
116     auto *LLVMFPM = cast<llvm::FPMathOperator>(&*LLVMIt++);
117     EXPECT_EQ(FPM->isFast(), LLVMFPM->isFast());
118     EXPECT_EQ(FPM->hasAllowReassoc(), LLVMFPM->hasAllowReassoc());
119     EXPECT_EQ(FPM->hasNoNaNs(), LLVMFPM->hasNoNaNs());
120     EXPECT_EQ(FPM->hasNoInfs(), LLVMFPM->hasNoInfs());
121     EXPECT_EQ(FPM->hasNoSignedZeros(), LLVMFPM->hasNoSignedZeros());
122     EXPECT_EQ(FPM->hasAllowReciprocal(), LLVMFPM->hasAllowReciprocal());
123     EXPECT_EQ(FPM->hasAllowContract(), LLVMFPM->hasAllowContract());
124     EXPECT_EQ(FPM->hasApproxFunc(), LLVMFPM->hasApproxFunc());
125 
126     // There doesn't seem to be an operator== for FastMathFlags so let's do a
127     // string comparison instead.
128     std::string Str1;
129     raw_string_ostream SS1(Str1);
130     std::string Str2;
131     raw_string_ostream SS2(Str2);
132     FPM->getFastMathFlags().print(SS1);
133     LLVMFPM->getFastMathFlags().print(SS2);
134     EXPECT_EQ(Str1, Str2);
135 
136     EXPECT_EQ(FPM->getFPAccuracy(), LLVMFPM->getFPAccuracy());
137     EXPECT_EQ(
138         sandboxir::FPMathOperator::isSupportedFloatingPointType(FPM->getType()),
139         llvm::FPMathOperator::isSupportedFloatingPointType(LLVMFPM->getType()));
140   }
141 }
142