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