154566ba5Svporpo //===- OperatorTest.cpp ---------------------------------------------------===// 254566ba5Svporpo // 354566ba5Svporpo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 454566ba5Svporpo // See https://llvm.org/LICENSE.txt for license information. 554566ba5Svporpo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 654566ba5Svporpo // 754566ba5Svporpo //===----------------------------------------------------------------------===// 854566ba5Svporpo 954566ba5Svporpo #include "llvm/SandboxIR/Operator.h" 1054566ba5Svporpo #include "llvm/AsmParser/Parser.h" 1154566ba5Svporpo #include "llvm/SandboxIR/Context.h" 1254566ba5Svporpo #include "llvm/SandboxIR/Function.h" 1354566ba5Svporpo #include "llvm/SandboxIR/Instruction.h" 1454566ba5Svporpo #include "llvm/SandboxIR/Module.h" 1554566ba5Svporpo #include "llvm/SandboxIR/Value.h" 1654566ba5Svporpo #include "llvm/Support/SourceMgr.h" 1754566ba5Svporpo #include "gtest/gtest.h" 1854566ba5Svporpo 1954566ba5Svporpo using namespace llvm; 2054566ba5Svporpo 2154566ba5Svporpo struct OperatorTest : public testing::Test { 2254566ba5Svporpo LLVMContext C; 2354566ba5Svporpo std::unique_ptr<Module> M; 2454566ba5Svporpo 2554566ba5Svporpo void parseIR(LLVMContext &C, const char *IR) { 2654566ba5Svporpo SMDiagnostic Err; 2754566ba5Svporpo M = parseAssemblyString(IR, Err, C); 2854566ba5Svporpo if (!M) 2954566ba5Svporpo Err.print("OperatorTest", errs()); 3054566ba5Svporpo } 3154566ba5Svporpo BasicBlock *getBasicBlockByName(Function &F, StringRef Name) { 3254566ba5Svporpo for (BasicBlock &BB : F) 3354566ba5Svporpo if (BB.getName() == Name) 3454566ba5Svporpo return &BB; 3554566ba5Svporpo llvm_unreachable("Expected to find basic block!"); 3654566ba5Svporpo } 3754566ba5Svporpo }; 3854566ba5Svporpo 3954566ba5Svporpo TEST_F(OperatorTest, Operator) { 4054566ba5Svporpo parseIR(C, R"IR( 4154566ba5Svporpo define void @foo(i8 %v1) { 4254566ba5Svporpo %add0 = add i8 %v1, 42 4354566ba5Svporpo %add1 = add nuw i8 %v1, 42 4454566ba5Svporpo ret void 4554566ba5Svporpo } 4654566ba5Svporpo )IR"); 4754566ba5Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 4854566ba5Svporpo sandboxir::Context Ctx(C); 4954566ba5Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 5054566ba5Svporpo auto *BB = &*F->begin(); 5154566ba5Svporpo auto It = BB->begin(); 5254566ba5Svporpo auto *OperatorI0 = cast<sandboxir::Operator>(&*It++); 5354566ba5Svporpo auto *OperatorI1 = cast<sandboxir::Operator>(&*It++); 5454566ba5Svporpo EXPECT_FALSE(OperatorI0->hasPoisonGeneratingFlags()); 5554566ba5Svporpo EXPECT_TRUE(OperatorI1->hasPoisonGeneratingFlags()); 5654566ba5Svporpo } 5754566ba5Svporpo 5854566ba5Svporpo TEST_F(OperatorTest, OverflowingBinaryOperator) { 5954566ba5Svporpo parseIR(C, R"IR( 6054566ba5Svporpo define void @foo(i8 %v1) { 6154566ba5Svporpo %add = add i8 %v1, 42 6254566ba5Svporpo %addNSW = add nsw i8 %v1, 42 6354566ba5Svporpo %addNUW = add nuw i8 %v1, 42 6454566ba5Svporpo ret void 6554566ba5Svporpo } 6654566ba5Svporpo )IR"); 6754566ba5Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 6854566ba5Svporpo sandboxir::Context Ctx(C); 6954566ba5Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 7054566ba5Svporpo auto *BB = &*F->begin(); 7154566ba5Svporpo auto It = BB->begin(); 7254566ba5Svporpo auto *Add = cast<sandboxir::OverflowingBinaryOperator>(&*It++); 7354566ba5Svporpo auto *AddNSW = cast<sandboxir::OverflowingBinaryOperator>(&*It++); 7454566ba5Svporpo auto *AddNUW = cast<sandboxir::OverflowingBinaryOperator>(&*It++); 7554566ba5Svporpo EXPECT_FALSE(Add->hasNoUnsignedWrap()); 7654566ba5Svporpo EXPECT_FALSE(Add->hasNoSignedWrap()); 7754566ba5Svporpo EXPECT_EQ(Add->getNoWrapKind(), llvm::OverflowingBinaryOperator::AnyWrap); 7854566ba5Svporpo 7954566ba5Svporpo EXPECT_FALSE(AddNSW->hasNoUnsignedWrap()); 8054566ba5Svporpo EXPECT_TRUE(AddNSW->hasNoSignedWrap()); 8154566ba5Svporpo EXPECT_EQ(AddNSW->getNoWrapKind(), 8254566ba5Svporpo llvm::OverflowingBinaryOperator::NoSignedWrap); 8354566ba5Svporpo 8454566ba5Svporpo EXPECT_TRUE(AddNUW->hasNoUnsignedWrap()); 8554566ba5Svporpo EXPECT_FALSE(AddNUW->hasNoSignedWrap()); 8654566ba5Svporpo EXPECT_EQ(AddNUW->getNoWrapKind(), 8754566ba5Svporpo llvm::OverflowingBinaryOperator::NoUnsignedWrap); 8854566ba5Svporpo } 89*a24a420cSvporpo 90*a24a420cSvporpo TEST_F(OperatorTest, FPMathOperator) { 91*a24a420cSvporpo parseIR(C, R"IR( 92*a24a420cSvporpo define void @foo(float %v1, double %v2) { 93*a24a420cSvporpo %fadd = fadd float %v1, 42.0 94*a24a420cSvporpo %Fast = fadd fast float %v1, 42.0 95*a24a420cSvporpo %Reassoc = fmul reassoc float %v1, 42.0 96*a24a420cSvporpo %NNAN = fmul nnan float %v1, 42.0 97*a24a420cSvporpo %NINF = fmul ninf float %v1, 42.0 98*a24a420cSvporpo %NSZ = fmul nsz float %v1, 42.0 99*a24a420cSvporpo %ARCP = fmul arcp float %v1, 42.0 100*a24a420cSvporpo %CONTRACT = fmul contract float %v1, 42.0 101*a24a420cSvporpo %AFN = fmul afn double %v2, 42.0 102*a24a420cSvporpo ret void 103*a24a420cSvporpo } 104*a24a420cSvporpo )IR"); 105*a24a420cSvporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 106*a24a420cSvporpo auto *LLVMBB = &*LLVMF->begin(); 107*a24a420cSvporpo auto LLVMIt = LLVMBB->begin(); 108*a24a420cSvporpo 109*a24a420cSvporpo sandboxir::Context Ctx(C); 110*a24a420cSvporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 111*a24a420cSvporpo auto *BB = &*F->begin(); 112*a24a420cSvporpo auto It = BB->begin(); 113*a24a420cSvporpo auto TermIt = BB->getTerminator()->getIterator(); 114*a24a420cSvporpo while (It != TermIt) { 115*a24a420cSvporpo auto *FPM = cast<sandboxir::FPMathOperator>(&*It++); 116*a24a420cSvporpo auto *LLVMFPM = cast<llvm::FPMathOperator>(&*LLVMIt++); 117*a24a420cSvporpo EXPECT_EQ(FPM->isFast(), LLVMFPM->isFast()); 118*a24a420cSvporpo EXPECT_EQ(FPM->hasAllowReassoc(), LLVMFPM->hasAllowReassoc()); 119*a24a420cSvporpo EXPECT_EQ(FPM->hasNoNaNs(), LLVMFPM->hasNoNaNs()); 120*a24a420cSvporpo EXPECT_EQ(FPM->hasNoInfs(), LLVMFPM->hasNoInfs()); 121*a24a420cSvporpo EXPECT_EQ(FPM->hasNoSignedZeros(), LLVMFPM->hasNoSignedZeros()); 122*a24a420cSvporpo EXPECT_EQ(FPM->hasAllowReciprocal(), LLVMFPM->hasAllowReciprocal()); 123*a24a420cSvporpo EXPECT_EQ(FPM->hasAllowContract(), LLVMFPM->hasAllowContract()); 124*a24a420cSvporpo EXPECT_EQ(FPM->hasApproxFunc(), LLVMFPM->hasApproxFunc()); 125*a24a420cSvporpo 126*a24a420cSvporpo // There doesn't seem to be an operator== for FastMathFlags so let's do a 127*a24a420cSvporpo // string comparison instead. 128*a24a420cSvporpo std::string Str1; 129*a24a420cSvporpo raw_string_ostream SS1(Str1); 130*a24a420cSvporpo std::string Str2; 131*a24a420cSvporpo raw_string_ostream SS2(Str2); 132*a24a420cSvporpo FPM->getFastMathFlags().print(SS1); 133*a24a420cSvporpo LLVMFPM->getFastMathFlags().print(SS2); 134*a24a420cSvporpo EXPECT_EQ(Str1, Str2); 135*a24a420cSvporpo 136*a24a420cSvporpo EXPECT_EQ(FPM->getFPAccuracy(), LLVMFPM->getFPAccuracy()); 137*a24a420cSvporpo EXPECT_EQ( 138*a24a420cSvporpo sandboxir::FPMathOperator::isSupportedFloatingPointType(FPM->getType()), 139*a24a420cSvporpo llvm::FPMathOperator::isSupportedFloatingPointType(LLVMFPM->getType())); 140*a24a420cSvporpo } 141*a24a420cSvporpo } 142