1f9efc295SVasileios Porpodas //===- SandboxIRTest.cpp --------------------------------------------------===// 2f9efc295SVasileios Porpodas // 3f9efc295SVasileios Porpodas // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f9efc295SVasileios Porpodas // See https://llvm.org/LICENSE.txt for license information. 5f9efc295SVasileios Porpodas // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f9efc295SVasileios Porpodas // 7f9efc295SVasileios Porpodas //===----------------------------------------------------------------------===// 8f9efc295SVasileios Porpodas 9f9efc295SVasileios Porpodas #include "llvm/AsmParser/Parser.h" 10f9efc295SVasileios Porpodas #include "llvm/IR/BasicBlock.h" 1166d87350SJorge Gorbe Moya #include "llvm/IR/Constants.h" 12f9765a28Svporpo #include "llvm/IR/DataLayout.h" 13f9efc295SVasileios Porpodas #include "llvm/IR/Function.h" 14f9efc295SVasileios Porpodas #include "llvm/IR/Instruction.h" 15f9efc295SVasileios Porpodas #include "llvm/IR/Module.h" 162018f4ccSVasileios Porpodas #include "llvm/SandboxIR/BasicBlock.h" 172018f4ccSVasileios Porpodas #include "llvm/SandboxIR/Constant.h" 18e22b07e7Svporpo #include "llvm/SandboxIR/Function.h" 192018f4ccSVasileios Porpodas #include "llvm/SandboxIR/Instruction.h" 202018f4ccSVasileios Porpodas #include "llvm/SandboxIR/Module.h" 21d1edef56SSterling-Augustine #include "llvm/SandboxIR/Utils.h" 222018f4ccSVasileios Porpodas #include "llvm/SandboxIR/Value.h" 23f9efc295SVasileios Porpodas #include "llvm/Support/SourceMgr.h" 2412a8f504SJorge Gorbe Moya #include "gmock/gmock.h" 25f9efc295SVasileios Porpodas #include "gtest/gtest.h" 26f9efc295SVasileios Porpodas 27f9efc295SVasileios Porpodas using namespace llvm; 28f9efc295SVasileios Porpodas 29f9efc295SVasileios Porpodas struct SandboxIRTest : public testing::Test { 30f9efc295SVasileios Porpodas LLVMContext C; 31f9efc295SVasileios Porpodas std::unique_ptr<Module> M; 32f9efc295SVasileios Porpodas 33f9efc295SVasileios Porpodas void parseIR(LLVMContext &C, const char *IR) { 34f9efc295SVasileios Porpodas SMDiagnostic Err; 35f9efc295SVasileios Porpodas M = parseAssemblyString(IR, Err, C); 36f9efc295SVasileios Porpodas if (!M) 37f9efc295SVasileios Porpodas Err.print("SandboxIRTest", errs()); 38f9efc295SVasileios Porpodas } 3950881d03Svporpo BasicBlock *getBasicBlockByName(Function &F, StringRef Name) { 4050881d03Svporpo for (BasicBlock &BB : F) 4150881d03Svporpo if (BB.getName() == Name) 4250881d03Svporpo return &BB; 4350881d03Svporpo llvm_unreachable("Expected to find basic block!"); 4450881d03Svporpo } 45f9efc295SVasileios Porpodas }; 46f9efc295SVasileios Porpodas 472d8b2822Svporpo TEST_F(SandboxIRTest, ClassID) { 48d5f5dc9dSvporpo parseIR(C, R"IR( 49d5f5dc9dSvporpo define void @foo(i32 %v1) { 50d5f5dc9dSvporpo %add = add i32 %v1, 42 51d5f5dc9dSvporpo ret void 52d5f5dc9dSvporpo } 53d5f5dc9dSvporpo )IR"); 54d5f5dc9dSvporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 55d5f5dc9dSvporpo llvm::BasicBlock *LLVMBB = &*LLVMF->begin(); 56d5f5dc9dSvporpo llvm::Instruction *LLVMAdd = &*LLVMBB->begin(); 57d5f5dc9dSvporpo auto *LLVMC = cast<llvm::Constant>(LLVMAdd->getOperand(1)); 58d5f5dc9dSvporpo 59d5f5dc9dSvporpo sandboxir::Context Ctx(C); 602d8b2822Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 612d8b2822Svporpo sandboxir::Argument *Arg0 = F->getArg(0); 622d8b2822Svporpo sandboxir::BasicBlock *BB = &*F->begin(); 632d8b2822Svporpo sandboxir::Instruction *AddI = &*BB->begin(); 642d8b2822Svporpo sandboxir::Constant *Const0 = cast<sandboxir::Constant>(Ctx.getValue(LLVMC)); 65d5f5dc9dSvporpo 66d5f5dc9dSvporpo EXPECT_TRUE(isa<sandboxir::Function>(F)); 67d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Function>(Arg0)); 682d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Function>(BB)); 692d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Function>(AddI)); 70d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Function>(Const0)); 71d5f5dc9dSvporpo 72d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Argument>(F)); 73d5f5dc9dSvporpo EXPECT_TRUE(isa<sandboxir::Argument>(Arg0)); 742d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Argument>(BB)); 752d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Argument>(AddI)); 76d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Argument>(Const0)); 77d5f5dc9dSvporpo 78d5f5dc9dSvporpo EXPECT_TRUE(isa<sandboxir::Constant>(F)); 79d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Constant>(Arg0)); 802d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Constant>(BB)); 812d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Constant>(AddI)); 82d5f5dc9dSvporpo EXPECT_TRUE(isa<sandboxir::Constant>(Const0)); 83d5f5dc9dSvporpo 84d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::OpaqueInst>(F)); 85d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Arg0)); 862d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::OpaqueInst>(BB)); 876ec169d3Svporpo EXPECT_FALSE(isa<sandboxir::OpaqueInst>(AddI)); 88d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Const0)); 89d5f5dc9dSvporpo 90d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Instruction>(F)); 91d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Instruction>(Arg0)); 922d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::Instruction>(BB)); 932d8b2822Svporpo EXPECT_TRUE(isa<sandboxir::Instruction>(AddI)); 94d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::Instruction>(Const0)); 95d5f5dc9dSvporpo 96372a6beaSvporpo EXPECT_TRUE(isa<sandboxir::User>(F)); 97d5f5dc9dSvporpo EXPECT_FALSE(isa<sandboxir::User>(Arg0)); 982d8b2822Svporpo EXPECT_FALSE(isa<sandboxir::User>(BB)); 992d8b2822Svporpo EXPECT_TRUE(isa<sandboxir::User>(AddI)); 100d5f5dc9dSvporpo EXPECT_TRUE(isa<sandboxir::User>(Const0)); 10150881d03Svporpo 10250881d03Svporpo #ifndef NDEBUG 1032d8b2822Svporpo std::string Buff; 1042d8b2822Svporpo raw_string_ostream BS(Buff); 10553517231Svporpo F->dumpOS(BS); 10653517231Svporpo Arg0->dumpOS(BS); 10753517231Svporpo BB->dumpOS(BS); 10853517231Svporpo AddI->dumpOS(BS); 10953517231Svporpo Const0->dumpOS(BS); 11050881d03Svporpo #endif 11150881d03Svporpo } 11250881d03Svporpo 113f33d519cSvporpo TEST_F(SandboxIRTest, ConstantInt) { 114f33d519cSvporpo parseIR(C, R"IR( 115f33d519cSvporpo define void @foo(i32 %v0) { 116f33d519cSvporpo %add0 = add i32 %v0, 42 117f33d519cSvporpo ret void 118f33d519cSvporpo } 119f33d519cSvporpo )IR"); 120f33d519cSvporpo Function &LLVMF = *M->getFunction("foo"); 121b91b1f0bSvporpo auto *LLVMBB = &*LLVMF.begin(); 122b91b1f0bSvporpo auto *LLVMAdd0 = &*LLVMBB->begin(); 123b91b1f0bSvporpo auto *LLVMFortyTwo = cast<llvm::ConstantInt>(LLVMAdd0->getOperand(1)); 124f33d519cSvporpo sandboxir::Context Ctx(C); 125f33d519cSvporpo 126f33d519cSvporpo auto &F = *Ctx.createFunction(&LLVMF); 127f33d519cSvporpo auto &BB = *F.begin(); 128f33d519cSvporpo auto It = BB.begin(); 129f33d519cSvporpo auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++); 130f33d519cSvporpo auto *FortyTwo = cast<sandboxir::ConstantInt>(Add0->getOperand(1)); 131f33d519cSvporpo 132f33d519cSvporpo // Check that creating an identical constant gives us the same object. 133034f2b38Svporpo auto *NewCI = 134034f2b38Svporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42); 135f33d519cSvporpo EXPECT_EQ(NewCI, FortyTwo); 136b91b1f0bSvporpo { 137b91b1f0bSvporpo // Check getTrue(Ctx). 138b91b1f0bSvporpo auto *True = sandboxir::ConstantInt::getTrue(Ctx); 139b91b1f0bSvporpo EXPECT_EQ(True, Ctx.getValue(llvm::ConstantInt::getTrue(C))); 140b91b1f0bSvporpo // Check getFalse(Ctx). 141b91b1f0bSvporpo auto *False = sandboxir::ConstantInt::getFalse(Ctx); 142b91b1f0bSvporpo EXPECT_EQ(False, Ctx.getValue(llvm::ConstantInt::getFalse(C))); 143b91b1f0bSvporpo // Check getBool(Ctx). 144b91b1f0bSvporpo auto *Bool = sandboxir::ConstantInt::getBool(Ctx, true); 145b91b1f0bSvporpo EXPECT_EQ(Bool, Ctx.getValue(llvm::ConstantInt::getBool(C, true))); 146b91b1f0bSvporpo } 147b91b1f0bSvporpo { 148b91b1f0bSvporpo auto *Int1Ty = sandboxir::Type::getInt1Ty(Ctx); 149b91b1f0bSvporpo auto *LLVMInt1Ty = llvm::Type::getInt1Ty(C); 150b91b1f0bSvporpo // Check getTrue(Ty). 151b91b1f0bSvporpo auto *True = sandboxir::ConstantInt::getTrue(Int1Ty); 152b91b1f0bSvporpo EXPECT_EQ(True, Ctx.getValue(llvm::ConstantInt::getTrue(LLVMInt1Ty))); 153b91b1f0bSvporpo // Check getFalse(Ty). 154b91b1f0bSvporpo auto *False = sandboxir::ConstantInt::getFalse(Int1Ty); 155b91b1f0bSvporpo EXPECT_EQ(False, Ctx.getValue(llvm::ConstantInt::getFalse(LLVMInt1Ty))); 156b91b1f0bSvporpo // Check getBool(Ty). 157b91b1f0bSvporpo auto *Bool = sandboxir::ConstantInt::getBool(Int1Ty, true); 158b91b1f0bSvporpo EXPECT_EQ(Bool, Ctx.getValue(llvm::ConstantInt::getBool(LLVMInt1Ty, true))); 159b91b1f0bSvporpo } 160b91b1f0bSvporpo 161b91b1f0bSvporpo auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 162b91b1f0bSvporpo auto *LLVMInt32Ty = llvm::Type::getInt32Ty(C); 163b91b1f0bSvporpo { 164b91b1f0bSvporpo // Check get(Type, V). 165b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::get(Int32Ty, 43); 166b91b1f0bSvporpo auto *LLVMFortyThree = llvm::ConstantInt::get(LLVMInt32Ty, 43); 167f33d519cSvporpo EXPECT_NE(FortyThree, FortyTwo); 168b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 169b91b1f0bSvporpo } 170b91b1f0bSvporpo { 171b91b1f0bSvporpo // Check get(Type, V, IsSigned). 172b91b1f0bSvporpo auto *FortyThree = 173b91b1f0bSvporpo sandboxir::ConstantInt::get(Int32Ty, 43, /*IsSigned=*/true); 174b91b1f0bSvporpo auto *LLVMFortyThree = 175b91b1f0bSvporpo llvm::ConstantInt::get(LLVMInt32Ty, 43, /*IsSigned=*/true); 176b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 177b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 178b91b1f0bSvporpo } 179b91b1f0bSvporpo 180b91b1f0bSvporpo { 181b91b1f0bSvporpo // Check get(IntegerType, V). 182b91b1f0bSvporpo auto *FortyThree = 183b91b1f0bSvporpo sandboxir::ConstantInt::get(sandboxir::IntegerType::get(Ctx, 32), 43); 184b91b1f0bSvporpo auto *LLVMFortyThree = 185b91b1f0bSvporpo llvm::ConstantInt::get(llvm::IntegerType::get(C, 32), 43); 186b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 187b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 188b91b1f0bSvporpo } 189b91b1f0bSvporpo { 190b91b1f0bSvporpo // Check get(IntegerType, V, IsSigned). 191b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::get( 192b91b1f0bSvporpo sandboxir::IntegerType::get(Ctx, 32), 43, /*IsSigned=*/true); 193b91b1f0bSvporpo auto *LLVMFortyThree = llvm::ConstantInt::get(llvm::IntegerType::get(C, 32), 194b91b1f0bSvporpo 43, /*IsSigned=*/true); 195b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 196b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 197b91b1f0bSvporpo } 198b91b1f0bSvporpo 199b91b1f0bSvporpo { 200b91b1f0bSvporpo // Check getSigned(IntegerType, V). 201b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::getSigned( 202b91b1f0bSvporpo sandboxir::IntegerType::get(Ctx, 32), 43); 203b91b1f0bSvporpo auto *LLVMFortyThree = 204b91b1f0bSvporpo llvm::ConstantInt::getSigned(llvm::IntegerType::get(C, 32), 43); 205b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 206b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 207b91b1f0bSvporpo } 208b91b1f0bSvporpo { 209b91b1f0bSvporpo // Check getSigned(Type, V). 210b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::getSigned(Int32Ty, 43); 211b91b1f0bSvporpo auto *LLVMFortyThree = llvm::ConstantInt::getSigned(LLVMInt32Ty, 43); 212b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 213b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 214b91b1f0bSvporpo } 215b91b1f0bSvporpo { 216b91b1f0bSvporpo // Check get(Ctx, APInt). 217b91b1f0bSvporpo APInt APInt43(32, 43); 218b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::get(Ctx, APInt43); 219b91b1f0bSvporpo auto *LLVMFortyThree = llvm::ConstantInt::get(C, APInt43); 220b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 221b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 222b91b1f0bSvporpo } 223b91b1f0bSvporpo { 224b91b1f0bSvporpo // Check get(Ty, Str, Radix). 225b91b1f0bSvporpo StringRef Str("43"); 226b91b1f0bSvporpo uint8_t Radix(10); 227b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::get( 228b91b1f0bSvporpo sandboxir::IntegerType::get(Ctx, 32), Str, Radix); 229b91b1f0bSvporpo auto *LLVMFortyThree = 230b91b1f0bSvporpo llvm::ConstantInt::get(llvm::IntegerType::get(C, 32), Str, Radix); 231b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 232b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 233b91b1f0bSvporpo } 234b91b1f0bSvporpo { 235b91b1f0bSvporpo // Check get(Ty, APInt). 236b91b1f0bSvporpo APInt APInt43(32, 43); 237b91b1f0bSvporpo auto *FortyThree = sandboxir::ConstantInt::get(Int32Ty, APInt43); 238b91b1f0bSvporpo auto *LLVMFortyThree = llvm::ConstantInt::get(LLVMInt32Ty, APInt43); 239b91b1f0bSvporpo EXPECT_NE(FortyThree, FortyTwo); 240b91b1f0bSvporpo EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree)); 241b91b1f0bSvporpo } 242b91b1f0bSvporpo // Check getValue(). 243b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getValue(), LLVMFortyTwo->getValue()); 244b91b1f0bSvporpo // Check getBitWidth(). 245b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getBitWidth(), LLVMFortyTwo->getBitWidth()); 246b91b1f0bSvporpo // Check getZExtValue(). 247b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getZExtValue(), LLVMFortyTwo->getZExtValue()); 248b91b1f0bSvporpo // Check getSExtValue(). 249b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getSExtValue(), LLVMFortyTwo->getSExtValue()); 250b91b1f0bSvporpo // Check getMaybeAlignValue(). 251b91b1f0bSvporpo auto *SixtyFour = 252b91b1f0bSvporpo cast<sandboxir::ConstantInt>(sandboxir::ConstantInt::get(Int32Ty, 64)); 253b91b1f0bSvporpo auto *LLVMSixtyFour = 254b91b1f0bSvporpo cast<llvm::ConstantInt>(llvm::ConstantInt::get(LLVMInt32Ty, 64)); 255b91b1f0bSvporpo EXPECT_EQ(SixtyFour->getMaybeAlignValue(), 256b91b1f0bSvporpo LLVMSixtyFour->getMaybeAlignValue()); 257b91b1f0bSvporpo // Check getAlignValue(). 258b91b1f0bSvporpo EXPECT_EQ(SixtyFour->getAlignValue(), LLVMSixtyFour->getAlignValue()); 259b91b1f0bSvporpo // Check equalsInt(). 260b91b1f0bSvporpo EXPECT_TRUE(FortyTwo->equalsInt(42)); 261b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->equalsInt(43)); 262b91b1f0bSvporpo // Check getIntegerType(). 263b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getIntegerType(), sandboxir::IntegerType::get(Ctx, 32)); 264b91b1f0bSvporpo // Check isValueValidForType(). 265b91b1f0bSvporpo EXPECT_TRUE( 266b91b1f0bSvporpo sandboxir::ConstantInt::isValueValidForType(Int32Ty, (uint64_t)42)); 267b91b1f0bSvporpo EXPECT_TRUE( 268b91b1f0bSvporpo sandboxir::ConstantInt::isValueValidForType(Int32Ty, (int64_t)42)); 269b91b1f0bSvporpo // Check isNegative(). 270b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isNegative()); 271b91b1f0bSvporpo EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, -42)); 272b91b1f0bSvporpo // Check isZero(). 273b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isZero()); 274b91b1f0bSvporpo EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, 0)->isZero()); 275b91b1f0bSvporpo // Check isOne(). 276b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isOne()); 277b91b1f0bSvporpo EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, 1)->isOne()); 278b91b1f0bSvporpo // Check isMinusOne(). 279b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isMinusOne()); 280b91b1f0bSvporpo EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, -1)->isMinusOne()); 281b91b1f0bSvporpo // Check isMaxValue(). 282b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isMaxValue(/*Signed=*/true)); 283b91b1f0bSvporpo EXPECT_TRUE( 284b91b1f0bSvporpo sandboxir::ConstantInt::get(Int32Ty, std::numeric_limits<int32_t>::max()) 285b91b1f0bSvporpo ->isMaxValue(/*Signed=*/true)); 286b91b1f0bSvporpo // Check isMinValue(). 287b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->isMinValue(/*Signed=*/true)); 288b91b1f0bSvporpo EXPECT_TRUE( 289b91b1f0bSvporpo sandboxir::ConstantInt::get(Int32Ty, std::numeric_limits<int32_t>::min()) 290b91b1f0bSvporpo ->isMinValue(/*Signed=*/true)); 291b91b1f0bSvporpo // Check uge(). 292b91b1f0bSvporpo EXPECT_TRUE(FortyTwo->uge(41)); 293b91b1f0bSvporpo EXPECT_FALSE(FortyTwo->uge(43)); 294b91b1f0bSvporpo // Check getLimitedValue(). 295b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getLimitedValue(40u), 40u); 296b91b1f0bSvporpo EXPECT_EQ(FortyTwo->getLimitedValue(50u), 42u); 297f33d519cSvporpo } 298f33d519cSvporpo 2992c7e1b88Svporpo TEST_F(SandboxIRTest, ConstantFP) { 3002c7e1b88Svporpo parseIR(C, R"IR( 3012c7e1b88Svporpo define void @foo(float %v0, double %v1) { 3022c7e1b88Svporpo %fadd0 = fadd float %v0, 42.0 3032c7e1b88Svporpo %fadd1 = fadd double %v1, 43.0 3042c7e1b88Svporpo ret void 3052c7e1b88Svporpo } 3062c7e1b88Svporpo )IR"); 3072c7e1b88Svporpo Function &LLVMF = *M->getFunction("foo"); 3082c7e1b88Svporpo sandboxir::Context Ctx(C); 3092c7e1b88Svporpo 3102c7e1b88Svporpo auto &F = *Ctx.createFunction(&LLVMF); 3112c7e1b88Svporpo auto &BB = *F.begin(); 3122c7e1b88Svporpo auto It = BB.begin(); 3132c7e1b88Svporpo auto *FAdd0 = cast<sandboxir::BinaryOperator>(&*It++); 3142c7e1b88Svporpo auto *FAdd1 = cast<sandboxir::BinaryOperator>(&*It++); 3152c7e1b88Svporpo auto *FortyTwo = cast<sandboxir::ConstantFP>(FAdd0->getOperand(1)); 3162c7e1b88Svporpo [[maybe_unused]] auto *FortyThree = 3172c7e1b88Svporpo cast<sandboxir::ConstantFP>(FAdd1->getOperand(1)); 3182c7e1b88Svporpo 3192c7e1b88Svporpo auto *FloatTy = sandboxir::Type::getFloatTy(Ctx); 3202c7e1b88Svporpo auto *DoubleTy = sandboxir::Type::getDoubleTy(Ctx); 3212c7e1b88Svporpo auto *LLVMFloatTy = Type::getFloatTy(C); 3222c7e1b88Svporpo auto *LLVMDoubleTy = Type::getDoubleTy(C); 3232c7e1b88Svporpo // Check that creating an identical constant gives us the same object. 3242c7e1b88Svporpo auto *NewFortyTwo = sandboxir::ConstantFP::get(FloatTy, 42.0); 3252c7e1b88Svporpo EXPECT_EQ(NewFortyTwo, FortyTwo); 3262c7e1b88Svporpo // Check get(Type, double). 3272c7e1b88Svporpo auto *FortyFour = 3282c7e1b88Svporpo cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::get(FloatTy, 44.0)); 3292c7e1b88Svporpo auto *LLVMFortyFour = 3302c7e1b88Svporpo cast<llvm::ConstantFP>(llvm::ConstantFP::get(LLVMFloatTy, 44.0)); 3312c7e1b88Svporpo EXPECT_NE(FortyFour, FortyTwo); 3322c7e1b88Svporpo EXPECT_EQ(FortyFour, Ctx.getValue(LLVMFortyFour)); 3332c7e1b88Svporpo // Check get(Type, APFloat). 3342c7e1b88Svporpo auto *FortyFive = cast<sandboxir::ConstantFP>( 3352c7e1b88Svporpo sandboxir::ConstantFP::get(DoubleTy, APFloat(45.0))); 3362c7e1b88Svporpo auto *LLVMFortyFive = cast<llvm::ConstantFP>( 3372c7e1b88Svporpo llvm::ConstantFP::get(LLVMDoubleTy, APFloat(45.0))); 3382c7e1b88Svporpo EXPECT_EQ(FortyFive, Ctx.getValue(LLVMFortyFive)); 3392c7e1b88Svporpo // Check get(Type, StringRef). 3402c7e1b88Svporpo auto *FortySix = sandboxir::ConstantFP::get(FloatTy, "46.0"); 3412c7e1b88Svporpo EXPECT_EQ(FortySix, Ctx.getValue(llvm::ConstantFP::get(LLVMFloatTy, "46.0"))); 3422c7e1b88Svporpo // Check get(APFloat). 3432c7e1b88Svporpo auto *FortySeven = sandboxir::ConstantFP::get(APFloat(47.0), Ctx); 3442c7e1b88Svporpo EXPECT_EQ(FortySeven, Ctx.getValue(llvm::ConstantFP::get(C, APFloat(47.0)))); 3452c7e1b88Svporpo // Check getNaN(). 3462c7e1b88Svporpo { 3472c7e1b88Svporpo auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy); 3482c7e1b88Svporpo EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN(LLVMFloatTy))); 3492c7e1b88Svporpo } 3502c7e1b88Svporpo { 3512c7e1b88Svporpo auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy, /*Negative=*/true); 3522c7e1b88Svporpo EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN(LLVMFloatTy, 3532c7e1b88Svporpo /*Negative=*/true))); 3542c7e1b88Svporpo } 3552c7e1b88Svporpo { 3562c7e1b88Svporpo auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy, /*Negative=*/true, 3572c7e1b88Svporpo /*Payload=*/1); 3582c7e1b88Svporpo EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN( 3592c7e1b88Svporpo LLVMFloatTy, /*Negative=*/true, /*Payload=*/1))); 3602c7e1b88Svporpo } 3612c7e1b88Svporpo // Check getQNaN(). 3622c7e1b88Svporpo { 3632c7e1b88Svporpo auto *QNaN = sandboxir::ConstantFP::getQNaN(FloatTy); 3642c7e1b88Svporpo EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN(LLVMFloatTy))); 3652c7e1b88Svporpo } 3662c7e1b88Svporpo { 3672c7e1b88Svporpo auto *QNaN = sandboxir::ConstantFP::getQNaN(FloatTy, /*Negative=*/true); 3682c7e1b88Svporpo EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN(LLVMFloatTy, 3692c7e1b88Svporpo /*Negative=*/true))); 3702c7e1b88Svporpo } 3712c7e1b88Svporpo { 3722c7e1b88Svporpo APInt Payload(1, 1); 3732c7e1b88Svporpo auto *QNaN = 3742c7e1b88Svporpo sandboxir::ConstantFP::getQNaN(FloatTy, /*Negative=*/true, &Payload); 3752c7e1b88Svporpo EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN( 3762c7e1b88Svporpo LLVMFloatTy, /*Negative=*/true, &Payload))); 3772c7e1b88Svporpo } 3782c7e1b88Svporpo // Check getSNaN(). 3792c7e1b88Svporpo { 3802c7e1b88Svporpo auto *SNaN = sandboxir::ConstantFP::getSNaN(FloatTy); 3812c7e1b88Svporpo EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN(LLVMFloatTy))); 3822c7e1b88Svporpo } 3832c7e1b88Svporpo { 3842c7e1b88Svporpo auto *SNaN = sandboxir::ConstantFP::getSNaN(FloatTy, /*Negative=*/true); 3852c7e1b88Svporpo EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN(LLVMFloatTy, 3862c7e1b88Svporpo /*Negative=*/true))); 3872c7e1b88Svporpo } 3882c7e1b88Svporpo { 3892c7e1b88Svporpo APInt Payload(1, 1); 3902c7e1b88Svporpo auto *SNaN = 3912c7e1b88Svporpo sandboxir::ConstantFP::getSNaN(FloatTy, /*Negative=*/true, &Payload); 3922c7e1b88Svporpo EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN( 3932c7e1b88Svporpo LLVMFloatTy, /*Negative=*/true, &Payload))); 3942c7e1b88Svporpo } 3952c7e1b88Svporpo 3962c7e1b88Svporpo // Check getZero(). 3972c7e1b88Svporpo { 3982c7e1b88Svporpo auto *Zero = sandboxir::ConstantFP::getZero(FloatTy); 3992c7e1b88Svporpo EXPECT_EQ(Zero, Ctx.getValue(llvm::ConstantFP::getZero(LLVMFloatTy))); 4002c7e1b88Svporpo } 4012c7e1b88Svporpo { 4022c7e1b88Svporpo auto *Zero = sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true); 4032c7e1b88Svporpo EXPECT_EQ(Zero, Ctx.getValue(llvm::ConstantFP::getZero(LLVMFloatTy, 4042c7e1b88Svporpo /*Negative=*/true))); 4052c7e1b88Svporpo } 4062c7e1b88Svporpo 4072c7e1b88Svporpo // Check getNegativeZero(). 4082c7e1b88Svporpo auto *NegZero = cast<sandboxir::ConstantFP>( 4092c7e1b88Svporpo sandboxir::ConstantFP::getNegativeZero(FloatTy)); 4102c7e1b88Svporpo EXPECT_EQ(NegZero, 4112c7e1b88Svporpo Ctx.getValue(llvm::ConstantFP::getNegativeZero(LLVMFloatTy))); 4122c7e1b88Svporpo 4132c7e1b88Svporpo // Check getInfinity(). 4142c7e1b88Svporpo { 4152c7e1b88Svporpo auto *Inf = sandboxir::ConstantFP::getInfinity(FloatTy); 4162c7e1b88Svporpo EXPECT_EQ(Inf, Ctx.getValue(llvm::ConstantFP::getInfinity(LLVMFloatTy))); 4172c7e1b88Svporpo } 4182c7e1b88Svporpo { 4192c7e1b88Svporpo auto *Inf = sandboxir::ConstantFP::getInfinity(FloatTy, /*Negative=*/true); 4202c7e1b88Svporpo EXPECT_EQ(Inf, Ctx.getValue(llvm::ConstantFP::getInfinity( 4212c7e1b88Svporpo LLVMFloatTy, /*Negative=*/true))); 4222c7e1b88Svporpo } 4232c7e1b88Svporpo 4242c7e1b88Svporpo // Check isValueValidForType(). 4252c7e1b88Svporpo APFloat V(1.1); 4262c7e1b88Svporpo EXPECT_EQ(sandboxir::ConstantFP::isValueValidForType(FloatTy, V), 4272c7e1b88Svporpo llvm::ConstantFP::isValueValidForType(LLVMFloatTy, V)); 4282c7e1b88Svporpo // Check getValueAPF(). 4292c7e1b88Svporpo EXPECT_EQ(FortyFour->getValueAPF(), LLVMFortyFour->getValueAPF()); 4302c7e1b88Svporpo // Check getValue(). 4312c7e1b88Svporpo EXPECT_EQ(FortyFour->getValue(), LLVMFortyFour->getValue()); 4322c7e1b88Svporpo // Check isZero(). 4332c7e1b88Svporpo EXPECT_EQ(FortyFour->isZero(), LLVMFortyFour->isZero()); 4342c7e1b88Svporpo EXPECT_TRUE(sandboxir::ConstantFP::getZero(FloatTy)); 4352c7e1b88Svporpo EXPECT_TRUE(sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true)); 4362c7e1b88Svporpo // Check isNegative(). 4372c7e1b88Svporpo EXPECT_TRUE(cast<sandboxir::ConstantFP>( 4382c7e1b88Svporpo sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true)) 4392c7e1b88Svporpo ->isNegative()); 4402c7e1b88Svporpo // Check isInfinity(). 4412c7e1b88Svporpo EXPECT_TRUE( 4422c7e1b88Svporpo cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::getInfinity(FloatTy)) 4432c7e1b88Svporpo ->isInfinity()); 4442c7e1b88Svporpo // Check isNaN(). 4452c7e1b88Svporpo EXPECT_TRUE( 4462c7e1b88Svporpo cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::getNaN(FloatTy)) 4472c7e1b88Svporpo ->isNaN()); 4482c7e1b88Svporpo // Check isExactlyValue(APFloat). 4492c7e1b88Svporpo EXPECT_TRUE(NegZero->isExactlyValue(NegZero->getValueAPF())); 4502c7e1b88Svporpo // Check isExactlyValue(double). 4512c7e1b88Svporpo EXPECT_TRUE(NegZero->isExactlyValue(-0.0)); 4522c7e1b88Svporpo } 4532c7e1b88Svporpo 454814aa432Svporpo // Tests ConstantArray, ConstantStruct and ConstantVector. 455814aa432Svporpo TEST_F(SandboxIRTest, ConstantAggregate) { 456814aa432Svporpo // Note: we are using i42 to avoid the creation of ConstantDataVector or 457814aa432Svporpo // ConstantDataArray. 458814aa432Svporpo parseIR(C, R"IR( 459814aa432Svporpo define void @foo() { 460814aa432Svporpo %array = extractvalue [2 x i42] [i42 0, i42 1], 0 461814aa432Svporpo %struct = extractvalue {i42, i42} {i42 0, i42 1}, 0 462814aa432Svporpo %vector = extractelement <2 x i42> <i42 0, i42 1>, i32 0 463814aa432Svporpo ret void 464814aa432Svporpo } 465814aa432Svporpo )IR"); 466814aa432Svporpo Function &LLVMF = *M->getFunction("foo"); 467814aa432Svporpo sandboxir::Context Ctx(C); 468814aa432Svporpo 469814aa432Svporpo auto &F = *Ctx.createFunction(&LLVMF); 470814aa432Svporpo auto &BB = *F.begin(); 471814aa432Svporpo auto It = BB.begin(); 472814aa432Svporpo auto *I0 = &*It++; 473814aa432Svporpo auto *I1 = &*It++; 474814aa432Svporpo auto *I2 = &*It++; 475814aa432Svporpo // Check classof() and creation. 476814aa432Svporpo auto *Array = cast<sandboxir::ConstantArray>(I0->getOperand(0)); 477814aa432Svporpo EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Array)); 478814aa432Svporpo auto *Struct = cast<sandboxir::ConstantStruct>(I1->getOperand(0)); 479814aa432Svporpo EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Struct)); 480814aa432Svporpo auto *Vector = cast<sandboxir::ConstantVector>(I2->getOperand(0)); 481814aa432Svporpo EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Vector)); 482814aa432Svporpo 483814aa432Svporpo auto *ZeroI42 = cast<sandboxir::ConstantInt>(Array->getOperand(0)); 484814aa432Svporpo auto *OneI42 = cast<sandboxir::ConstantInt>(Array->getOperand(1)); 485814aa432Svporpo // Check ConstantArray::get(), getType(). 486814aa432Svporpo auto *NewCA = 487814aa432Svporpo sandboxir::ConstantArray::get(Array->getType(), {ZeroI42, OneI42}); 488814aa432Svporpo EXPECT_EQ(NewCA, Array); 489814aa432Svporpo 490814aa432Svporpo // Check ConstantStruct::get(), getType(). 491814aa432Svporpo auto *NewCS = 492814aa432Svporpo sandboxir::ConstantStruct::get(Struct->getType(), {ZeroI42, OneI42}); 493814aa432Svporpo EXPECT_EQ(NewCS, Struct); 494814aa432Svporpo // Check ConstantStruct::get(...). 495814aa432Svporpo auto *NewCS2 = 496814aa432Svporpo sandboxir::ConstantStruct::get(Struct->getType(), ZeroI42, OneI42); 497814aa432Svporpo EXPECT_EQ(NewCS2, Struct); 498814aa432Svporpo // Check ConstantStruct::getAnon(ArayRef). 499814aa432Svporpo auto *AnonCS = sandboxir::ConstantStruct::getAnon({ZeroI42, OneI42}); 500814aa432Svporpo EXPECT_FALSE(cast<sandboxir::StructType>(AnonCS->getType())->isPacked()); 501814aa432Svporpo auto *AnonCSPacked = 502814aa432Svporpo sandboxir::ConstantStruct::getAnon({ZeroI42, OneI42}, /*Packed=*/true); 503814aa432Svporpo EXPECT_TRUE(cast<sandboxir::StructType>(AnonCSPacked->getType())->isPacked()); 504814aa432Svporpo // Check ConstantStruct::getAnon(Ctx, ArrayRef). 505814aa432Svporpo auto *AnonCS2 = sandboxir::ConstantStruct::getAnon(Ctx, {ZeroI42, OneI42}); 506814aa432Svporpo EXPECT_EQ(AnonCS2, AnonCS); 507814aa432Svporpo auto *AnonCS2Packed = sandboxir::ConstantStruct::getAnon( 508814aa432Svporpo Ctx, {ZeroI42, OneI42}, /*Packed=*/true); 509814aa432Svporpo EXPECT_EQ(AnonCS2Packed, AnonCSPacked); 510814aa432Svporpo // Check ConstantStruct::getTypeForElements(Ctx, ArrayRef). 511814aa432Svporpo auto *StructTy = 512814aa432Svporpo sandboxir::ConstantStruct::getTypeForElements(Ctx, {ZeroI42, OneI42}); 513814aa432Svporpo EXPECT_EQ(StructTy, Struct->getType()); 514814aa432Svporpo EXPECT_FALSE(StructTy->isPacked()); 515814aa432Svporpo // Check ConstantStruct::getTypeForElements(Ctx, ArrayRef, Packed). 516814aa432Svporpo auto *StructTyPacked = sandboxir::ConstantStruct::getTypeForElements( 517814aa432Svporpo Ctx, {ZeroI42, OneI42}, /*Packed=*/true); 518814aa432Svporpo EXPECT_TRUE(StructTyPacked->isPacked()); 519814aa432Svporpo // Check ConstantStruct::getTypeForElements(ArrayRef). 520814aa432Svporpo auto *StructTy2 = 521814aa432Svporpo sandboxir::ConstantStruct::getTypeForElements(Ctx, {ZeroI42, OneI42}); 522814aa432Svporpo EXPECT_EQ(StructTy2, Struct->getType()); 523814aa432Svporpo // Check ConstantStruct::getTypeForElements(ArrayRef, Packed). 524814aa432Svporpo auto *StructTy2Packed = sandboxir::ConstantStruct::getTypeForElements( 525814aa432Svporpo Ctx, {ZeroI42, OneI42}, /*Packed=*/true); 526814aa432Svporpo EXPECT_EQ(StructTy2Packed, StructTyPacked); 527814aa432Svporpo } 528814aa432Svporpo 529df50751dSvporpo TEST_F(SandboxIRTest, ConstantAggregateZero) { 530df50751dSvporpo parseIR(C, R"IR( 531df50751dSvporpo define void @foo(ptr %ptr, {i32, i8} %v1, <2 x i8> %v2) { 532df50751dSvporpo %extr0 = extractvalue [2 x i8] zeroinitializer, 0 533df50751dSvporpo %extr1 = extractvalue {i32, i8} zeroinitializer, 0 534df50751dSvporpo %extr2 = extractelement <2 x i8> zeroinitializer, i32 0 535df50751dSvporpo ret void 536df50751dSvporpo } 537df50751dSvporpo )IR"); 538df50751dSvporpo Function &LLVMF = *M->getFunction("foo"); 539df50751dSvporpo sandboxir::Context Ctx(C); 540df50751dSvporpo 541df50751dSvporpo auto &F = *Ctx.createFunction(&LLVMF); 542df50751dSvporpo auto &BB = *F.begin(); 543df50751dSvporpo auto It = BB.begin(); 544df50751dSvporpo auto *Extr0 = &*It++; 545df50751dSvporpo auto *Extr1 = &*It++; 546df50751dSvporpo auto *Extr2 = &*It++; 547df50751dSvporpo [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 548df50751dSvporpo auto *Zero32 = 549df50751dSvporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0); 550df50751dSvporpo auto *Zero8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0); 551df50751dSvporpo auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx); 552df50751dSvporpo auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 553df50751dSvporpo auto *ArrayTy = sandboxir::ArrayType::get(Int8Ty, 2u); 554df50751dSvporpo auto *StructTy = sandboxir::StructType::get(Ctx, {Int32Ty, Int8Ty}); 555df50751dSvporpo auto *VectorTy = 556df50751dSvporpo sandboxir::VectorType::get(Int8Ty, ElementCount::getFixed(2u)); 557df50751dSvporpo 558df50751dSvporpo // Check creation and classof(). 559df50751dSvporpo auto *ArrayCAZ = cast<sandboxir::ConstantAggregateZero>(Extr0->getOperand(0)); 560df50751dSvporpo EXPECT_EQ(ArrayCAZ->getType(), ArrayTy); 561df50751dSvporpo auto *StructCAZ = 562df50751dSvporpo cast<sandboxir::ConstantAggregateZero>(Extr1->getOperand(0)); 563df50751dSvporpo EXPECT_EQ(StructCAZ->getType(), StructTy); 564df50751dSvporpo auto *VectorCAZ = 565df50751dSvporpo cast<sandboxir::ConstantAggregateZero>(Extr2->getOperand(0)); 566df50751dSvporpo EXPECT_EQ(VectorCAZ->getType(), VectorTy); 567df50751dSvporpo // Check get(). 568df50751dSvporpo auto *SameVectorCAZ = 569df50751dSvporpo sandboxir::ConstantAggregateZero::get(sandboxir::VectorType::get( 570df50751dSvporpo sandboxir::Type::getInt8Ty(Ctx), ElementCount::getFixed(2))); 571df50751dSvporpo EXPECT_EQ(SameVectorCAZ, VectorCAZ); // Should be uniqued. 572df50751dSvporpo auto *NewVectorCAZ = 573df50751dSvporpo sandboxir::ConstantAggregateZero::get(sandboxir::VectorType::get( 574df50751dSvporpo sandboxir::Type::getInt8Ty(Ctx), ElementCount::getFixed(4))); 575df50751dSvporpo EXPECT_NE(NewVectorCAZ, VectorCAZ); 576df50751dSvporpo // Check getSequentialElement(). 577df50751dSvporpo auto *SeqElm = VectorCAZ->getSequentialElement(); 578df50751dSvporpo EXPECT_EQ(SeqElm, 579df50751dSvporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0)); 580df50751dSvporpo // Check getStructElement(). 581df50751dSvporpo auto *StructElm0 = StructCAZ->getStructElement(0); 582df50751dSvporpo auto *StructElm1 = StructCAZ->getStructElement(1); 583df50751dSvporpo EXPECT_EQ(StructElm0, Zero32); 584df50751dSvporpo EXPECT_EQ(StructElm1, Zero8); 585df50751dSvporpo // Check getElementValue(Constant). 586df50751dSvporpo EXPECT_EQ(ArrayCAZ->getElementValue(Zero32), Zero8); 587df50751dSvporpo EXPECT_EQ(StructCAZ->getElementValue(Zero32), Zero32); 588df50751dSvporpo EXPECT_EQ(VectorCAZ->getElementValue(Zero32), Zero8); 589df50751dSvporpo // Check getElementValue(unsigned). 590df50751dSvporpo EXPECT_EQ(ArrayCAZ->getElementValue(0u), Zero8); 591df50751dSvporpo EXPECT_EQ(StructCAZ->getElementValue(0u), Zero32); 592df50751dSvporpo EXPECT_EQ(VectorCAZ->getElementValue(0u), Zero8); 593df50751dSvporpo // Check getElementCount(). 594df50751dSvporpo EXPECT_EQ(ArrayCAZ->getElementCount(), ElementCount::getFixed(2)); 595df50751dSvporpo EXPECT_EQ(NewVectorCAZ->getElementCount(), ElementCount::getFixed(4)); 596df50751dSvporpo } 597df50751dSvporpo 598950bb685Svporpo TEST_F(SandboxIRTest, ConstantPointerNull) { 599950bb685Svporpo parseIR(C, R"IR( 600950bb685Svporpo define ptr @foo() { 601950bb685Svporpo ret ptr null 602950bb685Svporpo } 603950bb685Svporpo )IR"); 604950bb685Svporpo Function &LLVMF = *M->getFunction("foo"); 605950bb685Svporpo sandboxir::Context Ctx(C); 606950bb685Svporpo 607950bb685Svporpo auto &F = *Ctx.createFunction(&LLVMF); 608950bb685Svporpo auto &BB = *F.begin(); 609950bb685Svporpo auto It = BB.begin(); 610950bb685Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 611950bb685Svporpo // Check classof() and creation. 612950bb685Svporpo auto *CPNull = cast<sandboxir::ConstantPointerNull>(Ret->getReturnValue()); 613950bb685Svporpo // Check get(). 614950bb685Svporpo auto *NewCPNull = 615950bb685Svporpo sandboxir::ConstantPointerNull::get(sandboxir::PointerType::get(Ctx, 0u)); 616950bb685Svporpo EXPECT_EQ(NewCPNull, CPNull); 617950bb685Svporpo auto *NewCPNull2 = 618950bb685Svporpo sandboxir::ConstantPointerNull::get(sandboxir::PointerType::get(Ctx, 1u)); 619950bb685Svporpo EXPECT_NE(NewCPNull2, CPNull); 620950bb685Svporpo // Check getType(). 621950bb685Svporpo EXPECT_EQ(CPNull->getType(), sandboxir::PointerType::get(Ctx, 0u)); 622950bb685Svporpo EXPECT_EQ(NewCPNull2->getType(), sandboxir::PointerType::get(Ctx, 1u)); 623950bb685Svporpo } 624950bb685Svporpo 625fd2da9e5Svporpo TEST_F(SandboxIRTest, PoisonValue) { 626fd2da9e5Svporpo parseIR(C, R"IR( 627fd2da9e5Svporpo define void @foo() { 628fd2da9e5Svporpo %i0 = add i32 poison, poison 629fd2da9e5Svporpo %i1 = add <2 x i32> poison, poison 630fd2da9e5Svporpo %i2 = extractvalue {i32, i8} poison, 0 631fd2da9e5Svporpo ret void 632fd2da9e5Svporpo } 633fd2da9e5Svporpo )IR"); 634fd2da9e5Svporpo Function &LLVMF = *M->getFunction("foo"); 635fd2da9e5Svporpo sandboxir::Context Ctx(C); 636fd2da9e5Svporpo 637fd2da9e5Svporpo auto &F = *Ctx.createFunction(&LLVMF); 638fd2da9e5Svporpo auto &BB = *F.begin(); 639fd2da9e5Svporpo auto It = BB.begin(); 640fd2da9e5Svporpo auto *I0 = &*It++; 641fd2da9e5Svporpo auto *I1 = &*It++; 642fd2da9e5Svporpo auto *I2 = &*It++; 643fd2da9e5Svporpo auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 644fd2da9e5Svporpo auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx); 645fd2da9e5Svporpo auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u); 646fd2da9e5Svporpo auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u); 647fd2da9e5Svporpo 648fd2da9e5Svporpo // Check classof() and creation. 649fd2da9e5Svporpo auto *Poison = cast<sandboxir::PoisonValue>(I0->getOperand(0)); 650fd2da9e5Svporpo EXPECT_EQ(Poison->getType(), Int32Ty); 651ae02211eSvporpo EXPECT_TRUE(isa<sandboxir::UndefValue>(Poison)); // Poison is Undef 652fd2da9e5Svporpo // Check get(). 653fd2da9e5Svporpo auto *NewPoison = sandboxir::PoisonValue::get(Int32Ty); 654fd2da9e5Svporpo EXPECT_EQ(NewPoison, Poison); 655fd2da9e5Svporpo auto *NewPoison2 = 656fd2da9e5Svporpo sandboxir::PoisonValue::get(sandboxir::PointerType::get(Ctx, 0u)); 657fd2da9e5Svporpo EXPECT_NE(NewPoison2, Poison); 658fd2da9e5Svporpo // Check getSequentialElement(). 659fd2da9e5Svporpo auto *PoisonVector = cast<sandboxir::PoisonValue>(I1->getOperand(0)); 660fd2da9e5Svporpo auto *SeqElm = PoisonVector->getSequentialElement(); 661fd2da9e5Svporpo EXPECT_EQ(SeqElm->getType(), Int32Ty); 662fd2da9e5Svporpo // Check getStructElement(). 663fd2da9e5Svporpo auto *PoisonStruct = cast<sandboxir::PoisonValue>(I2->getOperand(0)); 664fd2da9e5Svporpo auto *StrElm0 = PoisonStruct->getStructElement(0); 665fd2da9e5Svporpo auto *StrElm1 = PoisonStruct->getStructElement(1); 666fd2da9e5Svporpo EXPECT_EQ(StrElm0->getType(), Int32Ty); 667fd2da9e5Svporpo EXPECT_EQ(StrElm1->getType(), Int8Ty); 668fd2da9e5Svporpo // Check getElementValue(Constant) 669fd2da9e5Svporpo EXPECT_EQ(PoisonStruct->getElementValue(Zero32), 670fd2da9e5Svporpo sandboxir::PoisonValue::get(Int32Ty)); 671fd2da9e5Svporpo EXPECT_EQ(PoisonStruct->getElementValue(One32), 672fd2da9e5Svporpo sandboxir::PoisonValue::get(Int8Ty)); 673fd2da9e5Svporpo // Check getElementValue(unsigned) 674fd2da9e5Svporpo EXPECT_EQ(PoisonStruct->getElementValue(0u), 675fd2da9e5Svporpo sandboxir::PoisonValue::get(Int32Ty)); 676fd2da9e5Svporpo EXPECT_EQ(PoisonStruct->getElementValue(1u), 677fd2da9e5Svporpo sandboxir::PoisonValue::get(Int8Ty)); 678fd2da9e5Svporpo } 679fd2da9e5Svporpo 680ae02211eSvporpo TEST_F(SandboxIRTest, UndefValue) { 681ae02211eSvporpo parseIR(C, R"IR( 682ae02211eSvporpo define void @foo() { 683ae02211eSvporpo %i0 = add i32 undef, undef 684ae02211eSvporpo %i1 = add <2 x i32> undef, undef 685ae02211eSvporpo %i2 = extractvalue {i32, i8} undef, 0 686ae02211eSvporpo ret void 687ae02211eSvporpo } 688ae02211eSvporpo )IR"); 689ae02211eSvporpo Function &LLVMF = *M->getFunction("foo"); 690ae02211eSvporpo sandboxir::Context Ctx(C); 691ae02211eSvporpo 692ae02211eSvporpo auto &F = *Ctx.createFunction(&LLVMF); 693ae02211eSvporpo auto &BB = *F.begin(); 694ae02211eSvporpo auto It = BB.begin(); 695ae02211eSvporpo auto *I0 = &*It++; 696ae02211eSvporpo auto *I1 = &*It++; 697ae02211eSvporpo auto *I2 = &*It++; 698ae02211eSvporpo auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx); 699ae02211eSvporpo auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx); 700ae02211eSvporpo auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u); 701ae02211eSvporpo auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u); 702ae02211eSvporpo 703ae02211eSvporpo // Check classof() and creation. 704ae02211eSvporpo auto *Undef = cast<sandboxir::UndefValue>(I0->getOperand(0)); 705ae02211eSvporpo EXPECT_EQ(Undef->getType(), Int32Ty); 706ae02211eSvporpo EXPECT_FALSE(isa<sandboxir::PoisonValue>(Undef)); // Undef is not Poison 707ae02211eSvporpo // Check get(). 708ae02211eSvporpo auto *NewUndef = sandboxir::UndefValue::get(Int32Ty); 709ae02211eSvporpo EXPECT_EQ(NewUndef, Undef); 710ae02211eSvporpo auto *NewUndef2 = 711ae02211eSvporpo sandboxir::UndefValue::get(sandboxir::PointerType::get(Ctx, 0u)); 712ae02211eSvporpo EXPECT_NE(NewUndef2, Undef); 713ae02211eSvporpo // Check getSequentialElement(). 714ae02211eSvporpo auto *UndefVector = cast<sandboxir::UndefValue>(I1->getOperand(0)); 715ae02211eSvporpo auto *SeqElm = UndefVector->getSequentialElement(); 716ae02211eSvporpo EXPECT_EQ(SeqElm->getType(), Int32Ty); 717ae02211eSvporpo // Check getStructElement(). 718ae02211eSvporpo auto *UndefStruct = cast<sandboxir::UndefValue>(I2->getOperand(0)); 719ae02211eSvporpo auto *StrElm0 = UndefStruct->getStructElement(0); 720ae02211eSvporpo auto *StrElm1 = UndefStruct->getStructElement(1); 721ae02211eSvporpo EXPECT_EQ(StrElm0->getType(), Int32Ty); 722ae02211eSvporpo EXPECT_EQ(StrElm1->getType(), Int8Ty); 723ae02211eSvporpo // Check getElementValue(Constant) 724ae02211eSvporpo EXPECT_EQ(UndefStruct->getElementValue(Zero32), 725ae02211eSvporpo sandboxir::UndefValue::get(Int32Ty)); 726ae02211eSvporpo EXPECT_EQ(UndefStruct->getElementValue(One32), 727ae02211eSvporpo sandboxir::UndefValue::get(Int8Ty)); 728ae02211eSvporpo // Check getElementValue(unsigned) 729ae02211eSvporpo EXPECT_EQ(UndefStruct->getElementValue(0u), 730ae02211eSvporpo sandboxir::UndefValue::get(Int32Ty)); 731ae02211eSvporpo EXPECT_EQ(UndefStruct->getElementValue(1u), 732ae02211eSvporpo sandboxir::UndefValue::get(Int8Ty)); 733ae02211eSvporpo // Check getNumElements(). 734ae02211eSvporpo EXPECT_EQ(UndefVector->getNumElements(), 2u); 735ae02211eSvporpo EXPECT_EQ(UndefStruct->getNumElements(), 2u); 736ae02211eSvporpo } 737ae02211eSvporpo 7386d859c17Svporpo TEST_F(SandboxIRTest, GlobalValue) { 7396d859c17Svporpo parseIR(C, R"IR( 7406d859c17Svporpo declare external void @bar() 7416d859c17Svporpo define void @foo() { 7426d859c17Svporpo call void @bar() 7436d859c17Svporpo ret void 7446d859c17Svporpo } 7456d859c17Svporpo )IR"); 7466d859c17Svporpo Function &LLVMF = *M->getFunction("foo"); 7476d859c17Svporpo auto *LLVMBB = &*LLVMF.begin(); 7486d859c17Svporpo auto LLVMIt = LLVMBB->begin(); 7496d859c17Svporpo auto *LLVMCall = cast<llvm::CallInst>(&*LLVMIt++); 7506d859c17Svporpo auto *LLVMGV = cast<llvm::GlobalValue>(LLVMCall->getCalledOperand()); 7516d859c17Svporpo sandboxir::Context Ctx(C); 7526d859c17Svporpo 7536d859c17Svporpo auto &F = *Ctx.createFunction(&LLVMF); 7546d859c17Svporpo auto *BB = &*F.begin(); 7556d859c17Svporpo auto It = BB->begin(); 7566d859c17Svporpo auto *Call = cast<sandboxir::CallInst>(&*It++); 7576d859c17Svporpo [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 7586d859c17Svporpo 7596d859c17Svporpo // Check classof(), creation, getFunction(), getBasicBlock(). 7606d859c17Svporpo auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand()); 7616d859c17Svporpo // Check getAddressSpace(). 7626d859c17Svporpo EXPECT_EQ(GV->getAddressSpace(), LLVMGV->getAddressSpace()); 7636d859c17Svporpo // Check hasGlobalUnnamedAddr(). 7646d859c17Svporpo EXPECT_EQ(GV->hasGlobalUnnamedAddr(), LLVMGV->hasGlobalUnnamedAddr()); 7656d859c17Svporpo // Check hasAtLeastLocalUnnamedAddr(). 7666d859c17Svporpo EXPECT_EQ(GV->hasAtLeastLocalUnnamedAddr(), 7676d859c17Svporpo LLVMGV->hasAtLeastLocalUnnamedAddr()); 7686d859c17Svporpo // Check getUnnamedAddr(). 7696d859c17Svporpo EXPECT_EQ(GV->getUnnamedAddr(), LLVMGV->getUnnamedAddr()); 7706d859c17Svporpo // Check setUnnamedAddr(). 7716d859c17Svporpo auto OrigUnnamedAddr = GV->getUnnamedAddr(); 7726d859c17Svporpo auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global; 7736d859c17Svporpo EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr); 7746d859c17Svporpo GV->setUnnamedAddr(NewUnnamedAddr); 7756d859c17Svporpo EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr); 7766d859c17Svporpo GV->setUnnamedAddr(OrigUnnamedAddr); 7776d859c17Svporpo EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr); 7786d859c17Svporpo // Check getMinUnnamedAddr(). 7796d859c17Svporpo EXPECT_EQ( 7806d859c17Svporpo sandboxir::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr, 7816d859c17Svporpo NewUnnamedAddr), 7826d859c17Svporpo llvm::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr, NewUnnamedAddr)); 7836d859c17Svporpo // Check hasComdat(). 7846d859c17Svporpo EXPECT_EQ(GV->hasComdat(), LLVMGV->hasComdat()); 7856d859c17Svporpo // Check getVisibility(). 7866d859c17Svporpo EXPECT_EQ(GV->getVisibility(), LLVMGV->getVisibility()); 7876d859c17Svporpo // Check hasDefaultVisibility(). 7886d859c17Svporpo EXPECT_EQ(GV->hasDefaultVisibility(), LLVMGV->hasDefaultVisibility()); 7896d859c17Svporpo // Check hasHiddenVisibility(). 7906d859c17Svporpo EXPECT_EQ(GV->hasHiddenVisibility(), LLVMGV->hasHiddenVisibility()); 7916d859c17Svporpo // Check hasProtectedVisibility(). 7926d859c17Svporpo EXPECT_EQ(GV->hasProtectedVisibility(), LLVMGV->hasProtectedVisibility()); 7936d859c17Svporpo // Check setVisibility(). 7946d859c17Svporpo auto OrigVisibility = GV->getVisibility(); 7956d859c17Svporpo auto NewVisibility = 7966d859c17Svporpo sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility; 7976d859c17Svporpo EXPECT_NE(NewVisibility, OrigVisibility); 7986d859c17Svporpo GV->setVisibility(NewVisibility); 7996d859c17Svporpo EXPECT_EQ(GV->getVisibility(), NewVisibility); 8006d859c17Svporpo GV->setVisibility(OrigVisibility); 8016d859c17Svporpo EXPECT_EQ(GV->getVisibility(), OrigVisibility); 8026d859c17Svporpo } 8036d859c17Svporpo 8049f738c84Svporpo TEST_F(SandboxIRTest, GlobalObject) { 8059f738c84Svporpo parseIR(C, R"IR( 8069f738c84Svporpo declare external void @bar() 8079f738c84Svporpo define void @foo() { 8089f738c84Svporpo call void @bar() 8099f738c84Svporpo ret void 8109f738c84Svporpo } 8119f738c84Svporpo )IR"); 8129f738c84Svporpo Function &LLVMF = *M->getFunction("foo"); 8139f738c84Svporpo auto *LLVMBB = &*LLVMF.begin(); 8149f738c84Svporpo auto LLVMIt = LLVMBB->begin(); 8159f738c84Svporpo auto *LLVMCall = cast<llvm::CallInst>(&*LLVMIt++); 8169f738c84Svporpo auto *LLVMGO = cast<llvm::GlobalObject>(LLVMCall->getCalledOperand()); 8179f738c84Svporpo sandboxir::Context Ctx(C); 8189f738c84Svporpo 8199f738c84Svporpo auto &F = *Ctx.createFunction(&LLVMF); 8209f738c84Svporpo auto *BB = &*F.begin(); 8219f738c84Svporpo auto It = BB->begin(); 8229f738c84Svporpo auto *Call = cast<sandboxir::CallInst>(&*It++); 8239f738c84Svporpo // Check classof(), creation. 8249f738c84Svporpo auto *GO = cast<sandboxir::GlobalObject>(Call->getCalledOperand()); 8259f738c84Svporpo // Check getAlignment(). 8269f738c84Svporpo EXPECT_EQ(GO->getAlignment(), LLVMGO->getAlignment()); 8279f738c84Svporpo // Check getAlign(). 8289f738c84Svporpo EXPECT_EQ(GO->getAlign(), LLVMGO->getAlign()); 8299f738c84Svporpo // Check setAlignment(). 8309f738c84Svporpo auto OrigMaybeAlign = GO->getAlign(); 8319f738c84Svporpo auto NewMaybeAlign = MaybeAlign(128); 8329f738c84Svporpo EXPECT_NE(NewMaybeAlign, OrigMaybeAlign); 8339f738c84Svporpo GO->setAlignment(NewMaybeAlign); 8349f738c84Svporpo EXPECT_EQ(GO->getAlign(), NewMaybeAlign); 8359f738c84Svporpo GO->setAlignment(OrigMaybeAlign); 8369f738c84Svporpo EXPECT_EQ(GO->getAlign(), OrigMaybeAlign); 8379f738c84Svporpo // Check getGlobalObjectSubClassData(). 8389f738c84Svporpo EXPECT_EQ(GO->getGlobalObjectSubClassData(), 8399f738c84Svporpo LLVMGO->getGlobalObjectSubClassData()); 8409f738c84Svporpo // Check setGlobalObjectSubClassData(). 8419f738c84Svporpo auto OrigGOSCD = GO->getGlobalObjectSubClassData(); 8429f738c84Svporpo auto NewGOSCD = 1u; 8439f738c84Svporpo EXPECT_NE(NewGOSCD, OrigGOSCD); 8449f738c84Svporpo GO->setGlobalObjectSubClassData(NewGOSCD); 8459f738c84Svporpo EXPECT_EQ(GO->getGlobalObjectSubClassData(), NewGOSCD); 8469f738c84Svporpo GO->setGlobalObjectSubClassData(OrigGOSCD); 8479f738c84Svporpo EXPECT_EQ(GO->getGlobalObjectSubClassData(), OrigGOSCD); 8489f738c84Svporpo // Check hasSection(). 8499f738c84Svporpo EXPECT_EQ(GO->hasSection(), LLVMGO->hasSection()); 8509f738c84Svporpo // Check getSection(). 8519f738c84Svporpo EXPECT_EQ(GO->getSection(), LLVMGO->getSection()); 8529f738c84Svporpo // Check setSection(). 8539f738c84Svporpo auto OrigSection = GO->getSection(); 8549f738c84Svporpo auto NewSection = ".some_section"; 8559f738c84Svporpo EXPECT_NE(NewSection, OrigSection); 8569f738c84Svporpo GO->setSection(NewSection); 8579f738c84Svporpo EXPECT_EQ(GO->getSection(), NewSection); 8589f738c84Svporpo GO->setSection(OrigSection); 8599f738c84Svporpo EXPECT_EQ(GO->getSection(), OrigSection); 8609f738c84Svporpo // Check hasComdat(). 8619f738c84Svporpo EXPECT_EQ(GO->hasComdat(), LLVMGO->hasComdat()); 8629f738c84Svporpo // Check getVCallVisibility(). 8639f738c84Svporpo EXPECT_EQ(GO->getVCallVisibility(), LLVMGO->getVCallVisibility()); 8649f738c84Svporpo // Check canIncreaseAlignment(). 8659f738c84Svporpo EXPECT_EQ(GO->canIncreaseAlignment(), LLVMGO->canIncreaseAlignment()); 8669f738c84Svporpo } 8679f738c84Svporpo 868ae3e8258Svporpo TEST_F(SandboxIRTest, GlobalIFunc) { 869ae3e8258Svporpo parseIR(C, R"IR( 870ae3e8258Svporpo declare external void @bar() 871ae3e8258Svporpo @ifunc0 = ifunc void(), ptr @foo 872ae3e8258Svporpo @ifunc1 = ifunc void(), ptr @foo 873ae3e8258Svporpo define void @foo() { 874ae3e8258Svporpo call void @ifunc0() 875ae3e8258Svporpo call void @ifunc1() 876ae3e8258Svporpo call void @bar() 877ae3e8258Svporpo ret void 878ae3e8258Svporpo } 879ae3e8258Svporpo )IR"); 880ae3e8258Svporpo Function &LLVMF = *M->getFunction("foo"); 881ae3e8258Svporpo auto *LLVMBB = &*LLVMF.begin(); 882ae3e8258Svporpo auto LLVMIt = LLVMBB->begin(); 883ae3e8258Svporpo auto *LLVMCall0 = cast<llvm::CallInst>(&*LLVMIt++); 884ae3e8258Svporpo auto *LLVMIFunc0 = cast<llvm::GlobalIFunc>(LLVMCall0->getCalledOperand()); 885ae3e8258Svporpo 886ae3e8258Svporpo sandboxir::Context Ctx(C); 887ae3e8258Svporpo 888ae3e8258Svporpo auto &F = *Ctx.createFunction(&LLVMF); 889ae3e8258Svporpo auto *BB = &*F.begin(); 890ae3e8258Svporpo auto It = BB->begin(); 891ae3e8258Svporpo auto *Call0 = cast<sandboxir::CallInst>(&*It++); 892ae3e8258Svporpo auto *Call1 = cast<sandboxir::CallInst>(&*It++); 893ae3e8258Svporpo auto *CallBar = cast<sandboxir::CallInst>(&*It++); 894ae3e8258Svporpo // Check classof(), creation. 895ae3e8258Svporpo auto *IFunc0 = cast<sandboxir::GlobalIFunc>(Call0->getCalledOperand()); 896ae3e8258Svporpo auto *IFunc1 = cast<sandboxir::GlobalIFunc>(Call1->getCalledOperand()); 897ae3e8258Svporpo auto *Bar = cast<sandboxir::Function>(CallBar->getCalledOperand()); 898ae3e8258Svporpo 899ae3e8258Svporpo // Check getIterator(). 900ae3e8258Svporpo { 901ae3e8258Svporpo auto It0 = IFunc0->getIterator(); 902ae3e8258Svporpo auto It1 = IFunc1->getIterator(); 903ae3e8258Svporpo EXPECT_EQ(&*It0, IFunc0); 904ae3e8258Svporpo EXPECT_EQ(&*It1, IFunc1); 905ae3e8258Svporpo EXPECT_EQ(std::next(It0), It1); 906ae3e8258Svporpo EXPECT_EQ(std::prev(It1), It0); 907ae3e8258Svporpo EXPECT_EQ(&*std::next(It0), IFunc1); 908ae3e8258Svporpo EXPECT_EQ(&*std::prev(It1), IFunc0); 909ae3e8258Svporpo } 910ae3e8258Svporpo // Check getReverseIterator(). 911ae3e8258Svporpo { 912ae3e8258Svporpo auto RevIt0 = IFunc0->getReverseIterator(); 913ae3e8258Svporpo auto RevIt1 = IFunc1->getReverseIterator(); 914ae3e8258Svporpo EXPECT_EQ(&*RevIt0, IFunc0); 915ae3e8258Svporpo EXPECT_EQ(&*RevIt1, IFunc1); 916ae3e8258Svporpo EXPECT_EQ(std::prev(RevIt0), RevIt1); 917ae3e8258Svporpo EXPECT_EQ(std::next(RevIt1), RevIt0); 918ae3e8258Svporpo EXPECT_EQ(&*std::prev(RevIt0), IFunc1); 919ae3e8258Svporpo EXPECT_EQ(&*std::next(RevIt1), IFunc0); 920ae3e8258Svporpo } 921ae3e8258Svporpo 922ae3e8258Svporpo // Check setResolver(), getResolver(). 923ae3e8258Svporpo EXPECT_EQ(IFunc0->getResolver(), Ctx.getValue(LLVMIFunc0->getResolver())); 924ae3e8258Svporpo auto *OrigResolver = IFunc0->getResolver(); 925ae3e8258Svporpo auto *NewResolver = Bar; 926ae3e8258Svporpo EXPECT_NE(NewResolver, OrigResolver); 927ae3e8258Svporpo IFunc0->setResolver(NewResolver); 928ae3e8258Svporpo EXPECT_EQ(IFunc0->getResolver(), NewResolver); 929ae3e8258Svporpo IFunc0->setResolver(OrigResolver); 930ae3e8258Svporpo EXPECT_EQ(IFunc0->getResolver(), OrigResolver); 931ae3e8258Svporpo // Check getResolverFunction(). 932ae3e8258Svporpo EXPECT_EQ(IFunc0->getResolverFunction(), 933ae3e8258Svporpo Ctx.getValue(LLVMIFunc0->getResolverFunction())); 934ae3e8258Svporpo // Check isValidLinkage(). 935ae3e8258Svporpo for (auto L : 936ae3e8258Svporpo {GlobalValue::ExternalLinkage, GlobalValue::AvailableExternallyLinkage, 937ae3e8258Svporpo GlobalValue::LinkOnceAnyLinkage, GlobalValue::LinkOnceODRLinkage, 938ae3e8258Svporpo GlobalValue::WeakAnyLinkage, GlobalValue::WeakODRLinkage, 939ae3e8258Svporpo GlobalValue::AppendingLinkage, GlobalValue::InternalLinkage, 940ae3e8258Svporpo GlobalValue::PrivateLinkage, GlobalValue::ExternalWeakLinkage, 941ae3e8258Svporpo GlobalValue::CommonLinkage}) { 942ae3e8258Svporpo EXPECT_EQ(IFunc0->isValidLinkage(L), LLVMIFunc0->isValidLinkage(L)); 943ae3e8258Svporpo } 944ae3e8258Svporpo } 945ae3e8258Svporpo 946b9bf831eSvporpo TEST_F(SandboxIRTest, GlobalVariable) { 947b9bf831eSvporpo parseIR(C, R"IR( 948b9bf831eSvporpo @glob0 = global i32 42 949b9bf831eSvporpo @glob1 = global i32 43 950b9bf831eSvporpo define void @foo() { 951b9bf831eSvporpo %ld0 = load i32, ptr @glob0 952b9bf831eSvporpo %ld1 = load i32, ptr @glob1 953b9bf831eSvporpo ret void 954b9bf831eSvporpo } 955b9bf831eSvporpo )IR"); 956b9bf831eSvporpo Function &LLVMF = *M->getFunction("foo"); 957b9bf831eSvporpo auto *LLVMBB = &*LLVMF.begin(); 958b9bf831eSvporpo auto LLVMIt = LLVMBB->begin(); 959b9bf831eSvporpo auto *LLVMLd0 = cast<llvm::LoadInst>(&*LLVMIt++); 960b9bf831eSvporpo auto *LLVMGV0 = cast<llvm::GlobalVariable>(LLVMLd0->getPointerOperand()); 961b9bf831eSvporpo sandboxir::Context Ctx(C); 962b9bf831eSvporpo 963b9bf831eSvporpo auto &F = *Ctx.createFunction(&LLVMF); 964b9bf831eSvporpo auto *BB = &*F.begin(); 965b9bf831eSvporpo auto It = BB->begin(); 966b9bf831eSvporpo auto *Ld0 = cast<sandboxir::LoadInst>(&*It++); 967b9bf831eSvporpo auto *Ld1 = cast<sandboxir::LoadInst>(&*It++); 968b9bf831eSvporpo // Check classof(), creation. 969b9bf831eSvporpo auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand()); 970b9bf831eSvporpo auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand()); 971b9bf831eSvporpo // Check getIterator(). 972b9bf831eSvporpo { 973b9bf831eSvporpo auto It0 = GV0->getIterator(); 974b9bf831eSvporpo auto It1 = GV1->getIterator(); 975b9bf831eSvporpo EXPECT_EQ(&*It0, GV0); 976b9bf831eSvporpo EXPECT_EQ(&*It1, GV1); 977b9bf831eSvporpo EXPECT_EQ(std::next(It0), It1); 978b9bf831eSvporpo EXPECT_EQ(std::prev(It1), It0); 979b9bf831eSvporpo EXPECT_EQ(&*std::next(It0), GV1); 980b9bf831eSvporpo EXPECT_EQ(&*std::prev(It1), GV0); 981b9bf831eSvporpo } 982b9bf831eSvporpo // Check getReverseIterator(). 983b9bf831eSvporpo { 984b9bf831eSvporpo auto RevIt0 = GV0->getReverseIterator(); 985b9bf831eSvporpo auto RevIt1 = GV1->getReverseIterator(); 986b9bf831eSvporpo EXPECT_EQ(&*RevIt0, GV0); 987b9bf831eSvporpo EXPECT_EQ(&*RevIt1, GV1); 988b9bf831eSvporpo EXPECT_EQ(std::prev(RevIt0), RevIt1); 989b9bf831eSvporpo EXPECT_EQ(std::next(RevIt1), RevIt0); 990b9bf831eSvporpo EXPECT_EQ(&*std::prev(RevIt0), GV1); 991b9bf831eSvporpo EXPECT_EQ(&*std::next(RevIt1), GV0); 992b9bf831eSvporpo } 993b9bf831eSvporpo // Check hasInitializer(). 994b9bf831eSvporpo EXPECT_EQ(GV0->hasInitializer(), LLVMGV0->hasInitializer()); 995b9bf831eSvporpo // Check hasDefinitiveInitializer(). 996b9bf831eSvporpo EXPECT_EQ(GV0->hasDefinitiveInitializer(), 997b9bf831eSvporpo LLVMGV0->hasDefinitiveInitializer()); 998b9bf831eSvporpo // Check hasUniqueInitializer(). 999b9bf831eSvporpo EXPECT_EQ(GV0->hasUniqueInitializer(), LLVMGV0->hasUniqueInitializer()); 1000b9bf831eSvporpo // Check getInitializer(). 1001b9bf831eSvporpo EXPECT_EQ(GV0->getInitializer(), Ctx.getValue(LLVMGV0->getInitializer())); 1002b9bf831eSvporpo // Check setInitializer(). 1003b9bf831eSvporpo auto *OrigInitializer = GV0->getInitializer(); 1004b9bf831eSvporpo auto *NewInitializer = GV1->getInitializer(); 1005b9bf831eSvporpo EXPECT_NE(NewInitializer, OrigInitializer); 1006b9bf831eSvporpo GV0->setInitializer(NewInitializer); 1007b9bf831eSvporpo EXPECT_EQ(GV0->getInitializer(), NewInitializer); 1008b9bf831eSvporpo GV0->setInitializer(OrigInitializer); 1009b9bf831eSvporpo EXPECT_EQ(GV0->getInitializer(), OrigInitializer); 1010b9bf831eSvporpo // Check isConstant(). 1011b9bf831eSvporpo EXPECT_EQ(GV0->isConstant(), LLVMGV0->isConstant()); 1012b9bf831eSvporpo // Check setConstant(). 1013b9bf831eSvporpo bool OrigIsConstant = GV0->isConstant(); 1014b9bf831eSvporpo bool NewIsConstant = !OrigIsConstant; 1015b9bf831eSvporpo GV0->setConstant(NewIsConstant); 1016b9bf831eSvporpo EXPECT_EQ(GV0->isConstant(), NewIsConstant); 1017b9bf831eSvporpo GV0->setConstant(OrigIsConstant); 1018b9bf831eSvporpo EXPECT_EQ(GV0->isConstant(), OrigIsConstant); 1019b9bf831eSvporpo // Check isExternallyInitialized(). 1020b9bf831eSvporpo EXPECT_EQ(GV0->isExternallyInitialized(), LLVMGV0->isExternallyInitialized()); 1021b9bf831eSvporpo // Check setExternallyInitialized(). 1022b9bf831eSvporpo bool OrigIsExtInit = GV0->isExternallyInitialized(); 1023b9bf831eSvporpo bool NewIsExtInit = !OrigIsExtInit; 1024b9bf831eSvporpo GV0->setExternallyInitialized(NewIsExtInit); 1025b9bf831eSvporpo EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit); 1026b9bf831eSvporpo GV0->setExternallyInitialized(OrigIsExtInit); 1027b9bf831eSvporpo EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit); 1028b9bf831eSvporpo for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) { 1029b9bf831eSvporpo // Check hasAttribute(AttrKind). 1030b9bf831eSvporpo auto Kind = static_cast<Attribute::AttrKind>(KindIdx); 1031b9bf831eSvporpo EXPECT_EQ(GV0->hasAttribute(Kind), LLVMGV0->hasAttribute(Kind)); 1032b9bf831eSvporpo // Check hasAttribute(StringRef). 1033b9bf831eSvporpo StringRef KindStr = Attribute::getNameFromAttrKind(Kind); 1034b9bf831eSvporpo EXPECT_EQ(GV0->hasAttribute(KindStr), LLVMGV0->hasAttribute(KindStr)); 1035b9bf831eSvporpo } 1036b9bf831eSvporpo // Check hasAttributes(). 1037b9bf831eSvporpo EXPECT_EQ(GV0->hasAttributes(), LLVMGV0->hasAttributes()); 1038b9bf831eSvporpo 1039b9bf831eSvporpo for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) { 1040b9bf831eSvporpo // Check getAttribute(AttrKind). 1041b9bf831eSvporpo auto Kind = static_cast<Attribute::AttrKind>(KindIdx); 1042b9bf831eSvporpo EXPECT_EQ(GV0->getAttribute(Kind), LLVMGV0->getAttribute(Kind)); 1043b9bf831eSvporpo // Check getAttribute(StringRef). 1044b9bf831eSvporpo StringRef KindStr = Attribute::getNameFromAttrKind(Kind); 1045b9bf831eSvporpo EXPECT_EQ(GV0->getAttribute(KindStr), LLVMGV0->getAttribute(KindStr)); 1046b9bf831eSvporpo } 1047b9bf831eSvporpo // Check getAttributes(). 1048b9bf831eSvporpo EXPECT_EQ(GV0->getAttributes(), LLVMGV0->getAttributes()); 1049b9bf831eSvporpo // Check getAttributesAsList(). 1050b9bf831eSvporpo EXPECT_THAT(GV0->getAttributesAsList(0u), 1051b9bf831eSvporpo testing::ContainerEq(LLVMGV0->getAttributesAsList(0u))); 1052b9bf831eSvporpo // Check hasImplicitSection(). 1053b9bf831eSvporpo EXPECT_EQ(GV0->hasImplicitSection(), LLVMGV0->hasImplicitSection()); 1054b9bf831eSvporpo // Check getCodeModelRaw(). 1055b9bf831eSvporpo EXPECT_EQ(GV0->getCodeModelRaw(), LLVMGV0->getCodeModelRaw()); 1056b9bf831eSvporpo // Check getCodeModel(). 1057b9bf831eSvporpo EXPECT_EQ(GV0->getCodeModel(), LLVMGV0->getCodeModel()); 1058b9bf831eSvporpo } 1059b9bf831eSvporpo 10609a312d47Svporpo TEST_F(SandboxIRTest, GlobalAlias) { 10619a312d47Svporpo parseIR(C, R"IR( 10629a312d47Svporpo @alias0 = dso_local alias void(), ptr @foo 10639a312d47Svporpo @alias1 = dso_local alias void(), ptr @foo 10649a312d47Svporpo declare void @bar(); 10659a312d47Svporpo define void @foo() { 10669a312d47Svporpo call void @alias0() 10679a312d47Svporpo call void @alias1() 10689a312d47Svporpo call void @bar() 10699a312d47Svporpo ret void 10709a312d47Svporpo } 10719a312d47Svporpo )IR"); 10729a312d47Svporpo Function &LLVMF = *M->getFunction("foo"); 10739a312d47Svporpo auto *LLVMBB = &*LLVMF.begin(); 10749a312d47Svporpo auto LLVMIt = LLVMBB->begin(); 10759a312d47Svporpo auto *LLVMCall0 = cast<llvm::CallInst>(&*LLVMIt++); 10769a312d47Svporpo auto *LLVMAlias0 = cast<llvm::GlobalAlias>(LLVMCall0->getCalledOperand()); 10779a312d47Svporpo sandboxir::Context Ctx(C); 10789a312d47Svporpo 10799a312d47Svporpo auto &F = *Ctx.createFunction(&LLVMF); 10809a312d47Svporpo auto *BB = &*F.begin(); 10819a312d47Svporpo auto It = BB->begin(); 10829a312d47Svporpo auto *Call0 = cast<sandboxir::CallInst>(&*It++); 10839a312d47Svporpo auto *Call1 = cast<sandboxir::CallInst>(&*It++); 10849a312d47Svporpo auto *CallBar = cast<sandboxir::CallInst>(&*It++); 10859a312d47Svporpo auto *CalleeBar = cast<sandboxir::Constant>(CallBar->getCalledOperand()); 10869a312d47Svporpo // Check classof(), creation. 10879a312d47Svporpo auto *Alias0 = cast<sandboxir::GlobalAlias>(Call0->getCalledOperand()); 10889a312d47Svporpo auto *Alias1 = cast<sandboxir::GlobalAlias>(Call1->getCalledOperand()); 10899a312d47Svporpo // Check getIterator(). 10909a312d47Svporpo { 10919a312d47Svporpo auto It0 = Alias0->getIterator(); 10929a312d47Svporpo auto It1 = Alias1->getIterator(); 10939a312d47Svporpo EXPECT_EQ(&*It0, Alias0); 10949a312d47Svporpo EXPECT_EQ(&*It1, Alias1); 10959a312d47Svporpo EXPECT_EQ(std::next(It0), It1); 10969a312d47Svporpo EXPECT_EQ(std::prev(It1), It0); 10979a312d47Svporpo EXPECT_EQ(&*std::next(It0), Alias1); 10989a312d47Svporpo EXPECT_EQ(&*std::prev(It1), Alias0); 10999a312d47Svporpo } 11009a312d47Svporpo // Check getReverseIterator(). 11019a312d47Svporpo { 11029a312d47Svporpo auto RevIt0 = Alias0->getReverseIterator(); 11039a312d47Svporpo auto RevIt1 = Alias1->getReverseIterator(); 11049a312d47Svporpo EXPECT_EQ(&*RevIt0, Alias0); 11059a312d47Svporpo EXPECT_EQ(&*RevIt1, Alias1); 11069a312d47Svporpo EXPECT_EQ(std::prev(RevIt0), RevIt1); 11079a312d47Svporpo EXPECT_EQ(std::next(RevIt1), RevIt0); 11089a312d47Svporpo EXPECT_EQ(&*std::prev(RevIt0), Alias1); 11099a312d47Svporpo EXPECT_EQ(&*std::next(RevIt1), Alias0); 11109a312d47Svporpo } 11119a312d47Svporpo // Check getAliasee(). 11129a312d47Svporpo EXPECT_EQ(Alias0->getAliasee(), Ctx.getValue(LLVMAlias0->getAliasee())); 11139a312d47Svporpo // Check setAliasee(). 11149a312d47Svporpo auto *OrigAliasee = Alias0->getAliasee(); 11159a312d47Svporpo auto *NewAliasee = CalleeBar; 11169a312d47Svporpo EXPECT_NE(NewAliasee, OrigAliasee); 11179a312d47Svporpo Alias0->setAliasee(NewAliasee); 11189a312d47Svporpo EXPECT_EQ(Alias0->getAliasee(), NewAliasee); 11199a312d47Svporpo Alias0->setAliasee(OrigAliasee); 11209a312d47Svporpo EXPECT_EQ(Alias0->getAliasee(), OrigAliasee); 11219a312d47Svporpo // Check getAliaseeObject(). 11229a312d47Svporpo EXPECT_EQ(Alias0->getAliaseeObject(), 11239a312d47Svporpo Ctx.getValue(LLVMAlias0->getAliaseeObject())); 11249a312d47Svporpo } 11259a312d47Svporpo 112674c0ab6fSvporpo TEST_F(SandboxIRTest, NoCFIValue) { 112774c0ab6fSvporpo parseIR(C, R"IR( 112874c0ab6fSvporpo define void @foo() { 112974c0ab6fSvporpo call void no_cfi @foo() 113074c0ab6fSvporpo ret void 113174c0ab6fSvporpo } 113274c0ab6fSvporpo )IR"); 113374c0ab6fSvporpo Function &LLVMF = *M->getFunction("foo"); 113474c0ab6fSvporpo sandboxir::Context Ctx(C); 113574c0ab6fSvporpo 113674c0ab6fSvporpo auto &F = *Ctx.createFunction(&LLVMF); 113774c0ab6fSvporpo auto *BB = &*F.begin(); 113874c0ab6fSvporpo auto It = BB->begin(); 113974c0ab6fSvporpo auto *Call = cast<sandboxir::CallInst>(&*It++); 114074c0ab6fSvporpo // Check classof(), creation. 114174c0ab6fSvporpo auto *NoCFI = cast<sandboxir::NoCFIValue>(Call->getCalledOperand()); 114274c0ab6fSvporpo // Check get(). 114374c0ab6fSvporpo auto *NewNoCFI = sandboxir::NoCFIValue::get(&F); 114474c0ab6fSvporpo EXPECT_EQ(NewNoCFI, NoCFI); 114574c0ab6fSvporpo // Check getGlobalValue(). 114674c0ab6fSvporpo EXPECT_EQ(NoCFI->getGlobalValue(), &F); 114774c0ab6fSvporpo // Check getType(). 114874c0ab6fSvporpo EXPECT_EQ(NoCFI->getType(), F.getType()); 114974c0ab6fSvporpo } 115074c0ab6fSvporpo 1151c0b1c623Svporpo TEST_F(SandboxIRTest, ConstantPtrAuth) { 1152c0b1c623Svporpo parseIR(C, R"IR( 1153c0b1c623Svporpo define ptr @foo() { 1154c0b1c623Svporpo ret ptr ptrauth (ptr @foo, i32 2, i64 1234) 1155c0b1c623Svporpo } 1156c0b1c623Svporpo )IR"); 1157c0b1c623Svporpo Function &LLVMF = *M->getFunction("foo"); 1158c0b1c623Svporpo auto *LLVMBB = &*LLVMF.begin(); 1159c0b1c623Svporpo auto *LLVMRet = cast<llvm::ReturnInst>(&*LLVMBB->begin()); 1160c0b1c623Svporpo auto *LLVMPtrAuth = cast<llvm::ConstantPtrAuth>(LLVMRet->getReturnValue()); 1161c0b1c623Svporpo sandboxir::Context Ctx(C); 1162c0b1c623Svporpo 1163c0b1c623Svporpo auto &F = *Ctx.createFunction(&LLVMF); 1164c0b1c623Svporpo auto *BB = &*F.begin(); 1165c0b1c623Svporpo auto It = BB->begin(); 1166c0b1c623Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1167c0b1c623Svporpo // Check classof(), creation. 1168c0b1c623Svporpo auto *PtrAuth = cast<sandboxir::ConstantPtrAuth>(Ret->getReturnValue()); 1169c0b1c623Svporpo // Check get(), getKey(), getDiscriminator(), getAddrDiscriminator(). 1170c0b1c623Svporpo auto *NewPtrAuth = sandboxir::ConstantPtrAuth::get( 1171c0b1c623Svporpo &F, PtrAuth->getKey(), PtrAuth->getDiscriminator(), 1172c0b1c623Svporpo PtrAuth->getAddrDiscriminator()); 1173c0b1c623Svporpo EXPECT_EQ(NewPtrAuth, PtrAuth); 1174c0b1c623Svporpo // Check hasAddressDiscriminator(). 1175c0b1c623Svporpo EXPECT_EQ(PtrAuth->hasAddressDiscriminator(), 1176c0b1c623Svporpo LLVMPtrAuth->hasAddressDiscriminator()); 1177c0b1c623Svporpo // Check hasSpecialAddressDiscriminator(). 1178c0b1c623Svporpo EXPECT_EQ(PtrAuth->hasSpecialAddressDiscriminator(0u), 1179c0b1c623Svporpo LLVMPtrAuth->hasSpecialAddressDiscriminator(0u)); 1180c0b1c623Svporpo // Check isKnownCompatibleWith(). 1181c0b1c623Svporpo const DataLayout &DL = M->getDataLayout(); 1182c0b1c623Svporpo EXPECT_TRUE(PtrAuth->isKnownCompatibleWith(PtrAuth->getKey(), 1183c0b1c623Svporpo PtrAuth->getDiscriminator(), DL)); 1184c0b1c623Svporpo // Check getWithSameSchema(). 1185c0b1c623Svporpo EXPECT_EQ(PtrAuth->getWithSameSchema(&F), PtrAuth); 1186c0b1c623Svporpo } 1187c0b1c623Svporpo 1188416c3ce0Svporpo TEST_F(SandboxIRTest, ConstantExpr) { 1189416c3ce0Svporpo parseIR(C, R"IR( 1190416c3ce0Svporpo define i32 @foo() { 1191416c3ce0Svporpo ret i32 ptrtoint (ptr @foo to i32) 1192416c3ce0Svporpo } 1193416c3ce0Svporpo )IR"); 1194416c3ce0Svporpo Function &LLVMF = *M->getFunction("foo"); 1195416c3ce0Svporpo sandboxir::Context Ctx(C); 1196416c3ce0Svporpo 1197416c3ce0Svporpo auto &F = *Ctx.createFunction(&LLVMF); 1198416c3ce0Svporpo auto *BB = &*F.begin(); 1199416c3ce0Svporpo auto It = BB->begin(); 1200416c3ce0Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1201416c3ce0Svporpo // Check classof(), creation. 1202416c3ce0Svporpo [[maybe_unused]] auto *ConstExpr = 1203416c3ce0Svporpo cast<sandboxir::ConstantExpr>(Ret->getReturnValue()); 1204416c3ce0Svporpo } 1205416c3ce0Svporpo 1206d14a600bSvporpo TEST_F(SandboxIRTest, BlockAddress) { 1207d14a600bSvporpo parseIR(C, R"IR( 1208d14a600bSvporpo define void @foo(ptr %ptr) { 1209d14a600bSvporpo bb0: 1210d14a600bSvporpo store ptr blockaddress(@foo, %bb0), ptr %ptr 1211d14a600bSvporpo ret void 1212d14a600bSvporpo bb1: 1213d14a600bSvporpo ret void 1214d14a600bSvporpo bb2: 1215d14a600bSvporpo ret void 1216d14a600bSvporpo } 1217d14a600bSvporpo )IR"); 1218d14a600bSvporpo Function &LLVMF = *M->getFunction("foo"); 1219d14a600bSvporpo sandboxir::Context Ctx(C); 1220d14a600bSvporpo 1221d14a600bSvporpo auto &F = *Ctx.createFunction(&LLVMF); 1222d14a600bSvporpo auto *BB0 = cast<sandboxir::BasicBlock>( 1223d14a600bSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb0"))); 1224d14a600bSvporpo auto *BB1 = cast<sandboxir::BasicBlock>( 1225d14a600bSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb1"))); 1226d14a600bSvporpo auto *BB2 = cast<sandboxir::BasicBlock>( 1227d14a600bSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb2"))); 1228d14a600bSvporpo auto It = BB0->begin(); 1229d14a600bSvporpo auto *SI = cast<sandboxir::StoreInst>(&*It++); 1230d14a600bSvporpo [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1231d14a600bSvporpo 1232d14a600bSvporpo // Check classof(), creation, getFunction(), getBasicBlock(). 1233d14a600bSvporpo auto *BB0Addr = cast<sandboxir::BlockAddress>(SI->getValueOperand()); 1234d14a600bSvporpo EXPECT_EQ(BB0Addr->getBasicBlock(), BB0); 1235d14a600bSvporpo EXPECT_EQ(BB0Addr->getFunction(), &F); 1236d14a600bSvporpo // Check get(F, BB). 1237d14a600bSvporpo auto *NewBB0Addr = sandboxir::BlockAddress::get(&F, BB0); 1238d14a600bSvporpo EXPECT_EQ(NewBB0Addr, BB0Addr); 1239d14a600bSvporpo // Check get(BB). 1240d14a600bSvporpo auto *NewBB0Addr2 = sandboxir::BlockAddress::get(BB0); 1241d14a600bSvporpo EXPECT_EQ(NewBB0Addr2, BB0Addr); 1242d14a600bSvporpo auto *BB1Addr = sandboxir::BlockAddress::get(BB1); 1243d14a600bSvporpo EXPECT_EQ(BB1Addr->getBasicBlock(), BB1); 1244d14a600bSvporpo EXPECT_NE(BB1Addr, BB0Addr); 1245d14a600bSvporpo // Check lookup(). 1246d14a600bSvporpo auto *LookupBB0Addr = sandboxir::BlockAddress::lookup(BB0); 1247d14a600bSvporpo EXPECT_EQ(LookupBB0Addr, BB0Addr); 1248d14a600bSvporpo auto *LookupBB1Addr = sandboxir::BlockAddress::lookup(BB1); 1249d14a600bSvporpo EXPECT_EQ(LookupBB1Addr, BB1Addr); 1250d14a600bSvporpo auto *LookupBB2Addr = sandboxir::BlockAddress::lookup(BB2); 1251d14a600bSvporpo EXPECT_EQ(LookupBB2Addr, nullptr); 1252d14a600bSvporpo } 1253d14a600bSvporpo 1254fffc7fb7Svporpo TEST_F(SandboxIRTest, DSOLocalEquivalent) { 1255fffc7fb7Svporpo parseIR(C, R"IR( 1256fffc7fb7Svporpo declare void @bar() 1257fffc7fb7Svporpo define void @foo() { 1258fffc7fb7Svporpo call void dso_local_equivalent @bar() 1259fffc7fb7Svporpo ret void 1260fffc7fb7Svporpo } 1261fffc7fb7Svporpo )IR"); 1262fffc7fb7Svporpo Function &LLVMF = *M->getFunction("foo"); 1263fffc7fb7Svporpo sandboxir::Context Ctx(C); 1264fffc7fb7Svporpo 1265fffc7fb7Svporpo auto &F = *Ctx.createFunction(&LLVMF); 1266fffc7fb7Svporpo auto *BB = &*F.begin(); 1267fffc7fb7Svporpo auto It = BB->begin(); 1268fffc7fb7Svporpo auto *CI = cast<sandboxir::CallInst>(&*It++); 1269fffc7fb7Svporpo // Check classof(). 1270fffc7fb7Svporpo auto *DSOLE = cast<sandboxir::DSOLocalEquivalent>(CI->getCalledOperand()); 1271fffc7fb7Svporpo // Check getGlobalValue(). 1272fffc7fb7Svporpo auto *GV = DSOLE->getGlobalValue(); 1273fffc7fb7Svporpo // Check get(). 1274fffc7fb7Svporpo auto *NewDSOLE = sandboxir::DSOLocalEquivalent::get(GV); 1275fffc7fb7Svporpo EXPECT_EQ(NewDSOLE, DSOLE); 1276fffc7fb7Svporpo } 1277fffc7fb7Svporpo 1278c9ab6979Svporpo TEST_F(SandboxIRTest, ConstantTokenNone) { 1279c9ab6979Svporpo parseIR(C, R"IR( 1280c9ab6979Svporpo define void @foo(ptr %ptr) { 1281c9ab6979Svporpo bb0: 1282c9ab6979Svporpo %cs = catchswitch within none [label %handler] unwind to caller 1283c9ab6979Svporpo handler: 1284c9ab6979Svporpo ret void 1285c9ab6979Svporpo } 1286c9ab6979Svporpo )IR"); 1287c9ab6979Svporpo Function &LLVMF = *M->getFunction("foo"); 1288c9ab6979Svporpo sandboxir::Context Ctx(C); 1289c9ab6979Svporpo 1290c9ab6979Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 1291c9ab6979Svporpo auto *BB0 = cast<sandboxir::BasicBlock>( 1292c9ab6979Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb0"))); 1293c9ab6979Svporpo auto *CS = cast<sandboxir::CatchSwitchInst>(&*BB0->begin()); 1294c9ab6979Svporpo 1295c9ab6979Svporpo // Check classof(), creation, getFunction(), getBasicBlock(). 1296c9ab6979Svporpo auto *CTN = cast<sandboxir::ConstantTokenNone>(CS->getParentPad()); 1297c9ab6979Svporpo // Check get(). 1298c9ab6979Svporpo auto *NewCTN = sandboxir::ConstantTokenNone::get(Ctx); 1299c9ab6979Svporpo EXPECT_EQ(NewCTN, CTN); 1300c9ab6979Svporpo } 1301c9ab6979Svporpo 1302797a2ec6SVasileios Porpodas TEST_F(SandboxIRTest, Use) { 1303797a2ec6SVasileios Porpodas parseIR(C, R"IR( 1304797a2ec6SVasileios Porpodas define i32 @foo(i32 %v0, i32 %v1) { 1305797a2ec6SVasileios Porpodas %add0 = add i32 %v0, %v1 1306797a2ec6SVasileios Porpodas ret i32 %add0 1307797a2ec6SVasileios Porpodas } 1308797a2ec6SVasileios Porpodas )IR"); 1309797a2ec6SVasileios Porpodas Function &LLVMF = *M->getFunction("foo"); 1310797a2ec6SVasileios Porpodas sandboxir::Context Ctx(C); 1311797a2ec6SVasileios Porpodas 1312797a2ec6SVasileios Porpodas BasicBlock *LLVMBB = &*LLVMF.begin(); 1313797a2ec6SVasileios Porpodas auto LLVMBBIt = LLVMBB->begin(); 1314797a2ec6SVasileios Porpodas Instruction *LLVMI0 = &*LLVMBBIt++; 1315ecd2bf73Svporpo Instruction *LLVMRet = &*LLVMBBIt++; 1316ecd2bf73Svporpo Argument *LLVMArg0 = LLVMF.getArg(0); 1317ecd2bf73Svporpo Argument *LLVMArg1 = LLVMF.getArg(1); 1318797a2ec6SVasileios Porpodas 1319797a2ec6SVasileios Porpodas auto &F = *Ctx.createFunction(&LLVMF); 1320797a2ec6SVasileios Porpodas auto &BB = *F.begin(); 1321797a2ec6SVasileios Porpodas auto *Arg0 = F.getArg(0); 1322797a2ec6SVasileios Porpodas auto *Arg1 = F.getArg(1); 1323797a2ec6SVasileios Porpodas auto It = BB.begin(); 1324797a2ec6SVasileios Porpodas auto *I0 = &*It++; 13257467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1326797a2ec6SVasileios Porpodas 1327797a2ec6SVasileios Porpodas SmallVector<sandboxir::Argument *> Args{Arg0, Arg1}; 1328797a2ec6SVasileios Porpodas unsigned OpIdx = 0; 1329797a2ec6SVasileios Porpodas for (sandboxir::Use Use : I0->operands()) { 1330797a2ec6SVasileios Porpodas // Check Use.getOperandNo(). 1331797a2ec6SVasileios Porpodas EXPECT_EQ(Use.getOperandNo(), OpIdx); 1332797a2ec6SVasileios Porpodas // Check Use.getUser(). 1333797a2ec6SVasileios Porpodas EXPECT_EQ(Use.getUser(), I0); 1334797a2ec6SVasileios Porpodas // Check Use.getContext(). 1335797a2ec6SVasileios Porpodas EXPECT_EQ(Use.getContext(), &Ctx); 1336797a2ec6SVasileios Porpodas // Check Use.get(). 1337797a2ec6SVasileios Porpodas sandboxir::Value *Op = Use.get(); 1338797a2ec6SVasileios Porpodas EXPECT_EQ(Op, Ctx.getValue(LLVMI0->getOperand(OpIdx))); 1339797a2ec6SVasileios Porpodas // Check Use.getUser(). 1340797a2ec6SVasileios Porpodas EXPECT_EQ(Use.getUser(), I0); 1341797a2ec6SVasileios Porpodas // Check implicit cast to Value. 1342797a2ec6SVasileios Porpodas sandboxir::Value *Cast = Use; 1343797a2ec6SVasileios Porpodas EXPECT_EQ(Cast, Op); 1344797a2ec6SVasileios Porpodas // Check that Use points to the correct operand. 1345797a2ec6SVasileios Porpodas EXPECT_EQ(Op, Args[OpIdx]); 1346797a2ec6SVasileios Porpodas // Check getOperand(). 1347797a2ec6SVasileios Porpodas EXPECT_EQ(Op, I0->getOperand(OpIdx)); 1348797a2ec6SVasileios Porpodas // Check getOperandUse(). 1349797a2ec6SVasileios Porpodas EXPECT_EQ(Use, I0->getOperandUse(OpIdx)); 1350797a2ec6SVasileios Porpodas ++OpIdx; 1351797a2ec6SVasileios Porpodas } 1352797a2ec6SVasileios Porpodas EXPECT_EQ(OpIdx, 2u); 1353797a2ec6SVasileios Porpodas 1354797a2ec6SVasileios Porpodas // Check Use.operator==() and Use.operator!=(). 1355797a2ec6SVasileios Porpodas sandboxir::Use UseA = I0->getOperandUse(0); 1356797a2ec6SVasileios Porpodas sandboxir::Use UseB = I0->getOperandUse(0); 1357797a2ec6SVasileios Porpodas EXPECT_TRUE(UseA == UseB); 1358797a2ec6SVasileios Porpodas EXPECT_FALSE(UseA != UseB); 1359797a2ec6SVasileios Porpodas 1360797a2ec6SVasileios Porpodas // Check getNumOperands(). 1361797a2ec6SVasileios Porpodas EXPECT_EQ(I0->getNumOperands(), 2u); 1362797a2ec6SVasileios Porpodas EXPECT_EQ(Ret->getNumOperands(), 1u); 1363797a2ec6SVasileios Porpodas 1364797a2ec6SVasileios Porpodas EXPECT_EQ(Ret->getOperand(0), I0); 1365797a2ec6SVasileios Porpodas 1366797a2ec6SVasileios Porpodas #ifndef NDEBUG 136753517231Svporpo // Check Use.dump(() 1368797a2ec6SVasileios Porpodas std::string Buff; 1369797a2ec6SVasileios Porpodas raw_string_ostream BS(Buff); 1370797a2ec6SVasileios Porpodas BS << "\n"; 137153517231Svporpo I0->getOperandUse(0).dumpOS(BS); 1372797a2ec6SVasileios Porpodas EXPECT_EQ(Buff, R"IR( 1373372a6beaSvporpo Def: i32 %v0 ; SB2. (Argument) 13746ec169d3Svporpo User: %add0 = add i32 %v0, %v1 ; SB5. (BinaryOperator) 1375797a2ec6SVasileios Porpodas OperandNo: 0 1376797a2ec6SVasileios Porpodas )IR"); 1377797a2ec6SVasileios Porpodas #endif // NDEBUG 1378797a2ec6SVasileios Porpodas 1379797a2ec6SVasileios Porpodas // Check Value.user_begin(). 1380797a2ec6SVasileios Porpodas sandboxir::Value::user_iterator UIt = I0->user_begin(); 1381797a2ec6SVasileios Porpodas sandboxir::User *U = *UIt; 1382797a2ec6SVasileios Porpodas EXPECT_EQ(U, Ret); 1383797a2ec6SVasileios Porpodas // Check Value.uses(). 1384797a2ec6SVasileios Porpodas EXPECT_EQ(range_size(I0->uses()), 1u); 1385797a2ec6SVasileios Porpodas EXPECT_EQ((*I0->uses().begin()).getUser(), Ret); 1386797a2ec6SVasileios Porpodas // Check Value.users(). 1387797a2ec6SVasileios Porpodas EXPECT_EQ(range_size(I0->users()), 1u); 1388797a2ec6SVasileios Porpodas EXPECT_EQ(*I0->users().begin(), Ret); 1389797a2ec6SVasileios Porpodas // Check Value.getNumUses(). 1390797a2ec6SVasileios Porpodas EXPECT_EQ(I0->getNumUses(), 1u); 1391797a2ec6SVasileios Porpodas // Check Value.hasNUsesOrMore(). 1392797a2ec6SVasileios Porpodas EXPECT_TRUE(I0->hasNUsesOrMore(0u)); 1393797a2ec6SVasileios Porpodas EXPECT_TRUE(I0->hasNUsesOrMore(1u)); 1394797a2ec6SVasileios Porpodas EXPECT_FALSE(I0->hasNUsesOrMore(2u)); 1395797a2ec6SVasileios Porpodas // Check Value.hasNUses(). 1396797a2ec6SVasileios Porpodas EXPECT_FALSE(I0->hasNUses(0u)); 1397797a2ec6SVasileios Porpodas EXPECT_TRUE(I0->hasNUses(1u)); 1398797a2ec6SVasileios Porpodas EXPECT_FALSE(I0->hasNUses(2u)); 1399ecd2bf73Svporpo 1400d1edef56SSterling-Augustine // Check Value.getExpectedType 1401d1edef56SSterling-Augustine 1402ecd2bf73Svporpo // Check User.setOperand(). 1403ecd2bf73Svporpo Ret->setOperand(0, Arg0); 1404ecd2bf73Svporpo EXPECT_EQ(Ret->getOperand(0), Arg0); 1405ecd2bf73Svporpo EXPECT_EQ(Ret->getOperandUse(0).get(), Arg0); 1406ecd2bf73Svporpo EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg0); 1407ecd2bf73Svporpo 1408ecd2bf73Svporpo Ret->setOperand(0, Arg1); 1409ecd2bf73Svporpo EXPECT_EQ(Ret->getOperand(0), Arg1); 1410ecd2bf73Svporpo EXPECT_EQ(Ret->getOperandUse(0).get(), Arg1); 1411ecd2bf73Svporpo EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg1); 1412ecd2bf73Svporpo } 1413ecd2bf73Svporpo 1414ecd2bf73Svporpo TEST_F(SandboxIRTest, RUOW) { 1415ecd2bf73Svporpo parseIR(C, R"IR( 1416ecd2bf73Svporpo declare void @bar0() 1417ecd2bf73Svporpo declare void @bar1() 1418ecd2bf73Svporpo 1419ecd2bf73Svporpo @glob0 = global ptr @bar0 1420ecd2bf73Svporpo @glob1 = global ptr @bar1 1421ecd2bf73Svporpo 1422ecd2bf73Svporpo define i32 @foo(i32 %arg0, i32 %arg1) { 1423ecd2bf73Svporpo %add0 = add i32 %arg0, %arg1 1424ecd2bf73Svporpo %gep1 = getelementptr i8, ptr @glob0, i32 1 1425ecd2bf73Svporpo %gep2 = getelementptr i8, ptr @glob1, i32 1 1426ecd2bf73Svporpo ret i32 %add0 1427ecd2bf73Svporpo } 1428ecd2bf73Svporpo )IR"); 1429ecd2bf73Svporpo llvm::Function &LLVMF = *M->getFunction("foo"); 1430ecd2bf73Svporpo sandboxir::Context Ctx(C); 1431ecd2bf73Svporpo 1432ecd2bf73Svporpo auto &F = *Ctx.createFunction(&LLVMF); 1433ecd2bf73Svporpo auto &BB = *F.begin(); 1434ecd2bf73Svporpo auto *Arg0 = F.getArg(0); 1435ecd2bf73Svporpo auto *Arg1 = F.getArg(1); 1436ecd2bf73Svporpo auto It = BB.begin(); 1437ecd2bf73Svporpo auto *I0 = &*It++; 1438ecd2bf73Svporpo auto *I1 = &*It++; 1439ecd2bf73Svporpo auto *I2 = &*It++; 14407467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1441ecd2bf73Svporpo 1442ecd2bf73Svporpo bool Replaced; 1443ecd2bf73Svporpo // Try to replace an operand that doesn't match. 1444ecd2bf73Svporpo Replaced = I0->replaceUsesOfWith(Ret, Arg1); 1445ecd2bf73Svporpo EXPECT_FALSE(Replaced); 1446ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(0), Arg0); 1447ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(1), Arg1); 1448ecd2bf73Svporpo 1449ecd2bf73Svporpo // Replace I0 operands when operands differ. 1450ecd2bf73Svporpo Replaced = I0->replaceUsesOfWith(Arg0, Arg1); 1451ecd2bf73Svporpo EXPECT_TRUE(Replaced); 1452ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(0), Arg1); 1453ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(1), Arg1); 1454ecd2bf73Svporpo 1455ecd2bf73Svporpo // Replace I0 operands when operands are the same. 1456ecd2bf73Svporpo Replaced = I0->replaceUsesOfWith(Arg1, Arg0); 1457ecd2bf73Svporpo EXPECT_TRUE(Replaced); 1458ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(0), Arg0); 1459ecd2bf73Svporpo EXPECT_EQ(I0->getOperand(1), Arg0); 1460ecd2bf73Svporpo 1461ecd2bf73Svporpo // Replace Ret operand. 1462ecd2bf73Svporpo Replaced = Ret->replaceUsesOfWith(I0, Arg0); 1463ecd2bf73Svporpo EXPECT_TRUE(Replaced); 1464ecd2bf73Svporpo EXPECT_EQ(Ret->getOperand(0), Arg0); 1465ecd2bf73Svporpo // Check RAUW on constant. 1466ecd2bf73Svporpo auto *Glob0 = cast<sandboxir::Constant>(I1->getOperand(0)); 1467ecd2bf73Svporpo auto *Glob1 = cast<sandboxir::Constant>(I2->getOperand(0)); 1468ecd2bf73Svporpo auto *Glob0Op = Glob0->getOperand(0); 1469ecd2bf73Svporpo Glob0->replaceUsesOfWith(Glob0Op, Glob1); 1470ecd2bf73Svporpo EXPECT_EQ(Glob0->getOperand(0), Glob1); 1471ecd2bf73Svporpo } 1472ecd2bf73Svporpo 1473ecd2bf73Svporpo TEST_F(SandboxIRTest, RAUW_RUWIf) { 1474ecd2bf73Svporpo parseIR(C, R"IR( 1475ecd2bf73Svporpo define void @foo(ptr %ptr) { 1476ecd2bf73Svporpo %ld0 = load float, ptr %ptr 1477ecd2bf73Svporpo %ld1 = load float, ptr %ptr 1478ecd2bf73Svporpo store float %ld0, ptr %ptr 1479ecd2bf73Svporpo store float %ld0, ptr %ptr 1480ecd2bf73Svporpo ret void 1481ecd2bf73Svporpo } 1482ecd2bf73Svporpo )IR"); 1483ecd2bf73Svporpo llvm::Function &LLVMF = *M->getFunction("foo"); 1484ecd2bf73Svporpo sandboxir::Context Ctx(C); 1485ecd2bf73Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF.begin(); 1486ecd2bf73Svporpo 1487ecd2bf73Svporpo Ctx.createFunction(&LLVMF); 1488ecd2bf73Svporpo auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB)); 1489ecd2bf73Svporpo auto It = BB->begin(); 1490ecd2bf73Svporpo sandboxir::Instruction *Ld0 = &*It++; 1491ecd2bf73Svporpo sandboxir::Instruction *Ld1 = &*It++; 1492ecd2bf73Svporpo sandboxir::Instruction *St0 = &*It++; 1493ecd2bf73Svporpo sandboxir::Instruction *St1 = &*It++; 1494ecd2bf73Svporpo // Check RUWIf when the lambda returns false. 1495ecd2bf73Svporpo Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; }); 1496ecd2bf73Svporpo EXPECT_EQ(St0->getOperand(0), Ld0); 1497ecd2bf73Svporpo EXPECT_EQ(St1->getOperand(0), Ld0); 1498ecd2bf73Svporpo // Check RUWIf when the lambda returns true. 1499ecd2bf73Svporpo Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; }); 1500ecd2bf73Svporpo EXPECT_EQ(St0->getOperand(0), Ld1); 1501ecd2bf73Svporpo EXPECT_EQ(St1->getOperand(0), Ld1); 1502ecd2bf73Svporpo St0->setOperand(0, Ld0); 1503ecd2bf73Svporpo St1->setOperand(0, Ld0); 1504ecd2bf73Svporpo // Check RUWIf user == St0. 1505ecd2bf73Svporpo Ld0->replaceUsesWithIf( 1506ecd2bf73Svporpo Ld1, [St0](const sandboxir::Use &Use) { return Use.getUser() == St0; }); 1507ecd2bf73Svporpo EXPECT_EQ(St0->getOperand(0), Ld1); 1508ecd2bf73Svporpo EXPECT_EQ(St1->getOperand(0), Ld0); 1509ecd2bf73Svporpo St0->setOperand(0, Ld0); 1510ecd2bf73Svporpo // Check RUWIf user == St1. 1511ecd2bf73Svporpo Ld0->replaceUsesWithIf( 1512ecd2bf73Svporpo Ld1, [St1](const sandboxir::Use &Use) { return Use.getUser() == St1; }); 1513ecd2bf73Svporpo EXPECT_EQ(St0->getOperand(0), Ld0); 1514ecd2bf73Svporpo EXPECT_EQ(St1->getOperand(0), Ld1); 1515ecd2bf73Svporpo St1->setOperand(0, Ld0); 1516ecd2bf73Svporpo // Check RAUW. 1517ecd2bf73Svporpo Ld1->replaceAllUsesWith(Ld0); 1518ecd2bf73Svporpo EXPECT_EQ(St0->getOperand(0), Ld0); 1519ecd2bf73Svporpo EXPECT_EQ(St1->getOperand(0), Ld0); 1520797a2ec6SVasileios Porpodas } 1521797a2ec6SVasileios Porpodas 1522797a2ec6SVasileios Porpodas // Check that the operands/users are counted correctly. 1523797a2ec6SVasileios Porpodas // I1 1524797a2ec6SVasileios Porpodas // / \ 1525797a2ec6SVasileios Porpodas // \ / 1526797a2ec6SVasileios Porpodas // I2 1527797a2ec6SVasileios Porpodas TEST_F(SandboxIRTest, DuplicateUses) { 1528797a2ec6SVasileios Porpodas parseIR(C, R"IR( 1529797a2ec6SVasileios Porpodas define void @foo(i8 %v) { 1530797a2ec6SVasileios Porpodas %I1 = add i8 %v, %v 1531797a2ec6SVasileios Porpodas %I2 = add i8 %I1, %I1 1532797a2ec6SVasileios Porpodas ret void 1533797a2ec6SVasileios Porpodas } 1534797a2ec6SVasileios Porpodas )IR"); 1535797a2ec6SVasileios Porpodas Function &LLVMF = *M->getFunction("foo"); 1536797a2ec6SVasileios Porpodas sandboxir::Context Ctx(C); 1537797a2ec6SVasileios Porpodas auto *F = Ctx.createFunction(&LLVMF); 1538797a2ec6SVasileios Porpodas auto *BB = &*F->begin(); 1539797a2ec6SVasileios Porpodas auto It = BB->begin(); 1540797a2ec6SVasileios Porpodas auto *I1 = &*It++; 1541797a2ec6SVasileios Porpodas auto *I2 = &*It++; 1542797a2ec6SVasileios Porpodas EXPECT_EQ(range_size(I1->users()), 2u); 1543797a2ec6SVasileios Porpodas EXPECT_EQ(range_size(I2->operands()), 2u); 1544797a2ec6SVasileios Porpodas } 1545797a2ec6SVasileios Porpodas 154650881d03Svporpo TEST_F(SandboxIRTest, Function) { 154750881d03Svporpo parseIR(C, R"IR( 1548ae3e8258Svporpo define void @foo0(i32 %arg0, i32 %arg1) { 154950881d03Svporpo bb0: 155050881d03Svporpo br label %bb1 155150881d03Svporpo bb1: 155250881d03Svporpo ret void 155350881d03Svporpo } 1554ae3e8258Svporpo define void @foo1() { 1555ae3e8258Svporpo ret void 1556ae3e8258Svporpo } 1557ae3e8258Svporpo 155850881d03Svporpo )IR"); 1559ae3e8258Svporpo llvm::Function *LLVMF0 = &*M->getFunction("foo0"); 1560ae3e8258Svporpo llvm::Function *LLVMF1 = &*M->getFunction("foo1"); 1561ae3e8258Svporpo llvm::Argument *LLVMArg0 = LLVMF0->getArg(0); 1562ae3e8258Svporpo llvm::Argument *LLVMArg1 = LLVMF0->getArg(1); 156350881d03Svporpo 156450881d03Svporpo sandboxir::Context Ctx(C); 1565ae3e8258Svporpo sandboxir::Function *F0 = Ctx.createFunction(LLVMF0); 1566ae3e8258Svporpo sandboxir::Function *F1 = Ctx.createFunction(LLVMF1); 1567ae3e8258Svporpo 1568ae3e8258Svporpo // Check getIterator(). 1569ae3e8258Svporpo { 1570ae3e8258Svporpo auto It0 = F0->getIterator(); 1571ae3e8258Svporpo auto It1 = F1->getIterator(); 1572ae3e8258Svporpo EXPECT_EQ(&*It0, F0); 1573ae3e8258Svporpo EXPECT_EQ(&*It1, F1); 1574ae3e8258Svporpo EXPECT_EQ(std::next(It0), It1); 1575ae3e8258Svporpo EXPECT_EQ(std::prev(It1), It0); 1576ae3e8258Svporpo EXPECT_EQ(&*std::next(It0), F1); 1577ae3e8258Svporpo EXPECT_EQ(&*std::prev(It1), F0); 1578ae3e8258Svporpo } 1579ae3e8258Svporpo // Check getReverseIterator(). 1580ae3e8258Svporpo { 1581ae3e8258Svporpo auto RevIt0 = F0->getReverseIterator(); 1582ae3e8258Svporpo auto RevIt1 = F1->getReverseIterator(); 1583ae3e8258Svporpo EXPECT_EQ(&*RevIt0, F0); 1584ae3e8258Svporpo EXPECT_EQ(&*RevIt1, F1); 1585ae3e8258Svporpo EXPECT_EQ(std::prev(RevIt0), RevIt1); 1586ae3e8258Svporpo EXPECT_EQ(std::next(RevIt1), RevIt0); 1587ae3e8258Svporpo EXPECT_EQ(&*std::prev(RevIt0), F1); 1588ae3e8258Svporpo EXPECT_EQ(&*std::next(RevIt1), F0); 1589ae3e8258Svporpo } 159050881d03Svporpo 159150881d03Svporpo // Check F arguments 1592ae3e8258Svporpo EXPECT_EQ(F0->arg_size(), 2u); 1593ae3e8258Svporpo EXPECT_FALSE(F0->arg_empty()); 1594ae3e8258Svporpo EXPECT_EQ(F0->getArg(0), Ctx.getValue(LLVMArg0)); 1595ae3e8258Svporpo EXPECT_EQ(F0->getArg(1), Ctx.getValue(LLVMArg1)); 159650881d03Svporpo 159750881d03Svporpo // Check F.begin(), F.end(), Function::iterator 1598ae3e8258Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF0->begin(); 1599ae3e8258Svporpo for (sandboxir::BasicBlock &BB : *F0) { 160050881d03Svporpo EXPECT_EQ(&BB, Ctx.getValue(LLVMBB)); 160150881d03Svporpo LLVMBB = LLVMBB->getNextNode(); 160250881d03Svporpo } 160350881d03Svporpo 160450881d03Svporpo #ifndef NDEBUG 160550881d03Svporpo { 160650881d03Svporpo // Check F.dumpNameAndArgs() 160750881d03Svporpo std::string Buff; 160850881d03Svporpo raw_string_ostream BS(Buff); 1609ae3e8258Svporpo F0->dumpNameAndArgs(BS); 1610ae3e8258Svporpo EXPECT_EQ(Buff, "void @foo0(i32 %arg0, i32 %arg1)"); 161150881d03Svporpo } 161250881d03Svporpo { 161350881d03Svporpo // Check F.dump() 161450881d03Svporpo std::string Buff; 161550881d03Svporpo raw_string_ostream BS(Buff); 161650881d03Svporpo BS << "\n"; 1617ae3e8258Svporpo F0->dumpOS(BS); 161850881d03Svporpo EXPECT_EQ(Buff, R"IR( 1619ae3e8258Svporpo void @foo0(i32 %arg0, i32 %arg1) { 162050881d03Svporpo bb0: 1621372a6beaSvporpo br label %bb1 ; SB4. (Br) 162250881d03Svporpo 162350881d03Svporpo bb1: 1624372a6beaSvporpo ret void ; SB6. (Ret) 162550881d03Svporpo } 162650881d03Svporpo )IR"); 162750881d03Svporpo } 162850881d03Svporpo #endif // NDEBUG 162950881d03Svporpo } 163050881d03Svporpo 16317e5df5bcSvporpo TEST_F(SandboxIRTest, Module) { 16327e5df5bcSvporpo parseIR(C, R"IR( 16337e5df5bcSvporpo @glob0 = global i32 42 16347e5df5bcSvporpo @glob1 = global i32 43 16357e5df5bcSvporpo @internal0 = internal global i32 42 16367e5df5bcSvporpo @const0 = constant i32 42 16377e5df5bcSvporpo @alias0 = dso_local alias void(), ptr @foo 16387e5df5bcSvporpo @ifunc = ifunc void(), ptr @foo 16397e5df5bcSvporpo define void @foo() { 16407e5df5bcSvporpo ret void 16417e5df5bcSvporpo } 16427e5df5bcSvporpo define void @bar() { 16437e5df5bcSvporpo ret void 16447e5df5bcSvporpo } 16457e5df5bcSvporpo )IR"); 16467e5df5bcSvporpo llvm::Module *LLVMM = &*M; 16477e5df5bcSvporpo llvm::Function *LLVMFFoo = &*M->getFunction("foo"); 16487e5df5bcSvporpo llvm::Function *LLVMFBar = &*M->getFunction("bar"); 16497e5df5bcSvporpo 16507e5df5bcSvporpo sandboxir::Context Ctx(C); 16517e5df5bcSvporpo auto *M = Ctx.createModule(LLVMM); 16527e5df5bcSvporpo // Check getContext(). 16537e5df5bcSvporpo EXPECT_EQ(&M->getContext(), &Ctx); 16547e5df5bcSvporpo // Check getFunction(). 16557e5df5bcSvporpo auto *FFoo = M->getFunction("foo"); 16567e5df5bcSvporpo auto *FBar = M->getFunction("bar"); 16577e5df5bcSvporpo EXPECT_EQ(FFoo, Ctx.getValue(LLVMFFoo)); 16587e5df5bcSvporpo EXPECT_EQ(FBar, Ctx.getValue(LLVMFBar)); 16597e5df5bcSvporpo // Check getDataLayout(). 16607e5df5bcSvporpo EXPECT_EQ(&M->getDataLayout(), &LLVMM->getDataLayout()); 16617e5df5bcSvporpo // Check getSourceFileName(). 16627e5df5bcSvporpo EXPECT_EQ(M->getSourceFileName(), LLVMM->getSourceFileName()); 16637e5df5bcSvporpo // Check getGlobalVariable(). 16647e5df5bcSvporpo for (const char *Name : {"global0", "global1", "internal0"}) 16657e5df5bcSvporpo EXPECT_EQ(M->getGlobalVariable(Name), 16667e5df5bcSvporpo Ctx.getValue(LLVMM->getGlobalVariable(Name))); 16677e5df5bcSvporpo // Check getGlobalVariable(AllowInternal). 16687e5df5bcSvporpo { 16697e5df5bcSvporpo auto *Internal0 = M->getGlobalVariable("internal0", /*AllowInternal=*/true); 16707e5df5bcSvporpo EXPECT_TRUE(Internal0 != nullptr); 16717e5df5bcSvporpo EXPECT_EQ(Internal0, Ctx.getValue(LLVMM->getNamedGlobal("internal0"))); 16727e5df5bcSvporpo } 16737e5df5bcSvporpo // Check getNamedGlobal(). 16747e5df5bcSvporpo { 16757e5df5bcSvporpo auto *Internal = M->getNamedGlobal("internal0"); 16767e5df5bcSvporpo EXPECT_TRUE(Internal != nullptr); 16777e5df5bcSvporpo EXPECT_EQ(Internal, Ctx.getValue(LLVMM->getNamedGlobal("internal0"))); 16787e5df5bcSvporpo } 16797e5df5bcSvporpo // Check getNamedAlias(). 16807e5df5bcSvporpo auto *Alias0 = M->getNamedAlias("alias0"); 16817e5df5bcSvporpo EXPECT_EQ(Alias0, Ctx.getValue(LLVMM->getNamedAlias("alias0"))); 16827e5df5bcSvporpo EXPECT_EQ(M->getNamedAlias("aliasFOO"), nullptr); 16837e5df5bcSvporpo // Check getNamedIFunc(). 16847e5df5bcSvporpo auto *IFunc0 = M->getNamedIFunc("ifunc0"); 16857e5df5bcSvporpo EXPECT_EQ(IFunc0, Ctx.getValue(LLVMM->getNamedAlias("ifunc0"))); 16867e5df5bcSvporpo EXPECT_EQ(M->getNamedIFunc("ifuncFOO"), nullptr); 16877e5df5bcSvporpo } 16887e5df5bcSvporpo 168950881d03Svporpo TEST_F(SandboxIRTest, BasicBlock) { 169050881d03Svporpo parseIR(C, R"IR( 169150881d03Svporpo define void @foo(i32 %v1) { 169250881d03Svporpo bb0: 169350881d03Svporpo br label %bb1 169450881d03Svporpo bb1: 169550881d03Svporpo ret void 169650881d03Svporpo } 169750881d03Svporpo )IR"); 169850881d03Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 169950881d03Svporpo llvm::BasicBlock *LLVMBB0 = getBasicBlockByName(*LLVMF, "bb0"); 170050881d03Svporpo llvm::BasicBlock *LLVMBB1 = getBasicBlockByName(*LLVMF, "bb1"); 170150881d03Svporpo 170250881d03Svporpo sandboxir::Context Ctx(C); 170350881d03Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 170450881d03Svporpo auto &BB0 = cast<sandboxir::BasicBlock>(*Ctx.getValue(LLVMBB0)); 170550881d03Svporpo auto &BB1 = cast<sandboxir::BasicBlock>(*Ctx.getValue(LLVMBB1)); 170650881d03Svporpo 170750881d03Svporpo // Check BB::classof() 170850881d03Svporpo EXPECT_TRUE(isa<sandboxir::Value>(BB0)); 170950881d03Svporpo EXPECT_FALSE(isa<sandboxir::User>(BB0)); 171050881d03Svporpo EXPECT_FALSE(isa<sandboxir::Instruction>(BB0)); 171150881d03Svporpo EXPECT_FALSE(isa<sandboxir::Constant>(BB0)); 171250881d03Svporpo EXPECT_FALSE(isa<sandboxir::Argument>(BB0)); 171350881d03Svporpo 171450881d03Svporpo // Check BB.getParent() 171550881d03Svporpo EXPECT_EQ(BB0.getParent(), F); 171650881d03Svporpo EXPECT_EQ(BB1.getParent(), F); 171750881d03Svporpo 171850881d03Svporpo // Check BBIterator, BB.begin(), BB.end(). 171950881d03Svporpo llvm::Instruction *LLVMI = &*LLVMBB0->begin(); 172050881d03Svporpo for (sandboxir::Instruction &I : BB0) { 172150881d03Svporpo EXPECT_EQ(&I, Ctx.getValue(LLVMI)); 172250881d03Svporpo LLVMI = LLVMI->getNextNode(); 1723b8466385Svporpo // Check getNodeParent(). 1724b8466385Svporpo EXPECT_EQ(I.getIterator().getNodeParent(), &BB0); 172550881d03Svporpo } 172650881d03Svporpo LLVMI = &*LLVMBB1->begin(); 172750881d03Svporpo for (sandboxir::Instruction &I : BB1) { 172850881d03Svporpo EXPECT_EQ(&I, Ctx.getValue(LLVMI)); 172950881d03Svporpo LLVMI = LLVMI->getNextNode(); 173050881d03Svporpo } 1731b8466385Svporpo // Check NodeParent() for BB::end(). 1732b8466385Svporpo EXPECT_EQ(BB0.end().getNodeParent(), &BB0); 173350881d03Svporpo 173450881d03Svporpo // Check BB.getTerminator() 173550881d03Svporpo EXPECT_EQ(BB0.getTerminator(), Ctx.getValue(LLVMBB0->getTerminator())); 173650881d03Svporpo EXPECT_EQ(BB1.getTerminator(), Ctx.getValue(LLVMBB1->getTerminator())); 173750881d03Svporpo 173850881d03Svporpo // Check BB.rbegin(), BB.rend() 173950881d03Svporpo EXPECT_EQ(&*BB0.rbegin(), BB0.getTerminator()); 174050881d03Svporpo EXPECT_EQ(&*std::prev(BB0.rend()), &*BB0.begin()); 174150881d03Svporpo 174250881d03Svporpo #ifndef NDEBUG 174350881d03Svporpo { 174450881d03Svporpo // Check BB.dump() 174550881d03Svporpo std::string Buff; 174650881d03Svporpo raw_string_ostream BS(Buff); 174750881d03Svporpo BS << "\n"; 174853517231Svporpo BB0.dumpOS(BS); 174950881d03Svporpo EXPECT_EQ(Buff, R"IR( 175050881d03Svporpo bb0: 1751372a6beaSvporpo br label %bb1 ; SB3. (Br) 175250881d03Svporpo )IR"); 175350881d03Svporpo } 175450881d03Svporpo #endif // NDEBUG 1755d5f5dc9dSvporpo } 1756bbcb3d6aSVasileios Porpodas 1757bbcb3d6aSVasileios Porpodas TEST_F(SandboxIRTest, Instruction) { 1758bbcb3d6aSVasileios Porpodas parseIR(C, R"IR( 175974405b9dSvporpo define void @foo(i8 %v1, ptr %ptr) { 176074405b9dSvporpo bb0: 1761bbcb3d6aSVasileios Porpodas %add0 = add i8 %v1, %v1 1762bbcb3d6aSVasileios Porpodas %sub1 = sub i8 %add0, %v1 1763bbcb3d6aSVasileios Porpodas ret void 176474405b9dSvporpo 176574405b9dSvporpo bb1: 176674405b9dSvporpo %add1 = add i8 %v1, %v1 176774405b9dSvporpo %sub2 = sub i8 %add1, %v1 176874405b9dSvporpo %ld0 = load i8, ptr %ptr 176974405b9dSvporpo store i8 %ld0, ptr %ptr 177074405b9dSvporpo store volatile i8 %ld0, ptr %ptr 177174405b9dSvporpo %atomicrmw = atomicrmw add ptr %ptr, i8 %v1 acquire 177274405b9dSvporpo %udiv = udiv i8 %ld0, %v1 1773f4042077Svporpo %urem = urem i8 %ld0, %v1 177451039101SSriraman Tallam call void @foo(), !dbg !1 177551039101SSriraman Tallam ret void, !tbaa !2 1776bbcb3d6aSVasileios Porpodas } 177751039101SSriraman Tallam 177851039101SSriraman Tallam !1 = !{} 177951039101SSriraman Tallam !2 = !{} 1780bbcb3d6aSVasileios Porpodas )IR"); 1781bbcb3d6aSVasileios Porpodas llvm::Function *LLVMF = &*M->getFunction("foo"); 178274405b9dSvporpo llvm::BasicBlock *LLVMBB1 = getBasicBlockByName(*LLVMF, "bb1"); 1783bbcb3d6aSVasileios Porpodas sandboxir::Context Ctx(C); 1784bbcb3d6aSVasileios Porpodas sandboxir::Function *F = Ctx.createFunction(LLVMF); 1785bbcb3d6aSVasileios Porpodas auto *Arg = F->getArg(0); 178674405b9dSvporpo auto *BB = cast<sandboxir::BasicBlock>( 178774405b9dSvporpo Ctx.getValue(getBasicBlockByName(*LLVMF, "bb0"))); 1788bbcb3d6aSVasileios Porpodas auto It = BB->begin(); 1789bbcb3d6aSVasileios Porpodas auto *I0 = &*It++; 1790bbcb3d6aSVasileios Porpodas auto *I1 = &*It++; 17917467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1792bbcb3d6aSVasileios Porpodas 1793bbcb3d6aSVasileios Porpodas // Check getPrevNode(). 1794bbcb3d6aSVasileios Porpodas EXPECT_EQ(Ret->getPrevNode(), I1); 1795bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getPrevNode(), I0); 1796bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getPrevNode(), nullptr); 1797bbcb3d6aSVasileios Porpodas 1798bbcb3d6aSVasileios Porpodas // Check getNextNode(). 1799bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNextNode(), I1); 1800bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getNextNode(), Ret); 1801bbcb3d6aSVasileios Porpodas EXPECT_EQ(Ret->getNextNode(), nullptr); 1802bbcb3d6aSVasileios Porpodas 1803bbcb3d6aSVasileios Porpodas // Check getIterator(). 1804bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getIterator(), std::next(BB->begin(), 0)); 1805bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getIterator(), std::next(BB->begin(), 1)); 1806bbcb3d6aSVasileios Porpodas EXPECT_EQ(Ret->getIterator(), std::next(BB->begin(), 2)); 1807bbcb3d6aSVasileios Porpodas 1808bbcb3d6aSVasileios Porpodas // Check getOpcode(). 18096ec169d3Svporpo EXPECT_EQ(I0->getOpcode(), sandboxir::Instruction::Opcode::Add); 18106ec169d3Svporpo EXPECT_EQ(I1->getOpcode(), sandboxir::Instruction::Opcode::Sub); 18117467f41aSvporpo EXPECT_EQ(Ret->getOpcode(), sandboxir::Instruction::Opcode::Ret); 1812bbcb3d6aSVasileios Porpodas 181351039101SSriraman Tallam // Check getOpcodeName(). 181413809b3dSVasileios Porpodas EXPECT_STREQ(I0->getOpcodeName(), "Add"); 181513809b3dSVasileios Porpodas EXPECT_STREQ(I1->getOpcodeName(), "Sub"); 181613809b3dSVasileios Porpodas EXPECT_STREQ(Ret->getOpcodeName(), "Ret"); 181751039101SSriraman Tallam 181813809b3dSVasileios Porpodas EXPECT_STREQ(sandboxir::Instruction::getOpcodeName( 181951039101SSriraman Tallam sandboxir::Instruction::Opcode::Alloca), 182051039101SSriraman Tallam "Alloca"); 182151039101SSriraman Tallam 1822bbcb3d6aSVasileios Porpodas // Check moveBefore(I). 1823bbcb3d6aSVasileios Porpodas I1->moveBefore(I0); 1824bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getPrevNode(), I1); 1825bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getNextNode(), I0); 1826bbcb3d6aSVasileios Porpodas 1827bbcb3d6aSVasileios Porpodas // Check moveAfter(I). 1828bbcb3d6aSVasileios Porpodas I1->moveAfter(I0); 1829bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNextNode(), I1); 1830bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getPrevNode(), I0); 1831bbcb3d6aSVasileios Porpodas 18326cbb2455Svporpo // Check comesBefore(I). 18336cbb2455Svporpo EXPECT_TRUE(I0->comesBefore(I1)); 18346cbb2455Svporpo EXPECT_FALSE(I1->comesBefore(I0)); 18356cbb2455Svporpo 1836bbcb3d6aSVasileios Porpodas // Check moveBefore(BB, It). 1837bbcb3d6aSVasileios Porpodas I1->moveBefore(*BB, BB->begin()); 1838bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getPrevNode(), nullptr); 1839bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getNextNode(), I0); 1840bbcb3d6aSVasileios Porpodas I1->moveBefore(*BB, BB->end()); 1841bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getNextNode(), nullptr); 1842bbcb3d6aSVasileios Porpodas EXPECT_EQ(Ret->getNextNode(), I1); 1843bbcb3d6aSVasileios Porpodas I1->moveBefore(*BB, std::next(BB->begin())); 1844bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNextNode(), I1); 1845bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getNextNode(), Ret); 1846bbcb3d6aSVasileios Porpodas 1847bbcb3d6aSVasileios Porpodas // Check removeFromParent(). 1848bbcb3d6aSVasileios Porpodas I0->removeFromParent(); 1849bbcb3d6aSVasileios Porpodas #ifndef NDEBUG 1850bbcb3d6aSVasileios Porpodas EXPECT_DEATH(I0->getPrevNode(), ".*Detached.*"); 1851bbcb3d6aSVasileios Porpodas EXPECT_DEATH(I0->getNextNode(), ".*Detached.*"); 1852bbcb3d6aSVasileios Porpodas #endif // NDEBUG 1853bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getParent(), nullptr); 1854bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getPrevNode(), nullptr); 1855bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getOperand(0), Arg); 1856bbcb3d6aSVasileios Porpodas 1857bbcb3d6aSVasileios Porpodas // Check insertBefore(). 1858bbcb3d6aSVasileios Porpodas I0->insertBefore(I1); 1859bbcb3d6aSVasileios Porpodas EXPECT_EQ(I1->getPrevNode(), I0); 1860bbcb3d6aSVasileios Porpodas 1861bbcb3d6aSVasileios Porpodas // Check insertInto(). 1862bbcb3d6aSVasileios Porpodas I0->removeFromParent(); 1863bbcb3d6aSVasileios Porpodas I0->insertInto(BB, BB->end()); 1864bbcb3d6aSVasileios Porpodas EXPECT_EQ(Ret->getNextNode(), I0); 1865bbcb3d6aSVasileios Porpodas I0->moveBefore(I1); 1866bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNextNode(), I1); 1867bbcb3d6aSVasileios Porpodas 1868bbcb3d6aSVasileios Porpodas // Check eraseFromParent(). 1869bbcb3d6aSVasileios Porpodas #ifndef NDEBUG 1870bbcb3d6aSVasileios Porpodas EXPECT_DEATH(I0->eraseFromParent(), "Still connected to users.*"); 1871bbcb3d6aSVasileios Porpodas #endif 1872bbcb3d6aSVasileios Porpodas I1->eraseFromParent(); 1873bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNumUses(), 0u); 1874bbcb3d6aSVasileios Porpodas EXPECT_EQ(I0->getNextNode(), Ret); 187574405b9dSvporpo 187674405b9dSvporpo for (auto &LLVMI : *LLVMBB1) { 187774405b9dSvporpo auto &I = cast<sandboxir::Instruction>(*Ctx.getValue(&LLVMI)); 1878f4042077Svporpo // Check isTerminator(). 1879f4042077Svporpo EXPECT_EQ(LLVMI.isTerminator(), I.isTerminator()); 1880f4042077Svporpo // Check isUnaryOp(). 1881f4042077Svporpo EXPECT_EQ(LLVMI.isUnaryOp(), I.isUnaryOp()); 1882f4042077Svporpo // Check isBinaryOp(). 1883f4042077Svporpo EXPECT_EQ(LLVMI.isBinaryOp(), I.isBinaryOp()); 1884f4042077Svporpo // Check isIntDivRem(). 1885f4042077Svporpo EXPECT_EQ(LLVMI.isIntDivRem(), I.isIntDivRem()); 1886f4042077Svporpo // Check isShift(). 1887f4042077Svporpo EXPECT_EQ(LLVMI.isShift(), I.isShift()); 1888f4042077Svporpo // Check isCast(). 1889f4042077Svporpo EXPECT_EQ(LLVMI.isCast(), I.isCast()); 189051039101SSriraman Tallam // Check isFuncletPad(). 189151039101SSriraman Tallam EXPECT_EQ(LLVMI.isFuncletPad(), I.isFuncletPad()); 189251039101SSriraman Tallam // Check isSpecialTerminator(). 189351039101SSriraman Tallam EXPECT_EQ(LLVMI.isSpecialTerminator(), I.isSpecialTerminator()); 189451039101SSriraman Tallam // Check isOnlyUserOfAnyOperand(). 189551039101SSriraman Tallam EXPECT_EQ(LLVMI.isOnlyUserOfAnyOperand(), I.isOnlyUserOfAnyOperand()); 189651039101SSriraman Tallam // Check isLogicalShift(). 189751039101SSriraman Tallam EXPECT_EQ(LLVMI.isLogicalShift(), I.isLogicalShift()); 189851039101SSriraman Tallam // Check hasMetadata(). 189951039101SSriraman Tallam EXPECT_EQ(LLVMI.hasMetadata(), I.hasMetadata()); 190051039101SSriraman Tallam // Check hasMetadataOtherThanDebugLoc(). 190151039101SSriraman Tallam EXPECT_EQ(LLVMI.hasMetadataOtherThanDebugLoc(), 190251039101SSriraman Tallam I.hasMetadataOtherThanDebugLoc()); 190374405b9dSvporpo // Check isAssociative(). 190474405b9dSvporpo EXPECT_EQ(LLVMI.isAssociative(), I.isAssociative()); 190574405b9dSvporpo // Check isCommutative(). 190674405b9dSvporpo EXPECT_EQ(LLVMI.isCommutative(), I.isCommutative()); 190774405b9dSvporpo // Check isIdempotent(). 190874405b9dSvporpo EXPECT_EQ(LLVMI.isIdempotent(), I.isIdempotent()); 190974405b9dSvporpo // Check isNilpotent(). 191074405b9dSvporpo EXPECT_EQ(LLVMI.isNilpotent(), I.isNilpotent()); 191174405b9dSvporpo // Check mayWriteToMemory(). 191274405b9dSvporpo EXPECT_EQ(LLVMI.mayWriteToMemory(), I.mayWriteToMemory()); 191374405b9dSvporpo // Check mayReadFromMemory(). 191474405b9dSvporpo EXPECT_EQ(LLVMI.mayReadFromMemory(), I.mayReadFromMemory()); 191574405b9dSvporpo // Check mayReadOrWriteMemory(). 191674405b9dSvporpo EXPECT_EQ(LLVMI.mayReadOrWriteMemory(), I.mayReadOrWriteMemory()); 191774405b9dSvporpo // Check isAtomic(). 191874405b9dSvporpo EXPECT_EQ(LLVMI.isAtomic(), I.isAtomic()); 191974405b9dSvporpo if (I.isAtomic()) { 192074405b9dSvporpo // Check hasAtomicLoad(). 192174405b9dSvporpo EXPECT_EQ(LLVMI.hasAtomicLoad(), I.hasAtomicLoad()); 192274405b9dSvporpo // Check hasAtomicStore(). 192374405b9dSvporpo EXPECT_EQ(LLVMI.hasAtomicStore(), I.hasAtomicStore()); 192474405b9dSvporpo } 192574405b9dSvporpo // Check isVolatile(). 192674405b9dSvporpo EXPECT_EQ(LLVMI.isVolatile(), I.isVolatile()); 192774405b9dSvporpo // Check getAccessType(). 192874405b9dSvporpo EXPECT_EQ(Ctx.getType(LLVMI.getAccessType()), I.getAccessType()); 192974405b9dSvporpo // Check mayThrow(). 193074405b9dSvporpo EXPECT_EQ(LLVMI.mayThrow(), I.mayThrow()); 193174405b9dSvporpo // Check isFenceLike(). 193274405b9dSvporpo EXPECT_EQ(LLVMI.isFenceLike(), I.isFenceLike()); 193374405b9dSvporpo // Check mayHaveSideEffects(). 193474405b9dSvporpo EXPECT_EQ(LLVMI.mayHaveSideEffects(), I.mayHaveSideEffects()); 193574405b9dSvporpo } 1936bbcb3d6aSVasileios Porpodas } 193763625f44Svporpo 1938ff81f9fbSvporpo TEST_F(SandboxIRTest, VAArgInst) { 1939ff81f9fbSvporpo parseIR(C, R"IR( 1940ff81f9fbSvporpo define void @foo(ptr %va) { 1941ff81f9fbSvporpo %va_arg = va_arg ptr %va, i32 1942ff81f9fbSvporpo ret void 1943ff81f9fbSvporpo } 1944ff81f9fbSvporpo )IR"); 1945ff81f9fbSvporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 1946ff81f9fbSvporpo 1947ff81f9fbSvporpo sandboxir::Context Ctx(C); 1948ff81f9fbSvporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 1949ff81f9fbSvporpo auto *Arg = F->getArg(0); 1950ff81f9fbSvporpo auto *BB = &*F->begin(); 1951ff81f9fbSvporpo auto It = BB->begin(); 1952ff81f9fbSvporpo auto *VA = cast<sandboxir::VAArgInst>(&*It++); 1953ff81f9fbSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 1954ff81f9fbSvporpo 1955ff81f9fbSvporpo // Check getPointerOperand(). 1956ff81f9fbSvporpo EXPECT_EQ(VA->getPointerOperand(), Arg); 1957ff81f9fbSvporpo // Check getPOinterOperandIndex(). 1958ff81f9fbSvporpo EXPECT_EQ(sandboxir::VAArgInst::getPointerOperandIndex(), 1959ff81f9fbSvporpo llvm::VAArgInst::getPointerOperandIndex()); 1960ff81f9fbSvporpo // Check create(). 1961034f2b38Svporpo auto *NewVATy = sandboxir::Type::getInt8Ty(Ctx); 1962ff81f9fbSvporpo auto *NewVA = sandboxir::VAArgInst::create(Arg, NewVATy, Ret->getIterator(), 1963e1434a87Svporpo Ctx, "NewVA"); 1964ff81f9fbSvporpo EXPECT_EQ(NewVA->getNextNode(), Ret); 1965ff81f9fbSvporpo EXPECT_EQ(NewVA->getType(), NewVATy); 1966ff81f9fbSvporpo #ifndef NDEBUG 1967ff81f9fbSvporpo EXPECT_EQ(NewVA->getName(), "NewVA"); 1968ff81f9fbSvporpo #endif // NDEBUG 1969ff81f9fbSvporpo } 1970ff81f9fbSvporpo 19712a5ac9d9Svporpo TEST_F(SandboxIRTest, FreezeInst) { 19722a5ac9d9Svporpo parseIR(C, R"IR( 19732a5ac9d9Svporpo define void @foo(i8 %arg) { 19742a5ac9d9Svporpo freeze i8 %arg 19752a5ac9d9Svporpo ret void 19762a5ac9d9Svporpo } 19772a5ac9d9Svporpo )IR"); 19782a5ac9d9Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 19792a5ac9d9Svporpo 19802a5ac9d9Svporpo sandboxir::Context Ctx(C); 19812a5ac9d9Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 19822a5ac9d9Svporpo auto *Arg = F->getArg(0); 19832a5ac9d9Svporpo auto *BB = &*F->begin(); 19842a5ac9d9Svporpo auto It = BB->begin(); 19852a5ac9d9Svporpo auto *Freeze = cast<sandboxir::FreezeInst>(&*It++); 19862a5ac9d9Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 19872a5ac9d9Svporpo 19882a5ac9d9Svporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Freeze)); 19892a5ac9d9Svporpo EXPECT_EQ(Freeze->getOperand(0), Arg); 19902a5ac9d9Svporpo 19912a5ac9d9Svporpo // Check create(). 1992e1434a87Svporpo auto *NewFreeze = 1993e1434a87Svporpo sandboxir::FreezeInst::create(Arg, Ret->getIterator(), Ctx, "NewFreeze"); 19942a5ac9d9Svporpo EXPECT_EQ(NewFreeze->getNextNode(), Ret); 19952a5ac9d9Svporpo #ifndef NDEBUG 19962a5ac9d9Svporpo EXPECT_EQ(NewFreeze->getName(), "NewFreeze"); 19972a5ac9d9Svporpo #endif // NDEBUG 19982a5ac9d9Svporpo } 19992a5ac9d9Svporpo 2000d88876e7Svporpo TEST_F(SandboxIRTest, FenceInst) { 2001d88876e7Svporpo parseIR(C, R"IR( 2002d88876e7Svporpo define void @foo() { 2003d88876e7Svporpo fence syncscope("singlethread") seq_cst 2004d88876e7Svporpo ret void 2005d88876e7Svporpo } 2006d88876e7Svporpo )IR"); 2007d88876e7Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 2008d88876e7Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF->begin(); 2009d88876e7Svporpo auto *LLVMFence = cast<llvm::FenceInst>(&*LLVMBB->begin()); 2010d88876e7Svporpo sandboxir::Context Ctx(C); 2011d88876e7Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 2012d88876e7Svporpo auto *BB = &*F->begin(); 2013d88876e7Svporpo auto It = BB->begin(); 2014d88876e7Svporpo auto *Fence = cast<sandboxir::FenceInst>(&*It++); 2015d88876e7Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 2016d88876e7Svporpo 2017d88876e7Svporpo // Check getOrdering(). 2018d88876e7Svporpo EXPECT_EQ(Fence->getOrdering(), LLVMFence->getOrdering()); 2019d88876e7Svporpo // Check setOrdering(). 2020d88876e7Svporpo auto OrigOrdering = Fence->getOrdering(); 2021d88876e7Svporpo auto NewOrdering = AtomicOrdering::Release; 2022d88876e7Svporpo EXPECT_NE(NewOrdering, OrigOrdering); 2023d88876e7Svporpo Fence->setOrdering(NewOrdering); 2024d88876e7Svporpo EXPECT_EQ(Fence->getOrdering(), NewOrdering); 2025d88876e7Svporpo Fence->setOrdering(OrigOrdering); 2026d88876e7Svporpo EXPECT_EQ(Fence->getOrdering(), OrigOrdering); 2027d88876e7Svporpo // Check getSyncScopeID(). 2028d88876e7Svporpo EXPECT_EQ(Fence->getSyncScopeID(), LLVMFence->getSyncScopeID()); 2029d88876e7Svporpo // Check setSyncScopeID(). 2030d88876e7Svporpo auto OrigSSID = Fence->getSyncScopeID(); 2031d88876e7Svporpo auto NewSSID = SyncScope::System; 2032d88876e7Svporpo EXPECT_NE(NewSSID, OrigSSID); 2033d88876e7Svporpo Fence->setSyncScopeID(NewSSID); 2034d88876e7Svporpo EXPECT_EQ(Fence->getSyncScopeID(), NewSSID); 2035d88876e7Svporpo Fence->setSyncScopeID(OrigSSID); 2036d88876e7Svporpo EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID); 2037d88876e7Svporpo // Check create(). 2038d88876e7Svporpo auto *NewFence = 2039d88876e7Svporpo sandboxir::FenceInst::create(AtomicOrdering::Release, Ret->getIterator(), 2040635db5eeSvporpo Ctx, SyncScope::SingleThread); 2041d88876e7Svporpo EXPECT_EQ(NewFence->getNextNode(), Ret); 2042d88876e7Svporpo EXPECT_EQ(NewFence->getOrdering(), AtomicOrdering::Release); 2043d88876e7Svporpo EXPECT_EQ(NewFence->getSyncScopeID(), SyncScope::SingleThread); 2044d88876e7Svporpo } 2045d88876e7Svporpo 204673ffeeabSvporpo TEST_F(SandboxIRTest, SelectInst) { 204773ffeeabSvporpo parseIR(C, R"IR( 204873ffeeabSvporpo define void @foo(i1 %c0, i8 %v0, i8 %v1, i1 %c1) { 204973ffeeabSvporpo %sel = select i1 %c0, i8 %v0, i8 %v1 205073ffeeabSvporpo ret void 205173ffeeabSvporpo } 205273ffeeabSvporpo )IR"); 205373ffeeabSvporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 205473ffeeabSvporpo sandboxir::Context Ctx(C); 205573ffeeabSvporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 205673ffeeabSvporpo auto *Cond0 = F->getArg(0); 205773ffeeabSvporpo auto *V0 = F->getArg(1); 205873ffeeabSvporpo auto *V1 = F->getArg(2); 205973ffeeabSvporpo auto *Cond1 = F->getArg(3); 206073ffeeabSvporpo auto *BB = &*F->begin(); 206173ffeeabSvporpo auto It = BB->begin(); 206273ffeeabSvporpo auto *Select = cast<sandboxir::SelectInst>(&*It++); 2063956591beSJorge Gorbe Moya const auto *ConstSelect = Select; // To test the const getters. 206473ffeeabSvporpo auto *Ret = &*It++; 206573ffeeabSvporpo 206673ffeeabSvporpo // Check getCondition(). 206773ffeeabSvporpo EXPECT_EQ(Select->getCondition(), Cond0); 2068956591beSJorge Gorbe Moya EXPECT_EQ(ConstSelect->getCondition(), Cond0); 206973ffeeabSvporpo // Check getTrueValue(). 207073ffeeabSvporpo EXPECT_EQ(Select->getTrueValue(), V0); 2071956591beSJorge Gorbe Moya EXPECT_EQ(ConstSelect->getTrueValue(), V0); 207273ffeeabSvporpo // Check getFalseValue(). 207373ffeeabSvporpo EXPECT_EQ(Select->getFalseValue(), V1); 2074956591beSJorge Gorbe Moya EXPECT_EQ(ConstSelect->getFalseValue(), V1); 207573ffeeabSvporpo // Check setCondition(). 207673ffeeabSvporpo Select->setCondition(Cond1); 207773ffeeabSvporpo EXPECT_EQ(Select->getCondition(), Cond1); 207873ffeeabSvporpo // Check setTrueValue(). 207973ffeeabSvporpo Select->setTrueValue(V1); 208073ffeeabSvporpo EXPECT_EQ(Select->getTrueValue(), V1); 208173ffeeabSvporpo // Check setFalseValue(). 208273ffeeabSvporpo Select->setFalseValue(V0); 208373ffeeabSvporpo EXPECT_EQ(Select->getFalseValue(), V0); 2084956591beSJorge Gorbe Moya // Check swapValues(). 2085956591beSJorge Gorbe Moya Select->swapValues(); 2086956591beSJorge Gorbe Moya EXPECT_EQ(Select->getTrueValue(), V0); 2087956591beSJorge Gorbe Moya EXPECT_EQ(Select->getFalseValue(), V1); 2088956591beSJorge Gorbe Moya // Check areInvalidOperands. 2089956591beSJorge Gorbe Moya EXPECT_EQ(sandboxir::SelectInst::areInvalidOperands(Cond0, V0, V1), nullptr); 2090956591beSJorge Gorbe Moya EXPECT_NE(sandboxir::SelectInst::areInvalidOperands(V0, V1, Cond0), nullptr); 209173ffeeabSvporpo 209273ffeeabSvporpo { 209373ffeeabSvporpo // Check SelectInst::create() InsertBefore. 209473ffeeabSvporpo auto *NewSel = cast<sandboxir::SelectInst>(sandboxir::SelectInst::create( 2095635db5eeSvporpo Cond0, V0, V1, /*InsertBefore=*/Ret->getIterator(), Ctx)); 209673ffeeabSvporpo EXPECT_EQ(NewSel->getCondition(), Cond0); 209773ffeeabSvporpo EXPECT_EQ(NewSel->getTrueValue(), V0); 209873ffeeabSvporpo EXPECT_EQ(NewSel->getFalseValue(), V1); 209973ffeeabSvporpo EXPECT_EQ(NewSel->getNextNode(), Ret); 210073ffeeabSvporpo } 210173ffeeabSvporpo { 210273ffeeabSvporpo // Check SelectInst::create() InsertAtEnd. 210373ffeeabSvporpo auto *NewSel = cast<sandboxir::SelectInst>( 210473ffeeabSvporpo sandboxir::SelectInst::create(Cond0, V0, V1, /*InsertAtEnd=*/BB, Ctx)); 210573ffeeabSvporpo EXPECT_EQ(NewSel->getCondition(), Cond0); 210673ffeeabSvporpo EXPECT_EQ(NewSel->getTrueValue(), V0); 210773ffeeabSvporpo EXPECT_EQ(NewSel->getFalseValue(), V1); 210873ffeeabSvporpo EXPECT_EQ(NewSel->getPrevNode(), Ret); 210973ffeeabSvporpo } 211073ffeeabSvporpo { 211173ffeeabSvporpo // Check SelectInst::create() Folded. 2112034f2b38Svporpo auto *False = sandboxir::ConstantInt::get(sandboxir::Type::getInt1Ty(Ctx), 2113034f2b38Svporpo 0, /*IsSigned=*/false); 211473ffeeabSvporpo auto *FortyTwo = 2115034f2b38Svporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt1Ty(Ctx), 42, 211673ffeeabSvporpo /*IsSigned=*/false); 2117635db5eeSvporpo auto *NewSel = sandboxir::SelectInst::create(False, FortyTwo, FortyTwo, 2118635db5eeSvporpo Ret->getIterator(), Ctx); 211973ffeeabSvporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewSel)); 212073ffeeabSvporpo EXPECT_EQ(NewSel, FortyTwo); 212173ffeeabSvporpo } 212273ffeeabSvporpo } 212373ffeeabSvporpo 212415aa4ef0SJorge Gorbe Moya TEST_F(SandboxIRTest, ExtractElementInst) { 212515aa4ef0SJorge Gorbe Moya parseIR(C, R"IR( 212615aa4ef0SJorge Gorbe Moya define void @foo(<2 x i8> %vec, i32 %idx) { 212715aa4ef0SJorge Gorbe Moya %ins0 = extractelement <2 x i8> %vec, i32 %idx 212815aa4ef0SJorge Gorbe Moya ret void 212915aa4ef0SJorge Gorbe Moya } 213015aa4ef0SJorge Gorbe Moya )IR"); 213115aa4ef0SJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 213215aa4ef0SJorge Gorbe Moya sandboxir::Context Ctx(C); 213315aa4ef0SJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 213415aa4ef0SJorge Gorbe Moya auto *ArgVec = F.getArg(0); 213515aa4ef0SJorge Gorbe Moya auto *ArgIdx = F.getArg(1); 213615aa4ef0SJorge Gorbe Moya auto *BB = &*F.begin(); 213715aa4ef0SJorge Gorbe Moya auto It = BB->begin(); 213815aa4ef0SJorge Gorbe Moya auto *EI = cast<sandboxir::ExtractElementInst>(&*It++); 213915aa4ef0SJorge Gorbe Moya auto *Ret = &*It++; 214015aa4ef0SJorge Gorbe Moya 214115aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getOpcode(), sandboxir::Instruction::Opcode::ExtractElement); 214215aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getOperand(0), ArgVec); 214315aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getOperand(1), ArgIdx); 214415aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getVectorOperand(), ArgVec); 214515aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getIndexOperand(), ArgIdx); 214615aa4ef0SJorge Gorbe Moya EXPECT_EQ(EI->getVectorOperandType(), ArgVec->getType()); 214715aa4ef0SJorge Gorbe Moya 214815aa4ef0SJorge Gorbe Moya auto *NewI1 = 214915aa4ef0SJorge Gorbe Moya cast<sandboxir::ExtractElementInst>(sandboxir::ExtractElementInst::create( 2150e1434a87Svporpo ArgVec, ArgIdx, Ret->getIterator(), Ctx, "NewExtrBeforeRet")); 215115aa4ef0SJorge Gorbe Moya EXPECT_EQ(NewI1->getOperand(0), ArgVec); 215215aa4ef0SJorge Gorbe Moya EXPECT_EQ(NewI1->getOperand(1), ArgIdx); 215315aa4ef0SJorge Gorbe Moya EXPECT_EQ(NewI1->getNextNode(), Ret); 215415aa4ef0SJorge Gorbe Moya 215515aa4ef0SJorge Gorbe Moya auto *NewI2 = 215615aa4ef0SJorge Gorbe Moya cast<sandboxir::ExtractElementInst>(sandboxir::ExtractElementInst::create( 215715aa4ef0SJorge Gorbe Moya ArgVec, ArgIdx, BB, Ctx, "NewExtrAtEndOfBB")); 215815aa4ef0SJorge Gorbe Moya EXPECT_EQ(NewI2->getPrevNode(), Ret); 215915aa4ef0SJorge Gorbe Moya 216015aa4ef0SJorge Gorbe Moya auto *LLVMArgVec = LLVMF.getArg(0); 216115aa4ef0SJorge Gorbe Moya auto *LLVMArgIdx = LLVMF.getArg(1); 216215aa4ef0SJorge Gorbe Moya EXPECT_EQ(sandboxir::ExtractElementInst::isValidOperands(ArgVec, ArgIdx), 216315aa4ef0SJorge Gorbe Moya llvm::ExtractElementInst::isValidOperands(LLVMArgVec, LLVMArgIdx)); 216415aa4ef0SJorge Gorbe Moya EXPECT_EQ(sandboxir::ExtractElementInst::isValidOperands(ArgIdx, ArgVec), 216515aa4ef0SJorge Gorbe Moya llvm::ExtractElementInst::isValidOperands(LLVMArgIdx, LLVMArgVec)); 216615aa4ef0SJorge Gorbe Moya } 216715aa4ef0SJorge Gorbe Moya 216866d87350SJorge Gorbe Moya TEST_F(SandboxIRTest, InsertElementInst) { 216966d87350SJorge Gorbe Moya parseIR(C, R"IR( 217066d87350SJorge Gorbe Moya define void @foo(i8 %v0, i8 %v1, <2 x i8> %vec) { 217166d87350SJorge Gorbe Moya %ins0 = insertelement <2 x i8> poison, i8 %v0, i32 0 217266d87350SJorge Gorbe Moya %ins1 = insertelement <2 x i8> %ins0, i8 %v1, i32 1 217366d87350SJorge Gorbe Moya ret void 217466d87350SJorge Gorbe Moya } 217566d87350SJorge Gorbe Moya )IR"); 217666d87350SJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 217766d87350SJorge Gorbe Moya sandboxir::Context Ctx(C); 217866d87350SJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 217966d87350SJorge Gorbe Moya auto *Arg0 = F.getArg(0); 218066d87350SJorge Gorbe Moya auto *Arg1 = F.getArg(1); 218166d87350SJorge Gorbe Moya auto *ArgVec = F.getArg(2); 218266d87350SJorge Gorbe Moya auto *BB = &*F.begin(); 218366d87350SJorge Gorbe Moya auto It = BB->begin(); 218466d87350SJorge Gorbe Moya auto *Ins0 = cast<sandboxir::InsertElementInst>(&*It++); 218566d87350SJorge Gorbe Moya auto *Ins1 = cast<sandboxir::InsertElementInst>(&*It++); 218666d87350SJorge Gorbe Moya auto *Ret = &*It++; 218766d87350SJorge Gorbe Moya 218866d87350SJorge Gorbe Moya EXPECT_EQ(Ins0->getOpcode(), sandboxir::Instruction::Opcode::InsertElement); 218966d87350SJorge Gorbe Moya EXPECT_EQ(Ins0->getOperand(1), Arg0); 219066d87350SJorge Gorbe Moya EXPECT_EQ(Ins1->getOperand(1), Arg1); 219166d87350SJorge Gorbe Moya EXPECT_EQ(Ins1->getOperand(0), Ins0); 219266d87350SJorge Gorbe Moya auto *Poison = Ins0->getOperand(0); 219366d87350SJorge Gorbe Moya auto *Idx = Ins0->getOperand(2); 219466d87350SJorge Gorbe Moya auto *NewI1 = 219566d87350SJorge Gorbe Moya cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create( 2196635db5eeSvporpo Poison, Arg0, Idx, Ret->getIterator(), Ctx, "NewIns1")); 219766d87350SJorge Gorbe Moya EXPECT_EQ(NewI1->getOperand(0), Poison); 219866d87350SJorge Gorbe Moya EXPECT_EQ(NewI1->getNextNode(), Ret); 219966d87350SJorge Gorbe Moya 220066d87350SJorge Gorbe Moya auto *NewI2 = 220166d87350SJorge Gorbe Moya cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create( 220266d87350SJorge Gorbe Moya Poison, Arg0, Idx, BB, Ctx, "NewIns2")); 220366d87350SJorge Gorbe Moya EXPECT_EQ(NewI2->getPrevNode(), Ret); 220466d87350SJorge Gorbe Moya 220566d87350SJorge Gorbe Moya auto *LLVMArg0 = LLVMF.getArg(0); 220666d87350SJorge Gorbe Moya auto *LLVMArgVec = LLVMF.getArg(2); 2207034f2b38Svporpo auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0); 220866d87350SJorge Gorbe Moya auto *LLVMZero = llvm::ConstantInt::get(Type::getInt8Ty(C), 0); 220966d87350SJorge Gorbe Moya EXPECT_EQ( 221066d87350SJorge Gorbe Moya sandboxir::InsertElementInst::isValidOperands(ArgVec, Arg0, Zero), 221166d87350SJorge Gorbe Moya llvm::InsertElementInst::isValidOperands(LLVMArgVec, LLVMArg0, LLVMZero)); 221266d87350SJorge Gorbe Moya EXPECT_EQ( 221366d87350SJorge Gorbe Moya sandboxir::InsertElementInst::isValidOperands(Arg0, ArgVec, Zero), 221466d87350SJorge Gorbe Moya llvm::InsertElementInst::isValidOperands(LLVMArg0, LLVMArgVec, LLVMZero)); 221566d87350SJorge Gorbe Moya } 221666d87350SJorge Gorbe Moya 2217716594daSJorge Gorbe Moya TEST_F(SandboxIRTest, ShuffleVectorInst) { 2218716594daSJorge Gorbe Moya parseIR(C, R"IR( 2219716594daSJorge Gorbe Moya define void @foo(<2 x i8> %v1, <2 x i8> %v2) { 2220716594daSJorge Gorbe Moya %shuf = shufflevector <2 x i8> %v1, <2 x i8> %v2, <2 x i32> <i32 0, i32 2> 2221716594daSJorge Gorbe Moya %extr = extractelement <2 x i8> <i8 0, i8 1>, i32 0 2222716594daSJorge Gorbe Moya ret void 2223716594daSJorge Gorbe Moya } 2224716594daSJorge Gorbe Moya )IR"); 2225716594daSJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 2226716594daSJorge Gorbe Moya sandboxir::Context Ctx(C); 2227716594daSJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 2228716594daSJorge Gorbe Moya auto *ArgV1 = F.getArg(0); 2229716594daSJorge Gorbe Moya auto *ArgV2 = F.getArg(1); 2230716594daSJorge Gorbe Moya auto *BB = &*F.begin(); 2231716594daSJorge Gorbe Moya auto It = BB->begin(); 2232716594daSJorge Gorbe Moya auto *SVI = cast<sandboxir::ShuffleVectorInst>(&*It++); 2233716594daSJorge Gorbe Moya auto *EEI = cast<sandboxir::ExtractElementInst>(&*It++); 2234716594daSJorge Gorbe Moya auto *Ret = &*It++; 2235716594daSJorge Gorbe Moya 2236716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getOpcode(), sandboxir::Instruction::Opcode::ShuffleVector); 2237716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getOperand(0), ArgV1); 2238716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getOperand(1), ArgV2); 2239716594daSJorge Gorbe Moya 2240716594daSJorge Gorbe Moya // In order to test all the methods we need masks of different lengths, so we 2241716594daSJorge Gorbe Moya // can't simply reuse one of the instructions created above. This helper 2242716594daSJorge Gorbe Moya // creates a new `shufflevector %v1, %2, <mask>` with the given mask indices. 2243716594daSJorge Gorbe Moya auto CreateShuffleWithMask = [&](auto &&...Indices) { 2244716594daSJorge Gorbe Moya SmallVector<int, 4> Mask = {Indices...}; 2245716594daSJorge Gorbe Moya return cast<sandboxir::ShuffleVectorInst>( 2246e1434a87Svporpo sandboxir::ShuffleVectorInst::create(ArgV1, ArgV2, Mask, 2247e1434a87Svporpo Ret->getIterator(), Ctx)); 2248716594daSJorge Gorbe Moya }; 2249716594daSJorge Gorbe Moya 2250716594daSJorge Gorbe Moya // create (InsertBefore) 2251716594daSJorge Gorbe Moya auto *NewI1 = 2252716594daSJorge Gorbe Moya cast<sandboxir::ShuffleVectorInst>(sandboxir::ShuffleVectorInst::create( 2253e1434a87Svporpo ArgV1, ArgV2, ArrayRef<int>({0, 2, 1, 3}), Ret->getIterator(), Ctx, 2254716594daSJorge Gorbe Moya "NewShuffleBeforeRet")); 2255716594daSJorge Gorbe Moya EXPECT_EQ(NewI1->getOperand(0), ArgV1); 2256716594daSJorge Gorbe Moya EXPECT_EQ(NewI1->getOperand(1), ArgV2); 2257716594daSJorge Gorbe Moya EXPECT_EQ(NewI1->getNextNode(), Ret); 2258716594daSJorge Gorbe Moya #ifndef NDEBUG 2259716594daSJorge Gorbe Moya EXPECT_EQ(NewI1->getName(), "NewShuffleBeforeRet"); 2260716594daSJorge Gorbe Moya #endif 2261716594daSJorge Gorbe Moya 2262716594daSJorge Gorbe Moya // create (InsertAtEnd) 2263716594daSJorge Gorbe Moya auto *NewI2 = 2264716594daSJorge Gorbe Moya cast<sandboxir::ShuffleVectorInst>(sandboxir::ShuffleVectorInst::create( 2265716594daSJorge Gorbe Moya ArgV1, ArgV2, ArrayRef<int>({0, 1}), BB, Ctx, "NewShuffleAtEndOfBB")); 2266716594daSJorge Gorbe Moya EXPECT_EQ(NewI2->getPrevNode(), Ret); 2267716594daSJorge Gorbe Moya 2268716594daSJorge Gorbe Moya // Test the path that creates a folded constant. We're currently using an 2269716594daSJorge Gorbe Moya // extractelement instruction with a constant operand in the textual IR above 2270716594daSJorge Gorbe Moya // to obtain a constant vector to work with. 2271716594daSJorge Gorbe Moya // TODO: Refactor this once sandboxir::ConstantVector lands. 2272716594daSJorge Gorbe Moya auto *ShouldBeConstant = sandboxir::ShuffleVectorInst::create( 2273716594daSJorge Gorbe Moya EEI->getOperand(0), EEI->getOperand(0), ArrayRef<int>({0, 3}), BB, Ctx); 2274716594daSJorge Gorbe Moya EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant)); 2275716594daSJorge Gorbe Moya 2276716594daSJorge Gorbe Moya // isValidOperands 2277716594daSJorge Gorbe Moya auto *LLVMArgV1 = LLVMF.getArg(0); 2278716594daSJorge Gorbe Moya auto *LLVMArgV2 = LLVMF.getArg(1); 2279aa4c6557SJorge Gorbe Moya SmallVector<int, 2> Mask({1, 2}); 2280716594daSJorge Gorbe Moya EXPECT_EQ( 2281716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isValidOperands(ArgV1, ArgV2, Mask), 2282716594daSJorge Gorbe Moya llvm::ShuffleVectorInst::isValidOperands(LLVMArgV1, LLVMArgV2, Mask)); 2283716594daSJorge Gorbe Moya EXPECT_EQ(sandboxir::ShuffleVectorInst::isValidOperands(ArgV1, ArgV1, ArgV1), 2284716594daSJorge Gorbe Moya llvm::ShuffleVectorInst::isValidOperands(LLVMArgV1, LLVMArgV1, 2285716594daSJorge Gorbe Moya LLVMArgV1)); 2286716594daSJorge Gorbe Moya 2287716594daSJorge Gorbe Moya // commute 2288716594daSJorge Gorbe Moya { 2289716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2); 2290716594daSJorge Gorbe Moya I->commute(); 2291716594daSJorge Gorbe Moya EXPECT_EQ(I->getOperand(0), ArgV2); 2292716594daSJorge Gorbe Moya EXPECT_EQ(I->getOperand(1), ArgV1); 229304c827d0SJorge Gorbe Moya EXPECT_THAT(I->getShuffleMask(), testing::ElementsAre(2, 0)); 2294716594daSJorge Gorbe Moya } 2295716594daSJorge Gorbe Moya 2296716594daSJorge Gorbe Moya // getType 2297716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getType(), ArgV1->getType()); 2298716594daSJorge Gorbe Moya 2299716594daSJorge Gorbe Moya // getMaskValue 2300716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getMaskValue(0), 0); 2301716594daSJorge Gorbe Moya EXPECT_EQ(SVI->getMaskValue(1), 2); 2302716594daSJorge Gorbe Moya 2303716594daSJorge Gorbe Moya // getShuffleMask / getShuffleMaskForBitcode 2304716594daSJorge Gorbe Moya { 230504c827d0SJorge Gorbe Moya EXPECT_THAT(SVI->getShuffleMask(), testing::ElementsAre(0, 2)); 2306716594daSJorge Gorbe Moya 2307716594daSJorge Gorbe Moya SmallVector<int, 2> Result; 2308716594daSJorge Gorbe Moya SVI->getShuffleMask(Result); 230904c827d0SJorge Gorbe Moya EXPECT_THAT(Result, testing::ElementsAre(0, 2)); 2310716594daSJorge Gorbe Moya 2311716594daSJorge Gorbe Moya Result.clear(); 2312716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::getShuffleMask( 2313716594daSJorge Gorbe Moya SVI->getShuffleMaskForBitcode(), Result); 231404c827d0SJorge Gorbe Moya EXPECT_THAT(Result, testing::ElementsAre(0, 2)); 2315716594daSJorge Gorbe Moya } 2316716594daSJorge Gorbe Moya 2317716594daSJorge Gorbe Moya // convertShuffleMaskForBitcode 2318716594daSJorge Gorbe Moya { 2319716594daSJorge Gorbe Moya auto *C = sandboxir::ShuffleVectorInst::convertShuffleMaskForBitcode( 2320034f2b38Svporpo ArrayRef<int>({2, 3}), ArgV1->getType()); 2321716594daSJorge Gorbe Moya SmallVector<int, 2> Result; 2322716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::getShuffleMask(C, Result); 232304c827d0SJorge Gorbe Moya EXPECT_THAT(Result, testing::ElementsAre(2, 3)); 2324716594daSJorge Gorbe Moya } 2325716594daSJorge Gorbe Moya 2326716594daSJorge Gorbe Moya // setShuffleMask 2327716594daSJorge Gorbe Moya { 2328716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1); 2329716594daSJorge Gorbe Moya I->setShuffleMask(ArrayRef<int>({2, 3})); 233004c827d0SJorge Gorbe Moya EXPECT_THAT(I->getShuffleMask(), testing::ElementsAre(2, 3)); 2331716594daSJorge Gorbe Moya } 2332716594daSJorge Gorbe Moya 2333716594daSJorge Gorbe Moya // The following functions check different mask properties. Note that most 2334716594daSJorge Gorbe Moya // of these come in three different flavors: a method that checks the mask 2335716594daSJorge Gorbe Moya // in the current instructions and two static member functions that check 2336716594daSJorge Gorbe Moya // a mask given as an ArrayRef<int> or Constant*, so there's quite a bit of 2337716594daSJorge Gorbe Moya // repetition in order to check all of them. 2338716594daSJorge Gorbe Moya 2339716594daSJorge Gorbe Moya // changesLength / increasesLength 2340716594daSJorge Gorbe Moya { 2341716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1); 2342716594daSJorge Gorbe Moya EXPECT_TRUE(I->changesLength()); 2343716594daSJorge Gorbe Moya EXPECT_FALSE(I->increasesLength()); 2344716594daSJorge Gorbe Moya } 2345716594daSJorge Gorbe Moya { 2346716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 1); 2347716594daSJorge Gorbe Moya EXPECT_FALSE(I->changesLength()); 2348716594daSJorge Gorbe Moya EXPECT_FALSE(I->increasesLength()); 2349716594daSJorge Gorbe Moya } 2350716594daSJorge Gorbe Moya { 2351716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 1, 1); 2352716594daSJorge Gorbe Moya EXPECT_TRUE(I->changesLength()); 2353716594daSJorge Gorbe Moya EXPECT_TRUE(I->increasesLength()); 2354716594daSJorge Gorbe Moya } 2355716594daSJorge Gorbe Moya 2356716594daSJorge Gorbe Moya // isSingleSource / isSingleSourceMask 2357716594daSJorge Gorbe Moya { 2358716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1); 2359716594daSJorge Gorbe Moya EXPECT_TRUE(I->isSingleSource()); 2360716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSingleSourceMask( 2361716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2362716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSingleSourceMask( 2363716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2364716594daSJorge Gorbe Moya } 2365716594daSJorge Gorbe Moya { 2366716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2); 2367716594daSJorge Gorbe Moya EXPECT_FALSE(I->isSingleSource()); 2368716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSingleSourceMask( 2369716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2370716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSingleSourceMask( 2371716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2372716594daSJorge Gorbe Moya } 2373716594daSJorge Gorbe Moya 2374716594daSJorge Gorbe Moya // isIdentity / isIdentityMask 2375716594daSJorge Gorbe Moya { 2376716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1); 2377716594daSJorge Gorbe Moya EXPECT_TRUE(I->isIdentity()); 2378716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isIdentityMask( 2379716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2380716594daSJorge Gorbe Moya EXPECT_TRUE( 2381716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isIdentityMask(I->getShuffleMask(), 2)); 2382716594daSJorge Gorbe Moya } 2383716594daSJorge Gorbe Moya { 2384716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 0); 2385716594daSJorge Gorbe Moya EXPECT_FALSE(I->isIdentity()); 2386716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isIdentityMask( 2387716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2388716594daSJorge Gorbe Moya EXPECT_FALSE( 2389716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isIdentityMask(I->getShuffleMask(), 2)); 2390716594daSJorge Gorbe Moya } 2391716594daSJorge Gorbe Moya 2392716594daSJorge Gorbe Moya // isIdentityWithPadding 2393716594daSJorge Gorbe Moya EXPECT_TRUE(CreateShuffleWithMask(0, 1, -1, -1)->isIdentityWithPadding()); 2394716594daSJorge Gorbe Moya EXPECT_FALSE(CreateShuffleWithMask(0, 1)->isIdentityWithPadding()); 2395716594daSJorge Gorbe Moya 2396716594daSJorge Gorbe Moya // isIdentityWithExtract 2397716594daSJorge Gorbe Moya EXPECT_TRUE(CreateShuffleWithMask(0)->isIdentityWithExtract()); 2398716594daSJorge Gorbe Moya EXPECT_FALSE(CreateShuffleWithMask(0, 1)->isIdentityWithExtract()); 2399716594daSJorge Gorbe Moya EXPECT_FALSE(CreateShuffleWithMask(0, 1, 2)->isIdentityWithExtract()); 2400716594daSJorge Gorbe Moya EXPECT_FALSE(CreateShuffleWithMask(1)->isIdentityWithExtract()); 2401716594daSJorge Gorbe Moya 2402716594daSJorge Gorbe Moya // isConcat 2403716594daSJorge Gorbe Moya EXPECT_TRUE(CreateShuffleWithMask(0, 1, 2, 3)->isConcat()); 2404716594daSJorge Gorbe Moya EXPECT_FALSE(CreateShuffleWithMask(0, 3)->isConcat()); 2405716594daSJorge Gorbe Moya 2406716594daSJorge Gorbe Moya // isSelect / isSelectMask 2407716594daSJorge Gorbe Moya { 2408716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 3); 2409716594daSJorge Gorbe Moya EXPECT_TRUE(I->isSelect()); 2410716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSelectMask( 2411716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2412716594daSJorge Gorbe Moya EXPECT_TRUE( 2413716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isSelectMask(I->getShuffleMask(), 2)); 2414716594daSJorge Gorbe Moya } 2415716594daSJorge Gorbe Moya { 2416716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2); 2417716594daSJorge Gorbe Moya EXPECT_FALSE(I->isSelect()); 2418716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSelectMask( 2419716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2420716594daSJorge Gorbe Moya EXPECT_FALSE( 2421716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isSelectMask(I->getShuffleMask(), 2)); 2422716594daSJorge Gorbe Moya } 2423716594daSJorge Gorbe Moya 2424716594daSJorge Gorbe Moya // isReverse / isReverseMask 2425716594daSJorge Gorbe Moya { 2426716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 0); 2427716594daSJorge Gorbe Moya EXPECT_TRUE(I->isReverse()); 2428716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReverseMask( 2429716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2430716594daSJorge Gorbe Moya EXPECT_TRUE( 2431716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isReverseMask(I->getShuffleMask(), 2)); 2432716594daSJorge Gorbe Moya } 2433716594daSJorge Gorbe Moya { 2434716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 2); 2435716594daSJorge Gorbe Moya EXPECT_FALSE(I->isReverse()); 2436716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReverseMask( 2437716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2438716594daSJorge Gorbe Moya EXPECT_FALSE( 2439716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isReverseMask(I->getShuffleMask(), 2)); 2440716594daSJorge Gorbe Moya } 2441716594daSJorge Gorbe Moya 2442716594daSJorge Gorbe Moya // isZeroEltSplat / isZeroEltSplatMask 2443716594daSJorge Gorbe Moya { 2444716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 0); 2445716594daSJorge Gorbe Moya EXPECT_TRUE(I->isZeroEltSplat()); 2446716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask( 2447716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2448716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask( 2449716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2450716594daSJorge Gorbe Moya } 2451716594daSJorge Gorbe Moya { 2452716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 1); 2453716594daSJorge Gorbe Moya EXPECT_FALSE(I->isZeroEltSplat()); 2454716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask( 2455716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2456716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask( 2457716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2458716594daSJorge Gorbe Moya } 2459716594daSJorge Gorbe Moya 2460716594daSJorge Gorbe Moya // isTranspose / isTransposeMask 2461716594daSJorge Gorbe Moya { 2462716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2); 2463716594daSJorge Gorbe Moya EXPECT_TRUE(I->isTranspose()); 2464716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isTransposeMask( 2465716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2466716594daSJorge Gorbe Moya EXPECT_TRUE( 2467716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isTransposeMask(I->getShuffleMask(), 2)); 2468716594daSJorge Gorbe Moya } 2469716594daSJorge Gorbe Moya { 2470716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 1); 2471716594daSJorge Gorbe Moya EXPECT_FALSE(I->isTranspose()); 2472716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isTransposeMask( 2473716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2)); 2474716594daSJorge Gorbe Moya EXPECT_FALSE( 2475716594daSJorge Gorbe Moya sandboxir::ShuffleVectorInst::isTransposeMask(I->getShuffleMask(), 2)); 2476716594daSJorge Gorbe Moya } 2477716594daSJorge Gorbe Moya 2478716594daSJorge Gorbe Moya // isSplice / isSpliceMask 2479716594daSJorge Gorbe Moya { 2480716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 2); 2481716594daSJorge Gorbe Moya int Index; 2482716594daSJorge Gorbe Moya EXPECT_TRUE(I->isSplice(Index)); 2483716594daSJorge Gorbe Moya EXPECT_EQ(Index, 1); 2484716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSpliceMask( 2485716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, Index)); 2486716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSpliceMask(I->getShuffleMask(), 2487716594daSJorge Gorbe Moya 2, Index)); 2488716594daSJorge Gorbe Moya } 2489716594daSJorge Gorbe Moya { 2490716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(2, 1); 2491716594daSJorge Gorbe Moya int Index; 2492716594daSJorge Gorbe Moya EXPECT_FALSE(I->isSplice(Index)); 2493716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSpliceMask( 2494716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, Index)); 2495716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSpliceMask(I->getShuffleMask(), 2496716594daSJorge Gorbe Moya 2, Index)); 2497716594daSJorge Gorbe Moya } 2498716594daSJorge Gorbe Moya 2499716594daSJorge Gorbe Moya // isExtractSubvectorMask 2500716594daSJorge Gorbe Moya { 2501716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1); 2502716594daSJorge Gorbe Moya int Index; 2503716594daSJorge Gorbe Moya EXPECT_TRUE(I->isExtractSubvectorMask(Index)); 2504716594daSJorge Gorbe Moya EXPECT_EQ(Index, 1); 2505716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask( 2506716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, Index)); 2507716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask( 2508716594daSJorge Gorbe Moya I->getShuffleMask(), 2, Index)); 2509716594daSJorge Gorbe Moya } 2510716594daSJorge Gorbe Moya { 2511716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 2); 2512716594daSJorge Gorbe Moya int Index; 2513716594daSJorge Gorbe Moya EXPECT_FALSE(I->isExtractSubvectorMask(Index)); 2514716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask( 2515716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, Index)); 2516716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask( 2517716594daSJorge Gorbe Moya I->getShuffleMask(), 2, Index)); 2518716594daSJorge Gorbe Moya } 2519716594daSJorge Gorbe Moya 2520716594daSJorge Gorbe Moya // isInsertSubvectorMask 2521716594daSJorge Gorbe Moya { 2522716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2); 2523716594daSJorge Gorbe Moya int NumSubElts, Index; 2524716594daSJorge Gorbe Moya EXPECT_TRUE(I->isInsertSubvectorMask(NumSubElts, Index)); 2525716594daSJorge Gorbe Moya EXPECT_EQ(Index, 1); 2526716594daSJorge Gorbe Moya EXPECT_EQ(NumSubElts, 1); 2527716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask( 2528716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, NumSubElts, Index)); 2529716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask( 2530716594daSJorge Gorbe Moya I->getShuffleMask(), 2, NumSubElts, Index)); 2531716594daSJorge Gorbe Moya } 2532716594daSJorge Gorbe Moya { 2533716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1); 2534716594daSJorge Gorbe Moya int NumSubElts, Index; 2535716594daSJorge Gorbe Moya EXPECT_FALSE(I->isInsertSubvectorMask(NumSubElts, Index)); 2536716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask( 2537716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), 2, NumSubElts, Index)); 2538716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask( 2539716594daSJorge Gorbe Moya I->getShuffleMask(), 2, NumSubElts, Index)); 2540716594daSJorge Gorbe Moya } 2541716594daSJorge Gorbe Moya 2542716594daSJorge Gorbe Moya // isReplicationMask 2543716594daSJorge Gorbe Moya { 2544716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 0, 0, 1, 1, 1); 2545716594daSJorge Gorbe Moya int ReplicationFactor, VF; 2546716594daSJorge Gorbe Moya EXPECT_TRUE(I->isReplicationMask(ReplicationFactor, VF)); 2547716594daSJorge Gorbe Moya EXPECT_EQ(ReplicationFactor, 3); 2548716594daSJorge Gorbe Moya EXPECT_EQ(VF, 2); 2549716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReplicationMask( 2550716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), ReplicationFactor, VF)); 2551716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReplicationMask( 2552716594daSJorge Gorbe Moya I->getShuffleMask(), ReplicationFactor, VF)); 2553716594daSJorge Gorbe Moya } 2554716594daSJorge Gorbe Moya { 2555716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(1, 2); 2556716594daSJorge Gorbe Moya int ReplicationFactor, VF; 2557716594daSJorge Gorbe Moya EXPECT_FALSE(I->isReplicationMask(ReplicationFactor, VF)); 2558716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReplicationMask( 2559716594daSJorge Gorbe Moya I->getShuffleMaskForBitcode(), ReplicationFactor, VF)); 2560716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReplicationMask( 2561716594daSJorge Gorbe Moya I->getShuffleMask(), ReplicationFactor, VF)); 2562716594daSJorge Gorbe Moya } 2563716594daSJorge Gorbe Moya 2564716594daSJorge Gorbe Moya // isOneUseSingleSourceMask 2565716594daSJorge Gorbe Moya { 2566716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1, 1, 0); 2567716594daSJorge Gorbe Moya EXPECT_TRUE(I->isOneUseSingleSourceMask(2)); 2568716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isOneUseSingleSourceMask( 2569716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2570716594daSJorge Gorbe Moya } 2571716594daSJorge Gorbe Moya { 2572716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 1, 0, 0); 2573716594daSJorge Gorbe Moya EXPECT_FALSE(I->isOneUseSingleSourceMask(2)); 2574716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isOneUseSingleSourceMask( 2575716594daSJorge Gorbe Moya I->getShuffleMask(), 2)); 2576716594daSJorge Gorbe Moya } 2577716594daSJorge Gorbe Moya 2578716594daSJorge Gorbe Moya // commuteShuffleMask 2579716594daSJorge Gorbe Moya { 2580716594daSJorge Gorbe Moya SmallVector<int, 4> M = {0, 2, 1, 3}; 2581716594daSJorge Gorbe Moya ShuffleVectorInst::commuteShuffleMask(M, 2); 258204c827d0SJorge Gorbe Moya EXPECT_THAT(M, testing::ElementsAre(2, 0, 3, 1)); 2583716594daSJorge Gorbe Moya } 2584716594daSJorge Gorbe Moya 2585716594daSJorge Gorbe Moya // isInterleave / isInterleaveMask 2586716594daSJorge Gorbe Moya { 2587716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 2, 1, 3); 2588716594daSJorge Gorbe Moya EXPECT_TRUE(I->isInterleave(2)); 2589716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInterleaveMask( 2590716594daSJorge Gorbe Moya I->getShuffleMask(), 2, 4)); 2591716594daSJorge Gorbe Moya SmallVector<unsigned, 4> StartIndexes; 2592716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInterleaveMask( 2593716594daSJorge Gorbe Moya I->getShuffleMask(), 2, 4, StartIndexes)); 259404c827d0SJorge Gorbe Moya EXPECT_THAT(StartIndexes, testing::ElementsAre(0, 2)); 2595716594daSJorge Gorbe Moya } 2596716594daSJorge Gorbe Moya { 2597716594daSJorge Gorbe Moya auto *I = CreateShuffleWithMask(0, 3, 1, 2); 2598716594daSJorge Gorbe Moya EXPECT_FALSE(I->isInterleave(2)); 2599716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInterleaveMask( 2600716594daSJorge Gorbe Moya I->getShuffleMask(), 2, 4)); 2601716594daSJorge Gorbe Moya } 2602716594daSJorge Gorbe Moya 2603716594daSJorge Gorbe Moya // isDeInterleaveMaskOfFactor 2604716594daSJorge Gorbe Moya { 2605716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor( 2606716594daSJorge Gorbe Moya ArrayRef<int>({0, 2}), 2)); 2607716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor( 2608716594daSJorge Gorbe Moya ArrayRef<int>({0, 1}), 2)); 2609716594daSJorge Gorbe Moya 2610716594daSJorge Gorbe Moya unsigned Index; 2611716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor( 2612716594daSJorge Gorbe Moya ArrayRef<int>({1, 3}), 2, Index)); 2613716594daSJorge Gorbe Moya EXPECT_EQ(Index, 1u); 2614716594daSJorge Gorbe Moya } 2615716594daSJorge Gorbe Moya 2616716594daSJorge Gorbe Moya // isBitRotateMask 2617716594daSJorge Gorbe Moya { 2618716594daSJorge Gorbe Moya unsigned NumSubElts, RotateAmt; 2619716594daSJorge Gorbe Moya EXPECT_TRUE(sandboxir::ShuffleVectorInst::isBitRotateMask( 2620716594daSJorge Gorbe Moya ArrayRef<int>({1, 0, 3, 2, 5, 4, 7, 6}), 8, 2, 2, NumSubElts, 2621716594daSJorge Gorbe Moya RotateAmt)); 2622716594daSJorge Gorbe Moya EXPECT_EQ(NumSubElts, 2u); 2623716594daSJorge Gorbe Moya EXPECT_EQ(RotateAmt, 8u); 2624716594daSJorge Gorbe Moya 2625716594daSJorge Gorbe Moya EXPECT_FALSE(sandboxir::ShuffleVectorInst::isBitRotateMask( 2626716594daSJorge Gorbe Moya ArrayRef<int>({0, 7, 1, 6, 2, 5, 3, 4}), 8, 2, 2, NumSubElts, 2627716594daSJorge Gorbe Moya RotateAmt)); 2628716594daSJorge Gorbe Moya } 2629716594daSJorge Gorbe Moya } 2630716594daSJorge Gorbe Moya 263118270868SJorge Gorbe Moya TEST_F(SandboxIRTest, ExtractValueInst) { 263218270868SJorge Gorbe Moya parseIR(C, R"IR( 263318270868SJorge Gorbe Moya define void @foo({i32, float} %agg) { 263418270868SJorge Gorbe Moya %ext_simple = extractvalue {i32, float} %agg, 0 263518270868SJorge Gorbe Moya %ext_nested = extractvalue {float, {i32}} undef, 1, 0 263618270868SJorge Gorbe Moya %const1 = extractvalue {i32, float} {i32 0, float 99.0}, 0 263718270868SJorge Gorbe Moya ret void 263818270868SJorge Gorbe Moya } 263918270868SJorge Gorbe Moya )IR"); 264018270868SJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 2641034f2b38Svporpo auto *LLVMBB = &*LLVMF.begin(); 2642034f2b38Svporpo auto LLVMIt = LLVMBB->begin(); 2643034f2b38Svporpo [[maybe_unused]] auto *LLVMExtSimple = 2644034f2b38Svporpo cast<llvm::ExtractValueInst>(&*LLVMIt++); 2645034f2b38Svporpo auto *LLVMExtNested = cast<llvm::ExtractValueInst>(&*LLVMIt++); 2646034f2b38Svporpo 264718270868SJorge Gorbe Moya sandboxir::Context Ctx(C); 264818270868SJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 264918270868SJorge Gorbe Moya auto *ArgAgg = F.getArg(0); 265018270868SJorge Gorbe Moya auto *BB = &*F.begin(); 265118270868SJorge Gorbe Moya auto It = BB->begin(); 265218270868SJorge Gorbe Moya auto *ExtSimple = cast<sandboxir::ExtractValueInst>(&*It++); 265318270868SJorge Gorbe Moya auto *ExtNested = cast<sandboxir::ExtractValueInst>(&*It++); 265418270868SJorge Gorbe Moya auto *Const1 = cast<sandboxir::ExtractValueInst>(&*It++); 265518270868SJorge Gorbe Moya auto *Ret = &*It++; 265618270868SJorge Gorbe Moya 265718270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->getOperand(0), ArgAgg); 265818270868SJorge Gorbe Moya 265918270868SJorge Gorbe Moya // create before instruction 266018270868SJorge Gorbe Moya auto *NewExtBeforeRet = 266118270868SJorge Gorbe Moya cast<sandboxir::ExtractValueInst>(sandboxir::ExtractValueInst::create( 2662e1434a87Svporpo ArgAgg, ArrayRef<unsigned>({0}), Ret->getIterator(), Ctx, 2663e1434a87Svporpo "NewExtBeforeRet")); 266418270868SJorge Gorbe Moya EXPECT_EQ(NewExtBeforeRet->getNextNode(), Ret); 266518270868SJorge Gorbe Moya #ifndef NDEBUG 266618270868SJorge Gorbe Moya EXPECT_EQ(NewExtBeforeRet->getName(), "NewExtBeforeRet"); 266718270868SJorge Gorbe Moya #endif // NDEBUG 266818270868SJorge Gorbe Moya 266918270868SJorge Gorbe Moya // create at end of BB 267018270868SJorge Gorbe Moya auto *NewExtAtEnd = 267118270868SJorge Gorbe Moya cast<sandboxir::ExtractValueInst>(sandboxir::ExtractValueInst::create( 2672e1434a87Svporpo ArgAgg, ArrayRef<unsigned>({0}), BB->end(), Ctx, "NewExtAtEnd")); 267318270868SJorge Gorbe Moya EXPECT_EQ(NewExtAtEnd->getPrevNode(), Ret); 267418270868SJorge Gorbe Moya #ifndef NDEBUG 267518270868SJorge Gorbe Moya EXPECT_EQ(NewExtAtEnd->getName(), "NewExtAtEnd"); 267618270868SJorge Gorbe Moya #endif // NDEBUG 267718270868SJorge Gorbe Moya 267818270868SJorge Gorbe Moya // Test the path that creates a folded constant. 267918270868SJorge Gorbe Moya auto *ShouldBeConstant = sandboxir::ExtractValueInst::create( 2680e1434a87Svporpo Const1->getOperand(0), ArrayRef<unsigned>({0}), BB->end(), Ctx); 268118270868SJorge Gorbe Moya EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant)); 268218270868SJorge Gorbe Moya 2683034f2b38Svporpo auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0); 268418270868SJorge Gorbe Moya EXPECT_EQ(ShouldBeConstant, Zero); 268518270868SJorge Gorbe Moya 268618270868SJorge Gorbe Moya // getIndexedType 2687034f2b38Svporpo sandboxir::Type *AggType = ExtNested->getAggregateOperand()->getType(); 2688034f2b38Svporpo llvm::Type *LLVMAggType = LLVMExtNested->getAggregateOperand()->getType(); 268918270868SJorge Gorbe Moya EXPECT_EQ(sandboxir::ExtractValueInst::getIndexedType( 269018270868SJorge Gorbe Moya AggType, ArrayRef<unsigned>({1, 0})), 2691034f2b38Svporpo Ctx.getType(llvm::ExtractValueInst::getIndexedType( 2692034f2b38Svporpo LLVMAggType, ArrayRef<unsigned>({1, 0})))); 269318270868SJorge Gorbe Moya 269418270868SJorge Gorbe Moya EXPECT_EQ(sandboxir::ExtractValueInst::getIndexedType( 269518270868SJorge Gorbe Moya AggType, ArrayRef<unsigned>({2})), 269618270868SJorge Gorbe Moya nullptr); 269718270868SJorge Gorbe Moya 269818270868SJorge Gorbe Moya // idx_begin / idx_end 269918270868SJorge Gorbe Moya { 270018270868SJorge Gorbe Moya SmallVector<int, 2> IndicesSimple(ExtSimple->idx_begin(), 270118270868SJorge Gorbe Moya ExtSimple->idx_end()); 270218270868SJorge Gorbe Moya EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); 270318270868SJorge Gorbe Moya 270418270868SJorge Gorbe Moya SmallVector<int, 2> IndicesNested(ExtNested->idx_begin(), 270518270868SJorge Gorbe Moya ExtNested->idx_end()); 270618270868SJorge Gorbe Moya EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); 270718270868SJorge Gorbe Moya } 270818270868SJorge Gorbe Moya 270918270868SJorge Gorbe Moya // indices 271018270868SJorge Gorbe Moya { 271118270868SJorge Gorbe Moya SmallVector<int, 2> IndicesSimple(ExtSimple->indices()); 271218270868SJorge Gorbe Moya EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); 271318270868SJorge Gorbe Moya 271418270868SJorge Gorbe Moya SmallVector<int, 2> IndicesNested(ExtNested->indices()); 271518270868SJorge Gorbe Moya EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); 271618270868SJorge Gorbe Moya } 271718270868SJorge Gorbe Moya 271818270868SJorge Gorbe Moya // getAggregateOperand 271918270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->getAggregateOperand(), ArgAgg); 272018270868SJorge Gorbe Moya const auto *ConstExtSimple = ExtSimple; 272118270868SJorge Gorbe Moya EXPECT_EQ(ConstExtSimple->getAggregateOperand(), ArgAgg); 272218270868SJorge Gorbe Moya 272318270868SJorge Gorbe Moya // getAggregateOperandIndex 272418270868SJorge Gorbe Moya EXPECT_EQ(sandboxir::ExtractValueInst::getAggregateOperandIndex(), 272518270868SJorge Gorbe Moya llvm::ExtractValueInst::getAggregateOperandIndex()); 272618270868SJorge Gorbe Moya 272718270868SJorge Gorbe Moya // getIndices 272818270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->getIndices().size(), 1u); 272918270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->getIndices()[0], 0u); 273018270868SJorge Gorbe Moya 273118270868SJorge Gorbe Moya // getNumIndices 273218270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->getNumIndices(), 1u); 273318270868SJorge Gorbe Moya 273418270868SJorge Gorbe Moya // hasIndices 273518270868SJorge Gorbe Moya EXPECT_EQ(ExtSimple->hasIndices(), true); 273618270868SJorge Gorbe Moya } 273718270868SJorge Gorbe Moya 2738b40677ccSJorge Gorbe Moya TEST_F(SandboxIRTest, InsertValueInst) { 2739b40677ccSJorge Gorbe Moya parseIR(C, R"IR( 2740b40677ccSJorge Gorbe Moya define void @foo({i32, float} %agg, i32 %i) { 2741b40677ccSJorge Gorbe Moya %ins_simple = insertvalue {i32, float} %agg, i32 %i, 0 2742b40677ccSJorge Gorbe Moya %ins_nested = insertvalue {float, {i32}} undef, i32 %i, 1, 0 2743b40677ccSJorge Gorbe Moya %const1 = insertvalue {i32, float} {i32 99, float 99.0}, i32 %i, 0 2744b40677ccSJorge Gorbe Moya %const2 = insertvalue {i32, float} {i32 0, float 99.0}, i32 %i, 0 2745b40677ccSJorge Gorbe Moya ret void 2746b40677ccSJorge Gorbe Moya } 2747b40677ccSJorge Gorbe Moya )IR"); 2748b40677ccSJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 2749b40677ccSJorge Gorbe Moya sandboxir::Context Ctx(C); 2750b40677ccSJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 2751b40677ccSJorge Gorbe Moya auto *ArgAgg = F.getArg(0); 2752b40677ccSJorge Gorbe Moya auto *ArgInt = F.getArg(1); 2753b40677ccSJorge Gorbe Moya auto *BB = &*F.begin(); 2754b40677ccSJorge Gorbe Moya auto It = BB->begin(); 2755b40677ccSJorge Gorbe Moya auto *InsSimple = cast<sandboxir::InsertValueInst>(&*It++); 2756b40677ccSJorge Gorbe Moya auto *InsNested = cast<sandboxir::InsertValueInst>(&*It++); 2757b40677ccSJorge Gorbe Moya // These "const" instructions are helpers to create constant struct operands. 2758b40677ccSJorge Gorbe Moya // TODO: Remove them once sandboxir::ConstantStruct gets added. 2759b40677ccSJorge Gorbe Moya auto *Const1 = cast<sandboxir::InsertValueInst>(&*It++); 2760b40677ccSJorge Gorbe Moya auto *Const2 = cast<sandboxir::InsertValueInst>(&*It++); 2761b40677ccSJorge Gorbe Moya auto *Ret = &*It++; 2762b40677ccSJorge Gorbe Moya 2763b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getOperand(0), ArgAgg); 2764b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getOperand(1), ArgInt); 2765b40677ccSJorge Gorbe Moya 2766b40677ccSJorge Gorbe Moya // create before instruction 2767b40677ccSJorge Gorbe Moya auto *NewInsBeforeRet = 2768b40677ccSJorge Gorbe Moya cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create( 2769e1434a87Svporpo ArgAgg, ArgInt, ArrayRef<unsigned>({0}), Ret->getIterator(), Ctx, 2770e1434a87Svporpo "NewInsBeforeRet")); 2771b40677ccSJorge Gorbe Moya EXPECT_EQ(NewInsBeforeRet->getNextNode(), Ret); 2772b40677ccSJorge Gorbe Moya #ifndef NDEBUG 2773b40677ccSJorge Gorbe Moya EXPECT_EQ(NewInsBeforeRet->getName(), "NewInsBeforeRet"); 2774b40677ccSJorge Gorbe Moya #endif // NDEBUG 2775b40677ccSJorge Gorbe Moya 2776b40677ccSJorge Gorbe Moya // create at end of BB 2777b40677ccSJorge Gorbe Moya auto *NewInsAtEnd = 2778b40677ccSJorge Gorbe Moya cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create( 2779e1434a87Svporpo ArgAgg, ArgInt, ArrayRef<unsigned>({0}), BB, Ctx, "NewInsAtEnd")); 2780b40677ccSJorge Gorbe Moya EXPECT_EQ(NewInsAtEnd->getPrevNode(), Ret); 2781b40677ccSJorge Gorbe Moya #ifndef NDEBUG 2782b40677ccSJorge Gorbe Moya EXPECT_EQ(NewInsAtEnd->getName(), "NewInsAtEnd"); 2783b40677ccSJorge Gorbe Moya #endif // NDEBUG 2784b40677ccSJorge Gorbe Moya 2785b40677ccSJorge Gorbe Moya // Test the path that creates a folded constant. 2786034f2b38Svporpo auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0); 2787b40677ccSJorge Gorbe Moya auto *ShouldBeConstant = sandboxir::InsertValueInst::create( 2788e1434a87Svporpo Const1->getOperand(0), Zero, ArrayRef<unsigned>({0}), BB, Ctx); 2789b40677ccSJorge Gorbe Moya auto *ExpectedConstant = Const2->getOperand(0); 2790b40677ccSJorge Gorbe Moya EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant)); 2791b40677ccSJorge Gorbe Moya EXPECT_EQ(ShouldBeConstant, ExpectedConstant); 2792b40677ccSJorge Gorbe Moya 2793b40677ccSJorge Gorbe Moya // idx_begin / idx_end 2794b40677ccSJorge Gorbe Moya { 2795b40677ccSJorge Gorbe Moya SmallVector<int, 2> IndicesSimple(InsSimple->idx_begin(), 2796b40677ccSJorge Gorbe Moya InsSimple->idx_end()); 2797b40677ccSJorge Gorbe Moya EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); 2798b40677ccSJorge Gorbe Moya 2799b40677ccSJorge Gorbe Moya SmallVector<int, 2> IndicesNested(InsNested->idx_begin(), 2800b40677ccSJorge Gorbe Moya InsNested->idx_end()); 2801b40677ccSJorge Gorbe Moya EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); 2802b40677ccSJorge Gorbe Moya } 2803b40677ccSJorge Gorbe Moya 2804b40677ccSJorge Gorbe Moya // indices 2805b40677ccSJorge Gorbe Moya { 2806b40677ccSJorge Gorbe Moya SmallVector<int, 2> IndicesSimple(InsSimple->indices()); 2807b40677ccSJorge Gorbe Moya EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u)); 2808b40677ccSJorge Gorbe Moya 2809b40677ccSJorge Gorbe Moya SmallVector<int, 2> IndicesNested(InsNested->indices()); 2810b40677ccSJorge Gorbe Moya EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u)); 2811b40677ccSJorge Gorbe Moya } 2812b40677ccSJorge Gorbe Moya 2813b40677ccSJorge Gorbe Moya // getAggregateOperand 2814b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getAggregateOperand(), ArgAgg); 2815b40677ccSJorge Gorbe Moya const auto *ConstInsSimple = InsSimple; 2816b40677ccSJorge Gorbe Moya EXPECT_EQ(ConstInsSimple->getAggregateOperand(), ArgAgg); 2817b40677ccSJorge Gorbe Moya 2818b40677ccSJorge Gorbe Moya // getAggregateOperandIndex 2819b40677ccSJorge Gorbe Moya EXPECT_EQ(sandboxir::InsertValueInst::getAggregateOperandIndex(), 2820b40677ccSJorge Gorbe Moya llvm::InsertValueInst::getAggregateOperandIndex()); 2821b40677ccSJorge Gorbe Moya 2822b40677ccSJorge Gorbe Moya // getInsertedValueOperand 2823b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getInsertedValueOperand(), ArgInt); 2824b40677ccSJorge Gorbe Moya EXPECT_EQ(ConstInsSimple->getInsertedValueOperand(), ArgInt); 2825b40677ccSJorge Gorbe Moya 2826b40677ccSJorge Gorbe Moya // getInsertedValueOperandIndex 2827b40677ccSJorge Gorbe Moya EXPECT_EQ(sandboxir::InsertValueInst::getInsertedValueOperandIndex(), 2828b40677ccSJorge Gorbe Moya llvm::InsertValueInst::getInsertedValueOperandIndex()); 2829b40677ccSJorge Gorbe Moya 2830b40677ccSJorge Gorbe Moya // getIndices 2831b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getIndices().size(), 1u); 2832b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getIndices()[0], 0u); 2833b40677ccSJorge Gorbe Moya 2834b40677ccSJorge Gorbe Moya // getNumIndices 2835b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->getNumIndices(), 1u); 2836b40677ccSJorge Gorbe Moya 2837b40677ccSJorge Gorbe Moya // hasIndices 2838b40677ccSJorge Gorbe Moya EXPECT_EQ(InsSimple->hasIndices(), true); 2839b40677ccSJorge Gorbe Moya } 2840b40677ccSJorge Gorbe Moya 2841c444548bSVasileios Porpodas TEST_F(SandboxIRTest, BranchInst) { 2842c444548bSVasileios Porpodas parseIR(C, R"IR( 2843c444548bSVasileios Porpodas define void @foo(i1 %cond0, i1 %cond2) { 2844c444548bSVasileios Porpodas bb0: 2845c444548bSVasileios Porpodas br i1 %cond0, label %bb1, label %bb2 2846c444548bSVasileios Porpodas bb1: 2847c444548bSVasileios Porpodas ret void 2848c444548bSVasileios Porpodas bb2: 2849c444548bSVasileios Porpodas ret void 2850c444548bSVasileios Porpodas } 2851c444548bSVasileios Porpodas )IR"); 2852c444548bSVasileios Porpodas llvm::Function *LLVMF = &*M->getFunction("foo"); 2853c444548bSVasileios Porpodas sandboxir::Context Ctx(C); 2854c444548bSVasileios Porpodas sandboxir::Function *F = Ctx.createFunction(LLVMF); 2855c444548bSVasileios Porpodas auto *Cond0 = F->getArg(0); 2856c444548bSVasileios Porpodas auto *Cond1 = F->getArg(1); 2857c444548bSVasileios Porpodas auto *BB0 = cast<sandboxir::BasicBlock>( 2858c444548bSVasileios Porpodas Ctx.getValue(getBasicBlockByName(*LLVMF, "bb0"))); 2859c444548bSVasileios Porpodas auto *BB1 = cast<sandboxir::BasicBlock>( 2860c444548bSVasileios Porpodas Ctx.getValue(getBasicBlockByName(*LLVMF, "bb1"))); 2861c444548bSVasileios Porpodas auto *Ret1 = BB1->getTerminator(); 2862c444548bSVasileios Porpodas auto *BB2 = cast<sandboxir::BasicBlock>( 2863c444548bSVasileios Porpodas Ctx.getValue(getBasicBlockByName(*LLVMF, "bb2"))); 2864c444548bSVasileios Porpodas auto *Ret2 = BB2->getTerminator(); 2865c444548bSVasileios Porpodas auto It = BB0->begin(); 2866c444548bSVasileios Porpodas auto *Br0 = cast<sandboxir::BranchInst>(&*It++); 2867c444548bSVasileios Porpodas // Check isUnconditional(). 2868c444548bSVasileios Porpodas EXPECT_FALSE(Br0->isUnconditional()); 2869c444548bSVasileios Porpodas // Check isConditional(). 2870c444548bSVasileios Porpodas EXPECT_TRUE(Br0->isConditional()); 2871c444548bSVasileios Porpodas // Check getCondition(). 2872c444548bSVasileios Porpodas EXPECT_EQ(Br0->getCondition(), Cond0); 2873c444548bSVasileios Porpodas // Check setCondition(). 2874c444548bSVasileios Porpodas Br0->setCondition(Cond1); 2875c444548bSVasileios Porpodas EXPECT_EQ(Br0->getCondition(), Cond1); 2876c444548bSVasileios Porpodas // Check getNumSuccessors(). 2877c444548bSVasileios Porpodas EXPECT_EQ(Br0->getNumSuccessors(), 2u); 2878c444548bSVasileios Porpodas // Check getSuccessor(). 2879c444548bSVasileios Porpodas EXPECT_EQ(Br0->getSuccessor(0), BB1); 2880c444548bSVasileios Porpodas EXPECT_EQ(Br0->getSuccessor(1), BB2); 2881c444548bSVasileios Porpodas // Check swapSuccessors(). 2882c444548bSVasileios Porpodas Br0->swapSuccessors(); 2883c444548bSVasileios Porpodas EXPECT_EQ(Br0->getSuccessor(0), BB2); 2884c444548bSVasileios Porpodas EXPECT_EQ(Br0->getSuccessor(1), BB1); 2885c444548bSVasileios Porpodas // Check successors(). 2886c444548bSVasileios Porpodas EXPECT_EQ(range_size(Br0->successors()), 2u); 2887c444548bSVasileios Porpodas unsigned SuccIdx = 0; 2888c444548bSVasileios Porpodas SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1, BB2}); 2889c444548bSVasileios Porpodas for (sandboxir::BasicBlock *Succ : Br0->successors()) 2890c444548bSVasileios Porpodas EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]); 2891c444548bSVasileios Porpodas 2892c444548bSVasileios Porpodas { 2893c444548bSVasileios Porpodas // Check unconditional BranchInst::create() InsertBefore. 2894e1434a87Svporpo auto *Br = sandboxir::BranchInst::create(BB1, Ret1->getIterator(), Ctx); 2895c444548bSVasileios Porpodas EXPECT_FALSE(Br->isConditional()); 2896c444548bSVasileios Porpodas EXPECT_TRUE(Br->isUnconditional()); 2897c444548bSVasileios Porpodas #ifndef NDEBUG 2898c444548bSVasileios Porpodas EXPECT_DEATH(Br->getCondition(), ".*condition.*"); 2899c444548bSVasileios Porpodas #endif // NDEBUG 2900c444548bSVasileios Porpodas unsigned SuccIdx = 0; 2901c444548bSVasileios Porpodas SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1}); 2902c444548bSVasileios Porpodas for (sandboxir::BasicBlock *Succ : Br->successors()) 2903c444548bSVasileios Porpodas EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]); 2904c444548bSVasileios Porpodas EXPECT_EQ(Br->getNextNode(), Ret1); 2905c444548bSVasileios Porpodas } 2906c444548bSVasileios Porpodas { 2907c444548bSVasileios Porpodas // Check unconditional BranchInst::create() InsertAtEnd. 2908c444548bSVasileios Porpodas auto *Br = sandboxir::BranchInst::create(BB1, /*InsertAtEnd=*/BB1, Ctx); 2909c444548bSVasileios Porpodas EXPECT_FALSE(Br->isConditional()); 2910c444548bSVasileios Porpodas EXPECT_TRUE(Br->isUnconditional()); 2911c444548bSVasileios Porpodas #ifndef NDEBUG 2912c444548bSVasileios Porpodas EXPECT_DEATH(Br->getCondition(), ".*condition.*"); 2913c444548bSVasileios Porpodas #endif // NDEBUG 2914c444548bSVasileios Porpodas unsigned SuccIdx = 0; 2915c444548bSVasileios Porpodas SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1}); 2916c444548bSVasileios Porpodas for (sandboxir::BasicBlock *Succ : Br->successors()) 2917c444548bSVasileios Porpodas EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]); 2918c444548bSVasileios Porpodas EXPECT_EQ(Br->getPrevNode(), Ret1); 2919c444548bSVasileios Porpodas } 2920c444548bSVasileios Porpodas { 2921c444548bSVasileios Porpodas // Check conditional BranchInst::create() InsertBefore. 2922c444548bSVasileios Porpodas auto *Br = sandboxir::BranchInst::create(BB1, BB2, Cond0, 2923e1434a87Svporpo Ret1->getIterator(), Ctx); 2924c444548bSVasileios Porpodas EXPECT_TRUE(Br->isConditional()); 2925c444548bSVasileios Porpodas EXPECT_EQ(Br->getCondition(), Cond0); 2926c444548bSVasileios Porpodas unsigned SuccIdx = 0; 2927c444548bSVasileios Porpodas SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1}); 2928c444548bSVasileios Porpodas for (sandboxir::BasicBlock *Succ : Br->successors()) 2929c444548bSVasileios Porpodas EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]); 2930c444548bSVasileios Porpodas EXPECT_EQ(Br->getNextNode(), Ret1); 2931c444548bSVasileios Porpodas } 2932c444548bSVasileios Porpodas { 2933c444548bSVasileios Porpodas // Check conditional BranchInst::create() InsertAtEnd. 2934c444548bSVasileios Porpodas auto *Br = sandboxir::BranchInst::create(BB1, BB2, Cond0, 2935c444548bSVasileios Porpodas /*InsertAtEnd=*/BB2, Ctx); 2936c444548bSVasileios Porpodas EXPECT_TRUE(Br->isConditional()); 2937c444548bSVasileios Porpodas EXPECT_EQ(Br->getCondition(), Cond0); 2938c444548bSVasileios Porpodas unsigned SuccIdx = 0; 2939c444548bSVasileios Porpodas SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1}); 2940c444548bSVasileios Porpodas for (sandboxir::BasicBlock *Succ : Br->successors()) 2941c444548bSVasileios Porpodas EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]); 2942c444548bSVasileios Porpodas EXPECT_EQ(Br->getPrevNode(), Ret2); 2943c444548bSVasileios Porpodas } 2944c444548bSVasileios Porpodas } 2945c444548bSVasileios Porpodas 294663625f44Svporpo TEST_F(SandboxIRTest, LoadInst) { 294763625f44Svporpo parseIR(C, R"IR( 294863625f44Svporpo define void @foo(ptr %arg0, ptr %arg1) { 294963625f44Svporpo %ld = load i8, ptr %arg0, align 64 2950745aa481SJulius Alexandre %vld = load volatile i8, ptr %arg0, align 64 295163625f44Svporpo ret void 295263625f44Svporpo } 295363625f44Svporpo )IR"); 295463625f44Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 295563625f44Svporpo sandboxir::Context Ctx(C); 295663625f44Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 295763625f44Svporpo auto *Arg0 = F->getArg(0); 295863625f44Svporpo auto *Arg1 = F->getArg(1); 295963625f44Svporpo auto *BB = &*F->begin(); 296063625f44Svporpo auto It = BB->begin(); 296163625f44Svporpo auto *Ld = cast<sandboxir::LoadInst>(&*It++); 2962f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Ld)); 2963b3b390b9SJulius Alexandre auto *VLd = cast<sandboxir::LoadInst>(&*It++); 29647467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 296595b366caSJulius Alexandre bool OrigVolatileValue; 296663625f44Svporpo 2967745aa481SJulius Alexandre // Check isVolatile() 2968745aa481SJulius Alexandre EXPECT_FALSE(Ld->isVolatile()); 2969745aa481SJulius Alexandre // Check isVolatile() 2970b3b390b9SJulius Alexandre EXPECT_TRUE(VLd->isVolatile()); 297163625f44Svporpo // Check getPointerOperand() 297263625f44Svporpo EXPECT_EQ(Ld->getPointerOperand(), Arg0); 297363625f44Svporpo // Check getAlign() 297463625f44Svporpo EXPECT_EQ(Ld->getAlign(), 64); 297563625f44Svporpo // Check create(InsertBefore) 2976e1434a87Svporpo sandboxir::LoadInst *NewLd = sandboxir::LoadInst::create( 2977e1434a87Svporpo Ld->getType(), Arg1, Align(8), Ret->getIterator(), Ctx, "NewLd"); 297841211919SJulius Alexandre EXPECT_FALSE(NewLd->isVolatile()); 297995b366caSJulius Alexandre OrigVolatileValue = NewLd->isVolatile(); 298095b366caSJulius Alexandre NewLd->setVolatile(true); 298195b366caSJulius Alexandre EXPECT_TRUE(NewLd->isVolatile()); 298295b366caSJulius Alexandre NewLd->setVolatile(OrigVolatileValue); 298395b366caSJulius Alexandre EXPECT_FALSE(NewLd->isVolatile()); 298463625f44Svporpo EXPECT_EQ(NewLd->getType(), Ld->getType()); 298563625f44Svporpo EXPECT_EQ(NewLd->getPointerOperand(), Arg1); 298663625f44Svporpo EXPECT_EQ(NewLd->getAlign(), 8); 298763625f44Svporpo EXPECT_EQ(NewLd->getName(), "NewLd"); 2988b3b390b9SJulius Alexandre // Check create(InsertBefore, IsVolatile=true) 2989e1434a87Svporpo sandboxir::LoadInst *NewVLd = sandboxir::LoadInst::create( 2990e1434a87Svporpo VLd->getType(), Arg1, Align(8), Ret->getIterator(), 2991b3b390b9SJulius Alexandre /*IsVolatile=*/true, Ctx, "NewVLd"); 299241211919SJulius Alexandre 299341211919SJulius Alexandre EXPECT_TRUE(NewVLd->isVolatile()); 299495b366caSJulius Alexandre OrigVolatileValue = NewVLd->isVolatile(); 299595b366caSJulius Alexandre NewVLd->setVolatile(false); 299695b366caSJulius Alexandre EXPECT_FALSE(NewVLd->isVolatile()); 299795b366caSJulius Alexandre NewVLd->setVolatile(OrigVolatileValue); 299895b366caSJulius Alexandre EXPECT_TRUE(NewVLd->isVolatile()); 299941211919SJulius Alexandre EXPECT_EQ(NewVLd->getName(), "NewVLd"); 3000b3b390b9SJulius Alexandre // Check create(InsertAtEnd) 3001b3b390b9SJulius Alexandre sandboxir::LoadInst *NewLdEnd = 3002b3b390b9SJulius Alexandre sandboxir::LoadInst::create(Ld->getType(), Arg1, Align(8), 3003b3b390b9SJulius Alexandre /*InsertAtEnd=*/BB, Ctx, "NewLdEnd"); 3004b3b390b9SJulius Alexandre EXPECT_FALSE(NewLdEnd->isVolatile()); 3005b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getName(), "NewLdEnd"); 3006b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getType(), Ld->getType()); 3007b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getPointerOperand(), Arg1); 3008b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getAlign(), 8); 3009b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getParent(), BB); 3010b3b390b9SJulius Alexandre EXPECT_EQ(NewLdEnd->getNextNode(), nullptr); 3011b3b390b9SJulius Alexandre // Check create(InsertAtEnd, IsVolatile=true) 3012b3b390b9SJulius Alexandre sandboxir::LoadInst *NewVLdEnd = 3013b3b390b9SJulius Alexandre sandboxir::LoadInst::create(VLd->getType(), Arg1, Align(8), 3014b3b390b9SJulius Alexandre /*InsertAtEnd=*/BB, 3015b3b390b9SJulius Alexandre /*IsVolatile=*/true, Ctx, "NewVLdEnd"); 3016b3b390b9SJulius Alexandre EXPECT_TRUE(NewVLdEnd->isVolatile()); 3017b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getName(), "NewVLdEnd"); 3018b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getType(), VLd->getType()); 3019b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getPointerOperand(), Arg1); 3020b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getAlign(), 8); 3021b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getParent(), BB); 3022b3b390b9SJulius Alexandre EXPECT_EQ(NewVLdEnd->getNextNode(), nullptr); 302363625f44Svporpo } 302452a46bc3Svporpo 302552a46bc3Svporpo TEST_F(SandboxIRTest, StoreInst) { 302652a46bc3Svporpo parseIR(C, R"IR( 302752a46bc3Svporpo define void @foo(i8 %val, ptr %ptr) { 302852a46bc3Svporpo store i8 %val, ptr %ptr, align 64 302942326c71SJulius Alexandre store volatile i8 %val, ptr %ptr, align 64 303052a46bc3Svporpo ret void 303152a46bc3Svporpo } 303252a46bc3Svporpo )IR"); 303352a46bc3Svporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 303452a46bc3Svporpo sandboxir::Context Ctx(C); 303552a46bc3Svporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 303652a46bc3Svporpo auto *Val = F->getArg(0); 303752a46bc3Svporpo auto *Ptr = F->getArg(1); 303852a46bc3Svporpo auto *BB = &*F->begin(); 303952a46bc3Svporpo auto It = BB->begin(); 304052a46bc3Svporpo auto *St = cast<sandboxir::StoreInst>(&*It++); 304142326c71SJulius Alexandre auto *VSt = cast<sandboxir::StoreInst>(&*It++); 30427467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 304395b366caSJulius Alexandre bool OrigVolatileValue; 304452a46bc3Svporpo 304552a46bc3Svporpo // Check that the StoreInst has been created correctly. 304642326c71SJulius Alexandre EXPECT_FALSE(St->isVolatile()); 304742326c71SJulius Alexandre EXPECT_TRUE(VSt->isVolatile()); 304852a46bc3Svporpo // Check getPointerOperand() 304952a46bc3Svporpo EXPECT_EQ(St->getValueOperand(), Val); 305052a46bc3Svporpo EXPECT_EQ(St->getPointerOperand(), Ptr); 305152a46bc3Svporpo // Check getAlign() 305252a46bc3Svporpo EXPECT_EQ(St->getAlign(), 64); 305352a46bc3Svporpo // Check create(InsertBefore) 305452a46bc3Svporpo sandboxir::StoreInst *NewSt = 3055e1434a87Svporpo sandboxir::StoreInst::create(Val, Ptr, Align(8), Ret->getIterator(), Ctx); 305642326c71SJulius Alexandre EXPECT_FALSE(NewSt->isVolatile()); 305795b366caSJulius Alexandre OrigVolatileValue = NewSt->isVolatile(); 305895b366caSJulius Alexandre NewSt->setVolatile(true); 305995b366caSJulius Alexandre EXPECT_TRUE(NewSt->isVolatile()); 306095b366caSJulius Alexandre NewSt->setVolatile(OrigVolatileValue); 306195b366caSJulius Alexandre EXPECT_FALSE(NewSt->isVolatile()); 306252a46bc3Svporpo EXPECT_EQ(NewSt->getType(), St->getType()); 306352a46bc3Svporpo EXPECT_EQ(NewSt->getValueOperand(), Val); 306452a46bc3Svporpo EXPECT_EQ(NewSt->getPointerOperand(), Ptr); 306552a46bc3Svporpo EXPECT_EQ(NewSt->getAlign(), 8); 306642326c71SJulius Alexandre EXPECT_EQ(NewSt->getNextNode(), Ret); 306742326c71SJulius Alexandre // Check create(InsertBefore, IsVolatile=true) 306842326c71SJulius Alexandre sandboxir::StoreInst *NewVSt = 3069e1434a87Svporpo sandboxir::StoreInst::create(Val, Ptr, Align(8), Ret->getIterator(), 307042326c71SJulius Alexandre /*IsVolatile=*/true, Ctx); 307142326c71SJulius Alexandre EXPECT_TRUE(NewVSt->isVolatile()); 307295b366caSJulius Alexandre OrigVolatileValue = NewVSt->isVolatile(); 307395b366caSJulius Alexandre NewVSt->setVolatile(false); 307495b366caSJulius Alexandre EXPECT_FALSE(NewVSt->isVolatile()); 307595b366caSJulius Alexandre NewVSt->setVolatile(OrigVolatileValue); 307695b366caSJulius Alexandre EXPECT_TRUE(NewVSt->isVolatile()); 307742326c71SJulius Alexandre EXPECT_EQ(NewVSt->getType(), VSt->getType()); 307842326c71SJulius Alexandre EXPECT_EQ(NewVSt->getValueOperand(), Val); 307942326c71SJulius Alexandre EXPECT_EQ(NewVSt->getPointerOperand(), Ptr); 308042326c71SJulius Alexandre EXPECT_EQ(NewVSt->getAlign(), 8); 308142326c71SJulius Alexandre EXPECT_EQ(NewVSt->getNextNode(), Ret); 308242326c71SJulius Alexandre // Check create(InsertAtEnd) 308342326c71SJulius Alexandre sandboxir::StoreInst *NewStEnd = 308442326c71SJulius Alexandre sandboxir::StoreInst::create(Val, Ptr, Align(8), 308542326c71SJulius Alexandre /*InsertAtEnd=*/BB, Ctx); 308642326c71SJulius Alexandre EXPECT_FALSE(NewStEnd->isVolatile()); 308742326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getType(), St->getType()); 308842326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getValueOperand(), Val); 308942326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getPointerOperand(), Ptr); 309042326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getAlign(), 8); 309142326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getParent(), BB); 309242326c71SJulius Alexandre EXPECT_EQ(NewStEnd->getNextNode(), nullptr); 309342326c71SJulius Alexandre // Check create(InsertAtEnd, IsVolatile=true) 309442326c71SJulius Alexandre sandboxir::StoreInst *NewVStEnd = 309542326c71SJulius Alexandre sandboxir::StoreInst::create(Val, Ptr, Align(8), 309642326c71SJulius Alexandre /*InsertAtEnd=*/BB, 309742326c71SJulius Alexandre /*IsVolatile=*/true, Ctx); 309842326c71SJulius Alexandre EXPECT_TRUE(NewVStEnd->isVolatile()); 309942326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getType(), VSt->getType()); 310042326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getValueOperand(), Val); 310142326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getPointerOperand(), Ptr); 310242326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getAlign(), 8); 310342326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getParent(), BB); 310442326c71SJulius Alexandre EXPECT_EQ(NewVStEnd->getNextNode(), nullptr); 310552a46bc3Svporpo } 31067467f41aSvporpo 31077467f41aSvporpo TEST_F(SandboxIRTest, ReturnInst) { 31087467f41aSvporpo parseIR(C, R"IR( 31097467f41aSvporpo define i8 @foo(i8 %val) { 31107467f41aSvporpo %add = add i8 %val, 42 31117467f41aSvporpo ret i8 %val 31127467f41aSvporpo } 31137467f41aSvporpo )IR"); 31147467f41aSvporpo llvm::Function *LLVMF = &*M->getFunction("foo"); 31157467f41aSvporpo sandboxir::Context Ctx(C); 31167467f41aSvporpo sandboxir::Function *F = Ctx.createFunction(LLVMF); 31177467f41aSvporpo auto *Val = F->getArg(0); 31187467f41aSvporpo auto *BB = &*F->begin(); 31197467f41aSvporpo auto It = BB->begin(); 31207467f41aSvporpo It++; 31217467f41aSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 31227467f41aSvporpo 31237467f41aSvporpo // Check that the ReturnInst has been created correctly. 31247467f41aSvporpo // Check getReturnValue(). 31257467f41aSvporpo EXPECT_EQ(Ret->getReturnValue(), Val); 31267467f41aSvporpo 31277467f41aSvporpo // Check create(InsertBefore) a void ReturnInst. 31287467f41aSvporpo auto *NewRet1 = cast<sandboxir::ReturnInst>( 31293a47bf63Svporpo sandboxir::ReturnInst::create(nullptr, Ret->getIterator(), Ctx)); 31307467f41aSvporpo EXPECT_EQ(NewRet1->getReturnValue(), nullptr); 31317467f41aSvporpo // Check create(InsertBefore) a non-void ReturnInst. 31327467f41aSvporpo auto *NewRet2 = cast<sandboxir::ReturnInst>( 31333a47bf63Svporpo sandboxir::ReturnInst::create(Val, Ret->getIterator(), Ctx)); 31347467f41aSvporpo EXPECT_EQ(NewRet2->getReturnValue(), Val); 31357467f41aSvporpo 31367467f41aSvporpo // Check create(InsertAtEnd) a void ReturnInst. 31377467f41aSvporpo auto *NewRet3 = cast<sandboxir::ReturnInst>( 31387467f41aSvporpo sandboxir::ReturnInst::create(nullptr, /*InsertAtEnd=*/BB, Ctx)); 31397467f41aSvporpo EXPECT_EQ(NewRet3->getReturnValue(), nullptr); 31407467f41aSvporpo // Check create(InsertAtEnd) a non-void ReturnInst. 31417467f41aSvporpo auto *NewRet4 = cast<sandboxir::ReturnInst>( 31427467f41aSvporpo sandboxir::ReturnInst::create(Val, /*InsertAtEnd=*/BB, Ctx)); 31437467f41aSvporpo EXPECT_EQ(NewRet4->getReturnValue(), Val); 31447467f41aSvporpo } 3145372a6beaSvporpo 3146372a6beaSvporpo TEST_F(SandboxIRTest, CallBase) { 3147372a6beaSvporpo parseIR(C, R"IR( 3148372a6beaSvporpo declare void @bar1(i8) 3149372a6beaSvporpo declare void @bar2() 3150372a6beaSvporpo declare void @bar3() 3151372a6beaSvporpo declare void @variadic(ptr, ...) 3152372a6beaSvporpo 3153372a6beaSvporpo define i8 @foo(i8 %arg0, i32 %arg1, ptr %indirectFoo) { 3154372a6beaSvporpo %call = call i8 @foo(i8 %arg0, i32 %arg1) 3155372a6beaSvporpo call void @bar1(i8 %arg0) 3156372a6beaSvporpo call void @bar2() 3157372a6beaSvporpo call void %indirectFoo() 3158372a6beaSvporpo call void @bar2() noreturn 3159372a6beaSvporpo tail call fastcc void @bar2() 3160372a6beaSvporpo call void (ptr, ...) @variadic(ptr %indirectFoo, i32 1) 3161372a6beaSvporpo ret i8 %call 3162372a6beaSvporpo } 3163372a6beaSvporpo )IR"); 3164372a6beaSvporpo llvm::Function &LLVMF = *M->getFunction("foo"); 3165372a6beaSvporpo unsigned ArgIdx = 0; 3166372a6beaSvporpo llvm::Argument *LLVMArg0 = LLVMF.getArg(ArgIdx++); 3167372a6beaSvporpo llvm::Argument *LLVMArg1 = LLVMF.getArg(ArgIdx++); 3168372a6beaSvporpo llvm::BasicBlock *LLVMBB = &*LLVMF.begin(); 3169372a6beaSvporpo SmallVector<llvm::CallBase *, 8> LLVMCalls; 3170372a6beaSvporpo auto LLVMIt = LLVMBB->begin(); 3171372a6beaSvporpo while (isa<llvm::CallBase>(&*LLVMIt)) 3172372a6beaSvporpo LLVMCalls.push_back(cast<llvm::CallBase>(&*LLVMIt++)); 3173372a6beaSvporpo 3174372a6beaSvporpo sandboxir::Context Ctx(C); 3175372a6beaSvporpo sandboxir::Function &F = *Ctx.createFunction(&LLVMF); 3176372a6beaSvporpo 3177372a6beaSvporpo for (llvm::CallBase *LLVMCall : LLVMCalls) { 3178372a6beaSvporpo // Check classof(Instruction *). 3179372a6beaSvporpo auto *Call = cast<sandboxir::CallBase>(Ctx.getValue(LLVMCall)); 3180372a6beaSvporpo // Check classof(Value *). 3181372a6beaSvporpo EXPECT_TRUE(isa<sandboxir::CallBase>((sandboxir::Value *)Call)); 3182372a6beaSvporpo // Check getFunctionType(). 3183034f2b38Svporpo EXPECT_EQ(Call->getFunctionType(), 3184034f2b38Svporpo Ctx.getType(LLVMCall->getFunctionType())); 3185372a6beaSvporpo // Check data_ops(). 3186372a6beaSvporpo EXPECT_EQ(range_size(Call->data_ops()), range_size(LLVMCall->data_ops())); 3187372a6beaSvporpo auto DataOpIt = Call->data_operands_begin(); 3188372a6beaSvporpo for (llvm::Use &LLVMUse : LLVMCall->data_ops()) { 3189372a6beaSvporpo Value *LLVMOp = LLVMUse.get(); 3190372a6beaSvporpo sandboxir::Use Use = *DataOpIt++; 3191372a6beaSvporpo EXPECT_EQ(Ctx.getValue(LLVMOp), Use.get()); 3192372a6beaSvporpo // Check isDataOperand(). 3193372a6beaSvporpo EXPECT_EQ(Call->isDataOperand(Use), LLVMCall->isDataOperand(&LLVMUse)); 3194372a6beaSvporpo // Check getDataOperandNo(). 3195372a6beaSvporpo EXPECT_EQ(Call->getDataOperandNo(Use), 3196372a6beaSvporpo LLVMCall->getDataOperandNo(&LLVMUse)); 3197372a6beaSvporpo // Check isArgOperand(). 3198372a6beaSvporpo EXPECT_EQ(Call->isArgOperand(Use), LLVMCall->isArgOperand(&LLVMUse)); 3199372a6beaSvporpo // Check isCallee(). 3200372a6beaSvporpo EXPECT_EQ(Call->isCallee(Use), LLVMCall->isCallee(&LLVMUse)); 3201372a6beaSvporpo } 3202372a6beaSvporpo // Check data_operands_empty(). 3203372a6beaSvporpo EXPECT_EQ(Call->data_operands_empty(), LLVMCall->data_operands_empty()); 3204372a6beaSvporpo // Check data_operands_size(). 3205372a6beaSvporpo EXPECT_EQ(Call->data_operands_size(), LLVMCall->data_operands_size()); 3206372a6beaSvporpo // Check getNumTotalBundleOperands(). 3207372a6beaSvporpo EXPECT_EQ(Call->getNumTotalBundleOperands(), 3208372a6beaSvporpo LLVMCall->getNumTotalBundleOperands()); 3209372a6beaSvporpo // Check args(). 3210372a6beaSvporpo EXPECT_EQ(range_size(Call->args()), range_size(LLVMCall->args())); 3211372a6beaSvporpo auto ArgIt = Call->arg_begin(); 3212372a6beaSvporpo for (llvm::Use &LLVMUse : LLVMCall->args()) { 3213372a6beaSvporpo Value *LLVMArg = LLVMUse.get(); 3214372a6beaSvporpo sandboxir::Use Use = *ArgIt++; 3215372a6beaSvporpo EXPECT_EQ(Ctx.getValue(LLVMArg), Use.get()); 3216372a6beaSvporpo } 3217372a6beaSvporpo // Check arg_empty(). 3218372a6beaSvporpo EXPECT_EQ(Call->arg_empty(), LLVMCall->arg_empty()); 3219372a6beaSvporpo // Check arg_size(). 3220372a6beaSvporpo EXPECT_EQ(Call->arg_size(), LLVMCall->arg_size()); 3221372a6beaSvporpo for (unsigned ArgIdx = 0, E = Call->arg_size(); ArgIdx != E; ++ArgIdx) { 3222372a6beaSvporpo // Check getArgOperand(). 3223372a6beaSvporpo EXPECT_EQ(Call->getArgOperand(ArgIdx), 3224372a6beaSvporpo Ctx.getValue(LLVMCall->getArgOperand(ArgIdx))); 3225372a6beaSvporpo // Check getArgOperandUse(). 3226372a6beaSvporpo sandboxir::Use Use = Call->getArgOperandUse(ArgIdx); 3227372a6beaSvporpo llvm::Use &LLVMUse = LLVMCall->getArgOperandUse(ArgIdx); 3228372a6beaSvporpo EXPECT_EQ(Use.get(), Ctx.getValue(LLVMUse.get())); 3229372a6beaSvporpo // Check getArgOperandNo(). 3230372a6beaSvporpo EXPECT_EQ(Call->getArgOperandNo(Use), 3231372a6beaSvporpo LLVMCall->getArgOperandNo(&LLVMUse)); 3232372a6beaSvporpo } 3233372a6beaSvporpo // Check hasArgument(). 3234372a6beaSvporpo SmallVector<llvm::Value *> TestArgs( 3235372a6beaSvporpo {LLVMArg0, LLVMArg1, &LLVMF, LLVMBB, LLVMCall}); 3236372a6beaSvporpo for (llvm::Value *LLVMV : TestArgs) { 3237372a6beaSvporpo sandboxir::Value *V = Ctx.getValue(LLVMV); 3238372a6beaSvporpo EXPECT_EQ(Call->hasArgument(V), LLVMCall->hasArgument(LLVMV)); 3239372a6beaSvporpo } 3240372a6beaSvporpo // Check getCalledOperand(). 3241372a6beaSvporpo EXPECT_EQ(Call->getCalledOperand(), 3242372a6beaSvporpo Ctx.getValue(LLVMCall->getCalledOperand())); 3243372a6beaSvporpo // Check getCalledOperandUse(). 3244372a6beaSvporpo EXPECT_EQ(Call->getCalledOperandUse().get(), 3245372a6beaSvporpo Ctx.getValue(LLVMCall->getCalledOperandUse())); 3246372a6beaSvporpo // Check getCalledFunction(). 3247372a6beaSvporpo if (LLVMCall->getCalledFunction() == nullptr) 3248372a6beaSvporpo EXPECT_EQ(Call->getCalledFunction(), nullptr); 3249372a6beaSvporpo else { 3250372a6beaSvporpo auto *LLVMCF = cast<llvm::Function>(LLVMCall->getCalledFunction()); 3251372a6beaSvporpo (void)LLVMCF; 3252372a6beaSvporpo EXPECT_EQ(Call->getCalledFunction(), 3253372a6beaSvporpo cast<sandboxir::Function>( 3254372a6beaSvporpo Ctx.getValue(LLVMCall->getCalledFunction()))); 3255372a6beaSvporpo } 3256372a6beaSvporpo // Check isIndirectCall(). 3257372a6beaSvporpo EXPECT_EQ(Call->isIndirectCall(), LLVMCall->isIndirectCall()); 3258372a6beaSvporpo // Check getCaller(). 3259372a6beaSvporpo EXPECT_EQ(Call->getCaller(), Ctx.getValue(LLVMCall->getCaller())); 3260372a6beaSvporpo // Check isMustTailCall(). 3261372a6beaSvporpo EXPECT_EQ(Call->isMustTailCall(), LLVMCall->isMustTailCall()); 3262372a6beaSvporpo // Check isTailCall(). 3263372a6beaSvporpo EXPECT_EQ(Call->isTailCall(), LLVMCall->isTailCall()); 3264372a6beaSvporpo // Check getIntrinsicID(). 3265372a6beaSvporpo EXPECT_EQ(Call->getIntrinsicID(), LLVMCall->getIntrinsicID()); 3266372a6beaSvporpo // Check getCallingConv(). 3267372a6beaSvporpo EXPECT_EQ(Call->getCallingConv(), LLVMCall->getCallingConv()); 3268372a6beaSvporpo // Check isInlineAsm(). 3269372a6beaSvporpo EXPECT_EQ(Call->isInlineAsm(), LLVMCall->isInlineAsm()); 3270372a6beaSvporpo } 3271372a6beaSvporpo 3272372a6beaSvporpo auto *Arg0 = F.getArg(0); 3273372a6beaSvporpo auto *Arg1 = F.getArg(1); 3274372a6beaSvporpo auto *BB = &*F.begin(); 3275372a6beaSvporpo auto It = BB->begin(); 3276372a6beaSvporpo auto *Call0 = cast<sandboxir::CallBase>(&*It++); 3277372a6beaSvporpo [[maybe_unused]] auto *Call1 = cast<sandboxir::CallBase>(&*It++); 3278372a6beaSvporpo auto *Call2 = cast<sandboxir::CallBase>(&*It++); 3279372a6beaSvporpo // Check setArgOperand 3280372a6beaSvporpo Call0->setArgOperand(0, Arg1); 3281372a6beaSvporpo EXPECT_EQ(Call0->getArgOperand(0), Arg1); 3282372a6beaSvporpo Call0->setArgOperand(0, Arg0); 3283372a6beaSvporpo EXPECT_EQ(Call0->getArgOperand(0), Arg0); 3284372a6beaSvporpo 3285372a6beaSvporpo auto *Bar3F = Ctx.createFunction(M->getFunction("bar3")); 3286372a6beaSvporpo 3287372a6beaSvporpo // Check setCalledOperand 3288372a6beaSvporpo auto *SvOp = Call0->getCalledOperand(); 3289372a6beaSvporpo Call0->setCalledOperand(Bar3F); 3290372a6beaSvporpo EXPECT_EQ(Call0->getCalledOperand(), Bar3F); 3291372a6beaSvporpo Call0->setCalledOperand(SvOp); 3292372a6beaSvporpo // Check setCalledFunction 3293372a6beaSvporpo Call2->setCalledFunction(Bar3F); 3294372a6beaSvporpo EXPECT_EQ(Call2->getCalledFunction(), Bar3F); 3295372a6beaSvporpo } 3296372a6beaSvporpo 3297372a6beaSvporpo TEST_F(SandboxIRTest, CallInst) { 3298372a6beaSvporpo parseIR(C, R"IR( 3299372a6beaSvporpo define i8 @foo(i8 %arg) { 3300372a6beaSvporpo %call = call i8 @foo(i8 %arg) 3301372a6beaSvporpo ret i8 %call 3302372a6beaSvporpo } 3303372a6beaSvporpo )IR"); 3304372a6beaSvporpo Function &LLVMF = *M->getFunction("foo"); 3305372a6beaSvporpo sandboxir::Context Ctx(C); 3306372a6beaSvporpo auto &F = *Ctx.createFunction(&LLVMF); 3307372a6beaSvporpo unsigned ArgIdx = 0; 3308372a6beaSvporpo auto *Arg0 = F.getArg(ArgIdx++); 3309372a6beaSvporpo auto *BB = &*F.begin(); 3310372a6beaSvporpo auto It = BB->begin(); 3311372a6beaSvporpo auto *Call = cast<sandboxir::CallInst>(&*It++); 3312372a6beaSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 3313372a6beaSvporpo EXPECT_EQ(Call->getNumOperands(), 2u); 3314372a6beaSvporpo EXPECT_EQ(Ret->getOpcode(), sandboxir::Instruction::Opcode::Ret); 3315034f2b38Svporpo sandboxir::FunctionType *FTy = F.getFunctionType(); 3316372a6beaSvporpo SmallVector<sandboxir::Value *, 1> Args; 3317372a6beaSvporpo Args.push_back(Arg0); 3318372a6beaSvporpo { 3319372a6beaSvporpo // Check create() WhereIt. 3320372a6beaSvporpo auto *Call = cast<sandboxir::CallInst>(sandboxir::CallInst::create( 33213a47bf63Svporpo FTy, &F, Args, /*WhereIt=*/Ret->getIterator(), Ctx)); 3322372a6beaSvporpo EXPECT_EQ(Call->getNextNode(), Ret); 3323372a6beaSvporpo EXPECT_EQ(Call->getCalledFunction(), &F); 3324372a6beaSvporpo EXPECT_EQ(range_size(Call->args()), 1u); 3325372a6beaSvporpo EXPECT_EQ(Call->getArgOperand(0), Arg0); 3326372a6beaSvporpo } 3327372a6beaSvporpo { 3328372a6beaSvporpo // Check create() InsertBefore. 3329372a6beaSvporpo auto *Call = cast<sandboxir::CallInst>( 33303a47bf63Svporpo sandboxir::CallInst::create(FTy, &F, Args, Ret->getIterator(), Ctx)); 3331372a6beaSvporpo EXPECT_EQ(Call->getNextNode(), Ret); 3332372a6beaSvporpo EXPECT_EQ(Call->getCalledFunction(), &F); 3333372a6beaSvporpo EXPECT_EQ(range_size(Call->args()), 1u); 3334372a6beaSvporpo EXPECT_EQ(Call->getArgOperand(0), Arg0); 3335372a6beaSvporpo } 3336372a6beaSvporpo { 3337372a6beaSvporpo // Check create() InsertAtEnd. 3338372a6beaSvporpo auto *Call = cast<sandboxir::CallInst>( 3339372a6beaSvporpo sandboxir::CallInst::create(FTy, &F, Args, /*InsertAtEnd=*/BB, Ctx)); 3340372a6beaSvporpo EXPECT_EQ(Call->getPrevNode(), Ret); 3341372a6beaSvporpo EXPECT_EQ(Call->getCalledFunction(), &F); 3342372a6beaSvporpo EXPECT_EQ(range_size(Call->args()), 1u); 3343372a6beaSvporpo EXPECT_EQ(Call->getArgOperand(0), Arg0); 3344372a6beaSvporpo } 3345372a6beaSvporpo } 3346db2aa50eSvporpo 3347db2aa50eSvporpo TEST_F(SandboxIRTest, InvokeInst) { 3348db2aa50eSvporpo parseIR(C, R"IR( 3349db2aa50eSvporpo define void @foo(i8 %arg) { 3350db2aa50eSvporpo bb0: 3351db2aa50eSvporpo invoke i8 @foo(i8 %arg) to label %normal_bb 3352db2aa50eSvporpo unwind label %exception_bb 3353db2aa50eSvporpo normal_bb: 3354db2aa50eSvporpo ret void 3355db2aa50eSvporpo exception_bb: 3356db2aa50eSvporpo %lpad = landingpad { ptr, i32} 3357db2aa50eSvporpo cleanup 3358db2aa50eSvporpo ret void 3359db2aa50eSvporpo other_bb: 3360db2aa50eSvporpo ret void 3361db2aa50eSvporpo } 3362db2aa50eSvporpo )IR"); 3363db2aa50eSvporpo Function &LLVMF = *M->getFunction("foo"); 3364db2aa50eSvporpo sandboxir::Context Ctx(C); 3365db2aa50eSvporpo auto &F = *Ctx.createFunction(&LLVMF); 3366db2aa50eSvporpo auto *Arg = F.getArg(0); 3367db2aa50eSvporpo auto *BB0 = cast<sandboxir::BasicBlock>( 3368db2aa50eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb0"))); 3369db2aa50eSvporpo auto *NormalBB = cast<sandboxir::BasicBlock>( 3370db2aa50eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb"))); 3371db2aa50eSvporpo auto *ExceptionBB = cast<sandboxir::BasicBlock>( 3372db2aa50eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb"))); 3373db2aa50eSvporpo auto *LandingPad = &*ExceptionBB->begin(); 3374db2aa50eSvporpo auto *OtherBB = cast<sandboxir::BasicBlock>( 3375db2aa50eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb"))); 3376db2aa50eSvporpo auto It = BB0->begin(); 3377db2aa50eSvporpo // Check classof(Instruction *). 3378db2aa50eSvporpo auto *Invoke = cast<sandboxir::InvokeInst>(&*It++); 3379db2aa50eSvporpo 3380db2aa50eSvporpo // Check getNormalDest(). 3381db2aa50eSvporpo EXPECT_EQ(Invoke->getNormalDest(), NormalBB); 3382db2aa50eSvporpo // Check getUnwindDest(). 3383db2aa50eSvporpo EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB); 3384db2aa50eSvporpo // Check getSuccessor(). 3385db2aa50eSvporpo EXPECT_EQ(Invoke->getSuccessor(0), NormalBB); 3386db2aa50eSvporpo EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB); 3387db2aa50eSvporpo // Check setNormalDest(). 3388db2aa50eSvporpo Invoke->setNormalDest(OtherBB); 3389db2aa50eSvporpo EXPECT_EQ(Invoke->getNormalDest(), OtherBB); 3390db2aa50eSvporpo EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB); 3391db2aa50eSvporpo // Check setUnwindDest(). 3392db2aa50eSvporpo Invoke->setUnwindDest(OtherBB); 3393db2aa50eSvporpo EXPECT_EQ(Invoke->getNormalDest(), OtherBB); 3394db2aa50eSvporpo EXPECT_EQ(Invoke->getUnwindDest(), OtherBB); 3395db2aa50eSvporpo // Check setSuccessor(). 3396db2aa50eSvporpo Invoke->setSuccessor(0, NormalBB); 3397db2aa50eSvporpo EXPECT_EQ(Invoke->getNormalDest(), NormalBB); 3398db2aa50eSvporpo Invoke->setSuccessor(1, ExceptionBB); 3399db2aa50eSvporpo EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB); 3400db2aa50eSvporpo // Check getLandingPadInst(). 3401db2aa50eSvporpo EXPECT_EQ(Invoke->getLandingPadInst(), LandingPad); 3402db2aa50eSvporpo 3403db2aa50eSvporpo { 3404db2aa50eSvporpo // Check create() WhereIt, WhereBB. 3405db2aa50eSvporpo SmallVector<sandboxir::Value *> Args({Arg}); 3406db2aa50eSvporpo auto *InsertBefore = &*BB0->begin(); 3407db2aa50eSvporpo auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create( 3408db2aa50eSvporpo F.getFunctionType(), &F, NormalBB, ExceptionBB, Args, 34093a47bf63Svporpo InsertBefore->getIterator(), Ctx)); 3410db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB); 3411db2aa50eSvporpo EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB); 3412db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore); 3413db2aa50eSvporpo } 3414db2aa50eSvporpo { 3415db2aa50eSvporpo // Check create() InsertBefore. 3416db2aa50eSvporpo SmallVector<sandboxir::Value *> Args({Arg}); 3417db2aa50eSvporpo auto *InsertBefore = &*BB0->begin(); 34183a47bf63Svporpo auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create( 34193a47bf63Svporpo F.getFunctionType(), &F, NormalBB, ExceptionBB, Args, 34203a47bf63Svporpo InsertBefore->getIterator(), Ctx)); 3421db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB); 3422db2aa50eSvporpo EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB); 3423db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore); 3424db2aa50eSvporpo } 3425db2aa50eSvporpo { 3426db2aa50eSvporpo // Check create() InsertAtEnd. 3427db2aa50eSvporpo SmallVector<sandboxir::Value *> Args({Arg}); 3428db2aa50eSvporpo auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create( 34293a47bf63Svporpo F.getFunctionType(), &F, NormalBB, ExceptionBB, Args, BB0, Ctx)); 3430db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB); 3431db2aa50eSvporpo EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB); 3432db2aa50eSvporpo EXPECT_EQ(NewInvoke->getParent(), BB0); 3433db2aa50eSvporpo EXPECT_EQ(NewInvoke->getNextNode(), nullptr); 3434db2aa50eSvporpo } 3435db2aa50eSvporpo } 3436cfb92be0Svporpo 3437cfb92be0Svporpo TEST_F(SandboxIRTest, CallBrInst) { 3438cfb92be0Svporpo parseIR(C, R"IR( 3439cfb92be0Svporpo define void @foo(i8 %arg) { 3440cfb92be0Svporpo bb0: 3441cfb92be0Svporpo callbr void asm "", ""() 3442cfb92be0Svporpo to label %bb1 [label %bb2] 3443cfb92be0Svporpo bb1: 3444cfb92be0Svporpo ret void 3445cfb92be0Svporpo bb2: 3446cfb92be0Svporpo ret void 3447cfb92be0Svporpo other_bb: 3448cfb92be0Svporpo ret void 3449cfb92be0Svporpo bb3: 3450cfb92be0Svporpo callbr void @foo(i8 %arg) 3451cfb92be0Svporpo to label %bb1 [label %bb2] 3452cfb92be0Svporpo } 3453cfb92be0Svporpo )IR"); 3454cfb92be0Svporpo Function &LLVMF = *M->getFunction("foo"); 3455cfb92be0Svporpo auto *LLVMBB0 = getBasicBlockByName(LLVMF, "bb0"); 3456cfb92be0Svporpo auto *LLVMCallBr = cast<llvm::CallBrInst>(&*LLVMBB0->begin()); 3457cfb92be0Svporpo sandboxir::Context Ctx(C); 3458cfb92be0Svporpo auto &F = *Ctx.createFunction(&LLVMF); 3459cfb92be0Svporpo auto *Arg = F.getArg(0); 3460cfb92be0Svporpo auto *BB0 = cast<sandboxir::BasicBlock>( 3461cfb92be0Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb0"))); 3462cfb92be0Svporpo auto *BB1 = cast<sandboxir::BasicBlock>( 3463cfb92be0Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb1"))); 3464cfb92be0Svporpo auto *BB2 = cast<sandboxir::BasicBlock>( 3465cfb92be0Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb2"))); 3466cfb92be0Svporpo auto *BB3 = cast<sandboxir::BasicBlock>( 3467cfb92be0Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb3"))); 3468cfb92be0Svporpo auto *OtherBB = cast<sandboxir::BasicBlock>( 3469cfb92be0Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb"))); 3470cfb92be0Svporpo auto It = BB0->begin(); 3471cfb92be0Svporpo // Check classof(Instruction *). 3472cfb92be0Svporpo auto *CallBr0 = cast<sandboxir::CallBrInst>(&*It++); 3473cfb92be0Svporpo 3474cfb92be0Svporpo It = BB3->begin(); 3475cfb92be0Svporpo auto *CallBr1 = cast<sandboxir::CallBrInst>(&*It++); 3476cfb92be0Svporpo for (sandboxir::CallBrInst *CallBr : {CallBr0, CallBr1}) { 3477cfb92be0Svporpo // Check getNumIndirectDests(). 3478cfb92be0Svporpo EXPECT_EQ(CallBr->getNumIndirectDests(), 1u); 3479cfb92be0Svporpo // Check getIndirectDestLabel(). 3480cfb92be0Svporpo EXPECT_EQ(CallBr->getIndirectDestLabel(0), 3481cfb92be0Svporpo Ctx.getValue(LLVMCallBr->getIndirectDestLabel(0))); 3482cfb92be0Svporpo // Check getIndirectDestLabelUse(). 3483cfb92be0Svporpo EXPECT_EQ(CallBr->getIndirectDestLabelUse(0), 3484cfb92be0Svporpo Ctx.getValue(LLVMCallBr->getIndirectDestLabelUse(0))); 3485cfb92be0Svporpo // Check getDefaultDest(). 3486cfb92be0Svporpo EXPECT_EQ(CallBr->getDefaultDest(), 3487cfb92be0Svporpo Ctx.getValue(LLVMCallBr->getDefaultDest())); 3488cfb92be0Svporpo // Check getIndirectDest(). 3489cfb92be0Svporpo EXPECT_EQ(CallBr->getIndirectDest(0), 3490cfb92be0Svporpo Ctx.getValue(LLVMCallBr->getIndirectDest(0))); 3491cfb92be0Svporpo // Check getIndirectDests(). 3492cfb92be0Svporpo auto Dests = CallBr->getIndirectDests(); 3493cfb92be0Svporpo EXPECT_EQ(Dests.size(), LLVMCallBr->getIndirectDests().size()); 3494cfb92be0Svporpo EXPECT_EQ(Dests[0], Ctx.getValue(LLVMCallBr->getIndirectDests()[0])); 3495cfb92be0Svporpo // Check getNumSuccessors(). 3496cfb92be0Svporpo EXPECT_EQ(CallBr->getNumSuccessors(), LLVMCallBr->getNumSuccessors()); 3497cfb92be0Svporpo // Check getSuccessor(). 3498cfb92be0Svporpo for (unsigned SuccIdx = 0, E = CallBr->getNumSuccessors(); SuccIdx != E; 3499cfb92be0Svporpo ++SuccIdx) 3500cfb92be0Svporpo EXPECT_EQ(CallBr->getSuccessor(SuccIdx), 3501cfb92be0Svporpo Ctx.getValue(LLVMCallBr->getSuccessor(SuccIdx))); 3502cfb92be0Svporpo // Check setDefaultDest(). 3503cfb92be0Svporpo auto *SvDefaultDest = CallBr->getDefaultDest(); 3504cfb92be0Svporpo CallBr->setDefaultDest(OtherBB); 3505cfb92be0Svporpo EXPECT_EQ(CallBr->getDefaultDest(), OtherBB); 3506cfb92be0Svporpo CallBr->setDefaultDest(SvDefaultDest); 3507cfb92be0Svporpo // Check setIndirectDest(). 3508cfb92be0Svporpo auto *SvIndirectDest = CallBr->getIndirectDest(0); 3509cfb92be0Svporpo CallBr->setIndirectDest(0, OtherBB); 3510cfb92be0Svporpo EXPECT_EQ(CallBr->getIndirectDest(0), OtherBB); 3511cfb92be0Svporpo CallBr->setIndirectDest(0, SvIndirectDest); 3512cfb92be0Svporpo } 3513cfb92be0Svporpo 3514cfb92be0Svporpo { 3515cfb92be0Svporpo // Check create() WhereIt, WhereBB. 3516cfb92be0Svporpo SmallVector<sandboxir::Value *> Args({Arg}); 3517cfb92be0Svporpo auto *NewCallBr = cast<sandboxir::CallBrInst>(sandboxir::CallBrInst::create( 35183a47bf63Svporpo F.getFunctionType(), &F, BB1, {BB2}, Args, BB0->end(), Ctx)); 3519cfb92be0Svporpo EXPECT_EQ(NewCallBr->getDefaultDest(), BB1); 3520cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u); 3521cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2); 3522cfb92be0Svporpo EXPECT_EQ(NewCallBr->getNextNode(), nullptr); 3523cfb92be0Svporpo EXPECT_EQ(NewCallBr->getParent(), BB0); 3524cfb92be0Svporpo } 3525cfb92be0Svporpo { 3526cfb92be0Svporpo // Check create() InsertBefore 3527cfb92be0Svporpo SmallVector<sandboxir::Value *> Args({Arg}); 3528cfb92be0Svporpo auto *InsertBefore = &*BB0->rbegin(); 35293a47bf63Svporpo auto *NewCallBr = cast<sandboxir::CallBrInst>( 35303a47bf63Svporpo sandboxir::CallBrInst::create(F.getFunctionType(), &F, BB1, {BB2}, Args, 35313a47bf63Svporpo InsertBefore->getIterator(), Ctx)); 3532cfb92be0Svporpo EXPECT_EQ(NewCallBr->getDefaultDest(), BB1); 3533cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u); 3534cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2); 3535cfb92be0Svporpo EXPECT_EQ(NewCallBr->getNextNode(), InsertBefore); 3536cfb92be0Svporpo } 3537cfb92be0Svporpo { 3538cfb92be0Svporpo // Check create() InsertAtEnd. 3539cfb92be0Svporpo SmallVector<sandboxir::Value *> Args({Arg}); 35403a47bf63Svporpo auto *NewCallBr = cast<sandboxir::CallBrInst>(sandboxir::CallBrInst::create( 35413a47bf63Svporpo F.getFunctionType(), &F, BB1, {BB2}, Args, BB0, Ctx)); 3542cfb92be0Svporpo EXPECT_EQ(NewCallBr->getDefaultDest(), BB1); 3543cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u); 3544cfb92be0Svporpo EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2); 3545cfb92be0Svporpo EXPECT_EQ(NewCallBr->getNextNode(), nullptr); 3546cfb92be0Svporpo EXPECT_EQ(NewCallBr->getParent(), BB0); 3547cfb92be0Svporpo } 3548cfb92be0Svporpo } 3549f9765a28Svporpo 3550e8b93ce2Svporpo TEST_F(SandboxIRTest, LandingPadInst) { 3551e8b93ce2Svporpo parseIR(C, R"IR( 3552e8b93ce2Svporpo define void @foo() { 3553e8b93ce2Svporpo entry: 3554e8b93ce2Svporpo invoke void @foo() 3555e8b93ce2Svporpo to label %bb unwind label %unwind 3556e8b93ce2Svporpo unwind: 3557e8b93ce2Svporpo %lpad = landingpad { ptr, i32 } 3558e8b93ce2Svporpo catch ptr null 3559e8b93ce2Svporpo ret void 3560e8b93ce2Svporpo bb: 3561e8b93ce2Svporpo ret void 3562e8b93ce2Svporpo } 3563e8b93ce2Svporpo )IR"); 3564e8b93ce2Svporpo Function &LLVMF = *M->getFunction("foo"); 3565e8b93ce2Svporpo auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind"); 3566e8b93ce2Svporpo auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMUnwind->begin()); 3567e8b93ce2Svporpo 3568e8b93ce2Svporpo sandboxir::Context Ctx(C); 3569e8b93ce2Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 3570e8b93ce2Svporpo auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind)); 3571e8b93ce2Svporpo auto *BB = cast<sandboxir::BasicBlock>( 3572e8b93ce2Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb"))); 3573e8b93ce2Svporpo auto It = Unwind->begin(); 3574e8b93ce2Svporpo auto *LPad = cast<sandboxir::LandingPadInst>(&*It++); 3575e8b93ce2Svporpo [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 3576e8b93ce2Svporpo 3577e8b93ce2Svporpo // Check isCleanup(). 3578e8b93ce2Svporpo EXPECT_EQ(LPad->isCleanup(), LLVMLPad->isCleanup()); 3579e8b93ce2Svporpo // Check setCleanup(). 3580e8b93ce2Svporpo auto OrigIsCleanup = LPad->isCleanup(); 3581e8b93ce2Svporpo auto NewIsCleanup = true; 3582e8b93ce2Svporpo EXPECT_NE(NewIsCleanup, OrigIsCleanup); 3583e8b93ce2Svporpo LPad->setCleanup(NewIsCleanup); 3584e8b93ce2Svporpo EXPECT_EQ(LPad->isCleanup(), NewIsCleanup); 3585e8b93ce2Svporpo LPad->setCleanup(OrigIsCleanup); 3586e8b93ce2Svporpo EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup); 3587e8b93ce2Svporpo // Check getNumClauses(). 3588e8b93ce2Svporpo EXPECT_EQ(LPad->getNumClauses(), LLVMLPad->getNumClauses()); 3589e8b93ce2Svporpo // Check getClause(). 3590e8b93ce2Svporpo for (auto Idx : seq<unsigned>(0, LPad->getNumClauses())) 3591e8b93ce2Svporpo EXPECT_EQ(LPad->getClause(Idx), Ctx.getValue(LLVMLPad->getClause(Idx))); 3592e8b93ce2Svporpo // Check isCatch(). 3593e8b93ce2Svporpo for (auto Idx : seq<unsigned>(0, LPad->getNumClauses())) 3594e8b93ce2Svporpo EXPECT_EQ(LPad->isCatch(Idx), LLVMLPad->isCatch(Idx)); 3595e8b93ce2Svporpo // Check isFilter(). 3596e8b93ce2Svporpo for (auto Idx : seq<unsigned>(0, LPad->getNumClauses())) 3597e8b93ce2Svporpo EXPECT_EQ(LPad->isFilter(Idx), LLVMLPad->isFilter(Idx)); 3598e8b93ce2Svporpo // Check create(). 3599e8b93ce2Svporpo auto *BBRet = &*BB->begin(); 36003a47bf63Svporpo auto *NewLPad = cast<sandboxir::LandingPadInst>( 36013a47bf63Svporpo sandboxir::LandingPadInst::create(sandboxir::Type::getInt8Ty(Ctx), 0, 36023a47bf63Svporpo BBRet->getIterator(), Ctx, "NewLPad")); 3603e8b93ce2Svporpo EXPECT_EQ(NewLPad->getNextNode(), BBRet); 3604e8b93ce2Svporpo EXPECT_FALSE(NewLPad->isCleanup()); 3605e8b93ce2Svporpo #ifndef NDEBUG 3606e8b93ce2Svporpo EXPECT_EQ(NewLPad->getName(), "NewLPad"); 3607e8b93ce2Svporpo #endif // NDEBUG 3608e8b93ce2Svporpo } 3609e8b93ce2Svporpo 36107854b16dSvporpo TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) { 36117854b16dSvporpo parseIR(C, R"IR( 36127854b16dSvporpo define void @foo() { 36137854b16dSvporpo dispatch: 36147854b16dSvporpo %cs = catchswitch within none [label %handler0] unwind to caller 36157854b16dSvporpo handler0: 36167854b16dSvporpo %catchpad = catchpad within %cs [ptr @foo] 36177854b16dSvporpo ret void 36187854b16dSvporpo handler1: 36197854b16dSvporpo %cleanuppad = cleanuppad within %cs [ptr @foo] 36207854b16dSvporpo ret void 36217854b16dSvporpo bb: 36227854b16dSvporpo ret void 36237854b16dSvporpo } 36247854b16dSvporpo )IR"); 36257854b16dSvporpo Function &LLVMF = *M->getFunction("foo"); 36267854b16dSvporpo BasicBlock *LLVMDispatch = getBasicBlockByName(LLVMF, "dispatch"); 36277854b16dSvporpo BasicBlock *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0"); 36287854b16dSvporpo BasicBlock *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1"); 36297854b16dSvporpo auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMHandler0->begin()); 36307854b16dSvporpo auto *LLVMCLP = cast<llvm::CleanupPadInst>(&*LLVMHandler1->begin()); 36317854b16dSvporpo 36327854b16dSvporpo sandboxir::Context Ctx(C); 36337854b16dSvporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 36347854b16dSvporpo auto *Dispatch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMDispatch)); 36357854b16dSvporpo auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0)); 36367854b16dSvporpo auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1)); 36377854b16dSvporpo auto *BB = cast<sandboxir::BasicBlock>( 36387854b16dSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb"))); 36397854b16dSvporpo auto *BBRet = cast<sandboxir::ReturnInst>(&*BB->begin()); 36407854b16dSvporpo auto *CS = cast<sandboxir::CatchSwitchInst>(&*Dispatch->begin()); 36417854b16dSvporpo [[maybe_unused]] auto *CP = 36427854b16dSvporpo cast<sandboxir::CatchPadInst>(&*Handler0->begin()); 36437854b16dSvporpo [[maybe_unused]] auto *CLP = 36447854b16dSvporpo cast<sandboxir::CleanupPadInst>(&*Handler1->begin()); 36457854b16dSvporpo 36467854b16dSvporpo // Check getCatchSwitch(). 36477854b16dSvporpo EXPECT_EQ(CP->getCatchSwitch(), CS); 36487854b16dSvporpo EXPECT_EQ(CP->getCatchSwitch(), Ctx.getValue(LLVMCP->getCatchSwitch())); 36497854b16dSvporpo 36507854b16dSvporpo for (llvm::FuncletPadInst *LLVMFPI : 36517854b16dSvporpo {static_cast<llvm::FuncletPadInst *>(LLVMCP), 36527854b16dSvporpo static_cast<llvm::FuncletPadInst *>(LLVMCLP)}) { 36537854b16dSvporpo auto *FPI = cast<sandboxir::FuncletPadInst>(Ctx.getValue(LLVMFPI)); 36547854b16dSvporpo // Check arg_size(). 36557854b16dSvporpo EXPECT_EQ(FPI->arg_size(), LLVMFPI->arg_size()); 36567854b16dSvporpo // Check getParentPad(). 36577854b16dSvporpo EXPECT_EQ(FPI->getParentPad(), Ctx.getValue(LLVMFPI->getParentPad())); 36587854b16dSvporpo // Check setParentPad(). 36597854b16dSvporpo auto *OrigParentPad = FPI->getParentPad(); 36607854b16dSvporpo auto *NewParentPad = Dispatch; 36617854b16dSvporpo EXPECT_NE(NewParentPad, OrigParentPad); 36627854b16dSvporpo FPI->setParentPad(NewParentPad); 36637854b16dSvporpo EXPECT_EQ(FPI->getParentPad(), NewParentPad); 36647854b16dSvporpo FPI->setParentPad(OrigParentPad); 36657854b16dSvporpo EXPECT_EQ(FPI->getParentPad(), OrigParentPad); 36667854b16dSvporpo // Check getArgOperand(). 36677854b16dSvporpo for (auto Idx : seq<unsigned>(0, FPI->arg_size())) 36687854b16dSvporpo EXPECT_EQ(FPI->getArgOperand(Idx), 36697854b16dSvporpo Ctx.getValue(LLVMFPI->getArgOperand(Idx))); 36707854b16dSvporpo // Check setArgOperand(). 36717854b16dSvporpo auto *OrigArgOperand = FPI->getArgOperand(0); 36727854b16dSvporpo auto *NewArgOperand = Dispatch; 36737854b16dSvporpo EXPECT_NE(NewArgOperand, OrigArgOperand); 36747854b16dSvporpo FPI->setArgOperand(0, NewArgOperand); 36757854b16dSvporpo EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand); 36767854b16dSvporpo FPI->setArgOperand(0, OrigArgOperand); 36777854b16dSvporpo EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand); 36787854b16dSvporpo } 36797854b16dSvporpo // Check CatchPadInst::create(). 36807854b16dSvporpo auto *NewCPI = cast<sandboxir::CatchPadInst>(sandboxir::CatchPadInst::create( 36813a47bf63Svporpo CS, {}, BBRet->getIterator(), Ctx, "NewCPI")); 36827854b16dSvporpo EXPECT_EQ(NewCPI->getCatchSwitch(), CS); 36837854b16dSvporpo EXPECT_EQ(NewCPI->arg_size(), 0u); 36847854b16dSvporpo EXPECT_EQ(NewCPI->getNextNode(), BBRet); 36857854b16dSvporpo #ifndef NDEBUG 36867854b16dSvporpo EXPECT_EQ(NewCPI->getName(), "NewCPI"); 36877854b16dSvporpo #endif // NDEBUG 36887854b16dSvporpo // Check CleanupPadInst::create(). 36897854b16dSvporpo auto *NewCLPI = 36907854b16dSvporpo cast<sandboxir::CleanupPadInst>(sandboxir::CleanupPadInst::create( 36913a47bf63Svporpo CS, {}, BBRet->getIterator(), Ctx, "NewCLPI")); 36927854b16dSvporpo EXPECT_EQ(NewCLPI->getParentPad(), CS); 36937854b16dSvporpo EXPECT_EQ(NewCLPI->arg_size(), 0u); 36947854b16dSvporpo EXPECT_EQ(NewCLPI->getNextNode(), BBRet); 36957854b16dSvporpo #ifndef NDEBUG 36967854b16dSvporpo EXPECT_EQ(NewCLPI->getName(), "NewCLPI"); 36977854b16dSvporpo #endif // NDEBUG 36987854b16dSvporpo } 36997854b16dSvporpo 37000d21c2b3Svporpo TEST_F(SandboxIRTest, CatchReturnInst) { 37010d21c2b3Svporpo parseIR(C, R"IR( 37020d21c2b3Svporpo define void @foo() { 37030d21c2b3Svporpo dispatch: 37040d21c2b3Svporpo %cs = catchswitch within none [label %catch] unwind to caller 37050d21c2b3Svporpo catch: 37060d21c2b3Svporpo %catchpad = catchpad within %cs [ptr @foo] 37070d21c2b3Svporpo catchret from %catchpad to label %continue 37080d21c2b3Svporpo continue: 37090d21c2b3Svporpo ret void 37100d21c2b3Svporpo catch2: 37110d21c2b3Svporpo %catchpad2 = catchpad within %cs [ptr @foo] 37120d21c2b3Svporpo ret void 37130d21c2b3Svporpo } 37140d21c2b3Svporpo )IR"); 37150d21c2b3Svporpo Function &LLVMF = *M->getFunction("foo"); 37160d21c2b3Svporpo BasicBlock *LLVMCatch = getBasicBlockByName(LLVMF, "catch"); 37170d21c2b3Svporpo auto LLVMIt = LLVMCatch->begin(); 37180d21c2b3Svporpo [[maybe_unused]] auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMIt++); 37190d21c2b3Svporpo auto *LLVMCR = cast<llvm::CatchReturnInst>(&*LLVMIt++); 37200d21c2b3Svporpo 37210d21c2b3Svporpo sandboxir::Context Ctx(C); 37220d21c2b3Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 37230d21c2b3Svporpo auto *Catch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCatch)); 37240d21c2b3Svporpo auto *Catch2 = cast<sandboxir::BasicBlock>( 37250d21c2b3Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "catch2"))); 37260d21c2b3Svporpo auto It = Catch->begin(); 37270d21c2b3Svporpo [[maybe_unused]] auto *CP = cast<sandboxir::CatchPadInst>(&*It++); 37280d21c2b3Svporpo auto *CR = cast<sandboxir::CatchReturnInst>(&*It++); 37290d21c2b3Svporpo auto *CP2 = cast<sandboxir::CatchPadInst>(&*Catch2->begin()); 37300d21c2b3Svporpo 37310d21c2b3Svporpo // Check getCatchPad(). 37320d21c2b3Svporpo EXPECT_EQ(CR->getCatchPad(), Ctx.getValue(LLVMCR->getCatchPad())); 37330d21c2b3Svporpo // Check setCatchPad(). 37340d21c2b3Svporpo auto *OrigCP = CR->getCatchPad(); 37350d21c2b3Svporpo auto *NewCP = CP2; 37360d21c2b3Svporpo EXPECT_NE(NewCP, OrigCP); 37370d21c2b3Svporpo CR->setCatchPad(NewCP); 37380d21c2b3Svporpo EXPECT_EQ(CR->getCatchPad(), NewCP); 37390d21c2b3Svporpo CR->setCatchPad(OrigCP); 37400d21c2b3Svporpo EXPECT_EQ(CR->getCatchPad(), OrigCP); 37410d21c2b3Svporpo // Check getSuccessor(). 37420d21c2b3Svporpo EXPECT_EQ(CR->getSuccessor(), Ctx.getValue(LLVMCR->getSuccessor())); 37430d21c2b3Svporpo // Check setSuccessor(). 37440d21c2b3Svporpo auto *OrigSucc = CR->getSuccessor(); 37450d21c2b3Svporpo auto *NewSucc = Catch; 37460d21c2b3Svporpo EXPECT_NE(NewSucc, OrigSucc); 37470d21c2b3Svporpo CR->setSuccessor(NewSucc); 37480d21c2b3Svporpo EXPECT_EQ(CR->getSuccessor(), NewSucc); 37490d21c2b3Svporpo CR->setSuccessor(OrigSucc); 37500d21c2b3Svporpo EXPECT_EQ(CR->getSuccessor(), OrigSucc); 37510d21c2b3Svporpo // Check getNumSuccessors(). 37520d21c2b3Svporpo EXPECT_EQ(CR->getNumSuccessors(), LLVMCR->getNumSuccessors()); 37530d21c2b3Svporpo // Check getCatchSwitchParentPad(). 37540d21c2b3Svporpo EXPECT_EQ(CR->getCatchSwitchParentPad(), 37550d21c2b3Svporpo Ctx.getValue(LLVMCR->getCatchSwitchParentPad())); 37560d21c2b3Svporpo // Check create(). 37574f3a0959Svporpo auto *CRI = cast<sandboxir::CatchReturnInst>( 37584f3a0959Svporpo sandboxir::CatchReturnInst::create(CP, Catch, CP->getIterator(), Ctx)); 37590d21c2b3Svporpo EXPECT_EQ(CRI->getNextNode(), CP); 37600d21c2b3Svporpo EXPECT_EQ(CRI->getCatchPad(), CP); 37610d21c2b3Svporpo EXPECT_EQ(CRI->getSuccessor(), Catch); 37620d21c2b3Svporpo } 37630d21c2b3Svporpo 3764d0213216Svporpo TEST_F(SandboxIRTest, CleanupReturnInst) { 3765d0213216Svporpo parseIR(C, R"IR( 3766d0213216Svporpo define void @foo() { 3767d0213216Svporpo dispatch: 3768d0213216Svporpo invoke void @foo() 3769d0213216Svporpo to label %throw unwind label %cleanup 3770d0213216Svporpo throw: 3771d0213216Svporpo ret void 3772d0213216Svporpo cleanup: 3773d0213216Svporpo %cleanuppad = cleanuppad within none [] 3774d0213216Svporpo cleanupret from %cleanuppad unwind label %cleanup2 3775d0213216Svporpo cleanup2: 3776d0213216Svporpo %cleanuppad2 = cleanuppad within none [] 3777d0213216Svporpo ret void 3778d0213216Svporpo } 3779d0213216Svporpo )IR"); 3780d0213216Svporpo Function &LLVMF = *M->getFunction("foo"); 3781d0213216Svporpo BasicBlock *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup"); 3782d0213216Svporpo auto LLVMIt = LLVMCleanup->begin(); 3783d0213216Svporpo [[maybe_unused]] auto *LLVMCP = cast<llvm::CleanupPadInst>(&*LLVMIt++); 3784d0213216Svporpo auto *LLVMCRI = cast<llvm::CleanupReturnInst>(&*LLVMIt++); 3785d0213216Svporpo 3786d0213216Svporpo sandboxir::Context Ctx(C); 3787d0213216Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 3788d0213216Svporpo auto *Throw = cast<sandboxir::BasicBlock>( 3789d0213216Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "throw"))); 3790d0213216Svporpo auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup)); 3791d0213216Svporpo auto *Cleanup2 = cast<sandboxir::BasicBlock>( 3792d0213216Svporpo Ctx.getValue(getBasicBlockByName(LLVMF, "cleanup2"))); 3793d0213216Svporpo auto It = Cleanup->begin(); 3794d0213216Svporpo [[maybe_unused]] auto *CP = cast<sandboxir::CleanupPadInst>(&*It++); 3795d0213216Svporpo auto *CRI = cast<sandboxir::CleanupReturnInst>(&*It++); 3796d0213216Svporpo It = Cleanup2->begin(); 3797d0213216Svporpo auto *CP2 = cast<sandboxir::CleanupPadInst>(&*It++); 3798d0213216Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 3799d0213216Svporpo 3800d0213216Svporpo // Check hasUnwindDest(). 3801d0213216Svporpo EXPECT_EQ(CRI->hasUnwindDest(), LLVMCRI->hasUnwindDest()); 3802d0213216Svporpo // Check unwindsToCaller(). 3803d0213216Svporpo EXPECT_EQ(CRI->unwindsToCaller(), LLVMCRI->unwindsToCaller()); 3804d0213216Svporpo // Check getCleanupPad(). 3805d0213216Svporpo EXPECT_EQ(CRI->getCleanupPad(), Ctx.getValue(LLVMCRI->getCleanupPad())); 3806d0213216Svporpo // Check setCleanupPad(). 3807d0213216Svporpo auto *OrigCleanupPad = CRI->getCleanupPad(); 3808d0213216Svporpo auto *NewCleanupPad = CP2; 3809d0213216Svporpo EXPECT_NE(NewCleanupPad, OrigCleanupPad); 3810d0213216Svporpo CRI->setCleanupPad(NewCleanupPad); 3811d0213216Svporpo EXPECT_EQ(CRI->getCleanupPad(), NewCleanupPad); 3812d0213216Svporpo CRI->setCleanupPad(OrigCleanupPad); 3813d0213216Svporpo EXPECT_EQ(CRI->getCleanupPad(), OrigCleanupPad); 3814d0213216Svporpo // Check setNumSuccessors(). 3815d0213216Svporpo EXPECT_EQ(CRI->getNumSuccessors(), LLVMCRI->getNumSuccessors()); 3816d0213216Svporpo // Check getUnwindDest(). 3817d0213216Svporpo EXPECT_EQ(CRI->getUnwindDest(), Ctx.getValue(LLVMCRI->getUnwindDest())); 3818d0213216Svporpo // Check setUnwindDest(). 3819d0213216Svporpo auto *OrigUnwindDest = CRI->getUnwindDest(); 3820d0213216Svporpo auto *NewUnwindDest = Throw; 3821d0213216Svporpo EXPECT_NE(NewUnwindDest, OrigUnwindDest); 3822d0213216Svporpo CRI->setUnwindDest(NewUnwindDest); 3823d0213216Svporpo EXPECT_EQ(CRI->getUnwindDest(), NewUnwindDest); 3824d0213216Svporpo CRI->setUnwindDest(OrigUnwindDest); 3825d0213216Svporpo EXPECT_EQ(CRI->getUnwindDest(), OrigUnwindDest); 3826d0213216Svporpo // Check create(). 3827d0213216Svporpo auto *UnwindBB = Cleanup; 38284f3a0959Svporpo auto *NewCRI = sandboxir::CleanupReturnInst::create(CP2, UnwindBB, 38294f3a0959Svporpo Ret->getIterator(), Ctx); 3830d0213216Svporpo EXPECT_EQ(NewCRI->getCleanupPad(), CP2); 3831d0213216Svporpo EXPECT_EQ(NewCRI->getUnwindDest(), UnwindBB); 3832d0213216Svporpo EXPECT_EQ(NewCRI->getNextNode(), Ret); 3833d0213216Svporpo } 3834d0213216Svporpo 3835f9765a28Svporpo TEST_F(SandboxIRTest, GetElementPtrInstruction) { 3836f9765a28Svporpo parseIR(C, R"IR( 3837f9765a28Svporpo define void @foo(ptr %ptr, <2 x ptr> %ptrs) { 3838f9765a28Svporpo %gep0 = getelementptr i8, ptr %ptr, i32 0 3839f9765a28Svporpo %gep1 = getelementptr nusw i8, ptr %ptr, i32 0 3840f9765a28Svporpo %gep2 = getelementptr nuw i8, ptr %ptr, i32 0 3841f9765a28Svporpo %gep3 = getelementptr inbounds {i32, {i32, i8}}, ptr %ptr, i32 1, i32 0 3842f9765a28Svporpo %gep4 = getelementptr inbounds {i8, i8, {i32, i16}}, <2 x ptr> %ptrs, i32 2, <2 x i32> <i32 0, i32 0> 3843f9765a28Svporpo ret void 3844f9765a28Svporpo } 3845f9765a28Svporpo )IR"); 3846f9765a28Svporpo Function &LLVMF = *M->getFunction("foo"); 3847f9765a28Svporpo BasicBlock *LLVMBB = &*LLVMF.begin(); 3848f9765a28Svporpo auto LLVMIt = LLVMBB->begin(); 3849f9765a28Svporpo SmallVector<llvm::GetElementPtrInst *, 4> LLVMGEPs; 3850f9765a28Svporpo while (isa<llvm::GetElementPtrInst>(&*LLVMIt)) 3851f9765a28Svporpo LLVMGEPs.push_back(cast<llvm::GetElementPtrInst>(&*LLVMIt++)); 3852f9765a28Svporpo auto *LLVMRet = cast<llvm::ReturnInst>(&*LLVMIt++); 3853f9765a28Svporpo sandboxir::Context Ctx(C); 3854f9765a28Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 3855f9765a28Svporpo 3856f9765a28Svporpo for (llvm::GetElementPtrInst *LLVMGEP : LLVMGEPs) { 3857f9765a28Svporpo // Check classof(). 3858f9765a28Svporpo auto *GEP = cast<sandboxir::GetElementPtrInst>(Ctx.getValue(LLVMGEP)); 3859f9765a28Svporpo // Check getSourceElementType(). 3860034f2b38Svporpo EXPECT_EQ(GEP->getSourceElementType(), 3861034f2b38Svporpo Ctx.getType(LLVMGEP->getSourceElementType())); 3862f9765a28Svporpo // Check getResultElementType(). 3863034f2b38Svporpo EXPECT_EQ(GEP->getResultElementType(), 3864034f2b38Svporpo Ctx.getType(LLVMGEP->getResultElementType())); 3865f9765a28Svporpo // Check getAddressSpace(). 3866f9765a28Svporpo EXPECT_EQ(GEP->getAddressSpace(), LLVMGEP->getAddressSpace()); 3867f9765a28Svporpo // Check indices(). 3868f9765a28Svporpo EXPECT_EQ(range_size(GEP->indices()), range_size(LLVMGEP->indices())); 3869f9765a28Svporpo auto IdxIt = GEP->idx_begin(); 3870f9765a28Svporpo for (llvm::Value *LLVMIdxV : LLVMGEP->indices()) { 3871f9765a28Svporpo sandboxir::Value *IdxV = *IdxIt++; 3872f9765a28Svporpo EXPECT_EQ(IdxV, Ctx.getValue(LLVMIdxV)); 3873f9765a28Svporpo } 3874f9765a28Svporpo // Check getPointerOperand(). 3875f9765a28Svporpo EXPECT_EQ(GEP->getPointerOperand(), 3876f9765a28Svporpo Ctx.getValue(LLVMGEP->getPointerOperand())); 3877f9765a28Svporpo // Check getPointerOperandIndex(). 3878f9765a28Svporpo EXPECT_EQ(GEP->getPointerOperandIndex(), LLVMGEP->getPointerOperandIndex()); 3879f9765a28Svporpo // Check getPointerOperandType(). 3880034f2b38Svporpo EXPECT_EQ(GEP->getPointerOperandType(), 3881034f2b38Svporpo Ctx.getType(LLVMGEP->getPointerOperandType())); 3882f9765a28Svporpo // Check getPointerAddressSpace(). 3883f9765a28Svporpo EXPECT_EQ(GEP->getPointerAddressSpace(), LLVMGEP->getPointerAddressSpace()); 3884f9765a28Svporpo // Check getNumIndices(). 3885f9765a28Svporpo EXPECT_EQ(GEP->getNumIndices(), LLVMGEP->getNumIndices()); 3886f9765a28Svporpo // Check hasIndices(). 3887f9765a28Svporpo EXPECT_EQ(GEP->hasIndices(), LLVMGEP->hasIndices()); 3888f9765a28Svporpo // Check hasAllConstantIndices(). 3889f9765a28Svporpo EXPECT_EQ(GEP->hasAllConstantIndices(), LLVMGEP->hasAllConstantIndices()); 3890f9765a28Svporpo // Check getNoWrapFlags(). 3891f9765a28Svporpo EXPECT_EQ(GEP->getNoWrapFlags(), LLVMGEP->getNoWrapFlags()); 3892f9765a28Svporpo // Check isInBounds(). 3893f9765a28Svporpo EXPECT_EQ(GEP->isInBounds(), LLVMGEP->isInBounds()); 3894f9765a28Svporpo // Check hasNoUnsignedWrap(). 3895f9765a28Svporpo EXPECT_EQ(GEP->hasNoUnsignedWrap(), LLVMGEP->hasNoUnsignedWrap()); 3896f9765a28Svporpo // Check accumulateConstantOffset(). 389775c7bca7SSergei Barannikov const DataLayout &DL = M->getDataLayout(); 3898f9765a28Svporpo APInt Offset1 = 3899f9765a28Svporpo APInt::getZero(DL.getIndexSizeInBits(GEP->getPointerAddressSpace())); 3900f9765a28Svporpo APInt Offset2 = 3901f9765a28Svporpo APInt::getZero(DL.getIndexSizeInBits(GEP->getPointerAddressSpace())); 3902f9765a28Svporpo EXPECT_EQ(GEP->accumulateConstantOffset(DL, Offset1), 3903f9765a28Svporpo LLVMGEP->accumulateConstantOffset(DL, Offset2)); 3904f9765a28Svporpo EXPECT_EQ(Offset1, Offset2); 3905f9765a28Svporpo } 3906f9765a28Svporpo 3907f9765a28Svporpo auto *BB = &*F.begin(); 3908f9765a28Svporpo auto *GEP0 = cast<sandboxir::GetElementPtrInst>(&*BB->begin()); 3909f9765a28Svporpo auto *Ret = cast<sandboxir::ReturnInst>(Ctx.getValue(LLVMRet)); 3910f9765a28Svporpo SmallVector<sandboxir::Value *> Indices(GEP0->indices()); 3911f9765a28Svporpo 3912f9765a28Svporpo // Check create() WhereIt, WhereBB. 3913f9765a28Svporpo auto *NewGEP0 = 3914f9765a28Svporpo cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create( 3915f9765a28Svporpo GEP0->getType(), GEP0->getPointerOperand(), Indices, 39164f3a0959Svporpo Ret->getIterator(), Ctx, "NewGEP0")); 3917f9765a28Svporpo EXPECT_EQ(NewGEP0->getName(), "NewGEP0"); 3918f9765a28Svporpo EXPECT_EQ(NewGEP0->getType(), GEP0->getType()); 3919f9765a28Svporpo EXPECT_EQ(NewGEP0->getPointerOperand(), GEP0->getPointerOperand()); 3920f9765a28Svporpo EXPECT_EQ(range_size(NewGEP0->indices()), range_size(GEP0->indices())); 3921f9765a28Svporpo for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(), 3922f9765a28Svporpo OldIt = GEP0->idx_begin(); 3923f9765a28Svporpo NewIt != NewItE; ++NewIt) { 3924f9765a28Svporpo sandboxir::Value *NewIdxV = *NewIt; 3925f9765a28Svporpo sandboxir::Value *OldIdxV = *OldIt; 3926f9765a28Svporpo EXPECT_EQ(NewIdxV, OldIdxV); 3927f9765a28Svporpo } 3928f9765a28Svporpo EXPECT_EQ(NewGEP0->getNextNode(), Ret); 3929f9765a28Svporpo 3930f9765a28Svporpo // Check create() InsertBefore. 3931f9765a28Svporpo auto *NewGEP1 = 3932f9765a28Svporpo cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create( 3933f9765a28Svporpo GEP0->getType(), GEP0->getPointerOperand(), Indices, 39344f3a0959Svporpo Ret->getIterator(), Ctx, "NewGEP1")); 3935f9765a28Svporpo EXPECT_EQ(NewGEP1->getName(), "NewGEP1"); 3936f9765a28Svporpo EXPECT_EQ(NewGEP1->getType(), GEP0->getType()); 3937f9765a28Svporpo EXPECT_EQ(NewGEP1->getPointerOperand(), GEP0->getPointerOperand()); 3938f9765a28Svporpo EXPECT_EQ(range_size(NewGEP1->indices()), range_size(GEP0->indices())); 3939f9765a28Svporpo for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(), 3940f9765a28Svporpo OldIt = GEP0->idx_begin(); 3941f9765a28Svporpo NewIt != NewItE; ++NewIt) { 3942f9765a28Svporpo sandboxir::Value *NewIdxV = *NewIt; 3943f9765a28Svporpo sandboxir::Value *OldIdxV = *OldIt; 3944f9765a28Svporpo EXPECT_EQ(NewIdxV, OldIdxV); 3945f9765a28Svporpo } 3946f9765a28Svporpo EXPECT_EQ(NewGEP1->getNextNode(), Ret); 3947f9765a28Svporpo 3948f9765a28Svporpo // Check create() InsertAtEnd. 3949f9765a28Svporpo auto *NewGEP2 = 3950f9765a28Svporpo cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create( 39514f3a0959Svporpo GEP0->getType(), GEP0->getPointerOperand(), Indices, BB, Ctx, 39524f3a0959Svporpo "NewGEP2")); 3953f9765a28Svporpo EXPECT_EQ(NewGEP2->getName(), "NewGEP2"); 3954f9765a28Svporpo EXPECT_EQ(NewGEP2->getType(), GEP0->getType()); 3955f9765a28Svporpo EXPECT_EQ(NewGEP2->getPointerOperand(), GEP0->getPointerOperand()); 3956f9765a28Svporpo EXPECT_EQ(range_size(NewGEP2->indices()), range_size(GEP0->indices())); 3957f9765a28Svporpo for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(), 3958f9765a28Svporpo OldIt = GEP0->idx_begin(); 3959f9765a28Svporpo NewIt != NewItE; ++NewIt) { 3960f9765a28Svporpo sandboxir::Value *NewIdxV = *NewIt; 3961f9765a28Svporpo sandboxir::Value *OldIdxV = *OldIt; 3962f9765a28Svporpo EXPECT_EQ(NewIdxV, OldIdxV); 3963f9765a28Svporpo } 3964f9765a28Svporpo EXPECT_EQ(NewGEP2->getPrevNode(), Ret); 3965f9765a28Svporpo EXPECT_EQ(NewGEP2->getNextNode(), nullptr); 3966f9765a28Svporpo } 3967eb03279dSvporpo 3968c4ae8b15Svporpo TEST_F(SandboxIRTest, Flags) { 3969c4ae8b15Svporpo parseIR(C, R"IR( 3970c4ae8b15Svporpo define void @foo(i32 %arg, float %farg) { 3971c4ae8b15Svporpo %add = add i32 %arg, %arg 3972c4ae8b15Svporpo %fadd = fadd float %farg, %farg 3973c4ae8b15Svporpo %udiv = udiv i32 %arg, %arg 3974c4ae8b15Svporpo ret void 3975c4ae8b15Svporpo } 3976c4ae8b15Svporpo )IR"); 3977c4ae8b15Svporpo Function &LLVMF = *M->getFunction("foo"); 3978c4ae8b15Svporpo BasicBlock *LLVMBB = &*LLVMF.begin(); 3979c4ae8b15Svporpo auto LLVMIt = LLVMBB->begin(); 3980c4ae8b15Svporpo auto *LLVMAdd = &*LLVMIt++; 3981c4ae8b15Svporpo auto *LLVMFAdd = &*LLVMIt++; 3982c4ae8b15Svporpo auto *LLVMUDiv = &*LLVMIt++; 3983c4ae8b15Svporpo 3984c4ae8b15Svporpo sandboxir::Context Ctx(C); 3985c4ae8b15Svporpo auto &F = *Ctx.createFunction(&LLVMF); 3986c4ae8b15Svporpo auto *BB = &*F.begin(); 3987c4ae8b15Svporpo auto It = BB->begin(); 3988c4ae8b15Svporpo auto *Add = &*It++; 3989c4ae8b15Svporpo auto *FAdd = &*It++; 3990c4ae8b15Svporpo auto *UDiv = &*It++; 3991c4ae8b15Svporpo 3992c4ae8b15Svporpo #define CHECK_FLAG(I, LLVMI, GETTER, SETTER) \ 3993c4ae8b15Svporpo { \ 3994c4ae8b15Svporpo EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \ 3995c4ae8b15Svporpo bool NewFlagVal = !I->GETTER(); \ 3996c4ae8b15Svporpo I->SETTER(NewFlagVal); \ 3997c4ae8b15Svporpo EXPECT_EQ(I->GETTER(), NewFlagVal); \ 3998c4ae8b15Svporpo EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \ 3999c4ae8b15Svporpo } 4000c4ae8b15Svporpo 4001c4ae8b15Svporpo CHECK_FLAG(Add, LLVMAdd, hasNoUnsignedWrap, setHasNoUnsignedWrap); 4002c4ae8b15Svporpo CHECK_FLAG(Add, LLVMAdd, hasNoSignedWrap, setHasNoSignedWrap); 4003c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, isFast, setFast); 4004c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReassoc, setHasAllowReassoc); 4005c4ae8b15Svporpo CHECK_FLAG(UDiv, LLVMUDiv, isExact, setIsExact); 4006c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasNoNaNs, setHasNoNaNs); 4007c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasNoInfs, setHasNoInfs); 4008c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasNoSignedZeros, setHasNoSignedZeros); 4009c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReciprocal, setHasAllowReciprocal); 4010c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasAllowContract, setHasAllowContract); 4011c4ae8b15Svporpo CHECK_FLAG(FAdd, LLVMFAdd, hasApproxFunc, setHasApproxFunc); 4012c4ae8b15Svporpo 4013c4ae8b15Svporpo // Check getFastMathFlags(), copyFastMathFlags(). 4014c4ae8b15Svporpo FAdd->setFastMathFlags(FastMathFlags::getFast()); 4015c4ae8b15Svporpo EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags()); 4016c4ae8b15Svporpo FastMathFlags OrigFMF = FAdd->getFastMathFlags(); 4017c4ae8b15Svporpo FastMathFlags NewFMF; 4018c4ae8b15Svporpo NewFMF.setAllowReassoc(true); 4019c4ae8b15Svporpo EXPECT_TRUE(NewFMF != OrigFMF); 4020c4ae8b15Svporpo FAdd->setFastMathFlags(NewFMF); 4021c4ae8b15Svporpo EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF); 4022c4ae8b15Svporpo FAdd->copyFastMathFlags(NewFMF); 4023c4ae8b15Svporpo EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF); 4024c4ae8b15Svporpo EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags()); 4025c4ae8b15Svporpo } 4026c4ae8b15Svporpo 40276e8c9703Svporpo TEST_F(SandboxIRTest, CatchSwitchInst) { 40286e8c9703Svporpo parseIR(C, R"IR( 40296e8c9703Svporpo define void @foo(i32 %cond0, i32 %cond1) { 40306e8c9703Svporpo bb0: 40316e8c9703Svporpo %cs0 = catchswitch within none [label %handler0, label %handler1] unwind to caller 40326e8c9703Svporpo bb1: 40336e8c9703Svporpo %cs1 = catchswitch within %cs0 [label %handler0, label %handler1] unwind label %cleanup 40346e8c9703Svporpo handler0: 40356e8c9703Svporpo ret void 40366e8c9703Svporpo handler1: 40376e8c9703Svporpo ret void 40386e8c9703Svporpo cleanup: 40396e8c9703Svporpo ret void 40406e8c9703Svporpo } 40416e8c9703Svporpo )IR"); 40426e8c9703Svporpo Function &LLVMF = *M->getFunction("foo"); 40436e8c9703Svporpo auto *LLVMBB0 = getBasicBlockByName(LLVMF, "bb0"); 40446e8c9703Svporpo auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1"); 40456e8c9703Svporpo auto *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0"); 40466e8c9703Svporpo auto *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1"); 40476e8c9703Svporpo auto *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup"); 40486e8c9703Svporpo auto *LLVMCS0 = cast<llvm::CatchSwitchInst>(&*LLVMBB0->begin()); 40496e8c9703Svporpo auto *LLVMCS1 = cast<llvm::CatchSwitchInst>(&*LLVMBB1->begin()); 40506e8c9703Svporpo 40516e8c9703Svporpo sandboxir::Context Ctx(C); 40526e8c9703Svporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 40536e8c9703Svporpo auto *BB0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB0)); 40546e8c9703Svporpo auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1)); 40556e8c9703Svporpo auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0)); 40566e8c9703Svporpo auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1)); 40576e8c9703Svporpo auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup)); 40586e8c9703Svporpo auto *CS0 = cast<sandboxir::CatchSwitchInst>(&*BB0->begin()); 40596e8c9703Svporpo auto *CS1 = cast<sandboxir::CatchSwitchInst>(&*BB1->begin()); 40606e8c9703Svporpo 40616e8c9703Svporpo // Check getParentPad(). 40626e8c9703Svporpo EXPECT_EQ(CS0->getParentPad(), Ctx.getValue(LLVMCS0->getParentPad())); 40636e8c9703Svporpo EXPECT_EQ(CS1->getParentPad(), Ctx.getValue(LLVMCS1->getParentPad())); 40646e8c9703Svporpo // Check setParentPad(). 40656e8c9703Svporpo auto *OrigPad = CS0->getParentPad(); 40666e8c9703Svporpo auto *NewPad = CS1; 40676e8c9703Svporpo EXPECT_NE(NewPad, OrigPad); 40686e8c9703Svporpo CS0->setParentPad(NewPad); 40696e8c9703Svporpo EXPECT_EQ(CS0->getParentPad(), NewPad); 40706e8c9703Svporpo CS0->setParentPad(OrigPad); 40716e8c9703Svporpo EXPECT_EQ(CS0->getParentPad(), OrigPad); 40726e8c9703Svporpo // Check hasUnwindDest(). 40736e8c9703Svporpo EXPECT_EQ(CS0->hasUnwindDest(), LLVMCS0->hasUnwindDest()); 40746e8c9703Svporpo EXPECT_EQ(CS1->hasUnwindDest(), LLVMCS1->hasUnwindDest()); 40756e8c9703Svporpo // Check unwindsToCaller(). 40766e8c9703Svporpo EXPECT_EQ(CS0->unwindsToCaller(), LLVMCS0->unwindsToCaller()); 40776e8c9703Svporpo EXPECT_EQ(CS1->unwindsToCaller(), LLVMCS1->unwindsToCaller()); 40786e8c9703Svporpo // Check getUnwindDest(). 40796e8c9703Svporpo EXPECT_EQ(CS0->getUnwindDest(), Ctx.getValue(LLVMCS0->getUnwindDest())); 40806e8c9703Svporpo EXPECT_EQ(CS1->getUnwindDest(), Ctx.getValue(LLVMCS1->getUnwindDest())); 40816e8c9703Svporpo // Check setUnwindDest(). 40826e8c9703Svporpo auto *OrigUnwindDest = CS1->getUnwindDest(); 40836e8c9703Svporpo auto *NewUnwindDest = BB0; 40846e8c9703Svporpo EXPECT_NE(NewUnwindDest, OrigUnwindDest); 40856e8c9703Svporpo CS1->setUnwindDest(NewUnwindDest); 40866e8c9703Svporpo EXPECT_EQ(CS1->getUnwindDest(), NewUnwindDest); 40876e8c9703Svporpo CS1->setUnwindDest(OrigUnwindDest); 40886e8c9703Svporpo EXPECT_EQ(CS1->getUnwindDest(), OrigUnwindDest); 40896e8c9703Svporpo // Check getNumHandlers(). 40906e8c9703Svporpo EXPECT_EQ(CS0->getNumHandlers(), LLVMCS0->getNumHandlers()); 40916e8c9703Svporpo EXPECT_EQ(CS1->getNumHandlers(), LLVMCS1->getNumHandlers()); 40926e8c9703Svporpo // Check handler_begin(), handler_end(). 40936e8c9703Svporpo auto It = CS0->handler_begin(); 40946e8c9703Svporpo EXPECT_EQ(*It++, Handler0); 40956e8c9703Svporpo EXPECT_EQ(*It++, Handler1); 40966e8c9703Svporpo EXPECT_EQ(It, CS0->handler_end()); 40976e8c9703Svporpo // Check handlers(). 40986e8c9703Svporpo SmallVector<sandboxir::BasicBlock *, 2> Handlers; 40996e8c9703Svporpo for (sandboxir::BasicBlock *Handler : CS0->handlers()) 41006e8c9703Svporpo Handlers.push_back(Handler); 41016e8c9703Svporpo EXPECT_EQ(Handlers.size(), 2u); 41026e8c9703Svporpo EXPECT_EQ(Handlers[0], Handler0); 41036e8c9703Svporpo EXPECT_EQ(Handlers[1], Handler1); 41046e8c9703Svporpo // Check addHandler(). 41056e8c9703Svporpo CS0->addHandler(BB0); 41066e8c9703Svporpo EXPECT_EQ(CS0->getNumHandlers(), 3u); 41076e8c9703Svporpo EXPECT_EQ(*std::next(CS0->handler_begin(), 2), BB0); 41086e8c9703Svporpo // Check getNumSuccessors(). 41096e8c9703Svporpo EXPECT_EQ(CS0->getNumSuccessors(), LLVMCS0->getNumSuccessors()); 41106e8c9703Svporpo EXPECT_EQ(CS1->getNumSuccessors(), LLVMCS1->getNumSuccessors()); 41116e8c9703Svporpo // Check getSuccessor(). 41126e8c9703Svporpo for (auto SuccIdx : seq<unsigned>(0, CS0->getNumSuccessors())) 41136e8c9703Svporpo EXPECT_EQ(CS0->getSuccessor(SuccIdx), 41146e8c9703Svporpo Ctx.getValue(LLVMCS0->getSuccessor(SuccIdx))); 41156e8c9703Svporpo // Check setSuccessor(). 41166e8c9703Svporpo auto *OrigSuccessor = CS0->getSuccessor(0); 41176e8c9703Svporpo auto *NewSuccessor = BB0; 41186e8c9703Svporpo EXPECT_NE(NewSuccessor, OrigSuccessor); 41196e8c9703Svporpo CS0->setSuccessor(0, NewSuccessor); 41206e8c9703Svporpo EXPECT_EQ(CS0->getSuccessor(0), NewSuccessor); 41216e8c9703Svporpo CS0->setSuccessor(0, OrigSuccessor); 41226e8c9703Svporpo EXPECT_EQ(CS0->getSuccessor(0), OrigSuccessor); 41236e8c9703Svporpo // Check create(). 41246e8c9703Svporpo CS1->eraseFromParent(); 41256e8c9703Svporpo auto *NewCSI = sandboxir::CatchSwitchInst::create( 41264f3a0959Svporpo CS0, Cleanup, 2, BB1->begin(), Ctx, "NewCSI"); 41276e8c9703Svporpo EXPECT_TRUE(isa<sandboxir::CatchSwitchInst>(NewCSI)); 41286e8c9703Svporpo EXPECT_EQ(NewCSI->getParentPad(), CS0); 41296e8c9703Svporpo } 41306e8c9703Svporpo 4131c664d7dfSvporpo TEST_F(SandboxIRTest, ResumeInst) { 4132c664d7dfSvporpo parseIR(C, R"IR( 4133c664d7dfSvporpo define void @foo() { 4134c664d7dfSvporpo entry: 4135c664d7dfSvporpo invoke void @foo() 4136c664d7dfSvporpo to label %bb unwind label %unwind 4137c664d7dfSvporpo bb: 4138c664d7dfSvporpo ret void 4139c664d7dfSvporpo unwind: 4140c664d7dfSvporpo %lpad = landingpad { ptr, i32 } 4141c664d7dfSvporpo cleanup 4142c664d7dfSvporpo resume { ptr, i32 } %lpad 4143c664d7dfSvporpo } 4144c664d7dfSvporpo )IR"); 4145c664d7dfSvporpo Function &LLVMF = *M->getFunction("foo"); 4146c664d7dfSvporpo auto *LLVMUnwindBB = getBasicBlockByName(LLVMF, "unwind"); 4147c664d7dfSvporpo auto LLVMIt = LLVMUnwindBB->begin(); 4148c664d7dfSvporpo [[maybe_unused]] auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMIt++); 4149c664d7dfSvporpo auto *LLVMResume = cast<llvm::ResumeInst>(&*LLVMIt++); 4150c664d7dfSvporpo 4151c664d7dfSvporpo sandboxir::Context Ctx(C); 4152c664d7dfSvporpo [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 4153c664d7dfSvporpo auto *UnwindBB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwindBB)); 4154c664d7dfSvporpo auto It = UnwindBB->begin(); 4155c664d7dfSvporpo auto *LPad = cast<sandboxir::LandingPadInst>(&*It++); 4156c664d7dfSvporpo auto *Resume = cast<sandboxir::ResumeInst>(&*It++); 4157c664d7dfSvporpo // Check getValue(). 4158c664d7dfSvporpo EXPECT_EQ(Resume->getValue(), LPad); 4159c664d7dfSvporpo EXPECT_EQ(Resume->getValue(), Ctx.getValue(LLVMResume->getValue())); 4160c664d7dfSvporpo // Check getNumSuccessors(). 4161c664d7dfSvporpo EXPECT_EQ(Resume->getNumSuccessors(), LLVMResume->getNumSuccessors()); 4162c664d7dfSvporpo // Check create(). 41634f3a0959Svporpo auto *NewResume = sandboxir::ResumeInst::create(LPad, UnwindBB->end(), Ctx); 4164c664d7dfSvporpo EXPECT_EQ(NewResume->getValue(), LPad); 4165c664d7dfSvporpo EXPECT_EQ(NewResume->getParent(), UnwindBB); 4166c664d7dfSvporpo EXPECT_EQ(NewResume->getNextNode(), nullptr); 4167c664d7dfSvporpo } 4168c664d7dfSvporpo 4169516c1a0eSvporpo TEST_F(SandboxIRTest, SwitchInst) { 4170516c1a0eSvporpo parseIR(C, R"IR( 4171516c1a0eSvporpo define void @foo(i32 %cond0, i32 %cond1) { 4172516c1a0eSvporpo entry: 4173516c1a0eSvporpo switch i32 %cond0, label %default [ i32 0, label %bb0 4174516c1a0eSvporpo i32 1, label %bb1 ] 4175516c1a0eSvporpo bb0: 4176516c1a0eSvporpo ret void 4177516c1a0eSvporpo bb1: 4178516c1a0eSvporpo ret void 4179516c1a0eSvporpo default: 4180516c1a0eSvporpo ret void 4181516c1a0eSvporpo } 4182516c1a0eSvporpo )IR"); 4183516c1a0eSvporpo Function &LLVMF = *M->getFunction("foo"); 4184516c1a0eSvporpo auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry"); 4185516c1a0eSvporpo auto *LLVMSwitch = cast<llvm::SwitchInst>(&*LLVMEntry->begin()); 4186516c1a0eSvporpo 4187516c1a0eSvporpo sandboxir::Context Ctx(C); 4188516c1a0eSvporpo auto &F = *Ctx.createFunction(&LLVMF); 4189516c1a0eSvporpo auto *Cond1 = F.getArg(1); 4190516c1a0eSvporpo auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry)); 4191516c1a0eSvporpo auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin()); 4192516c1a0eSvporpo auto *BB0 = cast<sandboxir::BasicBlock>( 4193516c1a0eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb0"))); 4194516c1a0eSvporpo auto *BB1 = cast<sandboxir::BasicBlock>( 4195516c1a0eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "bb1"))); 4196516c1a0eSvporpo auto *Default = cast<sandboxir::BasicBlock>( 4197516c1a0eSvporpo Ctx.getValue(getBasicBlockByName(LLVMF, "default"))); 4198516c1a0eSvporpo 4199516c1a0eSvporpo // Check getCondition(). 4200516c1a0eSvporpo EXPECT_EQ(Switch->getCondition(), Ctx.getValue(LLVMSwitch->getCondition())); 4201516c1a0eSvporpo // Check setCondition(). 4202516c1a0eSvporpo auto *OrigCond = Switch->getCondition(); 4203516c1a0eSvporpo auto *NewCond = Cond1; 4204516c1a0eSvporpo EXPECT_NE(NewCond, OrigCond); 4205516c1a0eSvporpo Switch->setCondition(NewCond); 4206516c1a0eSvporpo EXPECT_EQ(Switch->getCondition(), NewCond); 4207516c1a0eSvporpo Switch->setCondition(OrigCond); 4208516c1a0eSvporpo EXPECT_EQ(Switch->getCondition(), OrigCond); 4209516c1a0eSvporpo // Check getDefaultDest(). 4210516c1a0eSvporpo EXPECT_EQ(Switch->getDefaultDest(), 4211516c1a0eSvporpo Ctx.getValue(LLVMSwitch->getDefaultDest())); 4212516c1a0eSvporpo EXPECT_EQ(Switch->getDefaultDest(), Default); 4213516c1a0eSvporpo // Check defaultDestUndefined(). 4214516c1a0eSvporpo EXPECT_EQ(Switch->defaultDestUndefined(), LLVMSwitch->defaultDestUndefined()); 4215516c1a0eSvporpo // Check setDefaultDest(). 4216516c1a0eSvporpo auto *OrigDefaultDest = Switch->getDefaultDest(); 4217516c1a0eSvporpo auto *NewDefaultDest = Entry; 4218516c1a0eSvporpo EXPECT_NE(NewDefaultDest, OrigDefaultDest); 4219516c1a0eSvporpo Switch->setDefaultDest(NewDefaultDest); 4220516c1a0eSvporpo EXPECT_EQ(Switch->getDefaultDest(), NewDefaultDest); 4221516c1a0eSvporpo Switch->setDefaultDest(OrigDefaultDest); 4222516c1a0eSvporpo EXPECT_EQ(Switch->getDefaultDest(), OrigDefaultDest); 4223516c1a0eSvporpo // Check getNumCases(). 4224516c1a0eSvporpo EXPECT_EQ(Switch->getNumCases(), LLVMSwitch->getNumCases()); 4225516c1a0eSvporpo // Check getNumSuccessors(). 4226516c1a0eSvporpo EXPECT_EQ(Switch->getNumSuccessors(), LLVMSwitch->getNumSuccessors()); 4227516c1a0eSvporpo // Check getSuccessor(). 4228516c1a0eSvporpo for (auto SuccIdx : seq<unsigned>(0, Switch->getNumSuccessors())) 4229516c1a0eSvporpo EXPECT_EQ(Switch->getSuccessor(SuccIdx), 4230516c1a0eSvporpo Ctx.getValue(LLVMSwitch->getSuccessor(SuccIdx))); 4231516c1a0eSvporpo // Check setSuccessor(). 4232516c1a0eSvporpo auto *OrigSucc = Switch->getSuccessor(0); 4233516c1a0eSvporpo auto *NewSucc = Entry; 4234516c1a0eSvporpo EXPECT_NE(NewSucc, OrigSucc); 4235516c1a0eSvporpo Switch->setSuccessor(0, NewSucc); 4236516c1a0eSvporpo EXPECT_EQ(Switch->getSuccessor(0), NewSucc); 4237516c1a0eSvporpo Switch->setSuccessor(0, OrigSucc); 4238516c1a0eSvporpo EXPECT_EQ(Switch->getSuccessor(0), OrigSucc); 4239516c1a0eSvporpo // Check case_begin(), case_end(), CaseIt. 4240034f2b38Svporpo auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0); 4241034f2b38Svporpo auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1); 4242516c1a0eSvporpo auto CaseIt = Switch->case_begin(); 4243516c1a0eSvporpo { 4244516c1a0eSvporpo sandboxir::SwitchInst::CaseHandle Case = *CaseIt++; 4245516c1a0eSvporpo EXPECT_EQ(Case.getCaseValue(), Zero); 4246516c1a0eSvporpo EXPECT_EQ(Case.getCaseSuccessor(), BB0); 4247516c1a0eSvporpo EXPECT_EQ(Case.getCaseIndex(), 0u); 4248516c1a0eSvporpo EXPECT_EQ(Case.getSuccessorIndex(), 1u); 4249516c1a0eSvporpo } 4250516c1a0eSvporpo { 4251516c1a0eSvporpo sandboxir::SwitchInst::CaseHandle Case = *CaseIt++; 4252516c1a0eSvporpo EXPECT_EQ(Case.getCaseValue(), One); 4253516c1a0eSvporpo EXPECT_EQ(Case.getCaseSuccessor(), BB1); 4254516c1a0eSvporpo EXPECT_EQ(Case.getCaseIndex(), 1u); 4255516c1a0eSvporpo EXPECT_EQ(Case.getSuccessorIndex(), 2u); 4256516c1a0eSvporpo } 4257516c1a0eSvporpo EXPECT_EQ(CaseIt, Switch->case_end()); 4258516c1a0eSvporpo // Check cases(). 4259516c1a0eSvporpo unsigned CntCase = 0; 4260516c1a0eSvporpo for (auto &Case : Switch->cases()) { 4261516c1a0eSvporpo EXPECT_EQ(Case.getCaseIndex(), CntCase); 4262516c1a0eSvporpo ++CntCase; 4263516c1a0eSvporpo } 4264516c1a0eSvporpo EXPECT_EQ(CntCase, 2u); 4265516c1a0eSvporpo // Check case_default(). 4266516c1a0eSvporpo auto CaseDefault = *Switch->case_default(); 4267516c1a0eSvporpo EXPECT_EQ(CaseDefault.getCaseSuccessor(), Default); 4268516c1a0eSvporpo EXPECT_EQ(CaseDefault.getCaseIndex(), 4269516c1a0eSvporpo sandboxir::SwitchInst::DefaultPseudoIndex); 4270516c1a0eSvporpo // Check findCaseValue(). 4271516c1a0eSvporpo EXPECT_EQ(Switch->findCaseValue(Zero)->getCaseIndex(), 0u); 4272516c1a0eSvporpo EXPECT_EQ(Switch->findCaseValue(One)->getCaseIndex(), 1u); 4273516c1a0eSvporpo // Check findCaseDest(). 4274516c1a0eSvporpo EXPECT_EQ(Switch->findCaseDest(BB0), Zero); 4275516c1a0eSvporpo EXPECT_EQ(Switch->findCaseDest(BB1), One); 4276516c1a0eSvporpo EXPECT_EQ(Switch->findCaseDest(Entry), nullptr); 4277516c1a0eSvporpo // Check addCase(). 4278034f2b38Svporpo auto *Two = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 2); 4279516c1a0eSvporpo Switch->addCase(Two, Entry); 4280516c1a0eSvporpo auto CaseTwoIt = Switch->findCaseValue(Two); 4281516c1a0eSvporpo auto CaseTwo = *CaseTwoIt; 4282516c1a0eSvporpo EXPECT_EQ(CaseTwo.getCaseValue(), Two); 4283516c1a0eSvporpo EXPECT_EQ(CaseTwo.getCaseSuccessor(), Entry); 4284516c1a0eSvporpo EXPECT_EQ(Switch->getNumCases(), 3u); 4285516c1a0eSvporpo // Check removeCase(). 4286516c1a0eSvporpo auto RemovedIt = Switch->removeCase(CaseTwoIt); 4287516c1a0eSvporpo EXPECT_EQ(RemovedIt, Switch->case_end()); 4288516c1a0eSvporpo EXPECT_EQ(Switch->getNumCases(), 2u); 4289516c1a0eSvporpo // Check create(). 4290516c1a0eSvporpo auto NewSwitch = sandboxir::SwitchInst::create( 42914f3a0959Svporpo Cond1, Default, 1, Default->begin(), Ctx, "NewSwitch"); 4292516c1a0eSvporpo EXPECT_TRUE(isa<sandboxir::SwitchInst>(NewSwitch)); 4293516c1a0eSvporpo EXPECT_EQ(NewSwitch->getCondition(), Cond1); 4294516c1a0eSvporpo EXPECT_EQ(NewSwitch->getDefaultDest(), Default); 4295516c1a0eSvporpo } 4296516c1a0eSvporpo 4297ec29660cSvporpo TEST_F(SandboxIRTest, UnaryOperator) { 4298ec29660cSvporpo parseIR(C, R"IR( 4299ec29660cSvporpo define void @foo(float %arg0) { 4300ec29660cSvporpo %fneg = fneg float %arg0 4301ec29660cSvporpo %copyfrom = fadd reassoc float %arg0, 42.0 4302ec29660cSvporpo ret void 4303ec29660cSvporpo } 4304ec29660cSvporpo )IR"); 4305ec29660cSvporpo Function &LLVMF = *M->getFunction("foo"); 4306ec29660cSvporpo sandboxir::Context Ctx(C); 4307ec29660cSvporpo 4308ec29660cSvporpo auto &F = *Ctx.createFunction(&LLVMF); 4309ec29660cSvporpo auto *Arg0 = F.getArg(0); 4310ec29660cSvporpo auto *BB = &*F.begin(); 4311ec29660cSvporpo auto It = BB->begin(); 4312ec29660cSvporpo auto *I = cast<sandboxir::UnaryOperator>(&*It++); 4313ec29660cSvporpo auto *CopyFrom = cast<sandboxir::BinaryOperator>(&*It++); 4314ec29660cSvporpo auto *Ret = &*It++; 4315ec29660cSvporpo EXPECT_EQ(I->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4316ec29660cSvporpo EXPECT_EQ(I->getOperand(0), Arg0); 4317ec29660cSvporpo 4318ec29660cSvporpo { 4319ec29660cSvporpo // Check create() WhereIt, WhereBB. 4320ec29660cSvporpo auto *NewI = 4321ec29660cSvporpo cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create( 43224f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, Arg0, Ret->getIterator(), Ctx, 4323ec29660cSvporpo "New1")); 4324ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4325ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4326ec29660cSvporpo #ifndef NDEBUG 4327ec29660cSvporpo EXPECT_EQ(NewI->getName(), "New1"); 4328ec29660cSvporpo #endif // NDEBUG 4329ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4330ec29660cSvporpo } 4331ec29660cSvporpo { 4332ec29660cSvporpo // Check create() InsertBefore. 4333ec29660cSvporpo auto *NewI = 4334ec29660cSvporpo cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create( 43354f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, Arg0, Ret->getIterator(), Ctx, 43364f3a0959Svporpo "New2")); 4337ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4338ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4339ec29660cSvporpo #ifndef NDEBUG 4340ec29660cSvporpo EXPECT_EQ(NewI->getName(), "New2"); 4341ec29660cSvporpo #endif // NDEBUG 4342ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4343ec29660cSvporpo } 4344ec29660cSvporpo { 4345ec29660cSvporpo // Check create() InsertAtEnd. 4346ec29660cSvporpo auto *NewI = 4347ec29660cSvporpo cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create( 43484f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, Arg0, BB, Ctx, "New3")); 4349ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4350ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4351ec29660cSvporpo #ifndef NDEBUG 4352ec29660cSvporpo EXPECT_EQ(NewI->getName(), "New3"); 4353ec29660cSvporpo #endif // NDEBUG 4354ec29660cSvporpo EXPECT_EQ(NewI->getParent(), BB); 4355ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 4356ec29660cSvporpo } 4357ec29660cSvporpo { 4358ec29660cSvporpo // Check create() when it gets folded. 4359ec29660cSvporpo auto *FortyTwo = CopyFrom->getOperand(1); 4360ec29660cSvporpo auto *NewV = sandboxir::UnaryOperator::create( 43614f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, FortyTwo, Ret->getIterator(), Ctx, 4362ec29660cSvporpo "Folded"); 4363ec29660cSvporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewV)); 4364ec29660cSvporpo } 4365ec29660cSvporpo 4366ec29660cSvporpo { 4367ec29660cSvporpo // Check createWithCopiedFlags() WhereIt, WhereBB. 4368ec29660cSvporpo auto *NewI = cast<sandboxir::UnaryOperator>( 4369ec29660cSvporpo sandboxir::UnaryOperator::createWithCopiedFlags( 4370ec29660cSvporpo sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom, 43714f3a0959Svporpo Ret->getIterator(), Ctx, "NewCopyFrom1")); 4372ec29660cSvporpo EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc()); 4373ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4374ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4375ec29660cSvporpo #ifndef NDEBUG 4376ec29660cSvporpo EXPECT_EQ(NewI->getName(), "NewCopyFrom1"); 4377ec29660cSvporpo #endif // NDEBUG 4378ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4379ec29660cSvporpo } 4380ec29660cSvporpo { 4381ec29660cSvporpo // Check createWithCopiedFlags() InsertBefore, 4382ec29660cSvporpo auto *NewI = cast<sandboxir::UnaryOperator>( 4383ec29660cSvporpo sandboxir::UnaryOperator::createWithCopiedFlags( 4384ec29660cSvporpo sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom, 43854f3a0959Svporpo Ret->getIterator(), Ctx, "NewCopyFrom2")); 4386ec29660cSvporpo EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc()); 4387ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4388ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4389ec29660cSvporpo #ifndef NDEBUG 4390ec29660cSvporpo EXPECT_EQ(NewI->getName(), "NewCopyFrom2"); 4391ec29660cSvporpo #endif // NDEBUG 4392ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4393ec29660cSvporpo } 4394ec29660cSvporpo { 4395ec29660cSvporpo // Check createWithCopiedFlags() InsertAtEnd, 4396ec29660cSvporpo auto *NewI = cast<sandboxir::UnaryOperator>( 4397ec29660cSvporpo sandboxir::UnaryOperator::createWithCopiedFlags( 43984f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom, BB, Ctx, 43994f3a0959Svporpo "NewCopyFrom3")); 4400ec29660cSvporpo EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc()); 4401ec29660cSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg); 4402ec29660cSvporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 4403ec29660cSvporpo #ifndef NDEBUG 4404ec29660cSvporpo EXPECT_EQ(NewI->getName(), "NewCopyFrom3"); 4405ec29660cSvporpo #endif // NDEBUG 4406ec29660cSvporpo EXPECT_EQ(NewI->getParent(), BB); 4407ec29660cSvporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 4408ec29660cSvporpo } 4409ec29660cSvporpo { 4410ec29660cSvporpo // Check createWithCopiedFlags() when it gets folded. 4411ec29660cSvporpo auto *FortyTwo = CopyFrom->getOperand(1); 4412ec29660cSvporpo auto *NewV = sandboxir::UnaryOperator::createWithCopiedFlags( 44134f3a0959Svporpo sandboxir::Instruction::Opcode::FNeg, FortyTwo, CopyFrom, BB, Ctx, 44144f3a0959Svporpo "Folded"); 4415ec29660cSvporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewV)); 4416ec29660cSvporpo } 4417ec29660cSvporpo } 4418ec29660cSvporpo 44196ec169d3Svporpo TEST_F(SandboxIRTest, BinaryOperator) { 44206ec169d3Svporpo parseIR(C, R"IR( 44216ec169d3Svporpo define void @foo(i8 %arg0, i8 %arg1, float %farg0, float %farg1) { 44226ec169d3Svporpo %add = add i8 %arg0, %arg1 44236ec169d3Svporpo %fadd = fadd float %farg0, %farg1 44246ec169d3Svporpo %sub = sub i8 %arg0, %arg1 44256ec169d3Svporpo %fsub = fsub float %farg0, %farg1 44266ec169d3Svporpo %mul = mul i8 %arg0, %arg1 44276ec169d3Svporpo %fmul = fmul float %farg0, %farg1 44286ec169d3Svporpo %udiv = udiv i8 %arg0, %arg1 44296ec169d3Svporpo %sdiv = sdiv i8 %arg0, %arg1 44306ec169d3Svporpo %fdiv = fdiv float %farg0, %farg1 44316ec169d3Svporpo %urem = urem i8 %arg0, %arg1 44326ec169d3Svporpo %srem = srem i8 %arg0, %arg1 44336ec169d3Svporpo %frem = frem float %farg0, %farg1 44346ec169d3Svporpo %shl = shl i8 %arg0, %arg1 44356ec169d3Svporpo %lshr = lshr i8 %arg0, %arg1 44366ec169d3Svporpo %ashr = ashr i8 %arg0, %arg1 44376ec169d3Svporpo %and = and i8 %arg0, %arg1 44386ec169d3Svporpo %or = or i8 %arg0, %arg1 44396ec169d3Svporpo %xor = xor i8 %arg0, %arg1 44406ec169d3Svporpo 44416ec169d3Svporpo %copyfrom = add nsw i8 %arg0, %arg1 44426ec169d3Svporpo ret void 44436ec169d3Svporpo } 44446ec169d3Svporpo )IR"); 44456ec169d3Svporpo Function &LLVMF = *M->getFunction("foo"); 44466ec169d3Svporpo sandboxir::Context Ctx(C); 44476ec169d3Svporpo 44486ec169d3Svporpo auto &F = *Ctx.createFunction(&LLVMF); 44496ec169d3Svporpo auto *Arg0 = F.getArg(0); 44506ec169d3Svporpo auto *Arg1 = F.getArg(1); 44516ec169d3Svporpo auto *FArg0 = F.getArg(2); 44526ec169d3Svporpo auto *FArg1 = F.getArg(3); 44536ec169d3Svporpo auto *BB = &*F.begin(); 44546ec169d3Svporpo auto It = BB->begin(); 44556ec169d3Svporpo 44566ec169d3Svporpo #define CHECK_IBINOP(OPCODE) \ 44576ec169d3Svporpo { \ 44586ec169d3Svporpo auto *I = cast<sandboxir::BinaryOperator>(&*It++); \ 44596ec169d3Svporpo EXPECT_EQ(I->getOpcode(), OPCODE); \ 44606ec169d3Svporpo EXPECT_EQ(I->getOperand(0), Arg0); \ 44616ec169d3Svporpo EXPECT_EQ(I->getOperand(1), Arg1); \ 44626ec169d3Svporpo } 44636ec169d3Svporpo #define CHECK_FBINOP(OPCODE) \ 44646ec169d3Svporpo { \ 44656ec169d3Svporpo auto *I = cast<sandboxir::BinaryOperator>(&*It++); \ 44666ec169d3Svporpo EXPECT_EQ(I->getOpcode(), OPCODE); \ 44676ec169d3Svporpo EXPECT_EQ(I->getOperand(0), FArg0); \ 44686ec169d3Svporpo EXPECT_EQ(I->getOperand(1), FArg1); \ 44696ec169d3Svporpo } 44706ec169d3Svporpo 44716ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Add); 44726ec169d3Svporpo CHECK_FBINOP(sandboxir::Instruction::Opcode::FAdd); 44736ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Sub); 44746ec169d3Svporpo CHECK_FBINOP(sandboxir::Instruction::Opcode::FSub); 44756ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Mul); 44766ec169d3Svporpo CHECK_FBINOP(sandboxir::Instruction::Opcode::FMul); 44776ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::UDiv); 44786ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::SDiv); 44796ec169d3Svporpo CHECK_FBINOP(sandboxir::Instruction::Opcode::FDiv); 44806ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::URem); 44816ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::SRem); 44826ec169d3Svporpo CHECK_FBINOP(sandboxir::Instruction::Opcode::FRem); 44836ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Shl); 44846ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::LShr); 44856ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::AShr); 44866ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::And); 44876ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Or); 44886ec169d3Svporpo CHECK_IBINOP(sandboxir::Instruction::Opcode::Xor); 44896ec169d3Svporpo 44906ec169d3Svporpo auto *CopyFrom = cast<sandboxir::BinaryOperator>(&*It++); 44916ec169d3Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 44926ec169d3Svporpo 44936ec169d3Svporpo { 44946ec169d3Svporpo // Check create() WhereIt, WhereBB. 44956ec169d3Svporpo auto *NewI = 44966ec169d3Svporpo cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create( 44974f3a0959Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, Ret->getIterator(), 44984f3a0959Svporpo Ctx, "New1")); 44996ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45006ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45016ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45026ec169d3Svporpo #ifndef NDEBUG 45036ec169d3Svporpo EXPECT_EQ(NewI->getName(), "New1"); 45046ec169d3Svporpo #endif // NDEBUG 45056ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 45066ec169d3Svporpo } 45076ec169d3Svporpo { 45086ec169d3Svporpo // Check create() InsertBefore. 45096ec169d3Svporpo auto *NewI = 45106ec169d3Svporpo cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create( 45114f3a0959Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, Ret->getIterator(), 45124f3a0959Svporpo Ctx, "New2")); 45136ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45146ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45156ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45166ec169d3Svporpo #ifndef NDEBUG 45176ec169d3Svporpo EXPECT_EQ(NewI->getName(), "New2"); 45186ec169d3Svporpo #endif // NDEBUG 45196ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 45206ec169d3Svporpo } 45216ec169d3Svporpo { 45226ec169d3Svporpo // Check create() InsertAtEnd. 45236ec169d3Svporpo auto *NewI = 45246ec169d3Svporpo cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create( 45256ec169d3Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, 45266ec169d3Svporpo /*InsertAtEnd=*/BB, Ctx, "New3")); 45276ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45286ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45296ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45306ec169d3Svporpo #ifndef NDEBUG 45316ec169d3Svporpo EXPECT_EQ(NewI->getName(), "New3"); 45326ec169d3Svporpo #endif // NDEBUG 45336ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 45346ec169d3Svporpo EXPECT_EQ(NewI->getParent(), BB); 45356ec169d3Svporpo } 45366ec169d3Svporpo { 45376ec169d3Svporpo // Check create() when it gets folded. 4538034f2b38Svporpo auto *FortyTwo = 4539034f2b38Svporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42); 45406ec169d3Svporpo auto *NewV = sandboxir::BinaryOperator::create( 45416ec169d3Svporpo sandboxir::Instruction::Opcode::Add, FortyTwo, FortyTwo, 45424f3a0959Svporpo Ret->getIterator(), Ctx, "Folded"); 45436ec169d3Svporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewV)); 45446ec169d3Svporpo } 45456ec169d3Svporpo 45466ec169d3Svporpo { 45476ec169d3Svporpo // Check createWithCopiedFlags() WhereIt, WhereBB. 45486ec169d3Svporpo auto *NewI = cast<sandboxir::BinaryOperator>( 45496ec169d3Svporpo sandboxir::BinaryOperator::createWithCopiedFlags( 45506ec169d3Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom, 45514f3a0959Svporpo Ret->getIterator(), Ctx, "NewNSW1")); 45526ec169d3Svporpo EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap()); 45536ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45546ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45556ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45566ec169d3Svporpo #ifndef NDEBUG 45576ec169d3Svporpo EXPECT_EQ(NewI->getName(), "NewNSW1"); 45586ec169d3Svporpo #endif // NDEBUG 45596ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 45606ec169d3Svporpo } 45616ec169d3Svporpo { 45626ec169d3Svporpo // Check createWithCopiedFlags() InsertBefore. 45636ec169d3Svporpo auto *NewI = cast<sandboxir::BinaryOperator>( 45646ec169d3Svporpo sandboxir::BinaryOperator::createWithCopiedFlags( 45656ec169d3Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom, 45664f3a0959Svporpo Ret->getIterator(), Ctx, "NewNSW2")); 45676ec169d3Svporpo EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap()); 45686ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45696ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45706ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45716ec169d3Svporpo #ifndef NDEBUG 45726ec169d3Svporpo EXPECT_EQ(NewI->getName(), "NewNSW2"); 45736ec169d3Svporpo #endif // NDEBUG 45746ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 45756ec169d3Svporpo } 45766ec169d3Svporpo { 45776ec169d3Svporpo // Check createWithCopiedFlags() InsertAtEnd. 45786ec169d3Svporpo auto *NewI = cast<sandboxir::BinaryOperator>( 45796ec169d3Svporpo sandboxir::BinaryOperator::createWithCopiedFlags( 45804f3a0959Svporpo sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom, BB, Ctx, 45814f3a0959Svporpo "NewNSW3")); 45826ec169d3Svporpo EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap()); 45836ec169d3Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add); 45846ec169d3Svporpo EXPECT_EQ(NewI->getOperand(0), Arg0); 45856ec169d3Svporpo EXPECT_EQ(NewI->getOperand(1), Arg1); 45866ec169d3Svporpo #ifndef NDEBUG 45876ec169d3Svporpo EXPECT_EQ(NewI->getName(), "NewNSW3"); 45886ec169d3Svporpo #endif // NDEBUG 45896ec169d3Svporpo EXPECT_EQ(NewI->getParent(), BB); 45906ec169d3Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 45916ec169d3Svporpo } 45926ec169d3Svporpo { 45936ec169d3Svporpo // Check createWithCopiedFlags() when it gets folded. 4594034f2b38Svporpo auto *FortyTwo = 4595034f2b38Svporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42); 45966ec169d3Svporpo auto *NewV = sandboxir::BinaryOperator::createWithCopiedFlags( 45976ec169d3Svporpo sandboxir::Instruction::Opcode::Add, FortyTwo, FortyTwo, CopyFrom, 45984f3a0959Svporpo Ret->getIterator(), Ctx, "Folded"); 45996ec169d3Svporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewV)); 46006ec169d3Svporpo } 46016ec169d3Svporpo } 46026ec169d3Svporpo 46033b0a1ecbSvporpo TEST_F(SandboxIRTest, PossiblyDisjointInst) { 46043b0a1ecbSvporpo parseIR(C, R"IR( 46053b0a1ecbSvporpo define void @foo(i8 %arg0, i8 %arg1) { 46063b0a1ecbSvporpo %or = or i8 %arg0, %arg1 46073b0a1ecbSvporpo ret void 46083b0a1ecbSvporpo } 46093b0a1ecbSvporpo )IR"); 46103b0a1ecbSvporpo Function &LLVMF = *M->getFunction("foo"); 46113b0a1ecbSvporpo sandboxir::Context Ctx(C); 46123b0a1ecbSvporpo 46133b0a1ecbSvporpo auto &F = *Ctx.createFunction(&LLVMF); 46143b0a1ecbSvporpo auto *BB = &*F.begin(); 46153b0a1ecbSvporpo auto It = BB->begin(); 46163b0a1ecbSvporpo auto *PDI = cast<sandboxir::PossiblyDisjointInst>(&*It++); 46173b0a1ecbSvporpo 46183b0a1ecbSvporpo // Check setIsDisjoint(), isDisjoint(). 46193b0a1ecbSvporpo auto OrigIsDisjoint = PDI->isDisjoint(); 46203b0a1ecbSvporpo auto NewIsDisjoint = true; 46213b0a1ecbSvporpo EXPECT_NE(NewIsDisjoint, OrigIsDisjoint); 46223b0a1ecbSvporpo PDI->setIsDisjoint(NewIsDisjoint); 46233b0a1ecbSvporpo EXPECT_EQ(PDI->isDisjoint(), NewIsDisjoint); 46243b0a1ecbSvporpo PDI->setIsDisjoint(OrigIsDisjoint); 46253b0a1ecbSvporpo EXPECT_EQ(PDI->isDisjoint(), OrigIsDisjoint); 46263b0a1ecbSvporpo } 46273b0a1ecbSvporpo 4628ab5102d6Svporpo TEST_F(SandboxIRTest, AtomicRMWInst) { 4629ab5102d6Svporpo parseIR(C, R"IR( 4630ab5102d6Svporpo define void @foo(ptr %ptr, i8 %arg) { 4631ab5102d6Svporpo %atomicrmw = atomicrmw add ptr %ptr, i8 %arg acquire, align 128 4632ab5102d6Svporpo ret void 4633ab5102d6Svporpo } 4634ab5102d6Svporpo )IR"); 4635ab5102d6Svporpo llvm::Function &LLVMF = *M->getFunction("foo"); 4636ab5102d6Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF.begin(); 4637ab5102d6Svporpo auto LLVMIt = LLVMBB->begin(); 4638ab5102d6Svporpo auto *LLVMRMW = cast<llvm::AtomicRMWInst>(&*LLVMIt++); 4639ab5102d6Svporpo 4640ab5102d6Svporpo sandboxir::Context Ctx(C); 4641ab5102d6Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 4642ab5102d6Svporpo auto *Ptr = F->getArg(0); 4643ab5102d6Svporpo auto *Arg = F->getArg(1); 4644ab5102d6Svporpo auto *BB = &*F->begin(); 4645ab5102d6Svporpo auto It = BB->begin(); 4646ab5102d6Svporpo auto *RMW = cast<sandboxir::AtomicRMWInst>(&*It++); 4647ab5102d6Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 4648ab5102d6Svporpo 4649ab5102d6Svporpo // Check getOperationName(). 4650ab5102d6Svporpo EXPECT_EQ( 4651ab5102d6Svporpo sandboxir::AtomicRMWInst::getOperationName( 4652ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::Add), 4653ab5102d6Svporpo llvm::AtomicRMWInst::getOperationName(llvm::AtomicRMWInst::BinOp::Add)); 4654ab5102d6Svporpo // Check isFPOperation(). 4655ab5102d6Svporpo EXPECT_EQ( 4656ab5102d6Svporpo sandboxir::AtomicRMWInst::isFPOperation( 4657ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::Add), 4658ab5102d6Svporpo llvm::AtomicRMWInst::isFPOperation(llvm::AtomicRMWInst::BinOp::Add)); 4659ab5102d6Svporpo EXPECT_FALSE(sandboxir::AtomicRMWInst::isFPOperation( 4660ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::Add)); 4661ab5102d6Svporpo EXPECT_TRUE(sandboxir::AtomicRMWInst::isFPOperation( 4662ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::FAdd)); 4663ab5102d6Svporpo // Check setOperation(), getOperation(). 4664ab5102d6Svporpo EXPECT_EQ(RMW->getOperation(), LLVMRMW->getOperation()); 4665ab5102d6Svporpo RMW->setOperation(sandboxir::AtomicRMWInst::BinOp::Sub); 4666ab5102d6Svporpo EXPECT_EQ(RMW->getOperation(), sandboxir::AtomicRMWInst::BinOp::Sub); 4667ab5102d6Svporpo RMW->setOperation(sandboxir::AtomicRMWInst::BinOp::Add); 4668ab5102d6Svporpo // Check getAlign(). 4669ab5102d6Svporpo EXPECT_EQ(RMW->getAlign(), LLVMRMW->getAlign()); 4670ab5102d6Svporpo auto OrigAlign = RMW->getAlign(); 4671ab5102d6Svporpo Align NewAlign(256); 4672ab5102d6Svporpo EXPECT_NE(NewAlign, OrigAlign); 4673ab5102d6Svporpo RMW->setAlignment(NewAlign); 4674ab5102d6Svporpo EXPECT_EQ(RMW->getAlign(), NewAlign); 4675ab5102d6Svporpo RMW->setAlignment(OrigAlign); 4676ab5102d6Svporpo EXPECT_EQ(RMW->getAlign(), OrigAlign); 4677ab5102d6Svporpo // Check isVolatile(), setVolatile(). 4678ab5102d6Svporpo EXPECT_EQ(RMW->isVolatile(), LLVMRMW->isVolatile()); 4679ab5102d6Svporpo bool OrigV = RMW->isVolatile(); 4680ab5102d6Svporpo bool NewV = true; 4681ab5102d6Svporpo EXPECT_NE(NewV, OrigV); 4682ab5102d6Svporpo RMW->setVolatile(NewV); 4683ab5102d6Svporpo EXPECT_EQ(RMW->isVolatile(), NewV); 4684ab5102d6Svporpo RMW->setVolatile(OrigV); 4685ab5102d6Svporpo EXPECT_EQ(RMW->isVolatile(), OrigV); 4686ab5102d6Svporpo // Check getOrdering(), setOrdering(). 4687ab5102d6Svporpo EXPECT_EQ(RMW->getOrdering(), LLVMRMW->getOrdering()); 4688ab5102d6Svporpo auto OldOrdering = RMW->getOrdering(); 4689ab5102d6Svporpo auto NewOrdering = AtomicOrdering::Monotonic; 4690ab5102d6Svporpo EXPECT_NE(NewOrdering, OldOrdering); 4691ab5102d6Svporpo RMW->setOrdering(NewOrdering); 4692ab5102d6Svporpo EXPECT_EQ(RMW->getOrdering(), NewOrdering); 4693ab5102d6Svporpo RMW->setOrdering(OldOrdering); 4694ab5102d6Svporpo EXPECT_EQ(RMW->getOrdering(), OldOrdering); 4695ab5102d6Svporpo // Check getSyncScopeID(), setSyncScopeID(). 4696ab5102d6Svporpo EXPECT_EQ(RMW->getSyncScopeID(), LLVMRMW->getSyncScopeID()); 4697ab5102d6Svporpo auto OrigSSID = RMW->getSyncScopeID(); 4698ab5102d6Svporpo SyncScope::ID NewSSID = SyncScope::SingleThread; 4699ab5102d6Svporpo EXPECT_NE(NewSSID, OrigSSID); 4700ab5102d6Svporpo RMW->setSyncScopeID(NewSSID); 4701ab5102d6Svporpo EXPECT_EQ(RMW->getSyncScopeID(), NewSSID); 4702ab5102d6Svporpo RMW->setSyncScopeID(OrigSSID); 4703ab5102d6Svporpo EXPECT_EQ(RMW->getSyncScopeID(), OrigSSID); 4704ab5102d6Svporpo // Check getPointerOperand(). 4705ab5102d6Svporpo EXPECT_EQ(RMW->getPointerOperand(), 4706ab5102d6Svporpo Ctx.getValue(LLVMRMW->getPointerOperand())); 4707ab5102d6Svporpo // Check getValOperand(). 4708ab5102d6Svporpo EXPECT_EQ(RMW->getValOperand(), Ctx.getValue(LLVMRMW->getValOperand())); 4709ab5102d6Svporpo // Check getPointerAddressSpace(). 4710ab5102d6Svporpo EXPECT_EQ(RMW->getPointerAddressSpace(), LLVMRMW->getPointerAddressSpace()); 4711ab5102d6Svporpo // Check isFloatingPointOperation(). 4712ab5102d6Svporpo EXPECT_EQ(RMW->isFloatingPointOperation(), 4713ab5102d6Svporpo LLVMRMW->isFloatingPointOperation()); 4714ab5102d6Svporpo 4715ab5102d6Svporpo Align Align(1024); 4716ab5102d6Svporpo auto Ordering = AtomicOrdering::Acquire; 4717ab5102d6Svporpo auto SSID = SyncScope::System; 4718ab5102d6Svporpo { 4719ab5102d6Svporpo // Check create() WhereIt, WhereBB. 4720ab5102d6Svporpo auto *NewI = 4721ab5102d6Svporpo cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create( 4722ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering, 47234f3a0959Svporpo Ret->getIterator(), Ctx, SSID, "NewAtomicRMW1")); 4724ab5102d6Svporpo // Check getOpcode(). 4725ab5102d6Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW); 4726ab5102d6Svporpo // Check getAlign(). 4727ab5102d6Svporpo EXPECT_EQ(NewI->getAlign(), Align); 4728ab5102d6Svporpo // Check getSuccessOrdering(). 4729ab5102d6Svporpo EXPECT_EQ(NewI->getOrdering(), Ordering); 4730ab5102d6Svporpo // Check instr position. 4731ab5102d6Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4732ab5102d6Svporpo // Check getPointerOperand(). 4733ab5102d6Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 4734ab5102d6Svporpo // Check getValOperand(). 4735ab5102d6Svporpo EXPECT_EQ(NewI->getValOperand(), Arg); 4736ab5102d6Svporpo #ifndef NDEBUG 4737ab5102d6Svporpo // Check getName(). 4738ab5102d6Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicRMW1"); 4739ab5102d6Svporpo #endif // NDEBUG 4740ab5102d6Svporpo } 4741ab5102d6Svporpo { 4742ab5102d6Svporpo // Check create() InsertBefore. 4743ab5102d6Svporpo auto *NewI = 4744ab5102d6Svporpo cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create( 4745ab5102d6Svporpo sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering, 47464f3a0959Svporpo Ret->getIterator(), Ctx, SSID, "NewAtomicRMW2")); 4747ab5102d6Svporpo // Check getOpcode(). 4748ab5102d6Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW); 4749ab5102d6Svporpo // Check getAlign(). 4750ab5102d6Svporpo EXPECT_EQ(NewI->getAlign(), Align); 4751ab5102d6Svporpo // Check getSuccessOrdering(). 4752ab5102d6Svporpo EXPECT_EQ(NewI->getOrdering(), Ordering); 4753ab5102d6Svporpo // Check instr position. 4754ab5102d6Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 4755ab5102d6Svporpo // Check getPointerOperand(). 4756ab5102d6Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 4757ab5102d6Svporpo // Check getValOperand(). 4758ab5102d6Svporpo EXPECT_EQ(NewI->getValOperand(), Arg); 4759ab5102d6Svporpo #ifndef NDEBUG 4760ab5102d6Svporpo // Check getName(). 4761ab5102d6Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicRMW2"); 4762ab5102d6Svporpo #endif // NDEBUG 4763ab5102d6Svporpo } 4764ab5102d6Svporpo { 4765ab5102d6Svporpo // Check create() InsertAtEnd. 4766ab5102d6Svporpo auto *NewI = 4767ab5102d6Svporpo cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create( 47684f3a0959Svporpo sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering, BB, 47694f3a0959Svporpo Ctx, SSID, "NewAtomicRMW3")); 4770ab5102d6Svporpo // Check getOpcode(). 4771ab5102d6Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW); 4772ab5102d6Svporpo // Check getAlign(). 4773ab5102d6Svporpo EXPECT_EQ(NewI->getAlign(), Align); 4774ab5102d6Svporpo // Check getSuccessOrdering(). 4775ab5102d6Svporpo EXPECT_EQ(NewI->getOrdering(), Ordering); 4776ab5102d6Svporpo // Check instr position. 4777ab5102d6Svporpo EXPECT_EQ(NewI->getParent(), BB); 4778ab5102d6Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 4779ab5102d6Svporpo // Check getPointerOperand(). 4780ab5102d6Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 4781ab5102d6Svporpo // Check getValOperand(). 4782ab5102d6Svporpo EXPECT_EQ(NewI->getValOperand(), Arg); 4783ab5102d6Svporpo #ifndef NDEBUG 4784ab5102d6Svporpo // Check getName(). 4785ab5102d6Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicRMW3"); 4786ab5102d6Svporpo #endif // NDEBUG 4787ab5102d6Svporpo } 4788ab5102d6Svporpo } 4789ab5102d6Svporpo 479000a40422Svporpo TEST_F(SandboxIRTest, AtomicCmpXchgInst) { 479100a40422Svporpo parseIR(C, R"IR( 479200a40422Svporpo define void @foo(ptr %ptr, i8 %cmp, i8 %new) { 479300a40422Svporpo %cmpxchg = cmpxchg ptr %ptr, i8 %cmp, i8 %new monotonic monotonic, align 128 479400a40422Svporpo ret void 479500a40422Svporpo } 479600a40422Svporpo )IR"); 479700a40422Svporpo llvm::Function &LLVMF = *M->getFunction("foo"); 479800a40422Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF.begin(); 479900a40422Svporpo auto LLVMIt = LLVMBB->begin(); 480000a40422Svporpo auto *LLVMCmpXchg = cast<llvm::AtomicCmpXchgInst>(&*LLVMIt++); 480100a40422Svporpo 480200a40422Svporpo sandboxir::Context Ctx(C); 480300a40422Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 480400a40422Svporpo auto *Ptr = F->getArg(0); 480500a40422Svporpo auto *Cmp = F->getArg(1); 480600a40422Svporpo auto *New = F->getArg(2); 480700a40422Svporpo auto *BB = &*F->begin(); 480800a40422Svporpo auto It = BB->begin(); 480900a40422Svporpo auto *CmpXchg = cast<sandboxir::AtomicCmpXchgInst>(&*It++); 481000a40422Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 481100a40422Svporpo 481200a40422Svporpo // Check getAlign(), setAlignment(). 481300a40422Svporpo EXPECT_EQ(CmpXchg->getAlign(), LLVMCmpXchg->getAlign()); 481400a40422Svporpo auto OrigAlign = CmpXchg->getAlign(); 481500a40422Svporpo Align NewAlign(256); 481600a40422Svporpo EXPECT_NE(NewAlign, OrigAlign); 481700a40422Svporpo CmpXchg->setAlignment(NewAlign); 481800a40422Svporpo EXPECT_EQ(CmpXchg->getAlign(), NewAlign); 481900a40422Svporpo CmpXchg->setAlignment(OrigAlign); 482000a40422Svporpo EXPECT_EQ(CmpXchg->getAlign(), OrigAlign); 482100a40422Svporpo // Check isVolatile(), setVolatile(). 482200a40422Svporpo EXPECT_EQ(CmpXchg->isVolatile(), LLVMCmpXchg->isVolatile()); 482300a40422Svporpo bool OrigV = CmpXchg->isVolatile(); 482400a40422Svporpo bool NewV = true; 482500a40422Svporpo EXPECT_NE(NewV, OrigV); 482600a40422Svporpo CmpXchg->setVolatile(NewV); 482700a40422Svporpo EXPECT_EQ(CmpXchg->isVolatile(), NewV); 482800a40422Svporpo CmpXchg->setVolatile(OrigV); 482900a40422Svporpo EXPECT_EQ(CmpXchg->isVolatile(), OrigV); 483000a40422Svporpo // Check isWeak(), setWeak(). 483100a40422Svporpo EXPECT_EQ(CmpXchg->isWeak(), LLVMCmpXchg->isWeak()); 483200a40422Svporpo bool OrigWeak = CmpXchg->isWeak(); 483300a40422Svporpo bool NewWeak = true; 483400a40422Svporpo EXPECT_NE(NewWeak, OrigWeak); 483500a40422Svporpo CmpXchg->setWeak(NewWeak); 483600a40422Svporpo EXPECT_EQ(CmpXchg->isWeak(), NewWeak); 483700a40422Svporpo CmpXchg->setWeak(OrigWeak); 483800a40422Svporpo EXPECT_EQ(CmpXchg->isWeak(), OrigWeak); 483900a40422Svporpo // Check isValidSuccessOrdering(), isValidFailureOrdering(). 484000a40422Svporpo SmallVector<AtomicOrdering> AllOrderings( 484100a40422Svporpo {AtomicOrdering::NotAtomic, AtomicOrdering::Unordered, 484200a40422Svporpo AtomicOrdering::Monotonic, AtomicOrdering::Acquire, 484300a40422Svporpo AtomicOrdering::Release, AtomicOrdering::AcquireRelease, 484400a40422Svporpo AtomicOrdering::SequentiallyConsistent}); 484500a40422Svporpo for (auto Ordering : AllOrderings) { 484600a40422Svporpo EXPECT_EQ(sandboxir::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering), 484700a40422Svporpo llvm::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering)); 484800a40422Svporpo EXPECT_EQ(sandboxir::AtomicCmpXchgInst::isValidFailureOrdering(Ordering), 484900a40422Svporpo llvm::AtomicCmpXchgInst::isValidFailureOrdering(Ordering)); 485000a40422Svporpo } 485100a40422Svporpo // Check getSuccessOrdering(), setSuccessOrdering(). 485200a40422Svporpo EXPECT_EQ(CmpXchg->getSuccessOrdering(), LLVMCmpXchg->getSuccessOrdering()); 485300a40422Svporpo auto OldSuccOrdering = CmpXchg->getSuccessOrdering(); 485400a40422Svporpo auto NewSuccOrdering = AtomicOrdering::Acquire; 485500a40422Svporpo EXPECT_NE(NewSuccOrdering, OldSuccOrdering); 485600a40422Svporpo CmpXchg->setSuccessOrdering(NewSuccOrdering); 485700a40422Svporpo EXPECT_EQ(CmpXchg->getSuccessOrdering(), NewSuccOrdering); 485800a40422Svporpo CmpXchg->setSuccessOrdering(OldSuccOrdering); 485900a40422Svporpo EXPECT_EQ(CmpXchg->getSuccessOrdering(), OldSuccOrdering); 486000a40422Svporpo // Check getFailureOrdering(), setFailureOrdering(). 486100a40422Svporpo EXPECT_EQ(CmpXchg->getFailureOrdering(), LLVMCmpXchg->getFailureOrdering()); 486200a40422Svporpo auto OldFailOrdering = CmpXchg->getFailureOrdering(); 486300a40422Svporpo auto NewFailOrdering = AtomicOrdering::Acquire; 486400a40422Svporpo EXPECT_NE(NewFailOrdering, OldFailOrdering); 486500a40422Svporpo CmpXchg->setFailureOrdering(NewFailOrdering); 486600a40422Svporpo EXPECT_EQ(CmpXchg->getFailureOrdering(), NewFailOrdering); 486700a40422Svporpo CmpXchg->setFailureOrdering(OldFailOrdering); 486800a40422Svporpo EXPECT_EQ(CmpXchg->getFailureOrdering(), OldFailOrdering); 486900a40422Svporpo // Check getMergedOrdering(). 487000a40422Svporpo EXPECT_EQ(CmpXchg->getMergedOrdering(), LLVMCmpXchg->getMergedOrdering()); 487100a40422Svporpo // Check getSyncScopeID(), setSyncScopeID(). 487200a40422Svporpo EXPECT_EQ(CmpXchg->getSyncScopeID(), LLVMCmpXchg->getSyncScopeID()); 487300a40422Svporpo auto OrigSSID = CmpXchg->getSyncScopeID(); 487400a40422Svporpo SyncScope::ID NewSSID = SyncScope::SingleThread; 487500a40422Svporpo EXPECT_NE(NewSSID, OrigSSID); 487600a40422Svporpo CmpXchg->setSyncScopeID(NewSSID); 487700a40422Svporpo EXPECT_EQ(CmpXchg->getSyncScopeID(), NewSSID); 487800a40422Svporpo CmpXchg->setSyncScopeID(OrigSSID); 487900a40422Svporpo EXPECT_EQ(CmpXchg->getSyncScopeID(), OrigSSID); 488000a40422Svporpo // Check getPointerOperand(). 488100a40422Svporpo EXPECT_EQ(CmpXchg->getPointerOperand(), 488200a40422Svporpo Ctx.getValue(LLVMCmpXchg->getPointerOperand())); 488300a40422Svporpo // Check getCompareOperand(). 488400a40422Svporpo EXPECT_EQ(CmpXchg->getCompareOperand(), 488500a40422Svporpo Ctx.getValue(LLVMCmpXchg->getCompareOperand())); 488600a40422Svporpo // Check getNewValOperand(). 488700a40422Svporpo EXPECT_EQ(CmpXchg->getNewValOperand(), 488800a40422Svporpo Ctx.getValue(LLVMCmpXchg->getNewValOperand())); 488900a40422Svporpo // Check getPointerAddressSpace(). 489000a40422Svporpo EXPECT_EQ(CmpXchg->getPointerAddressSpace(), 489100a40422Svporpo LLVMCmpXchg->getPointerAddressSpace()); 489200a40422Svporpo 489300a40422Svporpo Align Align(1024); 489400a40422Svporpo auto SuccOrdering = AtomicOrdering::Acquire; 489500a40422Svporpo auto FailOrdering = AtomicOrdering::Monotonic; 489600a40422Svporpo auto SSID = SyncScope::System; 489700a40422Svporpo { 489800a40422Svporpo // Check create() WhereIt, WhereBB. 489900a40422Svporpo auto *NewI = 490000a40422Svporpo cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create( 490100a40422Svporpo Ptr, Cmp, New, Align, SuccOrdering, FailOrdering, 4902c029702fSvporpo Ret->getIterator(), Ctx, SSID, "NewAtomicCmpXchg1")); 490300a40422Svporpo // Check getOpcode(). 490400a40422Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg); 490500a40422Svporpo // Check getAlign(). 490600a40422Svporpo EXPECT_EQ(NewI->getAlign(), Align); 490700a40422Svporpo // Check getSuccessOrdering(). 490800a40422Svporpo EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering); 490900a40422Svporpo // Check getFailureOrdering(). 491000a40422Svporpo EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering); 491100a40422Svporpo // Check instr position. 491200a40422Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 491300a40422Svporpo // Check getPointerOperand(). 491400a40422Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 491500a40422Svporpo // Check getCompareOperand(). 491600a40422Svporpo EXPECT_EQ(NewI->getCompareOperand(), Cmp); 491700a40422Svporpo // Check getNewValOperand(). 491800a40422Svporpo EXPECT_EQ(NewI->getNewValOperand(), New); 491900a40422Svporpo #ifndef NDEBUG 492000a40422Svporpo // Check getName(). 492100a40422Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg1"); 492200a40422Svporpo #endif // NDEBUG 492300a40422Svporpo } 492400a40422Svporpo { 492500a40422Svporpo // Check create() InsertBefore. 492600a40422Svporpo auto *NewI = 492700a40422Svporpo cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create( 492800a40422Svporpo Ptr, Cmp, New, Align, SuccOrdering, FailOrdering, 4929c029702fSvporpo Ret->getIterator(), Ctx, SSID, "NewAtomicCmpXchg2")); 493000a40422Svporpo // Check getOpcode(). 493100a40422Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg); 493200a40422Svporpo // Check getAlign(). 493300a40422Svporpo EXPECT_EQ(NewI->getAlign(), Align); 493400a40422Svporpo // Check getSuccessOrdering(). 493500a40422Svporpo EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering); 493600a40422Svporpo // Check getFailureOrdering(). 493700a40422Svporpo EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering); 493800a40422Svporpo // Check instr position. 493900a40422Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 494000a40422Svporpo // Check getPointerOperand(). 494100a40422Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 494200a40422Svporpo // Check getCompareOperand(). 494300a40422Svporpo EXPECT_EQ(NewI->getCompareOperand(), Cmp); 494400a40422Svporpo // Check getNewValOperand(). 494500a40422Svporpo EXPECT_EQ(NewI->getNewValOperand(), New); 494600a40422Svporpo #ifndef NDEBUG 494700a40422Svporpo // Check getName(). 494800a40422Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg2"); 494900a40422Svporpo #endif // NDEBUG 495000a40422Svporpo } 495100a40422Svporpo { 495200a40422Svporpo // Check create() InsertAtEnd. 495300a40422Svporpo auto *NewI = 495400a40422Svporpo cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create( 4955c029702fSvporpo Ptr, Cmp, New, Align, SuccOrdering, FailOrdering, BB, Ctx, SSID, 4956c029702fSvporpo "NewAtomicCmpXchg3")); 495700a40422Svporpo // Check getOpcode(). 495800a40422Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg); 495900a40422Svporpo // Check getAlign(). 496000a40422Svporpo EXPECT_EQ(NewI->getAlign(), Align); 496100a40422Svporpo // Check getSuccessOrdering(). 496200a40422Svporpo EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering); 496300a40422Svporpo // Check getFailureOrdering(). 496400a40422Svporpo EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering); 496500a40422Svporpo // Check instr position. 496600a40422Svporpo EXPECT_EQ(NewI->getParent(), BB); 496700a40422Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 496800a40422Svporpo // Check getPointerOperand(). 496900a40422Svporpo EXPECT_EQ(NewI->getPointerOperand(), Ptr); 497000a40422Svporpo // Check getCompareOperand(). 497100a40422Svporpo EXPECT_EQ(NewI->getCompareOperand(), Cmp); 497200a40422Svporpo // Check getNewValOperand(). 497300a40422Svporpo EXPECT_EQ(NewI->getNewValOperand(), New); 497400a40422Svporpo #ifndef NDEBUG 497500a40422Svporpo // Check getName(). 497600a40422Svporpo EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg3"); 497700a40422Svporpo #endif // NDEBUG 497800a40422Svporpo } 497900a40422Svporpo } 498000a40422Svporpo 498136f0d648Svporpo TEST_F(SandboxIRTest, AllocaInst) { 498236f0d648Svporpo parseIR(C, R"IR( 498336f0d648Svporpo define void @foo() { 498436f0d648Svporpo %allocaScalar = alloca i32, align 1024 498536f0d648Svporpo %allocaArray = alloca i32, i32 42 498636f0d648Svporpo ret void 498736f0d648Svporpo } 498836f0d648Svporpo )IR"); 498975c7bca7SSergei Barannikov const DataLayout &DL = M->getDataLayout(); 499036f0d648Svporpo llvm::Function &LLVMF = *M->getFunction("foo"); 499136f0d648Svporpo llvm::BasicBlock *LLVMBB = &*LLVMF.begin(); 499236f0d648Svporpo auto LLVMIt = LLVMBB->begin(); 499336f0d648Svporpo auto *LLVMAllocaScalar = cast<llvm::AllocaInst>(&*LLVMIt++); 499436f0d648Svporpo auto *LLVMAllocaArray = cast<llvm::AllocaInst>(&*LLVMIt++); 499536f0d648Svporpo 499636f0d648Svporpo sandboxir::Context Ctx(C); 499736f0d648Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 499836f0d648Svporpo auto *BB = &*F->begin(); 499936f0d648Svporpo auto It = BB->begin(); 500036f0d648Svporpo auto *AllocaScalar = cast<sandboxir::AllocaInst>(&*It++); 500136f0d648Svporpo auto *AllocaArray = cast<sandboxir::AllocaInst>(&*It++); 500236f0d648Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 500336f0d648Svporpo 500436f0d648Svporpo // Check isArrayAllocation(). 500536f0d648Svporpo EXPECT_EQ(AllocaScalar->isArrayAllocation(), 500636f0d648Svporpo LLVMAllocaScalar->isArrayAllocation()); 500736f0d648Svporpo EXPECT_EQ(AllocaArray->isArrayAllocation(), 500836f0d648Svporpo LLVMAllocaArray->isArrayAllocation()); 500936f0d648Svporpo // Check getArraySize(). 501036f0d648Svporpo EXPECT_EQ(AllocaScalar->getArraySize(), 501136f0d648Svporpo Ctx.getValue(LLVMAllocaScalar->getArraySize())); 501236f0d648Svporpo EXPECT_EQ(AllocaArray->getArraySize(), 501336f0d648Svporpo Ctx.getValue(LLVMAllocaArray->getArraySize())); 501436f0d648Svporpo // Check getType(). 5015034f2b38Svporpo EXPECT_EQ(AllocaScalar->getType(), Ctx.getType(LLVMAllocaScalar->getType())); 5016034f2b38Svporpo EXPECT_EQ(AllocaArray->getType(), Ctx.getType(LLVMAllocaArray->getType())); 501736f0d648Svporpo // Check getAddressSpace(). 501836f0d648Svporpo EXPECT_EQ(AllocaScalar->getAddressSpace(), 501936f0d648Svporpo LLVMAllocaScalar->getAddressSpace()); 502036f0d648Svporpo EXPECT_EQ(AllocaArray->getAddressSpace(), LLVMAllocaArray->getAddressSpace()); 502136f0d648Svporpo // Check getAllocationSize(). 502236f0d648Svporpo EXPECT_EQ(AllocaScalar->getAllocationSize(DL), 502336f0d648Svporpo LLVMAllocaScalar->getAllocationSize(DL)); 502436f0d648Svporpo EXPECT_EQ(AllocaArray->getAllocationSize(DL), 502536f0d648Svporpo LLVMAllocaArray->getAllocationSize(DL)); 502636f0d648Svporpo // Check getAllocationSizeInBits(). 502736f0d648Svporpo EXPECT_EQ(AllocaScalar->getAllocationSizeInBits(DL), 502836f0d648Svporpo LLVMAllocaScalar->getAllocationSizeInBits(DL)); 502936f0d648Svporpo EXPECT_EQ(AllocaArray->getAllocationSizeInBits(DL), 503036f0d648Svporpo LLVMAllocaArray->getAllocationSizeInBits(DL)); 503136f0d648Svporpo // Check getAllocatedType(). 503236f0d648Svporpo EXPECT_EQ(AllocaScalar->getAllocatedType(), 5033034f2b38Svporpo Ctx.getType(LLVMAllocaScalar->getAllocatedType())); 503436f0d648Svporpo EXPECT_EQ(AllocaArray->getAllocatedType(), 5035034f2b38Svporpo Ctx.getType(LLVMAllocaArray->getAllocatedType())); 503636f0d648Svporpo // Check setAllocatedType(). 503736f0d648Svporpo auto *OrigType = AllocaScalar->getAllocatedType(); 5038034f2b38Svporpo auto *NewType = sandboxir::PointerType::get(Ctx, 0); 503936f0d648Svporpo EXPECT_NE(NewType, OrigType); 504036f0d648Svporpo AllocaScalar->setAllocatedType(NewType); 504136f0d648Svporpo EXPECT_EQ(AllocaScalar->getAllocatedType(), NewType); 504236f0d648Svporpo AllocaScalar->setAllocatedType(OrigType); 504336f0d648Svporpo EXPECT_EQ(AllocaScalar->getAllocatedType(), OrigType); 504436f0d648Svporpo // Check getAlign(). 504536f0d648Svporpo EXPECT_EQ(AllocaScalar->getAlign(), LLVMAllocaScalar->getAlign()); 504636f0d648Svporpo EXPECT_EQ(AllocaArray->getAlign(), LLVMAllocaArray->getAlign()); 504736f0d648Svporpo // Check setAlignment(). 504836f0d648Svporpo Align OrigAlign = AllocaScalar->getAlign(); 504936f0d648Svporpo Align NewAlign(16); 505036f0d648Svporpo EXPECT_NE(NewAlign, OrigAlign); 505136f0d648Svporpo AllocaScalar->setAlignment(NewAlign); 505236f0d648Svporpo EXPECT_EQ(AllocaScalar->getAlign(), NewAlign); 505336f0d648Svporpo AllocaScalar->setAlignment(OrigAlign); 505436f0d648Svporpo EXPECT_EQ(AllocaScalar->getAlign(), OrigAlign); 505536f0d648Svporpo // Check isStaticAlloca(). 505636f0d648Svporpo EXPECT_EQ(AllocaScalar->isStaticAlloca(), LLVMAllocaScalar->isStaticAlloca()); 505736f0d648Svporpo EXPECT_EQ(AllocaArray->isStaticAlloca(), LLVMAllocaArray->isStaticAlloca()); 505836f0d648Svporpo // Check isUsedWithInAlloca(), setUsedWithInAlloca(). 505936f0d648Svporpo EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), 506036f0d648Svporpo LLVMAllocaScalar->isUsedWithInAlloca()); 506136f0d648Svporpo bool OrigUsedWithInAlloca = AllocaScalar->isUsedWithInAlloca(); 506236f0d648Svporpo bool NewUsedWithInAlloca = true; 506336f0d648Svporpo EXPECT_NE(NewUsedWithInAlloca, OrigUsedWithInAlloca); 506436f0d648Svporpo AllocaScalar->setUsedWithInAlloca(NewUsedWithInAlloca); 506536f0d648Svporpo EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), NewUsedWithInAlloca); 506636f0d648Svporpo AllocaScalar->setUsedWithInAlloca(OrigUsedWithInAlloca); 506736f0d648Svporpo EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), OrigUsedWithInAlloca); 506836f0d648Svporpo 5069034f2b38Svporpo auto *Ty = sandboxir::Type::getInt32Ty(Ctx); 507036f0d648Svporpo unsigned AddrSpace = 42; 5071034f2b38Svporpo auto *PtrTy = sandboxir::PointerType::get(Ctx, AddrSpace); 5072034f2b38Svporpo auto *ArraySize = sandboxir::ConstantInt::get(Ty, 43); 507336f0d648Svporpo { 507436f0d648Svporpo // Check create() WhereIt, WhereBB. 507536f0d648Svporpo auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create( 5076c029702fSvporpo Ty, AddrSpace, Ret->getIterator(), Ctx, ArraySize, "NewAlloca1")); 507736f0d648Svporpo // Check getOpcode(). 507836f0d648Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca); 507936f0d648Svporpo // Check getType(). 508036f0d648Svporpo EXPECT_EQ(NewI->getType(), PtrTy); 508136f0d648Svporpo // Check getArraySize(). 508236f0d648Svporpo EXPECT_EQ(NewI->getArraySize(), ArraySize); 508336f0d648Svporpo // Check getAddrSpace(). 508436f0d648Svporpo EXPECT_EQ(NewI->getAddressSpace(), AddrSpace); 508536f0d648Svporpo // Check instr position. 508636f0d648Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 508736f0d648Svporpo } 508836f0d648Svporpo { 508936f0d648Svporpo // Check create() InsertBefore. 509036f0d648Svporpo auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create( 5091c029702fSvporpo Ty, AddrSpace, Ret->getIterator(), Ctx, ArraySize, "NewAlloca2")); 509236f0d648Svporpo // Check getOpcode(). 509336f0d648Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca); 509436f0d648Svporpo // Check getType(). 509536f0d648Svporpo EXPECT_EQ(NewI->getType(), PtrTy); 509636f0d648Svporpo // Check getArraySize(). 509736f0d648Svporpo EXPECT_EQ(NewI->getArraySize(), ArraySize); 509836f0d648Svporpo // Check getAddrSpace(). 509936f0d648Svporpo EXPECT_EQ(NewI->getAddressSpace(), AddrSpace); 510036f0d648Svporpo // Check instr position. 510136f0d648Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 510236f0d648Svporpo } 510336f0d648Svporpo { 510436f0d648Svporpo // Check create() InsertAtEnd. 510536f0d648Svporpo auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create( 5106c029702fSvporpo Ty, AddrSpace, BB, Ctx, ArraySize, "NewAlloca3")); 510736f0d648Svporpo // Check getOpcode(). 510836f0d648Svporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca); 510936f0d648Svporpo // Check getType(). 511036f0d648Svporpo EXPECT_EQ(NewI->getType(), PtrTy); 511136f0d648Svporpo // Check getArraySize(). 511236f0d648Svporpo EXPECT_EQ(NewI->getArraySize(), ArraySize); 511336f0d648Svporpo // Check getAddrSpace(). 511436f0d648Svporpo EXPECT_EQ(NewI->getAddressSpace(), AddrSpace); 511536f0d648Svporpo // Check instr position. 511636f0d648Svporpo EXPECT_EQ(NewI->getParent(), BB); 511736f0d648Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 511836f0d648Svporpo } 511936f0d648Svporpo } 512036f0d648Svporpo 5121eb03279dSvporpo TEST_F(SandboxIRTest, CastInst) { 5122eb03279dSvporpo parseIR(C, R"IR( 5123eb03279dSvporpo define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) { 5124eb03279dSvporpo %zext = zext i32 %arg to i64 5125eb03279dSvporpo %sext = sext i32 %arg to i64 5126eb03279dSvporpo %fptoui = fptoui float %farg to i32 5127eb03279dSvporpo %fptosi = fptosi float %farg to i32 5128eb03279dSvporpo %fpext = fpext float %farg to double 5129eb03279dSvporpo %ptrtoint = ptrtoint ptr %ptr to i32 5130eb03279dSvporpo %inttoptr = inttoptr i32 %arg to ptr 5131eb03279dSvporpo %sitofp = sitofp i32 %arg to float 5132eb03279dSvporpo %uitofp = uitofp i32 %arg to float 5133eb03279dSvporpo %trunc = trunc i32 %arg to i16 5134eb03279dSvporpo %fptrunc = fptrunc double %darg to float 5135eb03279dSvporpo %bitcast = bitcast i32 %arg to float 5136eb03279dSvporpo %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1) 5137eb03279dSvporpo ret void 5138eb03279dSvporpo } 5139eb03279dSvporpo )IR"); 5140eb03279dSvporpo Function &LLVMF = *M->getFunction("foo"); 5141eb03279dSvporpo sandboxir::Context Ctx(C); 5142eb03279dSvporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 5143eb03279dSvporpo unsigned ArgIdx = 0; 5144eb03279dSvporpo auto *Arg = F->getArg(ArgIdx++); 5145eb03279dSvporpo auto *BB = &*F->begin(); 5146eb03279dSvporpo auto It = BB->begin(); 5147eb03279dSvporpo 5148034f2b38Svporpo auto *Ti64 = sandboxir::Type::getInt64Ty(Ctx); 5149034f2b38Svporpo auto *Ti32 = sandboxir::Type::getInt32Ty(Ctx); 5150034f2b38Svporpo auto *Ti16 = sandboxir::Type::getInt16Ty(Ctx); 5151034f2b38Svporpo auto *Tdouble = sandboxir::Type::getDoubleTy(Ctx); 5152034f2b38Svporpo auto *Tfloat = sandboxir::Type::getFloatTy(Ctx); 5153830bd0e8SMats Jun Larsen auto *Tptr = sandboxir::PointerType::get(Ctx, 0); 5154830bd0e8SMats Jun Larsen auto *Tptr1 = sandboxir::PointerType::get(Ctx, 1); 5155eb03279dSvporpo 5156eb03279dSvporpo // Check classof(), getOpcode(), getSrcTy(), getDstTy() 5157eb03279dSvporpo auto *ZExt = cast<sandboxir::CastInst>(&*It++); 5158f9392fccSvporpo auto *ZExtI = cast<sandboxir::ZExtInst>(ZExt); 5159f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(ZExtI)); 5160f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(ZExtI)); 5161eb03279dSvporpo EXPECT_EQ(ZExt->getOpcode(), sandboxir::Instruction::Opcode::ZExt); 5162eb03279dSvporpo EXPECT_EQ(ZExt->getSrcTy(), Ti32); 5163eb03279dSvporpo EXPECT_EQ(ZExt->getDestTy(), Ti64); 5164eb03279dSvporpo 5165eb03279dSvporpo auto *SExt = cast<sandboxir::CastInst>(&*It++); 5166f9392fccSvporpo auto *SExtI = cast<sandboxir::SExtInst>(SExt); 5167f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SExt)); 5168f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SExtI)); 5169eb03279dSvporpo EXPECT_EQ(SExt->getOpcode(), sandboxir::Instruction::Opcode::SExt); 5170eb03279dSvporpo EXPECT_EQ(SExt->getSrcTy(), Ti32); 5171eb03279dSvporpo EXPECT_EQ(SExt->getDestTy(), Ti64); 5172eb03279dSvporpo 5173eb03279dSvporpo auto *FPToUI = cast<sandboxir::CastInst>(&*It++); 5174f9392fccSvporpo auto *FPToUII = cast<sandboxir::FPToUIInst>(FPToUI); 5175f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToUI)); 5176f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToUII)); 5177eb03279dSvporpo EXPECT_EQ(FPToUI->getOpcode(), sandboxir::Instruction::Opcode::FPToUI); 5178eb03279dSvporpo EXPECT_EQ(FPToUI->getSrcTy(), Tfloat); 5179eb03279dSvporpo EXPECT_EQ(FPToUI->getDestTy(), Ti32); 5180eb03279dSvporpo 5181eb03279dSvporpo auto *FPToSI = cast<sandboxir::CastInst>(&*It++); 5182f9392fccSvporpo auto *FPToSII = cast<sandboxir::FPToSIInst>(FPToSI); 5183f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToSI)); 5184f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToSII)); 5185eb03279dSvporpo EXPECT_EQ(FPToSI->getOpcode(), sandboxir::Instruction::Opcode::FPToSI); 5186eb03279dSvporpo EXPECT_EQ(FPToSI->getSrcTy(), Tfloat); 5187eb03279dSvporpo EXPECT_EQ(FPToSI->getDestTy(), Ti32); 5188eb03279dSvporpo 5189eb03279dSvporpo auto *FPExt = cast<sandboxir::CastInst>(&*It++); 5190f9392fccSvporpo auto *FPExtI = cast<sandboxir::FPExtInst>(FPExt); 5191f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPExt)); 5192f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPExtI)); 5193eb03279dSvporpo EXPECT_EQ(FPExt->getOpcode(), sandboxir::Instruction::Opcode::FPExt); 5194eb03279dSvporpo EXPECT_EQ(FPExt->getSrcTy(), Tfloat); 5195eb03279dSvporpo EXPECT_EQ(FPExt->getDestTy(), Tdouble); 5196eb03279dSvporpo 5197eb03279dSvporpo auto *PtrToInt = cast<sandboxir::CastInst>(&*It++); 5198f9392fccSvporpo auto *PtrToIntI = cast<sandboxir::PtrToIntInst>(PtrToInt); 5199f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(PtrToInt)); 5200f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(PtrToIntI)); 5201eb03279dSvporpo EXPECT_EQ(PtrToInt->getOpcode(), sandboxir::Instruction::Opcode::PtrToInt); 5202eb03279dSvporpo EXPECT_EQ(PtrToInt->getSrcTy(), Tptr); 5203eb03279dSvporpo EXPECT_EQ(PtrToInt->getDestTy(), Ti32); 5204eb03279dSvporpo 5205eb03279dSvporpo auto *IntToPtr = cast<sandboxir::CastInst>(&*It++); 5206f9392fccSvporpo auto *IntToPtrI = cast<sandboxir::IntToPtrInst>(IntToPtr); 5207f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(IntToPtr)); 5208f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(IntToPtrI)); 5209eb03279dSvporpo EXPECT_EQ(IntToPtr->getOpcode(), sandboxir::Instruction::Opcode::IntToPtr); 5210eb03279dSvporpo EXPECT_EQ(IntToPtr->getSrcTy(), Ti32); 5211eb03279dSvporpo EXPECT_EQ(IntToPtr->getDestTy(), Tptr); 5212eb03279dSvporpo 5213eb03279dSvporpo auto *SIToFP = cast<sandboxir::CastInst>(&*It++); 5214f9392fccSvporpo auto *SIToFPI = cast<sandboxir::SIToFPInst>(SIToFP); 5215f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SIToFP)); 5216f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SIToFPI)); 5217eb03279dSvporpo EXPECT_EQ(SIToFP->getOpcode(), sandboxir::Instruction::Opcode::SIToFP); 5218eb03279dSvporpo EXPECT_EQ(SIToFP->getSrcTy(), Ti32); 5219eb03279dSvporpo EXPECT_EQ(SIToFP->getDestTy(), Tfloat); 5220eb03279dSvporpo 5221eb03279dSvporpo auto *UIToFP = cast<sandboxir::CastInst>(&*It++); 5222f9392fccSvporpo auto *UIToFPI = cast<sandboxir::UIToFPInst>(UIToFP); 5223f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(UIToFP)); 5224f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(UIToFPI)); 5225eb03279dSvporpo EXPECT_EQ(UIToFP->getOpcode(), sandboxir::Instruction::Opcode::UIToFP); 5226eb03279dSvporpo EXPECT_EQ(UIToFP->getSrcTy(), Ti32); 5227eb03279dSvporpo EXPECT_EQ(UIToFP->getDestTy(), Tfloat); 5228eb03279dSvporpo 5229eb03279dSvporpo auto *Trunc = cast<sandboxir::CastInst>(&*It++); 5230f9392fccSvporpo auto *TruncI = cast<sandboxir::TruncInst>(Trunc); 5231f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Trunc)); 5232f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(TruncI)); 5233eb03279dSvporpo EXPECT_EQ(Trunc->getOpcode(), sandboxir::Instruction::Opcode::Trunc); 5234eb03279dSvporpo EXPECT_EQ(Trunc->getSrcTy(), Ti32); 5235eb03279dSvporpo EXPECT_EQ(Trunc->getDestTy(), Ti16); 5236eb03279dSvporpo 5237eb03279dSvporpo auto *FPTrunc = cast<sandboxir::CastInst>(&*It++); 5238f9392fccSvporpo auto *FPTruncI = cast<sandboxir::FPTruncInst>(FPTrunc); 5239f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPTrunc)); 5240f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPTruncI)); 5241eb03279dSvporpo EXPECT_EQ(FPTrunc->getOpcode(), sandboxir::Instruction::Opcode::FPTrunc); 5242eb03279dSvporpo EXPECT_EQ(FPTrunc->getSrcTy(), Tdouble); 5243eb03279dSvporpo EXPECT_EQ(FPTrunc->getDestTy(), Tfloat); 5244eb03279dSvporpo 5245eb03279dSvporpo auto *BitCast = cast<sandboxir::CastInst>(&*It++); 5246f9392fccSvporpo auto *BitCastI = cast<sandboxir::BitCastInst>(BitCast); 5247f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(BitCast)); 5248f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(BitCastI)); 5249eb03279dSvporpo EXPECT_EQ(BitCast->getOpcode(), sandboxir::Instruction::Opcode::BitCast); 5250eb03279dSvporpo EXPECT_EQ(BitCast->getSrcTy(), Ti32); 5251eb03279dSvporpo EXPECT_EQ(BitCast->getDestTy(), Tfloat); 5252eb03279dSvporpo 5253eb03279dSvporpo auto *AddrSpaceCast = cast<sandboxir::CastInst>(&*It++); 5254f9392fccSvporpo auto *AddrSpaceCastI = cast<sandboxir::AddrSpaceCastInst>(AddrSpaceCast); 5255f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(AddrSpaceCast)); 5256f9392fccSvporpo EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(AddrSpaceCastI)); 5257eb03279dSvporpo EXPECT_EQ(AddrSpaceCast->getOpcode(), 5258eb03279dSvporpo sandboxir::Instruction::Opcode::AddrSpaceCast); 5259eb03279dSvporpo EXPECT_EQ(AddrSpaceCast->getSrcTy(), Tptr); 5260eb03279dSvporpo EXPECT_EQ(AddrSpaceCast->getDestTy(), Tptr1); 5261eb03279dSvporpo 5262eb03279dSvporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 5263eb03279dSvporpo 5264eb03279dSvporpo { 5265eb03279dSvporpo // Check create() WhereIt, WhereBB 5266c029702fSvporpo auto *NewI = cast<sandboxir::CastInst>( 5267c029702fSvporpo sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::SExt, 5268c029702fSvporpo Arg, BB->end(), Ctx, "SExt")); 5269eb03279dSvporpo // Check getOpcode(). 5270eb03279dSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::SExt); 5271eb03279dSvporpo // Check getSrcTy(). 5272eb03279dSvporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 5273eb03279dSvporpo // Check getDestTy(). 5274eb03279dSvporpo EXPECT_EQ(NewI->getDestTy(), Ti64); 5275eb03279dSvporpo // Check instr position. 5276eb03279dSvporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 5277eb03279dSvporpo EXPECT_EQ(NewI->getPrevNode(), Ret); 5278eb03279dSvporpo } 5279eb03279dSvporpo 5280eb03279dSvporpo { 5281eb03279dSvporpo // Check create() InsertBefore. 5282eb03279dSvporpo auto *NewI = cast<sandboxir::CastInst>( 5283eb03279dSvporpo sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::ZExt, 5284c029702fSvporpo Arg, Ret->getIterator(), Ctx, "ZExt")); 5285eb03279dSvporpo // Check getOpcode(). 5286eb03279dSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt); 5287eb03279dSvporpo // Check getSrcTy(). 5288eb03279dSvporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 5289eb03279dSvporpo // Check getDestTy(). 5290eb03279dSvporpo EXPECT_EQ(NewI->getDestTy(), Ti64); 5291eb03279dSvporpo // Check instr position. 5292eb03279dSvporpo EXPECT_EQ(NewI->getNextNode(), Ret); 5293eb03279dSvporpo } 5294eb03279dSvporpo { 5295eb03279dSvporpo // Check create() InsertAtEnd. 5296c029702fSvporpo auto *NewI = cast<sandboxir::CastInst>(sandboxir::CastInst::create( 5297c029702fSvporpo Ti64, sandboxir::Instruction::Opcode::ZExt, Arg, BB, Ctx, "ZExt")); 5298eb03279dSvporpo // Check getOpcode(). 5299eb03279dSvporpo EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt); 5300eb03279dSvporpo // Check getSrcTy(). 5301eb03279dSvporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 5302eb03279dSvporpo // Check getDestTy(). 5303eb03279dSvporpo EXPECT_EQ(NewI->getDestTy(), Ti64); 5304eb03279dSvporpo // Check instr position. 5305eb03279dSvporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 5306eb03279dSvporpo EXPECT_EQ(NewI->getParent(), BB); 5307eb03279dSvporpo } 5308eb03279dSvporpo 5309eb03279dSvporpo { 5310eb03279dSvporpo #ifndef NDEBUG 5311eb03279dSvporpo // Check that passing a non-cast opcode crashes. 5312eb03279dSvporpo EXPECT_DEATH( 5313eb03279dSvporpo sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::Store, 5314c029702fSvporpo Arg, Ret->getIterator(), Ctx, "Bad"), 5315eb03279dSvporpo ".*Opcode.*"); 5316eb03279dSvporpo #endif // NDEBUG 5317eb03279dSvporpo } 5318eb03279dSvporpo } 53193cc288afSvporpo 5320af4a82e4Svporpo TEST_F(SandboxIRTest, PossiblyNonNegInst) { 5321af4a82e4Svporpo parseIR(C, R"IR( 5322af4a82e4Svporpo define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) { 5323af4a82e4Svporpo %zext = zext i32 %arg to i64 5324af4a82e4Svporpo %uitofp = uitofp i32 %arg to float 5325af4a82e4Svporpo 5326af4a82e4Svporpo %sext = sext i32 %arg to i64 5327af4a82e4Svporpo %fptoui = fptoui float %farg to i32 5328af4a82e4Svporpo %fptosi = fptosi float %farg to i32 5329af4a82e4Svporpo %fpext = fpext float %farg to double 5330af4a82e4Svporpo %ptrtoint = ptrtoint ptr %ptr to i32 5331af4a82e4Svporpo %inttoptr = inttoptr i32 %arg to ptr 5332af4a82e4Svporpo %sitofp = sitofp i32 %arg to float 5333af4a82e4Svporpo %trunc = trunc i32 %arg to i16 5334af4a82e4Svporpo %fptrunc = fptrunc double %darg to float 5335af4a82e4Svporpo %bitcast = bitcast i32 %arg to float 5336af4a82e4Svporpo %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1) 5337af4a82e4Svporpo ret void 5338af4a82e4Svporpo } 5339af4a82e4Svporpo )IR"); 5340af4a82e4Svporpo Function &LLVMF = *M->getFunction("foo"); 5341af4a82e4Svporpo sandboxir::Context Ctx(C); 5342af4a82e4Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 5343af4a82e4Svporpo auto *BB = &*F->begin(); 5344af4a82e4Svporpo auto It = BB->begin(); 5345af4a82e4Svporpo auto *PNNI0 = cast<sandboxir::PossiblyNonNegInst>(&*It++); 5346af4a82e4Svporpo auto *PNNI1 = cast<sandboxir::PossiblyNonNegInst>(&*It++); 5347af4a82e4Svporpo for (auto ItE = BB->end(); It != ItE; ++It) 5348af4a82e4Svporpo EXPECT_FALSE(isa<sandboxir::PossiblyNonNegInst>(&*It++)); 5349af4a82e4Svporpo 5350af4a82e4Svporpo for (auto *PNNI : {PNNI0, PNNI1}) { 5351af4a82e4Svporpo // Check setNonNeg(), hasNonNeg(). 5352af4a82e4Svporpo auto OrigNonNeg = PNNI->hasNonNeg(); 5353af4a82e4Svporpo auto NewNonNeg = true; 5354af4a82e4Svporpo EXPECT_NE(NewNonNeg, OrigNonNeg); 5355af4a82e4Svporpo PNNI->setNonNeg(NewNonNeg); 5356af4a82e4Svporpo EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg); 5357af4a82e4Svporpo PNNI->setNonNeg(OrigNonNeg); 5358af4a82e4Svporpo EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg); 5359af4a82e4Svporpo } 5360af4a82e4Svporpo } 5361af4a82e4Svporpo 53629227fd74Svporpo /// CastInst's subclasses are very similar so we can use a common test function 53639227fd74Svporpo /// for them. 53649227fd74Svporpo template <typename SubclassT, sandboxir::Instruction::Opcode OpcodeT> 5365034f2b38Svporpo void testCastInst(llvm::Module &M, llvm::Type *LLVMSrcTy, 5366034f2b38Svporpo llvm::Type *LLVMDstTy) { 53679227fd74Svporpo Function &LLVMF = *M.getFunction("foo"); 53689227fd74Svporpo sandboxir::Context Ctx(M.getContext()); 53699227fd74Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 5370034f2b38Svporpo sandboxir::Type *SrcTy = Ctx.getType(LLVMSrcTy); 5371034f2b38Svporpo sandboxir::Type *DstTy = Ctx.getType(LLVMDstTy); 53729227fd74Svporpo unsigned ArgIdx = 0; 53739227fd74Svporpo auto *Arg = F->getArg(ArgIdx++); 53749227fd74Svporpo auto *BB = &*F->begin(); 53759227fd74Svporpo auto It = BB->begin(); 53769227fd74Svporpo 53779227fd74Svporpo auto *CI = cast<SubclassT>(&*It++); 53789227fd74Svporpo EXPECT_EQ(CI->getOpcode(), OpcodeT); 53799227fd74Svporpo EXPECT_EQ(CI->getSrcTy(), SrcTy); 53809227fd74Svporpo EXPECT_EQ(CI->getDestTy(), DstTy); 53819227fd74Svporpo auto *Ret = cast<sandboxir::ReturnInst>(&*It++); 53829227fd74Svporpo 53839227fd74Svporpo { 53849227fd74Svporpo // Check create() WhereIt, WhereBB 53859227fd74Svporpo auto *NewI = 5386c029702fSvporpo cast<SubclassT>(SubclassT::create(Arg, DstTy, BB->end(), Ctx, "NewCI")); 53879227fd74Svporpo // Check getOpcode(). 53889227fd74Svporpo EXPECT_EQ(NewI->getOpcode(), OpcodeT); 53899227fd74Svporpo // Check getSrcTy(). 53909227fd74Svporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 53919227fd74Svporpo // Check getDestTy(). 53929227fd74Svporpo EXPECT_EQ(NewI->getDestTy(), DstTy); 53939227fd74Svporpo // Check instr position. 53949227fd74Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 53959227fd74Svporpo EXPECT_EQ(NewI->getPrevNode(), Ret); 53969227fd74Svporpo // Check instr name. 53979227fd74Svporpo EXPECT_EQ(NewI->getName(), "NewCI"); 53989227fd74Svporpo } 53999227fd74Svporpo { 54009227fd74Svporpo // Check create() InsertBefore. 5401c029702fSvporpo auto *NewI = cast<SubclassT>( 5402c029702fSvporpo SubclassT::create(Arg, DstTy, Ret->getIterator(), Ctx, "NewCI")); 54039227fd74Svporpo // Check getOpcode(). 54049227fd74Svporpo EXPECT_EQ(NewI->getOpcode(), OpcodeT); 54059227fd74Svporpo // Check getSrcTy(). 54069227fd74Svporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 54079227fd74Svporpo // Check getDestTy(). 54089227fd74Svporpo EXPECT_EQ(NewI->getDestTy(), DstTy); 54099227fd74Svporpo // Check instr position. 54109227fd74Svporpo EXPECT_EQ(NewI->getNextNode(), Ret); 54119227fd74Svporpo } 54129227fd74Svporpo { 54139227fd74Svporpo // Check create() InsertAtEnd. 54149227fd74Svporpo auto *NewI = 54159227fd74Svporpo cast<SubclassT>(SubclassT::create(Arg, DstTy, 54169227fd74Svporpo /*InsertAtEnd=*/BB, Ctx, "NewCI")); 54179227fd74Svporpo // Check getOpcode(). 54189227fd74Svporpo EXPECT_EQ(NewI->getOpcode(), OpcodeT); 54199227fd74Svporpo // Check getSrcTy(). 54209227fd74Svporpo EXPECT_EQ(NewI->getSrcTy(), Arg->getType()); 54219227fd74Svporpo // Check getDestTy(). 54229227fd74Svporpo EXPECT_EQ(NewI->getDestTy(), DstTy); 54239227fd74Svporpo // Check instr position. 54249227fd74Svporpo EXPECT_EQ(NewI->getNextNode(), nullptr); 54259227fd74Svporpo EXPECT_EQ(NewI->getParent(), BB); 54269227fd74Svporpo } 54279227fd74Svporpo } 54289227fd74Svporpo 5429b6b0a240Svporpo TEST_F(SandboxIRTest, TruncInst) { 5430b6b0a240Svporpo parseIR(C, R"IR( 5431b6b0a240Svporpo define void @foo(i64 %arg) { 5432b6b0a240Svporpo %trunc = trunc i64 %arg to i32 5433b6b0a240Svporpo ret void 5434b6b0a240Svporpo } 5435b6b0a240Svporpo )IR"); 5436b6b0a240Svporpo testCastInst<sandboxir::TruncInst, sandboxir::Instruction::Opcode::Trunc>( 5437b6b0a240Svporpo *M, 5438b6b0a240Svporpo /*SrcTy=*/Type::getInt64Ty(C), /*DstTy=*/Type::getInt32Ty(C)); 5439b6b0a240Svporpo } 5440b6b0a240Svporpo 5441b6b0a240Svporpo TEST_F(SandboxIRTest, ZExtInst) { 5442b6b0a240Svporpo parseIR(C, R"IR( 5443b6b0a240Svporpo define void @foo(i32 %arg) { 5444b6b0a240Svporpo %zext = zext i32 %arg to i64 5445b6b0a240Svporpo ret void 5446b6b0a240Svporpo } 5447b6b0a240Svporpo )IR"); 5448b6b0a240Svporpo testCastInst<sandboxir::ZExtInst, sandboxir::Instruction::Opcode::ZExt>( 5449b6b0a240Svporpo *M, 5450b6b0a240Svporpo /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getInt64Ty(C)); 5451b6b0a240Svporpo } 5452b6b0a240Svporpo 5453b6b0a240Svporpo TEST_F(SandboxIRTest, SExtInst) { 5454b6b0a240Svporpo parseIR(C, R"IR( 5455b6b0a240Svporpo define void @foo(i32 %arg) { 5456b6b0a240Svporpo %sext = sext i32 %arg to i64 5457b6b0a240Svporpo ret void 5458b6b0a240Svporpo } 5459b6b0a240Svporpo )IR"); 5460b6b0a240Svporpo testCastInst<sandboxir::SExtInst, sandboxir::Instruction::Opcode::SExt>( 5461b6b0a240Svporpo *M, 5462b6b0a240Svporpo /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getInt64Ty(C)); 5463b6b0a240Svporpo } 5464b6b0a240Svporpo 5465b6b0a240Svporpo TEST_F(SandboxIRTest, FPTruncInst) { 5466b6b0a240Svporpo parseIR(C, R"IR( 5467b6b0a240Svporpo define void @foo(double %arg) { 5468b6b0a240Svporpo %fptrunc = fptrunc double %arg to float 5469b6b0a240Svporpo ret void 5470b6b0a240Svporpo } 5471b6b0a240Svporpo )IR"); 5472b6b0a240Svporpo testCastInst<sandboxir::FPTruncInst, sandboxir::Instruction::Opcode::FPTrunc>( 5473b6b0a240Svporpo *M, 5474b6b0a240Svporpo /*SrcTy=*/Type::getDoubleTy(C), /*DstTy=*/Type::getFloatTy(C)); 5475b6b0a240Svporpo } 5476b6b0a240Svporpo 5477b6b0a240Svporpo TEST_F(SandboxIRTest, FPExtInst) { 5478b6b0a240Svporpo parseIR(C, R"IR( 5479b6b0a240Svporpo define void @foo(float %arg) { 5480b6b0a240Svporpo %fpext = fpext float %arg to double 5481b6b0a240Svporpo ret void 5482b6b0a240Svporpo } 5483b6b0a240Svporpo )IR"); 5484b6b0a240Svporpo testCastInst<sandboxir::FPExtInst, sandboxir::Instruction::Opcode::FPExt>( 5485b6b0a240Svporpo *M, 5486b6b0a240Svporpo /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getDoubleTy(C)); 5487b6b0a240Svporpo } 5488b6b0a240Svporpo 5489b6b0a240Svporpo TEST_F(SandboxIRTest, UIToFPInst) { 5490b6b0a240Svporpo parseIR(C, R"IR( 5491b6b0a240Svporpo define void @foo(i32 %arg) { 5492b6b0a240Svporpo %uitofp = uitofp i32 %arg to float 5493b6b0a240Svporpo ret void 5494b6b0a240Svporpo } 5495b6b0a240Svporpo )IR"); 5496b6b0a240Svporpo testCastInst<sandboxir::UIToFPInst, sandboxir::Instruction::Opcode::UIToFP>( 5497b6b0a240Svporpo *M, 5498b6b0a240Svporpo /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getFloatTy(C)); 5499b6b0a240Svporpo } 5500b6b0a240Svporpo 55016d3317e5Svporpo TEST_F(SandboxIRTest, SIToFPInst) { 55026d3317e5Svporpo parseIR(C, R"IR( 55036d3317e5Svporpo define void @foo(i32 %arg) { 55046d3317e5Svporpo %sitofp = sitofp i32 %arg to float 55056d3317e5Svporpo ret void 55066d3317e5Svporpo } 55076d3317e5Svporpo )IR"); 55089227fd74Svporpo testCastInst<sandboxir::SIToFPInst, sandboxir::Instruction::Opcode::SIToFP>( 55099227fd74Svporpo *M, 55109227fd74Svporpo /*SrcTy=*/Type::getInt32Ty(C), 55119227fd74Svporpo /*DstTy=*/Type::getFloatTy(C)); 55126d3317e5Svporpo } 55136d3317e5Svporpo 55148b17b129Svporpo TEST_F(SandboxIRTest, FPToUIInst) { 55158b17b129Svporpo parseIR(C, R"IR( 55168b17b129Svporpo define void @foo(float %arg) { 55178b17b129Svporpo %fptoui = fptoui float %arg to i32 55188b17b129Svporpo ret void 55198b17b129Svporpo } 55208b17b129Svporpo )IR"); 55219227fd74Svporpo testCastInst<sandboxir::FPToUIInst, sandboxir::Instruction::Opcode::FPToUI>( 55228b17b129Svporpo 55239227fd74Svporpo *M, /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getInt32Ty(C)); 55248b17b129Svporpo } 55258b17b129Svporpo 55269718f3deSvporpo TEST_F(SandboxIRTest, FPToSIInst) { 55279718f3deSvporpo parseIR(C, R"IR( 55289718f3deSvporpo define void @foo(float %arg) { 55299718f3deSvporpo %fptosi = fptosi float %arg to i32 55309718f3deSvporpo ret void 55319718f3deSvporpo } 55329718f3deSvporpo )IR"); 55339227fd74Svporpo testCastInst<sandboxir::FPToSIInst, sandboxir::Instruction::Opcode::FPToSI>( 55349227fd74Svporpo *M, /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getInt32Ty(C)); 55359718f3deSvporpo } 55369718f3deSvporpo 5537f0197a75Svporpo TEST_F(SandboxIRTest, IntToPtrInst) { 5538f0197a75Svporpo parseIR(C, R"IR( 5539f0197a75Svporpo define void @foo(i32 %arg) { 5540f0197a75Svporpo %inttoptr = inttoptr i32 %arg to ptr 5541f0197a75Svporpo ret void 5542f0197a75Svporpo } 5543f0197a75Svporpo )IR"); 55449227fd74Svporpo testCastInst<sandboxir::IntToPtrInst, 55459227fd74Svporpo sandboxir::Instruction::Opcode::IntToPtr>( 55469227fd74Svporpo *M, 55479227fd74Svporpo /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/PointerType::get(C, 0)); 5548f0197a75Svporpo } 5549f0197a75Svporpo 55503cc288afSvporpo TEST_F(SandboxIRTest, PtrToIntInst) { 55513cc288afSvporpo parseIR(C, R"IR( 55523cc288afSvporpo define void @foo(ptr %ptr) { 55533cc288afSvporpo %ptrtoint = ptrtoint ptr %ptr to i32 55543cc288afSvporpo ret void 55553cc288afSvporpo } 55563cc288afSvporpo )IR"); 55579227fd74Svporpo testCastInst<sandboxir::PtrToIntInst, 55589227fd74Svporpo sandboxir::Instruction::Opcode::PtrToInt>( 55599227fd74Svporpo *M, /*SrcTy=*/PointerType::get(C, 0), /*DstTy=*/Type::getInt32Ty(C)); 55603cc288afSvporpo } 5561e59c8322Svporpo 5562e59c8322Svporpo TEST_F(SandboxIRTest, BitCastInst) { 5563e59c8322Svporpo parseIR(C, R"IR( 5564e59c8322Svporpo define void @foo(i32 %arg) { 5565e59c8322Svporpo %bitcast = bitcast i32 %arg to float 5566e59c8322Svporpo ret void 5567e59c8322Svporpo } 5568e59c8322Svporpo )IR"); 55699227fd74Svporpo testCastInst<sandboxir::BitCastInst, sandboxir::Instruction::Opcode::BitCast>( 55709227fd74Svporpo *M, 55719227fd74Svporpo /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getFloatTy(C)); 5572e59c8322Svporpo } 5573d36c9f82Svporpo 5574d36c9f82Svporpo TEST_F(SandboxIRTest, AddrSpaceCastInst) { 5575d36c9f82Svporpo parseIR(C, R"IR( 5576d36c9f82Svporpo define void @foo(ptr %ptr) { 5577d36c9f82Svporpo %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1) 5578d36c9f82Svporpo ret void 5579d36c9f82Svporpo } 5580d36c9f82Svporpo )IR"); 55819227fd74Svporpo Type *Tptr0 = PointerType::get(C, 0); 55829227fd74Svporpo Type *Tptr1 = PointerType::get(C, 1); 55839227fd74Svporpo testCastInst<sandboxir::AddrSpaceCastInst, 55849227fd74Svporpo sandboxir::Instruction::Opcode::AddrSpaceCast>(*M, 55859227fd74Svporpo /*SrcTy=*/Tptr0, 55869227fd74Svporpo /*DstTy=*/Tptr1); 5587d36c9f82Svporpo Function &LLVMF = *M->getFunction("foo"); 5588d36c9f82Svporpo sandboxir::Context Ctx(C); 5589d36c9f82Svporpo sandboxir::Function *F = Ctx.createFunction(&LLVMF); 5590d36c9f82Svporpo unsigned ArgIdx = 0; 5591d36c9f82Svporpo auto *Arg = F->getArg(ArgIdx++); 5592d36c9f82Svporpo auto *BB = &*F->begin(); 5593d36c9f82Svporpo auto It = BB->begin(); 5594d36c9f82Svporpo 5595d36c9f82Svporpo auto *AddrSpaceCast = cast<sandboxir::AddrSpaceCastInst>(&*It++); 5596d36c9f82Svporpo EXPECT_EQ(AddrSpaceCast->getOpcode(), 5597d36c9f82Svporpo sandboxir::Instruction::Opcode::AddrSpaceCast); 5598d36c9f82Svporpo EXPECT_EQ(AddrSpaceCast->getPointerOperand(), Arg); 5599d36c9f82Svporpo EXPECT_EQ(sandboxir::AddrSpaceCastInst::getPointerOperandIndex(), 0u); 5600d36c9f82Svporpo EXPECT_EQ(AddrSpaceCast->getSrcAddressSpace(), 56019227fd74Svporpo cast<PointerType>(Tptr0)->getPointerAddressSpace()); 5602d36c9f82Svporpo EXPECT_EQ(AddrSpaceCast->getDestAddressSpace(), 5603d36c9f82Svporpo cast<PointerType>(Tptr1)->getPointerAddressSpace()); 5604d36c9f82Svporpo } 56053403b593SSterling-Augustine 56063403b593SSterling-Augustine TEST_F(SandboxIRTest, PHINode) { 56073403b593SSterling-Augustine parseIR(C, R"IR( 56083403b593SSterling-Augustine define void @foo(i32 %arg) { 56093403b593SSterling-Augustine bb1: 56103403b593SSterling-Augustine br label %bb2 56113403b593SSterling-Augustine 56123403b593SSterling-Augustine bb2: 561366f4e3f8SSterling-Augustine %phi = phi i32 [ %arg, %bb1 ], [ 0, %bb2 ], [ 1, %bb3 ], [ 2, %bb4 ], [ 3, %bb5 ] 56143403b593SSterling-Augustine br label %bb2 56153403b593SSterling-Augustine 56163403b593SSterling-Augustine bb3: 561766f4e3f8SSterling-Augustine br label %bb2 561866f4e3f8SSterling-Augustine 561966f4e3f8SSterling-Augustine bb4: 562066f4e3f8SSterling-Augustine br label %bb2 562166f4e3f8SSterling-Augustine 562266f4e3f8SSterling-Augustine bb5: 562366f4e3f8SSterling-Augustine br label %bb2 56243403b593SSterling-Augustine ret void 56253403b593SSterling-Augustine } 56263403b593SSterling-Augustine )IR"); 56273403b593SSterling-Augustine Function &LLVMF = *M->getFunction("foo"); 56283403b593SSterling-Augustine auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1"); 56293403b593SSterling-Augustine auto *LLVMBB2 = getBasicBlockByName(LLVMF, "bb2"); 56303403b593SSterling-Augustine auto *LLVMBB3 = getBasicBlockByName(LLVMF, "bb3"); 56313403b593SSterling-Augustine auto LLVMIt = LLVMBB2->begin(); 56323403b593SSterling-Augustine auto *LLVMPHI = cast<llvm::PHINode>(&*LLVMIt++); 56333403b593SSterling-Augustine sandboxir::Context Ctx(C); 56343403b593SSterling-Augustine sandboxir::Function *F = Ctx.createFunction(&LLVMF); 56353403b593SSterling-Augustine auto *Arg = F->getArg(0); 56363403b593SSterling-Augustine auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1)); 56373403b593SSterling-Augustine auto *BB2 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB2)); 56383403b593SSterling-Augustine auto *BB3 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB3)); 56393403b593SSterling-Augustine auto It = BB2->begin(); 56403403b593SSterling-Augustine // Check classof(). 56413403b593SSterling-Augustine auto *PHI = cast<sandboxir::PHINode>(&*It++); 56423403b593SSterling-Augustine auto *Br = cast<sandboxir::BranchInst>(&*It++); 56433403b593SSterling-Augustine // Check blocks(). 56443403b593SSterling-Augustine EXPECT_EQ(range_size(PHI->blocks()), range_size(LLVMPHI->blocks())); 56453403b593SSterling-Augustine auto BlockIt = PHI->block_begin(); 56463403b593SSterling-Augustine for (llvm::BasicBlock *LLVMBB : LLVMPHI->blocks()) { 56473403b593SSterling-Augustine sandboxir::BasicBlock *BB = *BlockIt++; 56483403b593SSterling-Augustine EXPECT_EQ(BB, Ctx.getValue(LLVMBB)); 56493403b593SSterling-Augustine } 56503403b593SSterling-Augustine // Check incoming_values(). 56513403b593SSterling-Augustine EXPECT_EQ(range_size(PHI->incoming_values()), 56523403b593SSterling-Augustine range_size(LLVMPHI->incoming_values())); 56533403b593SSterling-Augustine auto IncIt = PHI->incoming_values().begin(); 56543403b593SSterling-Augustine for (llvm::Value *LLVMV : LLVMPHI->incoming_values()) { 56553403b593SSterling-Augustine sandboxir::Value *IncV = *IncIt++; 56563403b593SSterling-Augustine EXPECT_EQ(IncV, Ctx.getValue(LLVMV)); 56573403b593SSterling-Augustine } 56583403b593SSterling-Augustine // Check getNumIncomingValues(). 56593403b593SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), LLVMPHI->getNumIncomingValues()); 56603403b593SSterling-Augustine // Check getIncomingValue(). 56613403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingValue(0), 56623403b593SSterling-Augustine Ctx.getValue(LLVMPHI->getIncomingValue(0))); 56633403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingValue(1), 56643403b593SSterling-Augustine Ctx.getValue(LLVMPHI->getIncomingValue(1))); 56653403b593SSterling-Augustine // Check setIncomingValue(). 56663403b593SSterling-Augustine auto *OrigV = PHI->getIncomingValue(0); 56673403b593SSterling-Augustine PHI->setIncomingValue(0, PHI); 56683403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingValue(0), PHI); 56693403b593SSterling-Augustine PHI->setIncomingValue(0, OrigV); 56703403b593SSterling-Augustine // Check getOperandNumForIncomingValue(). 56713403b593SSterling-Augustine EXPECT_EQ(sandboxir::PHINode::getOperandNumForIncomingValue(0), 56723403b593SSterling-Augustine llvm::PHINode::getOperandNumForIncomingValue(0)); 56733403b593SSterling-Augustine // Check getIncomingValueNumForOperand(). 56743403b593SSterling-Augustine EXPECT_EQ(sandboxir::PHINode::getIncomingValueNumForOperand(0), 56753403b593SSterling-Augustine llvm::PHINode::getIncomingValueNumForOperand(0)); 56763403b593SSterling-Augustine // Check getIncomingBlock(unsigned). 56773403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(0), 56783403b593SSterling-Augustine Ctx.getValue(LLVMPHI->getIncomingBlock(0))); 56793403b593SSterling-Augustine // Check getIncomingBlock(Use). 56803403b593SSterling-Augustine llvm::Use &LLVMUse = LLVMPHI->getOperandUse(0); 56813403b593SSterling-Augustine sandboxir::Use Use = PHI->getOperandUse(0); 56823403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(Use), 56833403b593SSterling-Augustine Ctx.getValue(LLVMPHI->getIncomingBlock(LLVMUse))); 56843403b593SSterling-Augustine // Check setIncomingBlock(). 56853403b593SSterling-Augustine sandboxir::BasicBlock *OrigBB = PHI->getIncomingBlock(0); 56863403b593SSterling-Augustine EXPECT_NE(OrigBB, BB2); 56873403b593SSterling-Augustine PHI->setIncomingBlock(0, BB2); 56883403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(0), BB2); 56893403b593SSterling-Augustine PHI->setIncomingBlock(0, OrigBB); 56903403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(0), OrigBB); 56913403b593SSterling-Augustine // Check addIncoming(). 56923403b593SSterling-Augustine unsigned OrigNumIncoming = PHI->getNumIncomingValues(); 56933403b593SSterling-Augustine PHI->addIncoming(Arg, BB3); 56943403b593SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), LLVMPHI->getNumIncomingValues()); 56953403b593SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming + 1); 56963403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingValue(OrigNumIncoming), Arg); 56973403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(OrigNumIncoming), BB3); 56983403b593SSterling-Augustine // Check removeIncomingValue(unsigned). 56993403b593SSterling-Augustine PHI->removeIncomingValue(OrigNumIncoming); 57003403b593SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming); 57013403b593SSterling-Augustine // Check removeIncomingValue(BasicBlock *). 57023403b593SSterling-Augustine PHI->addIncoming(Arg, BB3); 57033403b593SSterling-Augustine PHI->removeIncomingValue(BB3); 57043403b593SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming); 57053403b593SSterling-Augustine // Check getBasicBlockIndex(). 57063403b593SSterling-Augustine EXPECT_EQ(PHI->getBasicBlockIndex(BB1), LLVMPHI->getBasicBlockIndex(LLVMBB1)); 57073403b593SSterling-Augustine // Check getIncomingValueForBlock(). 57083403b593SSterling-Augustine EXPECT_EQ(PHI->getIncomingValueForBlock(BB1), 57093403b593SSterling-Augustine Ctx.getValue(LLVMPHI->getIncomingValueForBlock(LLVMBB1))); 57103403b593SSterling-Augustine // Check hasConstantValue(). 57113403b593SSterling-Augustine llvm::Value *ConstV = LLVMPHI->hasConstantValue(); 57123403b593SSterling-Augustine EXPECT_EQ(PHI->hasConstantValue(), 57133403b593SSterling-Augustine ConstV != nullptr ? Ctx.getValue(ConstV) : nullptr); 57143403b593SSterling-Augustine // Check hasConstantOrUndefValue(). 57153403b593SSterling-Augustine EXPECT_EQ(PHI->hasConstantOrUndefValue(), LLVMPHI->hasConstantOrUndefValue()); 57163403b593SSterling-Augustine // Check isComplete(). 57173403b593SSterling-Augustine EXPECT_EQ(PHI->isComplete(), LLVMPHI->isComplete()); 571866f4e3f8SSterling-Augustine // Check replaceIncomingValueIf 571966f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), 5u); 572066f4e3f8SSterling-Augustine auto *RemainBB0 = PHI->getIncomingBlock(0); 572166f4e3f8SSterling-Augustine auto *RemoveBB0 = PHI->getIncomingBlock(1); 572266f4e3f8SSterling-Augustine auto *RemainBB1 = PHI->getIncomingBlock(2); 572366f4e3f8SSterling-Augustine auto *RemoveBB1 = PHI->getIncomingBlock(3); 572466f4e3f8SSterling-Augustine auto *RemainBB2 = PHI->getIncomingBlock(4); 572566f4e3f8SSterling-Augustine PHI->removeIncomingValueIf([&](unsigned Idx) { 572666f4e3f8SSterling-Augustine return PHI->getIncomingBlock(Idx) == RemoveBB0 || 572766f4e3f8SSterling-Augustine PHI->getIncomingBlock(Idx) == RemoveBB1; 572866f4e3f8SSterling-Augustine }); 572966f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getNumIncomingValues(), 3u); 573066f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(0), RemainBB0); 573166f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(1), RemainBB1); 573266f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(2), RemainBB2); 573366f4e3f8SSterling-Augustine // Check replaceIncomingBlockWith 573466f4e3f8SSterling-Augustine OrigBB = RemainBB0; 573566f4e3f8SSterling-Augustine auto *NewBB = RemainBB1; 573666f4e3f8SSterling-Augustine EXPECT_NE(NewBB, OrigBB); 573766f4e3f8SSterling-Augustine PHI->replaceIncomingBlockWith(OrigBB, NewBB); 573866f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(0), NewBB); 573966f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(1), RemainBB1); 574066f4e3f8SSterling-Augustine EXPECT_EQ(PHI->getIncomingBlock(2), RemainBB2); 57413403b593SSterling-Augustine // Check create(). 5742c029702fSvporpo auto *NewPHI = cast<sandboxir::PHINode>(sandboxir::PHINode::create( 5743c029702fSvporpo PHI->getType(), 0, Br->getIterator(), Ctx, "NewPHI")); 57443403b593SSterling-Augustine EXPECT_EQ(NewPHI->getType(), PHI->getType()); 57453403b593SSterling-Augustine EXPECT_EQ(NewPHI->getNextNode(), Br); 57463403b593SSterling-Augustine EXPECT_EQ(NewPHI->getName(), "NewPHI"); 57473403b593SSterling-Augustine EXPECT_EQ(NewPHI->getNumIncomingValues(), 0u); 57483403b593SSterling-Augustine for (auto [Idx, V] : enumerate(PHI->incoming_values())) { 57493403b593SSterling-Augustine sandboxir::BasicBlock *IncBB = PHI->getIncomingBlock(Idx); 57503403b593SSterling-Augustine NewPHI->addIncoming(V, IncBB); 57513403b593SSterling-Augustine } 57523403b593SSterling-Augustine EXPECT_EQ(NewPHI->getNumIncomingValues(), PHI->getNumIncomingValues()); 57533403b593SSterling-Augustine } 5754e5464309SJulius Alexandre 5755840da2e8SSterling-Augustine static void checkSwapOperands(sandboxir::Context &Ctx, 5756840da2e8SSterling-Augustine llvm::sandboxir::CmpInst *Cmp, 5757840da2e8SSterling-Augustine llvm::CmpInst *LLVMCmp) { 5758840da2e8SSterling-Augustine auto OrigOp0 = Cmp->getOperand(0); 5759840da2e8SSterling-Augustine auto OrigOp1 = Cmp->getOperand(1); 5760840da2e8SSterling-Augustine EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(0)), OrigOp0); 5761840da2e8SSterling-Augustine EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(1)), OrigOp1); 5762840da2e8SSterling-Augustine // This checks the dispatch mechanism in CmpInst, as well as 5763840da2e8SSterling-Augustine // the specific implementations. 5764840da2e8SSterling-Augustine Cmp->swapOperands(); 5765840da2e8SSterling-Augustine EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(1)), OrigOp0); 5766840da2e8SSterling-Augustine EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(0)), OrigOp1); 5767840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getOperand(0), OrigOp1); 5768840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getOperand(1), OrigOp0); 5769840da2e8SSterling-Augustine // Undo it to keep the rest of the test consistent 5770840da2e8SSterling-Augustine Cmp->swapOperands(); 5771840da2e8SSterling-Augustine } 5772840da2e8SSterling-Augustine 5773840da2e8SSterling-Augustine static void checkCommonPredicates(sandboxir::CmpInst *Cmp, 5774840da2e8SSterling-Augustine llvm::CmpInst *LLVMCmp) { 5775840da2e8SSterling-Augustine // Check proper creation 5776840da2e8SSterling-Augustine auto Pred = Cmp->getPredicate(); 5777840da2e8SSterling-Augustine auto LLVMPred = LLVMCmp->getPredicate(); 5778840da2e8SSterling-Augustine EXPECT_EQ(Pred, LLVMPred); 5779840da2e8SSterling-Augustine // Check setPredicate 5780840da2e8SSterling-Augustine Cmp->setPredicate(llvm::CmpInst::FCMP_FALSE); 5781840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getPredicate(), llvm::CmpInst::FCMP_FALSE); 5782840da2e8SSterling-Augustine EXPECT_EQ(LLVMCmp->getPredicate(), llvm::CmpInst::FCMP_FALSE); 5783840da2e8SSterling-Augustine Cmp->setPredicate(Pred); 5784840da2e8SSterling-Augustine EXPECT_EQ(LLVMCmp->getPredicate(), Pred); 5785840da2e8SSterling-Augustine // Ensure the accessors properly forward to the underlying implementation 5786840da2e8SSterling-Augustine EXPECT_STREQ(sandboxir::CmpInst::getPredicateName(Pred).data(), 5787840da2e8SSterling-Augustine llvm::CmpInst::getPredicateName(LLVMPred).data()); 5788840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isFPPredicate(), LLVMCmp->isFPPredicate()); 5789840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isIntPredicate(), LLVMCmp->isIntPredicate()); 5790840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getInversePredicate(), LLVMCmp->getInversePredicate()); 5791840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getOrderedPredicate(), LLVMCmp->getOrderedPredicate()); 5792840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getUnorderedPredicate(), LLVMCmp->getUnorderedPredicate()); 5793840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getSwappedPredicate(), LLVMCmp->getSwappedPredicate()); 5794840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isStrictPredicate(), LLVMCmp->isStrictPredicate()); 5795840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isNonStrictPredicate(), LLVMCmp->isNonStrictPredicate()); 5796840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isRelational(), LLVMCmp->isRelational()); 5797840da2e8SSterling-Augustine if (Cmp->isRelational()) { 5798840da2e8SSterling-Augustine EXPECT_EQ(Cmp->getFlippedStrictnessPredicate(), 5799840da2e8SSterling-Augustine LLVMCmp->getFlippedStrictnessPredicate()); 5800840da2e8SSterling-Augustine } 5801840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isCommutative(), LLVMCmp->isCommutative()); 5802840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isTrueWhenEqual(), LLVMCmp->isTrueWhenEqual()); 5803840da2e8SSterling-Augustine EXPECT_EQ(Cmp->isFalseWhenEqual(), LLVMCmp->isFalseWhenEqual()); 5804840da2e8SSterling-Augustine EXPECT_EQ(sandboxir::CmpInst::isOrdered(Pred), 5805840da2e8SSterling-Augustine llvm::CmpInst::isOrdered(LLVMPred)); 5806840da2e8SSterling-Augustine EXPECT_EQ(sandboxir::CmpInst::isUnordered(Pred), 5807840da2e8SSterling-Augustine llvm::CmpInst::isUnordered(LLVMPred)); 5808840da2e8SSterling-Augustine } 5809840da2e8SSterling-Augustine 5810840da2e8SSterling-Augustine TEST_F(SandboxIRTest, ICmpInst) { 5811840da2e8SSterling-Augustine SCOPED_TRACE("SandboxIRTest sandboxir::ICmpInst tests"); 5812840da2e8SSterling-Augustine parseIR(C, R"IR( 5813840da2e8SSterling-Augustine define void @foo(i32 %i0, i32 %i1) { 5814840da2e8SSterling-Augustine bb: 5815840da2e8SSterling-Augustine %ine = icmp ne i32 %i0, %i1 5816840da2e8SSterling-Augustine %iugt = icmp ugt i32 %i0, %i1 5817840da2e8SSterling-Augustine %iuge = icmp uge i32 %i0, %i1 5818840da2e8SSterling-Augustine %iult = icmp ult i32 %i0, %i1 5819840da2e8SSterling-Augustine %iule = icmp ule i32 %i0, %i1 5820840da2e8SSterling-Augustine %isgt = icmp sgt i32 %i0, %i1 5821840da2e8SSterling-Augustine %isle = icmp sle i32 %i0, %i1 5822840da2e8SSterling-Augustine %ieg = icmp eq i32 %i0, %i1 5823840da2e8SSterling-Augustine ret void 5824840da2e8SSterling-Augustine } 5825840da2e8SSterling-Augustine )IR"); 5826840da2e8SSterling-Augustine Function &LLVMF = *M->getFunction("foo"); 5827840da2e8SSterling-Augustine sandboxir::Context Ctx(C); 5828840da2e8SSterling-Augustine [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 5829840da2e8SSterling-Augustine 5830840da2e8SSterling-Augustine auto *LLVMBB = getBasicBlockByName(LLVMF, "bb"); 5831840da2e8SSterling-Augustine auto LLVMIt = LLVMBB->begin(); 5832840da2e8SSterling-Augustine auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB)); 5833840da2e8SSterling-Augustine auto It = BB->begin(); 5834840da2e8SSterling-Augustine // Check classof() 5835840da2e8SSterling-Augustine while (auto *ICmp = dyn_cast<sandboxir::ICmpInst>(&*It++)) { 5836840da2e8SSterling-Augustine auto *LLVMICmp = cast<llvm::ICmpInst>(&*LLVMIt++); 5837840da2e8SSterling-Augustine checkSwapOperands(Ctx, ICmp, LLVMICmp); 5838840da2e8SSterling-Augustine checkCommonPredicates(ICmp, LLVMICmp); 5839840da2e8SSterling-Augustine EXPECT_EQ(ICmp->isSigned(), LLVMICmp->isSigned()); 5840840da2e8SSterling-Augustine EXPECT_EQ(ICmp->isUnsigned(), LLVMICmp->isUnsigned()); 5841840da2e8SSterling-Augustine EXPECT_EQ(ICmp->getSignedPredicate(), LLVMICmp->getSignedPredicate()); 5842840da2e8SSterling-Augustine EXPECT_EQ(ICmp->getUnsignedPredicate(), LLVMICmp->getUnsignedPredicate()); 5843840da2e8SSterling-Augustine } 584422d4ff15Svporpo auto *NewCmp = cast<sandboxir::CmpInst>( 5845840da2e8SSterling-Augustine sandboxir::CmpInst::create(llvm::CmpInst::ICMP_ULE, F.getArg(0), 584622d4ff15Svporpo F.getArg(1), BB->begin(), Ctx, "NewCmp")); 5847840da2e8SSterling-Augustine EXPECT_EQ(NewCmp, &*BB->begin()); 5848840da2e8SSterling-Augustine EXPECT_EQ(NewCmp->getPredicate(), llvm::CmpInst::ICMP_ULE); 5849840da2e8SSterling-Augustine EXPECT_EQ(NewCmp->getOperand(0), F.getArg(0)); 5850840da2e8SSterling-Augustine EXPECT_EQ(NewCmp->getOperand(1), F.getArg(1)); 5851840da2e8SSterling-Augustine #ifndef NDEBUG 5852840da2e8SSterling-Augustine EXPECT_EQ(NewCmp->getName(), "NewCmp"); 5853840da2e8SSterling-Augustine #endif // NDEBUG 5854840da2e8SSterling-Augustine // TODO: Improve this test when sandboxir::VectorType is more completely 5855840da2e8SSterling-Augustine // implemented. 5856840da2e8SSterling-Augustine sandboxir::Type *RT = 5857840da2e8SSterling-Augustine sandboxir::CmpInst::makeCmpResultType(F.getArg(0)->getType()); 5858840da2e8SSterling-Augustine EXPECT_TRUE(RT->isIntegerTy(1)); // Only one bit in a single comparison 585922d4ff15Svporpo 586022d4ff15Svporpo { 586122d4ff15Svporpo // Check create() when operands are constant. 586222d4ff15Svporpo auto *Const42 = 586322d4ff15Svporpo sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42); 586422d4ff15Svporpo auto *NewConstCmp = 586522d4ff15Svporpo sandboxir::CmpInst::create(llvm::CmpInst::ICMP_ULE, Const42, Const42, 586622d4ff15Svporpo BB->begin(), Ctx, "NewConstCmp"); 586722d4ff15Svporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewConstCmp)); 586822d4ff15Svporpo } 5869840da2e8SSterling-Augustine } 5870840da2e8SSterling-Augustine 5871840da2e8SSterling-Augustine TEST_F(SandboxIRTest, FCmpInst) { 5872840da2e8SSterling-Augustine SCOPED_TRACE("SandboxIRTest sandboxir::FCmpInst tests"); 5873840da2e8SSterling-Augustine parseIR(C, R"IR( 5874840da2e8SSterling-Augustine define void @foo(float %f0, float %f1) { 5875840da2e8SSterling-Augustine bb: 5876840da2e8SSterling-Augustine %ffalse = fcmp false float %f0, %f1 5877840da2e8SSterling-Augustine %foeq = fcmp oeq float %f0, %f1 5878840da2e8SSterling-Augustine %fogt = fcmp ogt float %f0, %f1 5879840da2e8SSterling-Augustine %folt = fcmp olt float %f0, %f1 5880840da2e8SSterling-Augustine %fole = fcmp ole float %f0, %f1 5881840da2e8SSterling-Augustine %fone = fcmp one float %f0, %f1 5882840da2e8SSterling-Augustine %ford = fcmp ord float %f0, %f1 5883840da2e8SSterling-Augustine %funo = fcmp uno float %f0, %f1 5884840da2e8SSterling-Augustine %fueq = fcmp ueq float %f0, %f1 5885840da2e8SSterling-Augustine %fugt = fcmp ugt float %f0, %f1 5886840da2e8SSterling-Augustine %fuge = fcmp uge float %f0, %f1 5887840da2e8SSterling-Augustine %fult = fcmp ult float %f0, %f1 5888840da2e8SSterling-Augustine %fule = fcmp ule float %f0, %f1 5889840da2e8SSterling-Augustine %fune = fcmp une float %f0, %f1 5890840da2e8SSterling-Augustine %ftrue = fcmp true float %f0, %f1 5891840da2e8SSterling-Augustine ret void 5892840da2e8SSterling-Augustine bb1: 5893840da2e8SSterling-Augustine %copyfrom = fadd reassoc float %f0, 42.0 5894840da2e8SSterling-Augustine ret void 5895840da2e8SSterling-Augustine } 5896840da2e8SSterling-Augustine )IR"); 5897840da2e8SSterling-Augustine Function &LLVMF = *M->getFunction("foo"); 5898840da2e8SSterling-Augustine sandboxir::Context Ctx(C); 5899840da2e8SSterling-Augustine [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF); 5900840da2e8SSterling-Augustine 5901840da2e8SSterling-Augustine auto *LLVMBB = getBasicBlockByName(LLVMF, "bb"); 5902840da2e8SSterling-Augustine auto LLVMIt = LLVMBB->begin(); 5903840da2e8SSterling-Augustine auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB)); 5904840da2e8SSterling-Augustine auto It = BB->begin(); 5905840da2e8SSterling-Augustine // Check classof() 5906840da2e8SSterling-Augustine while (auto *FCmp = dyn_cast<sandboxir::ICmpInst>(&*It++)) { 5907840da2e8SSterling-Augustine auto *LLVMFCmp = cast<llvm::ICmpInst>(&*LLVMIt++); 5908840da2e8SSterling-Augustine checkSwapOperands(Ctx, FCmp, LLVMFCmp); 5909840da2e8SSterling-Augustine checkCommonPredicates(FCmp, LLVMFCmp); 5910840da2e8SSterling-Augustine } 5911840da2e8SSterling-Augustine 5912840da2e8SSterling-Augustine auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1"); 5913840da2e8SSterling-Augustine auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1)); 5914840da2e8SSterling-Augustine auto It1 = BB1->begin(); 5915840da2e8SSterling-Augustine auto *CopyFrom = &*It1++; 5916840da2e8SSterling-Augustine CopyFrom->setFastMathFlags(FastMathFlags::getFast()); 5917840da2e8SSterling-Augustine 5918840da2e8SSterling-Augustine // create with default flags 591922d4ff15Svporpo auto *NewFCmp = cast<sandboxir::CmpInst>(sandboxir::CmpInst::create( 592022d4ff15Svporpo llvm::CmpInst::FCMP_ONE, F.getArg(0), F.getArg(1), It1, Ctx, "NewFCmp")); 5921840da2e8SSterling-Augustine EXPECT_EQ(NewFCmp->getPredicate(), llvm::CmpInst::FCMP_ONE); 5922840da2e8SSterling-Augustine EXPECT_EQ(NewFCmp->getOperand(0), F.getArg(0)); 5923840da2e8SSterling-Augustine EXPECT_EQ(NewFCmp->getOperand(1), F.getArg(1)); 5924840da2e8SSterling-Augustine #ifndef NDEBUG 5925840da2e8SSterling-Augustine EXPECT_EQ(NewFCmp->getName(), "NewFCmp"); 5926840da2e8SSterling-Augustine #endif // NDEBUG 5927840da2e8SSterling-Augustine FastMathFlags DefaultFMF = NewFCmp->getFastMathFlags(); 5928840da2e8SSterling-Augustine EXPECT_TRUE(CopyFrom->getFastMathFlags() != DefaultFMF); 5929840da2e8SSterling-Augustine // create with copied flags 593022d4ff15Svporpo auto *NewFCmpFlags = 593122d4ff15Svporpo cast<sandboxir::CmpInst>(sandboxir::CmpInst::createWithCopiedFlags( 5932ed5088a2Svporpo llvm::CmpInst::FCMP_ONE, F.getArg(0), F.getArg(1), CopyFrom, It1, Ctx, 593322d4ff15Svporpo "NewFCmpFlags")); 5934840da2e8SSterling-Augustine EXPECT_FALSE(NewFCmpFlags->getFastMathFlags() != 5935840da2e8SSterling-Augustine CopyFrom->getFastMathFlags()); 5936840da2e8SSterling-Augustine EXPECT_EQ(NewFCmpFlags->getPredicate(), llvm::CmpInst::FCMP_ONE); 5937840da2e8SSterling-Augustine EXPECT_EQ(NewFCmpFlags->getOperand(0), F.getArg(0)); 5938840da2e8SSterling-Augustine EXPECT_EQ(NewFCmpFlags->getOperand(1), F.getArg(1)); 5939840da2e8SSterling-Augustine #ifndef NDEBUG 5940840da2e8SSterling-Augustine EXPECT_EQ(NewFCmpFlags->getName(), "NewFCmpFlags"); 5941840da2e8SSterling-Augustine #endif // NDEBUG 594222d4ff15Svporpo 594322d4ff15Svporpo { 594422d4ff15Svporpo // Check create() when operands are constant. 594522d4ff15Svporpo auto *Const42 = 594622d4ff15Svporpo sandboxir::ConstantFP::get(sandboxir::Type::getFloatTy(Ctx), 42.0); 594722d4ff15Svporpo auto *NewConstCmp = 594822d4ff15Svporpo sandboxir::CmpInst::create(llvm::CmpInst::FCMP_ULE, Const42, Const42, 594922d4ff15Svporpo BB->begin(), Ctx, "NewConstCmp"); 595022d4ff15Svporpo EXPECT_TRUE(isa<sandboxir::Constant>(NewConstCmp)); 595122d4ff15Svporpo } 5952840da2e8SSterling-Augustine } 5953840da2e8SSterling-Augustine 5954e5464309SJulius Alexandre TEST_F(SandboxIRTest, UnreachableInst) { 5955e5464309SJulius Alexandre parseIR(C, R"IR( 5956e5464309SJulius Alexandre define void @foo() { 5957e5464309SJulius Alexandre unreachable 5958e5464309SJulius Alexandre } 5959e5464309SJulius Alexandre )IR"); 5960e5464309SJulius Alexandre llvm::Function *LLVMF = &*M->getFunction("foo"); 5961e5464309SJulius Alexandre sandboxir::Context Ctx(C); 5962e5464309SJulius Alexandre sandboxir::Function *F = Ctx.createFunction(LLVMF); 5963e5464309SJulius Alexandre auto *BB = &*F->begin(); 5964e5464309SJulius Alexandre auto It = BB->begin(); 5965e5464309SJulius Alexandre auto *UI = cast<sandboxir::UnreachableInst>(&*It++); 5966e5464309SJulius Alexandre 5967e5464309SJulius Alexandre EXPECT_EQ(UI->getNumSuccessors(), 0u); 5968e5464309SJulius Alexandre EXPECT_EQ(UI->getNumOfIRInstrs(), 1u); 5969e5464309SJulius Alexandre // Check create(InsertBefore) 5970e5464309SJulius Alexandre sandboxir::UnreachableInst *NewUI = 59713a47bf63Svporpo sandboxir::UnreachableInst::create(UI->getIterator(), Ctx); 5972e5464309SJulius Alexandre EXPECT_EQ(NewUI->getNextNode(), UI); 5973e5464309SJulius Alexandre // Check create(InsertAtEnd) 5974e5464309SJulius Alexandre sandboxir::UnreachableInst *NewUIEnd = 5975e5464309SJulius Alexandre sandboxir::UnreachableInst::create(/*InsertAtEnd=*/BB, Ctx); 5976e5464309SJulius Alexandre EXPECT_EQ(NewUIEnd->getParent(), BB); 5977e5464309SJulius Alexandre EXPECT_EQ(NewUIEnd->getNextNode(), nullptr); 5978e5464309SJulius Alexandre } 59793cf1018fSvporpo 59803cf1018fSvporpo /// Makes sure that all Instruction sub-classes have a classof(). 59813cf1018fSvporpo TEST_F(SandboxIRTest, CheckClassof) { 59823cf1018fSvporpo #define DEF_INSTR(ID, OPC, CLASS) \ 59833cf1018fSvporpo EXPECT_NE(&sandboxir::CLASS::classof, &sandboxir::Instruction::classof); 59849e85937bSvporpo #include "llvm/SandboxIR/Values.def" 59853cf1018fSvporpo } 59864df71ab7SJorge Gorbe Moya 59874df71ab7SJorge Gorbe Moya TEST_F(SandboxIRTest, InstructionCallbacks) { 59884df71ab7SJorge Gorbe Moya parseIR(C, R"IR( 59894df71ab7SJorge Gorbe Moya define void @foo(ptr %ptr, i8 %val) { 59904df71ab7SJorge Gorbe Moya ret void 59914df71ab7SJorge Gorbe Moya } 59924df71ab7SJorge Gorbe Moya )IR"); 59934df71ab7SJorge Gorbe Moya Function &LLVMF = *M->getFunction("foo"); 59944df71ab7SJorge Gorbe Moya sandboxir::Context Ctx(C); 59954df71ab7SJorge Gorbe Moya 59964df71ab7SJorge Gorbe Moya auto &F = *Ctx.createFunction(&LLVMF); 59974df71ab7SJorge Gorbe Moya auto &BB = *F.begin(); 59984df71ab7SJorge Gorbe Moya sandboxir::Argument *Ptr = F.getArg(0); 59994df71ab7SJorge Gorbe Moya sandboxir::Argument *Val = F.getArg(1); 60004df71ab7SJorge Gorbe Moya sandboxir::Instruction *Ret = &BB.front(); 60014df71ab7SJorge Gorbe Moya 60024df71ab7SJorge Gorbe Moya SmallVector<sandboxir::Instruction *> Inserted; 60034df71ab7SJorge Gorbe Moya auto InsertCbId = Ctx.registerCreateInstrCallback( 60044df71ab7SJorge Gorbe Moya [&Inserted](sandboxir::Instruction *I) { Inserted.push_back(I); }); 60054df71ab7SJorge Gorbe Moya 60064df71ab7SJorge Gorbe Moya SmallVector<sandboxir::Instruction *> Removed; 60074df71ab7SJorge Gorbe Moya auto RemoveCbId = Ctx.registerEraseInstrCallback( 60084df71ab7SJorge Gorbe Moya [&Removed](sandboxir::Instruction *I) { Removed.push_back(I); }); 60094df71ab7SJorge Gorbe Moya 60104df71ab7SJorge Gorbe Moya // Keep the moved instruction and the instruction pointed by the Where 60114df71ab7SJorge Gorbe Moya // iterator so we can check both callback arguments work as expected. 60124df71ab7SJorge Gorbe Moya SmallVector<std::pair<sandboxir::Instruction *, sandboxir::Instruction *>> 60134df71ab7SJorge Gorbe Moya Moved; 60144df71ab7SJorge Gorbe Moya auto MoveCbId = Ctx.registerMoveInstrCallback( 60154df71ab7SJorge Gorbe Moya [&Moved](sandboxir::Instruction *I, const sandboxir::BBIterator &Where) { 60164df71ab7SJorge Gorbe Moya // Use a nullptr to signal "move to end" to keep it single. We only 60174df71ab7SJorge Gorbe Moya // have a basic block in this test case anyway. 60184df71ab7SJorge Gorbe Moya if (Where == Where.getNodeParent()->end()) 60194df71ab7SJorge Gorbe Moya Moved.push_back(std::make_pair(I, nullptr)); 60204df71ab7SJorge Gorbe Moya else 60214df71ab7SJorge Gorbe Moya Moved.push_back(std::make_pair(I, &*Where)); 60224df71ab7SJorge Gorbe Moya }); 60234df71ab7SJorge Gorbe Moya 60244df71ab7SJorge Gorbe Moya // Two more insertion callbacks, to check that they're called in registration 60254df71ab7SJorge Gorbe Moya // order. 60264df71ab7SJorge Gorbe Moya SmallVector<int> Order; 60274df71ab7SJorge Gorbe Moya auto CheckOrderInsertCbId1 = Ctx.registerCreateInstrCallback( 60284df71ab7SJorge Gorbe Moya [&Order](sandboxir::Instruction *I) { Order.push_back(1); }); 60294df71ab7SJorge Gorbe Moya 60304df71ab7SJorge Gorbe Moya auto CheckOrderInsertCbId2 = Ctx.registerCreateInstrCallback( 60314df71ab7SJorge Gorbe Moya [&Order](sandboxir::Instruction *I) { Order.push_back(2); }); 60324df71ab7SJorge Gorbe Moya 60334df71ab7SJorge Gorbe Moya Ctx.save(); 60344df71ab7SJorge Gorbe Moya auto *NewI = sandboxir::StoreInst::create(Val, Ptr, /*Align=*/std::nullopt, 60354df71ab7SJorge Gorbe Moya Ret->getIterator(), Ctx); 60364df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::ElementsAre(NewI)); 60374df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::IsEmpty()); 60384df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::IsEmpty()); 60394df71ab7SJorge Gorbe Moya EXPECT_THAT(Order, testing::ElementsAre(1, 2)); 60404df71ab7SJorge Gorbe Moya 60414df71ab7SJorge Gorbe Moya Ret->moveBefore(NewI); 60424df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::ElementsAre(NewI)); 60434df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::IsEmpty()); 60444df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI))); 60454df71ab7SJorge Gorbe Moya 60464df71ab7SJorge Gorbe Moya Ret->eraseFromParent(); 60474df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::ElementsAre(NewI)); 60484df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::ElementsAre(Ret)); 60494df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI))); 60504df71ab7SJorge Gorbe Moya 60514df71ab7SJorge Gorbe Moya NewI->eraseFromParent(); 60524df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::ElementsAre(NewI)); 60534df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::ElementsAre(Ret, NewI)); 60544df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI))); 60554df71ab7SJorge Gorbe Moya 60564df71ab7SJorge Gorbe Moya // Check that after revert the callbacks have been called for the inverse 60574df71ab7SJorge Gorbe Moya // operations of the changes made so far. 60584df71ab7SJorge Gorbe Moya Ctx.revert(); 60594df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::ElementsAre(NewI, NewI, Ret)); 60604df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::ElementsAre(Ret, NewI, NewI)); 60614df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI), 60624df71ab7SJorge Gorbe Moya std::make_pair(Ret, nullptr))); 60634df71ab7SJorge Gorbe Moya EXPECT_THAT(Order, testing::ElementsAre(1, 2, 1, 2, 1, 2)); 60644df71ab7SJorge Gorbe Moya 60654df71ab7SJorge Gorbe Moya // Check that deregistration works. Do an operation of each type after 60664df71ab7SJorge Gorbe Moya // deregistering callbacks and check. 60674df71ab7SJorge Gorbe Moya Inserted.clear(); 60684df71ab7SJorge Gorbe Moya Removed.clear(); 60694df71ab7SJorge Gorbe Moya Moved.clear(); 60704df71ab7SJorge Gorbe Moya Ctx.unregisterCreateInstrCallback(InsertCbId); 60714df71ab7SJorge Gorbe Moya Ctx.unregisterEraseInstrCallback(RemoveCbId); 60724df71ab7SJorge Gorbe Moya Ctx.unregisterMoveInstrCallback(MoveCbId); 60734df71ab7SJorge Gorbe Moya Ctx.unregisterCreateInstrCallback(CheckOrderInsertCbId1); 60744df71ab7SJorge Gorbe Moya Ctx.unregisterCreateInstrCallback(CheckOrderInsertCbId2); 60754df71ab7SJorge Gorbe Moya auto *NewI2 = sandboxir::StoreInst::create(Val, Ptr, /*Align=*/std::nullopt, 60764df71ab7SJorge Gorbe Moya Ret->getIterator(), Ctx); 60774df71ab7SJorge Gorbe Moya Ret->moveBefore(NewI2); 60784df71ab7SJorge Gorbe Moya Ret->eraseFromParent(); 60794df71ab7SJorge Gorbe Moya EXPECT_THAT(Inserted, testing::IsEmpty()); 60804df71ab7SJorge Gorbe Moya EXPECT_THAT(Removed, testing::IsEmpty()); 60814df71ab7SJorge Gorbe Moya EXPECT_THAT(Moved, testing::IsEmpty()); 60824df71ab7SJorge Gorbe Moya } 6083*334a1cdbSvporpo 6084*334a1cdbSvporpo TEST_F(SandboxIRTest, FunctionObjectAlreadyExists) { 6085*334a1cdbSvporpo parseIR(C, R"IR( 6086*334a1cdbSvporpo define void @foo() { 6087*334a1cdbSvporpo call void @bar() 6088*334a1cdbSvporpo ret void 6089*334a1cdbSvporpo } 6090*334a1cdbSvporpo define void @bar() { 6091*334a1cdbSvporpo ret void 6092*334a1cdbSvporpo } 6093*334a1cdbSvporpo )IR"); 6094*334a1cdbSvporpo Function &LLVMFoo = *M->getFunction("foo"); 6095*334a1cdbSvporpo Function &LLVMBar = *M->getFunction("bar"); 6096*334a1cdbSvporpo sandboxir::Context Ctx(C); 6097*334a1cdbSvporpo // This will create a Function object for @bar(). 6098*334a1cdbSvporpo Ctx.createFunction(&LLVMFoo); 6099*334a1cdbSvporpo EXPECT_NE(Ctx.getValue(&LLVMBar), nullptr); 6100*334a1cdbSvporpo // This should not crash, even though there is already a value for LLVMBar. 6101*334a1cdbSvporpo Ctx.createFunction(&LLVMBar); 6102*334a1cdbSvporpo } 6103