6420 lines · cpp
1//===- SandboxIRTest.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/AsmParser/Parser.h"10#include "llvm/IR/BasicBlock.h"11#include "llvm/IR/Constants.h"12#include "llvm/IR/DataLayout.h"13#include "llvm/IR/Function.h"14#include "llvm/IR/Instruction.h"15#include "llvm/IR/Module.h"16#include "llvm/SandboxIR/BasicBlock.h"17#include "llvm/SandboxIR/Constant.h"18#include "llvm/SandboxIR/Function.h"19#include "llvm/SandboxIR/Instruction.h"20#include "llvm/SandboxIR/Module.h"21#include "llvm/SandboxIR/Utils.h"22#include "llvm/SandboxIR/Value.h"23#include "llvm/Support/SourceMgr.h"24#include "gmock/gmock.h"25#include "gtest/gtest.h"26 27using namespace llvm;28 29struct SandboxIRTest : public testing::Test {30 LLVMContext C;31 std::unique_ptr<Module> M;32 33 void parseIR(LLVMContext &C, const char *IR) {34 SMDiagnostic Err;35 M = parseAssemblyString(IR, Err, C);36 if (!M)37 Err.print("SandboxIRTest", errs());38 }39 BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {40 for (BasicBlock &BB : F)41 if (BB.getName() == Name)42 return &BB;43 llvm_unreachable("Expected to find basic block!");44 }45};46 47TEST_F(SandboxIRTest, ClassID) {48 parseIR(C, R"IR(49define void @foo(i32 %v1) {50 %add = add i32 %v1, 4251 ret void52}53)IR");54 llvm::Function *LLVMF = &*M->getFunction("foo");55 llvm::BasicBlock *LLVMBB = &*LLVMF->begin();56 llvm::Instruction *LLVMAdd = &*LLVMBB->begin();57 auto *LLVMC = cast<llvm::Constant>(LLVMAdd->getOperand(1));58 59 sandboxir::Context Ctx(C);60 sandboxir::Function *F = Ctx.createFunction(LLVMF);61 sandboxir::Argument *Arg0 = F->getArg(0);62 sandboxir::BasicBlock *BB = &*F->begin();63 sandboxir::Instruction *AddI = &*BB->begin();64 sandboxir::Constant *Const0 = cast<sandboxir::Constant>(Ctx.getValue(LLVMC));65 66 EXPECT_TRUE(isa<sandboxir::Function>(F));67 EXPECT_FALSE(isa<sandboxir::Function>(Arg0));68 EXPECT_FALSE(isa<sandboxir::Function>(BB));69 EXPECT_FALSE(isa<sandboxir::Function>(AddI));70 EXPECT_FALSE(isa<sandboxir::Function>(Const0));71 72 EXPECT_FALSE(isa<sandboxir::Argument>(F));73 EXPECT_TRUE(isa<sandboxir::Argument>(Arg0));74 EXPECT_FALSE(isa<sandboxir::Argument>(BB));75 EXPECT_FALSE(isa<sandboxir::Argument>(AddI));76 EXPECT_FALSE(isa<sandboxir::Argument>(Const0));77 78 EXPECT_TRUE(isa<sandboxir::Constant>(F));79 EXPECT_FALSE(isa<sandboxir::Constant>(Arg0));80 EXPECT_FALSE(isa<sandboxir::Constant>(BB));81 EXPECT_FALSE(isa<sandboxir::Constant>(AddI));82 EXPECT_TRUE(isa<sandboxir::Constant>(Const0));83 84 EXPECT_FALSE(isa<sandboxir::OpaqueInst>(F));85 EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Arg0));86 EXPECT_FALSE(isa<sandboxir::OpaqueInst>(BB));87 EXPECT_FALSE(isa<sandboxir::OpaqueInst>(AddI));88 EXPECT_FALSE(isa<sandboxir::OpaqueInst>(Const0));89 90 EXPECT_FALSE(isa<sandboxir::Instruction>(F));91 EXPECT_FALSE(isa<sandboxir::Instruction>(Arg0));92 EXPECT_FALSE(isa<sandboxir::Instruction>(BB));93 EXPECT_TRUE(isa<sandboxir::Instruction>(AddI));94 EXPECT_FALSE(isa<sandboxir::Instruction>(Const0));95 96 EXPECT_TRUE(isa<sandboxir::User>(F));97 EXPECT_FALSE(isa<sandboxir::User>(Arg0));98 EXPECT_FALSE(isa<sandboxir::User>(BB));99 EXPECT_TRUE(isa<sandboxir::User>(AddI));100 EXPECT_TRUE(isa<sandboxir::User>(Const0));101 102#ifndef NDEBUG103 std::string Buff;104 raw_string_ostream BS(Buff);105 F->dumpOS(BS);106 Arg0->dumpOS(BS);107 BB->dumpOS(BS);108 AddI->dumpOS(BS);109 Const0->dumpOS(BS);110#endif111}112 113TEST_F(SandboxIRTest, ConstantInt) {114 parseIR(C, R"IR(115define void @foo(i32 %v0) {116 %add0 = add i32 %v0, 42117 ret void118}119)IR");120 Function &LLVMF = *M->getFunction("foo");121 auto *LLVMBB = &*LLVMF.begin();122 auto *LLVMAdd0 = &*LLVMBB->begin();123 auto *LLVMFortyTwo = cast<llvm::ConstantInt>(LLVMAdd0->getOperand(1));124 sandboxir::Context Ctx(C);125 126 auto &F = *Ctx.createFunction(&LLVMF);127 auto &BB = *F.begin();128 auto It = BB.begin();129 auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++);130 auto *FortyTwo = cast<sandboxir::ConstantInt>(Add0->getOperand(1));131 132 // Check that creating an identical constant gives us the same object.133 auto *NewCI =134 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);135 EXPECT_EQ(NewCI, FortyTwo);136 {137 // Check getTrue(Ctx).138 auto *True = sandboxir::ConstantInt::getTrue(Ctx);139 EXPECT_EQ(True, Ctx.getValue(llvm::ConstantInt::getTrue(C)));140 // Check getFalse(Ctx).141 auto *False = sandboxir::ConstantInt::getFalse(Ctx);142 EXPECT_EQ(False, Ctx.getValue(llvm::ConstantInt::getFalse(C)));143 // Check getBool(Ctx).144 auto *Bool = sandboxir::ConstantInt::getBool(Ctx, true);145 EXPECT_EQ(Bool, Ctx.getValue(llvm::ConstantInt::getBool(C, true)));146 }147 {148 auto *Int1Ty = sandboxir::Type::getInt1Ty(Ctx);149 auto *LLVMInt1Ty = llvm::Type::getInt1Ty(C);150 // Check getTrue(Ty).151 auto *True = sandboxir::ConstantInt::getTrue(Int1Ty);152 EXPECT_EQ(True, Ctx.getValue(llvm::ConstantInt::getTrue(LLVMInt1Ty)));153 // Check getFalse(Ty).154 auto *False = sandboxir::ConstantInt::getFalse(Int1Ty);155 EXPECT_EQ(False, Ctx.getValue(llvm::ConstantInt::getFalse(LLVMInt1Ty)));156 // Check getBool(Ty).157 auto *Bool = sandboxir::ConstantInt::getBool(Int1Ty, true);158 EXPECT_EQ(Bool, Ctx.getValue(llvm::ConstantInt::getBool(LLVMInt1Ty, true)));159 }160 161 auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);162 auto *LLVMInt32Ty = llvm::Type::getInt32Ty(C);163 {164 // Check get(Type, V).165 auto *FortyThree = sandboxir::ConstantInt::get(Int32Ty, 43);166 auto *LLVMFortyThree = llvm::ConstantInt::get(LLVMInt32Ty, 43);167 EXPECT_NE(FortyThree, FortyTwo);168 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));169 }170 {171 // Check get(Type, V, IsSigned).172 auto *FortyThree =173 sandboxir::ConstantInt::get(Int32Ty, 43, /*IsSigned=*/true);174 auto *LLVMFortyThree =175 llvm::ConstantInt::get(LLVMInt32Ty, 43, /*IsSigned=*/true);176 EXPECT_NE(FortyThree, FortyTwo);177 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));178 }179 180 {181 // Check get(IntegerType, V).182 auto *FortyThree =183 sandboxir::ConstantInt::get(sandboxir::IntegerType::get(Ctx, 32), 43);184 auto *LLVMFortyThree =185 llvm::ConstantInt::get(llvm::IntegerType::get(C, 32), 43);186 EXPECT_NE(FortyThree, FortyTwo);187 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));188 }189 {190 // Check get(IntegerType, V, IsSigned).191 auto *FortyThree = sandboxir::ConstantInt::get(192 sandboxir::IntegerType::get(Ctx, 32), 43, /*IsSigned=*/true);193 auto *LLVMFortyThree = llvm::ConstantInt::get(llvm::IntegerType::get(C, 32),194 43, /*IsSigned=*/true);195 EXPECT_NE(FortyThree, FortyTwo);196 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));197 }198 199 {200 // Check getSigned(IntegerType, V).201 auto *FortyThree = sandboxir::ConstantInt::getSigned(202 sandboxir::IntegerType::get(Ctx, 32), 43);203 auto *LLVMFortyThree =204 llvm::ConstantInt::getSigned(llvm::IntegerType::get(C, 32), 43);205 EXPECT_NE(FortyThree, FortyTwo);206 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));207 }208 {209 // Check getSigned(Type, V).210 auto *FortyThree = sandboxir::ConstantInt::getSigned(Int32Ty, 43);211 auto *LLVMFortyThree = llvm::ConstantInt::getSigned(LLVMInt32Ty, 43);212 EXPECT_NE(FortyThree, FortyTwo);213 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));214 }215 {216 // Check get(Ctx, APInt).217 APInt APInt43(32, 43);218 auto *FortyThree = sandboxir::ConstantInt::get(Ctx, APInt43);219 auto *LLVMFortyThree = llvm::ConstantInt::get(C, APInt43);220 EXPECT_NE(FortyThree, FortyTwo);221 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));222 }223 {224 // Check get(Ty, Str, Radix).225 StringRef Str("43");226 uint8_t Radix(10);227 auto *FortyThree = sandboxir::ConstantInt::get(228 sandboxir::IntegerType::get(Ctx, 32), Str, Radix);229 auto *LLVMFortyThree =230 llvm::ConstantInt::get(llvm::IntegerType::get(C, 32), Str, Radix);231 EXPECT_NE(FortyThree, FortyTwo);232 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));233 }234 {235 // Check get(Ty, APInt).236 APInt APInt43(32, 43);237 auto *FortyThree = sandboxir::ConstantInt::get(Int32Ty, APInt43);238 auto *LLVMFortyThree = llvm::ConstantInt::get(LLVMInt32Ty, APInt43);239 EXPECT_NE(FortyThree, FortyTwo);240 EXPECT_EQ(FortyThree, Ctx.getValue(LLVMFortyThree));241 }242 // Check getValue().243 EXPECT_EQ(FortyTwo->getValue(), LLVMFortyTwo->getValue());244 // Check getBitWidth().245 EXPECT_EQ(FortyTwo->getBitWidth(), LLVMFortyTwo->getBitWidth());246 // Check getZExtValue().247 EXPECT_EQ(FortyTwo->getZExtValue(), LLVMFortyTwo->getZExtValue());248 // Check getSExtValue().249 EXPECT_EQ(FortyTwo->getSExtValue(), LLVMFortyTwo->getSExtValue());250 // Check getMaybeAlignValue().251 auto *SixtyFour =252 cast<sandboxir::ConstantInt>(sandboxir::ConstantInt::get(Int32Ty, 64));253 auto *LLVMSixtyFour =254 cast<llvm::ConstantInt>(llvm::ConstantInt::get(LLVMInt32Ty, 64));255 EXPECT_EQ(SixtyFour->getMaybeAlignValue(),256 LLVMSixtyFour->getMaybeAlignValue());257 // Check getAlignValue().258 EXPECT_EQ(SixtyFour->getAlignValue(), LLVMSixtyFour->getAlignValue());259 // Check equalsInt().260 EXPECT_TRUE(FortyTwo->equalsInt(42));261 EXPECT_FALSE(FortyTwo->equalsInt(43));262 // Check getIntegerType().263 EXPECT_EQ(FortyTwo->getIntegerType(), sandboxir::IntegerType::get(Ctx, 32));264 // Check isValueValidForType().265 EXPECT_TRUE(266 sandboxir::ConstantInt::isValueValidForType(Int32Ty, (uint64_t)42));267 EXPECT_TRUE(268 sandboxir::ConstantInt::isValueValidForType(Int32Ty, (int64_t)42));269 // Check isNegative().270 EXPECT_FALSE(FortyTwo->isNegative());271 EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, -42));272 // Check isZero().273 EXPECT_FALSE(FortyTwo->isZero());274 EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, 0)->isZero());275 // Check isOne().276 EXPECT_FALSE(FortyTwo->isOne());277 EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, 1)->isOne());278 // Check isMinusOne().279 EXPECT_FALSE(FortyTwo->isMinusOne());280 EXPECT_TRUE(sandboxir::ConstantInt::get(Int32Ty, -1)->isMinusOne());281 // Check isMaxValue().282 EXPECT_FALSE(FortyTwo->isMaxValue(/*Signed=*/true));283 EXPECT_TRUE(284 sandboxir::ConstantInt::get(Int32Ty, std::numeric_limits<int32_t>::max())285 ->isMaxValue(/*Signed=*/true));286 // Check isMinValue().287 EXPECT_FALSE(FortyTwo->isMinValue(/*Signed=*/true));288 EXPECT_TRUE(289 sandboxir::ConstantInt::get(Int32Ty, std::numeric_limits<int32_t>::min())290 ->isMinValue(/*Signed=*/true));291 // Check uge().292 EXPECT_TRUE(FortyTwo->uge(41));293 EXPECT_FALSE(FortyTwo->uge(43));294 // Check getLimitedValue().295 EXPECT_EQ(FortyTwo->getLimitedValue(40u), 40u);296 EXPECT_EQ(FortyTwo->getLimitedValue(50u), 42u);297}298 299TEST_F(SandboxIRTest, ConstantFP) {300 parseIR(C, R"IR(301define void @foo(float %v0, double %v1, half %v2) {302 %fadd0 = fadd float %v0, 42.0303 %fadd1 = fadd double %v1, 43.0304 %fadd2 = fadd half %v2, 44.0305 ret void306}307)IR");308 Function &LLVMF = *M->getFunction("foo");309 sandboxir::Context Ctx(C);310 311 auto &F = *Ctx.createFunction(&LLVMF);312 auto &BB = *F.begin();313 auto It = BB.begin();314 auto *FAdd0 = cast<sandboxir::BinaryOperator>(&*It++);315 auto *FAdd1 = cast<sandboxir::BinaryOperator>(&*It++);316 auto *FAdd2 = cast<sandboxir::BinaryOperator>(&*It++);317 auto *FortyTwo = cast<sandboxir::ConstantFP>(FAdd0->getOperand(1));318 [[maybe_unused]] auto *FortyThree =319 cast<sandboxir::ConstantFP>(FAdd1->getOperand(1));320 321 auto *FloatTy = sandboxir::Type::getFloatTy(Ctx);322 auto *DoubleTy = sandboxir::Type::getDoubleTy(Ctx);323 auto *HalfTy = sandboxir::Type::getHalfTy(Ctx);324 EXPECT_EQ(HalfTy, Ctx.getType(llvm::Type::getHalfTy(C)));325 EXPECT_EQ(FAdd2->getType(), HalfTy);326 auto *LLVMFloatTy = Type::getFloatTy(C);327 auto *LLVMDoubleTy = Type::getDoubleTy(C);328 // Check that creating an identical constant gives us the same object.329 auto *NewFortyTwo = sandboxir::ConstantFP::get(FloatTy, 42.0);330 EXPECT_EQ(NewFortyTwo, FortyTwo);331 // Check get(Type, double).332 auto *FortyFour =333 cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::get(FloatTy, 44.0));334 auto *LLVMFortyFour =335 cast<llvm::ConstantFP>(llvm::ConstantFP::get(LLVMFloatTy, 44.0));336 EXPECT_NE(FortyFour, FortyTwo);337 EXPECT_EQ(FortyFour, Ctx.getValue(LLVMFortyFour));338 // Check get(Type, APFloat).339 auto *FortyFive = cast<sandboxir::ConstantFP>(340 sandboxir::ConstantFP::get(DoubleTy, APFloat(45.0)));341 auto *LLVMFortyFive = cast<llvm::ConstantFP>(342 llvm::ConstantFP::get(LLVMDoubleTy, APFloat(45.0)));343 EXPECT_EQ(FortyFive, Ctx.getValue(LLVMFortyFive));344 // Check get(Type, StringRef).345 auto *FortySix = sandboxir::ConstantFP::get(FloatTy, "46.0");346 EXPECT_EQ(FortySix, Ctx.getValue(llvm::ConstantFP::get(LLVMFloatTy, "46.0")));347 // Check get(APFloat).348 auto *FortySeven = sandboxir::ConstantFP::get(APFloat(47.0), Ctx);349 EXPECT_EQ(FortySeven, Ctx.getValue(llvm::ConstantFP::get(C, APFloat(47.0))));350 // Check getNaN().351 {352 auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy);353 EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN(LLVMFloatTy)));354 }355 {356 auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy, /*Negative=*/true);357 EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN(LLVMFloatTy,358 /*Negative=*/true)));359 }360 {361 auto *NaN = sandboxir::ConstantFP::getNaN(FloatTy, /*Negative=*/true,362 /*Payload=*/1);363 EXPECT_EQ(NaN, Ctx.getValue(llvm::ConstantFP::getNaN(364 LLVMFloatTy, /*Negative=*/true, /*Payload=*/1)));365 }366 // Check getQNaN().367 {368 auto *QNaN = sandboxir::ConstantFP::getQNaN(FloatTy);369 EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN(LLVMFloatTy)));370 }371 {372 auto *QNaN = sandboxir::ConstantFP::getQNaN(FloatTy, /*Negative=*/true);373 EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN(LLVMFloatTy,374 /*Negative=*/true)));375 }376 {377 APInt Payload(1, 1);378 auto *QNaN =379 sandboxir::ConstantFP::getQNaN(FloatTy, /*Negative=*/true, &Payload);380 EXPECT_EQ(QNaN, Ctx.getValue(llvm::ConstantFP::getQNaN(381 LLVMFloatTy, /*Negative=*/true, &Payload)));382 }383 // Check getSNaN().384 {385 auto *SNaN = sandboxir::ConstantFP::getSNaN(FloatTy);386 EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN(LLVMFloatTy)));387 }388 {389 auto *SNaN = sandboxir::ConstantFP::getSNaN(FloatTy, /*Negative=*/true);390 EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN(LLVMFloatTy,391 /*Negative=*/true)));392 }393 {394 APInt Payload(1, 1);395 auto *SNaN =396 sandboxir::ConstantFP::getSNaN(FloatTy, /*Negative=*/true, &Payload);397 EXPECT_EQ(SNaN, Ctx.getValue(llvm::ConstantFP::getSNaN(398 LLVMFloatTy, /*Negative=*/true, &Payload)));399 }400 401 // Check getZero().402 {403 auto *Zero = sandboxir::ConstantFP::getZero(FloatTy);404 EXPECT_EQ(Zero, Ctx.getValue(llvm::ConstantFP::getZero(LLVMFloatTy)));405 }406 {407 auto *Zero = sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true);408 EXPECT_EQ(Zero, Ctx.getValue(llvm::ConstantFP::getZero(LLVMFloatTy,409 /*Negative=*/true)));410 }411 412 // Check getNegativeZero().413 auto *NegZero = cast<sandboxir::ConstantFP>(414 sandboxir::ConstantFP::getNegativeZero(FloatTy));415 EXPECT_EQ(NegZero,416 Ctx.getValue(llvm::ConstantFP::getNegativeZero(LLVMFloatTy)));417 418 // Check getInfinity().419 {420 auto *Inf = sandboxir::ConstantFP::getInfinity(FloatTy);421 EXPECT_EQ(Inf, Ctx.getValue(llvm::ConstantFP::getInfinity(LLVMFloatTy)));422 }423 {424 auto *Inf = sandboxir::ConstantFP::getInfinity(FloatTy, /*Negative=*/true);425 EXPECT_EQ(Inf, Ctx.getValue(llvm::ConstantFP::getInfinity(426 LLVMFloatTy, /*Negative=*/true)));427 }428 429 // Check isValueValidForType().430 APFloat V(1.1);431 EXPECT_EQ(sandboxir::ConstantFP::isValueValidForType(FloatTy, V),432 llvm::ConstantFP::isValueValidForType(LLVMFloatTy, V));433 // Check getValueAPF().434 EXPECT_EQ(FortyFour->getValueAPF(), LLVMFortyFour->getValueAPF());435 // Check getValue().436 EXPECT_EQ(FortyFour->getValue(), LLVMFortyFour->getValue());437 // Check isZero().438 EXPECT_EQ(FortyFour->isZero(), LLVMFortyFour->isZero());439 EXPECT_TRUE(sandboxir::ConstantFP::getZero(FloatTy));440 EXPECT_TRUE(sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true));441 // Check isNegative().442 EXPECT_TRUE(cast<sandboxir::ConstantFP>(443 sandboxir::ConstantFP::getZero(FloatTy, /*Negative=*/true))444 ->isNegative());445 // Check isInfinity().446 EXPECT_TRUE(447 cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::getInfinity(FloatTy))448 ->isInfinity());449 // Check isNaN().450 EXPECT_TRUE(451 cast<sandboxir::ConstantFP>(sandboxir::ConstantFP::getNaN(FloatTy))452 ->isNaN());453 // Check isExactlyValue(APFloat).454 EXPECT_TRUE(NegZero->isExactlyValue(NegZero->getValueAPF()));455 // Check isExactlyValue(double).456 EXPECT_TRUE(NegZero->isExactlyValue(-0.0));457}458 459// Tests ConstantArray, ConstantStruct and ConstantVector.460TEST_F(SandboxIRTest, ConstantAggregate) {461 // Note: we are using i42 to avoid the creation of ConstantDataVector or462 // ConstantDataArray.463 parseIR(C, R"IR(464define void @foo() {465 %array = extractvalue [2 x i42] [i42 0, i42 1], 0466 %struct = extractvalue {i42, i42} {i42 0, i42 1}, 0467 %vector = extractelement <2 x i42> <i42 0, i42 1>, i32 0468 ret void469}470)IR");471 Function &LLVMF = *M->getFunction("foo");472 sandboxir::Context Ctx(C);473 474 auto &F = *Ctx.createFunction(&LLVMF);475 auto &BB = *F.begin();476 auto It = BB.begin();477 auto *I0 = &*It++;478 auto *I1 = &*It++;479 auto *I2 = &*It++;480 // Check classof() and creation.481 auto *Array = cast<sandboxir::ConstantArray>(I0->getOperand(0));482 EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Array));483 auto *Struct = cast<sandboxir::ConstantStruct>(I1->getOperand(0));484 EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Struct));485 auto *Vector = cast<sandboxir::ConstantVector>(I2->getOperand(0));486 EXPECT_TRUE(isa<sandboxir::ConstantAggregate>(Vector));487 488 auto *ZeroI42 = cast<sandboxir::ConstantInt>(Array->getOperand(0));489 auto *OneI42 = cast<sandboxir::ConstantInt>(Array->getOperand(1));490 // Check ConstantArray::get(), getType().491 auto *NewCA =492 sandboxir::ConstantArray::get(Array->getType(), {ZeroI42, OneI42});493 EXPECT_EQ(NewCA, Array);494 495 // Check ConstantStruct::get(), getType().496 auto *NewCS =497 sandboxir::ConstantStruct::get(Struct->getType(), {ZeroI42, OneI42});498 EXPECT_EQ(NewCS, Struct);499 // Check ConstantStruct::get(...).500 auto *NewCS2 =501 sandboxir::ConstantStruct::get(Struct->getType(), ZeroI42, OneI42);502 EXPECT_EQ(NewCS2, Struct);503 // Check ConstantStruct::getAnon(ArayRef).504 auto *AnonCS = sandboxir::ConstantStruct::getAnon({ZeroI42, OneI42});505 EXPECT_FALSE(cast<sandboxir::StructType>(AnonCS->getType())->isPacked());506 auto *AnonCSPacked =507 sandboxir::ConstantStruct::getAnon({ZeroI42, OneI42}, /*Packed=*/true);508 EXPECT_TRUE(cast<sandboxir::StructType>(AnonCSPacked->getType())->isPacked());509 // Check ConstantStruct::getAnon(Ctx, ArrayRef).510 auto *AnonCS2 = sandboxir::ConstantStruct::getAnon(Ctx, {ZeroI42, OneI42});511 EXPECT_EQ(AnonCS2, AnonCS);512 auto *AnonCS2Packed = sandboxir::ConstantStruct::getAnon(513 Ctx, {ZeroI42, OneI42}, /*Packed=*/true);514 EXPECT_EQ(AnonCS2Packed, AnonCSPacked);515 // Check ConstantStruct::getTypeForElements(Ctx, ArrayRef).516 auto *StructTy =517 sandboxir::ConstantStruct::getTypeForElements(Ctx, {ZeroI42, OneI42});518 EXPECT_EQ(StructTy, Struct->getType());519 EXPECT_FALSE(StructTy->isPacked());520 // Check ConstantStruct::getTypeForElements(Ctx, ArrayRef, Packed).521 auto *StructTyPacked = sandboxir::ConstantStruct::getTypeForElements(522 Ctx, {ZeroI42, OneI42}, /*Packed=*/true);523 EXPECT_TRUE(StructTyPacked->isPacked());524 // Check ConstantStruct::getTypeForElements(ArrayRef).525 auto *StructTy2 =526 sandboxir::ConstantStruct::getTypeForElements(Ctx, {ZeroI42, OneI42});527 EXPECT_EQ(StructTy2, Struct->getType());528 // Check ConstantStruct::getTypeForElements(ArrayRef, Packed).529 auto *StructTy2Packed = sandboxir::ConstantStruct::getTypeForElements(530 Ctx, {ZeroI42, OneI42}, /*Packed=*/true);531 EXPECT_EQ(StructTy2Packed, StructTyPacked);532 533 // Check ConstantVector::get().534 auto *NewCV = sandboxir::ConstantVector::get({ZeroI42, OneI42});535 EXPECT_EQ(NewCV, Vector);536 // Check ConstantVector::getSplat(), getType().537 auto *SplatRaw =538 sandboxir::ConstantVector::getSplat(ElementCount::getFixed(2), OneI42);539 auto *Splat = cast<sandboxir::ConstantVector>(SplatRaw);540 EXPECT_EQ(Splat->getType()->getNumElements(), 2u);541 EXPECT_THAT(Splat->operands(), testing::ElementsAre(OneI42, OneI42));542 // Check ConstantVector::getSplatValue().543 EXPECT_EQ(Splat->getSplatValue(), OneI42);544}545 546TEST_F(SandboxIRTest, ConstantAggregateZero) {547 parseIR(C, R"IR(548define void @foo(ptr %ptr, {i32, i8} %v1, <2 x i8> %v2) {549 %extr0 = extractvalue [2 x i8] zeroinitializer, 0550 %extr1 = extractvalue {i32, i8} zeroinitializer, 0551 %extr2 = extractelement <2 x i8> zeroinitializer, i32 0552 ret void553}554)IR");555 Function &LLVMF = *M->getFunction("foo");556 sandboxir::Context Ctx(C);557 558 auto &F = *Ctx.createFunction(&LLVMF);559 auto &BB = *F.begin();560 auto It = BB.begin();561 auto *Extr0 = &*It++;562 auto *Extr1 = &*It++;563 auto *Extr2 = &*It++;564 [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);565 auto *Zero32 =566 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);567 auto *Zero8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0);568 auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);569 auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);570 auto *ArrayTy = sandboxir::ArrayType::get(Int8Ty, 2u);571 auto *StructTy = sandboxir::StructType::get(Ctx, {Int32Ty, Int8Ty});572 auto *VectorTy =573 sandboxir::VectorType::get(Int8Ty, ElementCount::getFixed(2u));574 575 // Check creation and classof().576 auto *ArrayCAZ = cast<sandboxir::ConstantAggregateZero>(Extr0->getOperand(0));577 EXPECT_EQ(ArrayCAZ->getType(), ArrayTy);578 auto *StructCAZ =579 cast<sandboxir::ConstantAggregateZero>(Extr1->getOperand(0));580 EXPECT_EQ(StructCAZ->getType(), StructTy);581 auto *VectorCAZ =582 cast<sandboxir::ConstantAggregateZero>(Extr2->getOperand(0));583 EXPECT_EQ(VectorCAZ->getType(), VectorTy);584 // Check get().585 auto *SameVectorCAZ =586 sandboxir::ConstantAggregateZero::get(sandboxir::VectorType::get(587 sandboxir::Type::getInt8Ty(Ctx), ElementCount::getFixed(2)));588 EXPECT_EQ(SameVectorCAZ, VectorCAZ); // Should be uniqued.589 auto *NewVectorCAZ =590 sandboxir::ConstantAggregateZero::get(sandboxir::VectorType::get(591 sandboxir::Type::getInt8Ty(Ctx), ElementCount::getFixed(4)));592 EXPECT_NE(NewVectorCAZ, VectorCAZ);593 // Check getSequentialElement().594 auto *SeqElm = VectorCAZ->getSequentialElement();595 EXPECT_EQ(SeqElm,596 sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0));597 // Check getStructElement().598 auto *StructElm0 = StructCAZ->getStructElement(0);599 auto *StructElm1 = StructCAZ->getStructElement(1);600 EXPECT_EQ(StructElm0, Zero32);601 EXPECT_EQ(StructElm1, Zero8);602 // Check getElementValue(Constant).603 EXPECT_EQ(ArrayCAZ->getElementValue(Zero32), Zero8);604 EXPECT_EQ(StructCAZ->getElementValue(Zero32), Zero32);605 EXPECT_EQ(VectorCAZ->getElementValue(Zero32), Zero8);606 // Check getElementValue(unsigned).607 EXPECT_EQ(ArrayCAZ->getElementValue(0u), Zero8);608 EXPECT_EQ(StructCAZ->getElementValue(0u), Zero32);609 EXPECT_EQ(VectorCAZ->getElementValue(0u), Zero8);610 // Check getElementCount().611 EXPECT_EQ(ArrayCAZ->getElementCount(), ElementCount::getFixed(2));612 EXPECT_EQ(NewVectorCAZ->getElementCount(), ElementCount::getFixed(4));613}614 615// Tests ConstantDataSequential, ConstantDataArray and ConstantDataVector.616TEST_F(SandboxIRTest, ConstantDataSequential) {617 parseIR(C, R"IR(618define void @foo() {619 %array = extractvalue [2 x i8] [i8 0, i8 1], 0620 %vector = extractelement <2 x i8> <i8 0, i8 1>, i32 0621 %farray = extractvalue [2 x float] [float 0.0, float 1.0], 0622 %fvector = extractelement <2 x double> <double 0.0, double 1.0>, i32 0623 %string = extractvalue [6 x i8] [i8 72, i8 69, i8 76, i8 76, i8 79, i8 0], 0624 %stringNoNull = extractvalue [5 x i8] [i8 72, i8 69, i8 76, i8 76, i8 79], 0625 %splat = extractelement <4 x i8> <i8 1, i8 1, i8 1, i8 1>, i32 0626 ret void627}628)IR");629 Function &LLVMF = *M->getFunction("foo");630 sandboxir::Context Ctx(C);631 632 auto &F = *Ctx.createFunction(&LLVMF);633 auto &BB = *F.begin();634 auto It = BB.begin();635 auto *I0 = &*It++;636 auto *I1 = &*It++;637 auto *I2 = &*It++;638 auto *I3 = &*It++;639 auto *I4 = &*It++;640 auto *I5 = &*It++;641 auto *I6 = &*It++;642 auto *Array = cast<sandboxir::ConstantDataArray>(I0->getOperand(0));643 EXPECT_TRUE(isa<sandboxir::ConstantDataSequential>(Array));644 auto *Vector = cast<sandboxir::ConstantDataVector>(I1->getOperand(0));645 EXPECT_TRUE(isa<sandboxir::ConstantDataVector>(Vector));646 auto *FArray = cast<sandboxir::ConstantDataArray>(I2->getOperand(0));647 EXPECT_TRUE(isa<sandboxir::ConstantDataSequential>(FArray));648 auto *FVector = cast<sandboxir::ConstantDataVector>(I3->getOperand(0));649 EXPECT_TRUE(isa<sandboxir::ConstantDataVector>(FVector));650 auto *String = cast<sandboxir::ConstantDataArray>(I4->getOperand(0));651 EXPECT_TRUE(isa<sandboxir::ConstantDataArray>(String));652 auto *StringNoNull = cast<sandboxir::ConstantDataArray>(I5->getOperand(0));653 EXPECT_TRUE(isa<sandboxir::ConstantDataArray>(StringNoNull));654 auto *Splat = cast<sandboxir::ConstantDataVector>(I6->getOperand(0));655 EXPECT_TRUE(isa<sandboxir::ConstantDataVector>(Splat));656 657 auto *Zero8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0);658 auto *One8 = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 1);659 660 // Check isElementTypeCompatible().661 for (llvm::Type *LLVMTy :662 {llvm::Type::getIntNTy(C, 42), llvm::Type::getInt8Ty(C)})663 EXPECT_EQ(llvm::ConstantDataSequential::isElementTypeCompatible(LLVMTy),664 sandboxir::ConstantDataSequential::isElementTypeCompatible(665 Ctx.getType(LLVMTy)));666 // Check getElementAsInteger().667 EXPECT_EQ(Array->getElementAsInteger(0), 0u);668 EXPECT_EQ(Array->getElementAsInteger(1), 1u);669 EXPECT_EQ(Vector->getElementAsInteger(0), 0u);670 EXPECT_EQ(Vector->getElementAsInteger(1), 1u);671 // Check getElementAsAPInt().672 EXPECT_EQ(Array->getElementAsAPInt(0), 0u);673 EXPECT_EQ(Array->getElementAsAPInt(1), 1u);674 EXPECT_EQ(Vector->getElementAsAPInt(0), 0u);675 EXPECT_EQ(Vector->getElementAsAPInt(1), 1u);676 // Check geteElementAsFloat().677 EXPECT_EQ(FArray->getElementAsFloat(0), 0.0);678 EXPECT_EQ(FArray->getElementAsFloat(1), 1.0);679 // Check getElementAsDouble().680 EXPECT_EQ(FVector->getElementAsDouble(0), 0.0);681 EXPECT_EQ(FVector->getElementAsDouble(1), 1.0);682 // Check getElementAsConstant().683 EXPECT_EQ(Array->getElementAsConstant(0), Zero8);684 EXPECT_EQ(Array->getElementAsConstant(1), One8);685 EXPECT_EQ(Vector->getElementAsConstant(0), Zero8);686 EXPECT_EQ(Vector->getElementAsConstant(1), One8);687 // Check getElementType().688 EXPECT_EQ(Array->getElementType(), sandboxir::Type::getInt8Ty(Ctx));689 EXPECT_EQ(Vector->getElementType(), sandboxir::Type::getInt8Ty(Ctx));690 EXPECT_EQ(FArray->getElementType(), sandboxir::Type::getFloatTy(Ctx));691 EXPECT_EQ(FVector->getElementType(), sandboxir::Type::getDoubleTy(Ctx));692 // Check getNumElements(),693 EXPECT_EQ(Array->getNumElements(), 2u);694 EXPECT_EQ(Vector->getNumElements(), 2u);695 EXPECT_EQ(FArray->getNumElements(), 2u);696 EXPECT_EQ(FVector->getNumElements(), 2u);697 // Check getElementByteSize().698 EXPECT_EQ(Array->getElementByteSize(), 1u);699 EXPECT_EQ(Vector->getElementByteSize(), 1u);700 EXPECT_EQ(FArray->getElementByteSize(), 4u);701 EXPECT_EQ(FVector->getElementByteSize(), 8u);702 // Check isString().703 EXPECT_EQ(Array->isString(), true);704 EXPECT_EQ(Vector->isString(), false);705 EXPECT_EQ(FArray->isString(), false);706 EXPECT_EQ(FVector->isString(), false);707 EXPECT_EQ(String->isString(), true);708 // Check isCString().709 EXPECT_EQ(Array->isCString(), false);710 EXPECT_EQ(Vector->isCString(), false);711 EXPECT_EQ(FArray->isCString(), false);712 EXPECT_EQ(FVector->isCString(), false);713 EXPECT_EQ(String->isCString(), true);714 // Check getAsString().715 char Data[] = {'H', 'E', 'L', 'L', 'O', '\0'};716 StringRef HelloWithNull(Data, 6);717 EXPECT_EQ(String->getAsString(), HelloWithNull);718 // Check getAsCString().719 EXPECT_EQ(String->getAsCString(), "HELLO");720 // Check getRawDataValues().721 EXPECT_EQ(String->getRawDataValues(), HelloWithNull);722 723 // Check ConstantDataArray member functions724 // ----------------------------------------725 // Check get<ElementTy>().726 EXPECT_EQ(sandboxir::ConstantDataArray::get<char>(Ctx, {0, 1}), Array);727 // Check get<ArrayTy>().728 SmallVector<char> Elmts({0, 1});729 EXPECT_EQ(sandboxir::ConstantDataArray::get<SmallVector<char>>(Ctx, Elmts),730 Array);731 // Check getRaw().732 EXPECT_EQ(sandboxir::ConstantDataArray::getRaw(StringRef("HELLO"), 5,733 Zero8->getType()),734 StringNoNull);735 // Check getFP().736 SmallVector<uint16_t> Elts16({42, 43});737 SmallVector<uint32_t> Elts32({42, 43});738 SmallVector<uint64_t> Elts64({42, 43});739 auto *F16Ty = sandboxir::Type::getHalfTy(Ctx);740 auto *F32Ty = sandboxir::Type::getFloatTy(Ctx);741 auto *F64Ty = sandboxir::Type::getDoubleTy(Ctx);742 743 auto *CDA16 = sandboxir::ConstantDataArray::getFP(F16Ty, Elts16);744 EXPECT_EQ(CDA16, cast<sandboxir::ConstantDataArray>(745 Ctx.getValue(llvm::ConstantDataArray::getFP(746 llvm::Type::getHalfTy(C), Elts16))));747 auto *CDA32 = sandboxir::ConstantDataArray::getFP(F32Ty, Elts32);748 EXPECT_EQ(CDA32, cast<sandboxir::ConstantDataArray>(749 Ctx.getValue(llvm::ConstantDataArray::getFP(750 llvm::Type::getFloatTy(C), Elts32))));751 auto *CDA64 = sandboxir::ConstantDataArray::getFP(F64Ty, Elts64);752 EXPECT_EQ(CDA64, cast<sandboxir::ConstantDataArray>(753 Ctx.getValue(llvm::ConstantDataArray::getFP(754 llvm::Type::getDoubleTy(C), Elts64))));755 // Check getString().756 EXPECT_EQ(sandboxir::ConstantDataArray::getString(Ctx, "HELLO"), String);757 758 EXPECT_EQ(sandboxir::ConstantDataArray::getString(Ctx, "HELLO",759 /*AddNull=*/false),760 StringNoNull);761 EXPECT_EQ(762 sandboxir::ConstantDataArray::getString(Ctx, "HELLO", /*AddNull=*/false),763 StringNoNull);764 765 {766 // Check ConstantDataArray member functions767 // ----------------------------------------768 // Check get().769 SmallVector<uint8_t> Elts8({0u, 1u});770 SmallVector<uint16_t> Elts16({0u, 1u});771 SmallVector<uint32_t> Elts32({0u, 1u});772 SmallVector<uint64_t> Elts64({0u, 1u});773 SmallVector<float> EltsF32({0.0, 1.0});774 SmallVector<double> EltsF64({0.0, 1.0});775 auto *CDV8 = sandboxir::ConstantDataVector::get(Ctx, Elts8);776 EXPECT_EQ(CDV8, cast<sandboxir::ConstantDataVector>(777 Ctx.getValue(llvm::ConstantDataVector::get(C, Elts8))));778 auto *CDV16 = sandboxir::ConstantDataVector::get(Ctx, Elts16);779 EXPECT_EQ(CDV16, cast<sandboxir::ConstantDataVector>(Ctx.getValue(780 llvm::ConstantDataVector::get(C, Elts16))));781 auto *CDV32 = sandboxir::ConstantDataVector::get(Ctx, Elts32);782 EXPECT_EQ(CDV32, cast<sandboxir::ConstantDataVector>(Ctx.getValue(783 llvm::ConstantDataVector::get(C, Elts32))));784 auto *CDVF32 = sandboxir::ConstantDataVector::get(Ctx, EltsF32);785 EXPECT_EQ(CDVF32, cast<sandboxir::ConstantDataVector>(Ctx.getValue(786 llvm::ConstantDataVector::get(C, EltsF32))));787 auto *CDVF64 = sandboxir::ConstantDataVector::get(Ctx, EltsF64);788 EXPECT_EQ(CDVF64, cast<sandboxir::ConstantDataVector>(Ctx.getValue(789 llvm::ConstantDataVector::get(C, EltsF64))));790 // Check getRaw().791 auto *CDVRaw = sandboxir::ConstantDataVector::getRaw(792 StringRef("HELLO"), 5, sandboxir::Type::getInt8Ty(Ctx));793 EXPECT_EQ(CDVRaw,794 cast<sandboxir::ConstantDataVector>(795 Ctx.getValue(llvm::ConstantDataVector::getRaw(796 StringRef("HELLO"), 5, llvm::Type::getInt8Ty(C)))));797 // Check getFP().798 auto *CDVFP16 = sandboxir::ConstantDataVector::getFP(F16Ty, Elts16);799 EXPECT_EQ(CDVFP16, cast<sandboxir::ConstantDataVector>(800 Ctx.getValue(llvm::ConstantDataVector::getFP(801 llvm::Type::getHalfTy(C), Elts16))));802 auto *CDVFP32 = sandboxir::ConstantDataVector::getFP(F32Ty, Elts32);803 EXPECT_EQ(CDVFP32, cast<sandboxir::ConstantDataVector>(804 Ctx.getValue(llvm::ConstantDataVector::getFP(805 llvm::Type::getFloatTy(C), Elts32))));806 auto *CDVFP64 = sandboxir::ConstantDataVector::getFP(F64Ty, Elts64);807 EXPECT_EQ(CDVFP64, cast<sandboxir::ConstantDataVector>(808 Ctx.getValue(llvm::ConstantDataVector::getFP(809 llvm::Type::getDoubleTy(C), Elts64))));810 // Check getSplat().811 auto *NewSplat = cast<sandboxir::ConstantDataVector>(812 sandboxir::ConstantDataVector::getSplat(4, One8));813 EXPECT_EQ(NewSplat, Splat);814 // Check isSplat().815 EXPECT_TRUE(NewSplat->isSplat());816 EXPECT_FALSE(Vector->isSplat());817 // Check getSplatValue().818 EXPECT_EQ(NewSplat->getSplatValue(), One8);819 // Check getType().820 EXPECT_TRUE(isa<sandboxir::FixedVectorType>(NewSplat->getType()));821 EXPECT_EQ(822 cast<sandboxir::FixedVectorType>(NewSplat->getType())->getNumElements(),823 4u);824 }825}826 827TEST_F(SandboxIRTest, ConstantPointerNull) {828 parseIR(C, R"IR(829define ptr @foo() {830 ret ptr null831}832)IR");833 Function &LLVMF = *M->getFunction("foo");834 sandboxir::Context Ctx(C);835 836 auto &F = *Ctx.createFunction(&LLVMF);837 auto &BB = *F.begin();838 auto It = BB.begin();839 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);840 // Check classof() and creation.841 auto *CPNull = cast<sandboxir::ConstantPointerNull>(Ret->getReturnValue());842 // Check get().843 auto *NewCPNull =844 sandboxir::ConstantPointerNull::get(sandboxir::PointerType::get(Ctx, 0u));845 EXPECT_EQ(NewCPNull, CPNull);846 auto *NewCPNull2 =847 sandboxir::ConstantPointerNull::get(sandboxir::PointerType::get(Ctx, 1u));848 EXPECT_NE(NewCPNull2, CPNull);849 // Check getType().850 EXPECT_EQ(CPNull->getType(), sandboxir::PointerType::get(Ctx, 0u));851 EXPECT_EQ(NewCPNull2->getType(), sandboxir::PointerType::get(Ctx, 1u));852}853 854TEST_F(SandboxIRTest, PoisonValue) {855 parseIR(C, R"IR(856define void @foo() {857 %i0 = add i32 poison, poison858 %i1 = add <2 x i32> poison, poison859 %i2 = extractvalue {i32, i8} poison, 0860 ret void861}862)IR");863 Function &LLVMF = *M->getFunction("foo");864 sandboxir::Context Ctx(C);865 866 auto &F = *Ctx.createFunction(&LLVMF);867 auto &BB = *F.begin();868 auto It = BB.begin();869 auto *I0 = &*It++;870 auto *I1 = &*It++;871 auto *I2 = &*It++;872 auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);873 auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);874 auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u);875 auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u);876 877 // Check classof() and creation.878 auto *Poison = cast<sandboxir::PoisonValue>(I0->getOperand(0));879 EXPECT_EQ(Poison->getType(), Int32Ty);880 EXPECT_TRUE(isa<sandboxir::UndefValue>(Poison)); // Poison is Undef881 // Check get().882 auto *NewPoison = sandboxir::PoisonValue::get(Int32Ty);883 EXPECT_EQ(NewPoison, Poison);884 auto *NewPoison2 =885 sandboxir::PoisonValue::get(sandboxir::PointerType::get(Ctx, 0u));886 EXPECT_NE(NewPoison2, Poison);887 // Check getSequentialElement().888 auto *PoisonVector = cast<sandboxir::PoisonValue>(I1->getOperand(0));889 auto *SeqElm = PoisonVector->getSequentialElement();890 EXPECT_EQ(SeqElm->getType(), Int32Ty);891 // Check getStructElement().892 auto *PoisonStruct = cast<sandboxir::PoisonValue>(I2->getOperand(0));893 auto *StrElm0 = PoisonStruct->getStructElement(0);894 auto *StrElm1 = PoisonStruct->getStructElement(1);895 EXPECT_EQ(StrElm0->getType(), Int32Ty);896 EXPECT_EQ(StrElm1->getType(), Int8Ty);897 // Check getElementValue(Constant)898 EXPECT_EQ(PoisonStruct->getElementValue(Zero32),899 sandboxir::PoisonValue::get(Int32Ty));900 EXPECT_EQ(PoisonStruct->getElementValue(One32),901 sandboxir::PoisonValue::get(Int8Ty));902 // Check getElementValue(unsigned)903 EXPECT_EQ(PoisonStruct->getElementValue(0u),904 sandboxir::PoisonValue::get(Int32Ty));905 EXPECT_EQ(PoisonStruct->getElementValue(1u),906 sandboxir::PoisonValue::get(Int8Ty));907}908 909TEST_F(SandboxIRTest, UndefValue) {910 parseIR(C, R"IR(911define void @foo() {912 %i0 = add i32 undef, undef913 %i1 = add <2 x i32> undef, undef914 %i2 = extractvalue {i32, i8} undef, 0915 ret void916}917)IR");918 Function &LLVMF = *M->getFunction("foo");919 sandboxir::Context Ctx(C);920 921 auto &F = *Ctx.createFunction(&LLVMF);922 auto &BB = *F.begin();923 auto It = BB.begin();924 auto *I0 = &*It++;925 auto *I1 = &*It++;926 auto *I2 = &*It++;927 auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);928 auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);929 auto *Zero32 = sandboxir::ConstantInt::get(Int32Ty, 0u);930 auto *One32 = sandboxir::ConstantInt::get(Int32Ty, 1u);931 932 // Check classof() and creation.933 auto *Undef = cast<sandboxir::UndefValue>(I0->getOperand(0));934 EXPECT_EQ(Undef->getType(), Int32Ty);935 EXPECT_FALSE(isa<sandboxir::PoisonValue>(Undef)); // Undef is not Poison936 // Check get().937 auto *NewUndef = sandboxir::UndefValue::get(Int32Ty);938 EXPECT_EQ(NewUndef, Undef);939 auto *NewUndef2 =940 sandboxir::UndefValue::get(sandboxir::PointerType::get(Ctx, 0u));941 EXPECT_NE(NewUndef2, Undef);942 // Check getSequentialElement().943 auto *UndefVector = cast<sandboxir::UndefValue>(I1->getOperand(0));944 auto *SeqElm = UndefVector->getSequentialElement();945 EXPECT_EQ(SeqElm->getType(), Int32Ty);946 // Check getStructElement().947 auto *UndefStruct = cast<sandboxir::UndefValue>(I2->getOperand(0));948 auto *StrElm0 = UndefStruct->getStructElement(0);949 auto *StrElm1 = UndefStruct->getStructElement(1);950 EXPECT_EQ(StrElm0->getType(), Int32Ty);951 EXPECT_EQ(StrElm1->getType(), Int8Ty);952 // Check getElementValue(Constant)953 EXPECT_EQ(UndefStruct->getElementValue(Zero32),954 sandboxir::UndefValue::get(Int32Ty));955 EXPECT_EQ(UndefStruct->getElementValue(One32),956 sandboxir::UndefValue::get(Int8Ty));957 // Check getElementValue(unsigned)958 EXPECT_EQ(UndefStruct->getElementValue(0u),959 sandboxir::UndefValue::get(Int32Ty));960 EXPECT_EQ(UndefStruct->getElementValue(1u),961 sandboxir::UndefValue::get(Int8Ty));962 // Check getNumElements().963 EXPECT_EQ(UndefVector->getNumElements(), 2u);964 EXPECT_EQ(UndefStruct->getNumElements(), 2u);965}966 967TEST_F(SandboxIRTest, GlobalValue) {968 parseIR(C, R"IR(969declare external void @bar()970define void @foo() {971 call void @bar()972 ret void973}974)IR");975 Function &LLVMF = *M->getFunction("foo");976 auto *LLVMBB = &*LLVMF.begin();977 auto LLVMIt = LLVMBB->begin();978 auto *LLVMCall = cast<llvm::CallInst>(&*LLVMIt++);979 auto *LLVMGV = cast<llvm::GlobalValue>(LLVMCall->getCalledOperand());980 sandboxir::Context Ctx(C);981 982 auto &F = *Ctx.createFunction(&LLVMF);983 auto *BB = &*F.begin();984 auto It = BB->begin();985 auto *Call = cast<sandboxir::CallInst>(&*It++);986 [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);987 988 // Check classof(), creation, getFunction(), getBasicBlock().989 auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand());990 // Check getAddressSpace().991 EXPECT_EQ(GV->getAddressSpace(), LLVMGV->getAddressSpace());992 // Check hasGlobalUnnamedAddr().993 EXPECT_EQ(GV->hasGlobalUnnamedAddr(), LLVMGV->hasGlobalUnnamedAddr());994 // Check hasAtLeastLocalUnnamedAddr().995 EXPECT_EQ(GV->hasAtLeastLocalUnnamedAddr(),996 LLVMGV->hasAtLeastLocalUnnamedAddr());997 // Check getUnnamedAddr().998 EXPECT_EQ(GV->getUnnamedAddr(), LLVMGV->getUnnamedAddr());999 // Check setUnnamedAddr().1000 auto OrigUnnamedAddr = GV->getUnnamedAddr();1001 auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global;1002 EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr);1003 GV->setUnnamedAddr(NewUnnamedAddr);1004 EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr);1005 GV->setUnnamedAddr(OrigUnnamedAddr);1006 EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr);1007 // Check getMinUnnamedAddr().1008 EXPECT_EQ(1009 sandboxir::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr,1010 NewUnnamedAddr),1011 llvm::GlobalValue::getMinUnnamedAddr(OrigUnnamedAddr, NewUnnamedAddr));1012 // Check hasComdat().1013 EXPECT_EQ(GV->hasComdat(), LLVMGV->hasComdat());1014 // Check getVisibility().1015 EXPECT_EQ(GV->getVisibility(), LLVMGV->getVisibility());1016 // Check hasDefaultVisibility().1017 EXPECT_EQ(GV->hasDefaultVisibility(), LLVMGV->hasDefaultVisibility());1018 // Check hasHiddenVisibility().1019 EXPECT_EQ(GV->hasHiddenVisibility(), LLVMGV->hasHiddenVisibility());1020 // Check hasProtectedVisibility().1021 EXPECT_EQ(GV->hasProtectedVisibility(), LLVMGV->hasProtectedVisibility());1022 // Check setVisibility().1023 auto OrigVisibility = GV->getVisibility();1024 auto NewVisibility =1025 sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility;1026 EXPECT_NE(NewVisibility, OrigVisibility);1027 GV->setVisibility(NewVisibility);1028 EXPECT_EQ(GV->getVisibility(), NewVisibility);1029 GV->setVisibility(OrigVisibility);1030 EXPECT_EQ(GV->getVisibility(), OrigVisibility);1031}1032 1033TEST_F(SandboxIRTest, GlobalObject) {1034 parseIR(C, R"IR(1035declare external void @bar()1036define void @foo() {1037 call void @bar()1038 ret void1039}1040)IR");1041 Function &LLVMF = *M->getFunction("foo");1042 auto *LLVMBB = &*LLVMF.begin();1043 auto LLVMIt = LLVMBB->begin();1044 auto *LLVMCall = cast<llvm::CallInst>(&*LLVMIt++);1045 auto *LLVMGO = cast<llvm::GlobalObject>(LLVMCall->getCalledOperand());1046 sandboxir::Context Ctx(C);1047 1048 auto &F = *Ctx.createFunction(&LLVMF);1049 auto *BB = &*F.begin();1050 auto It = BB->begin();1051 auto *Call = cast<sandboxir::CallInst>(&*It++);1052 // Check classof(), creation.1053 auto *GO = cast<sandboxir::GlobalObject>(Call->getCalledOperand());1054 // Check hasSection().1055 EXPECT_EQ(GO->hasSection(), LLVMGO->hasSection());1056 // Check getSection().1057 EXPECT_EQ(GO->getSection(), LLVMGO->getSection());1058 // Check setSection().1059 auto OrigSection = GO->getSection();1060 auto NewSection = ".some_section";1061 EXPECT_NE(NewSection, OrigSection);1062 GO->setSection(NewSection);1063 EXPECT_EQ(GO->getSection(), NewSection);1064 GO->setSection(OrigSection);1065 EXPECT_EQ(GO->getSection(), OrigSection);1066 // Check hasComdat().1067 EXPECT_EQ(GO->hasComdat(), LLVMGO->hasComdat());1068 // Check getVCallVisibility().1069 EXPECT_EQ(GO->getVCallVisibility(), LLVMGO->getVCallVisibility());1070 // Check canIncreaseAlignment().1071 EXPECT_EQ(GO->canIncreaseAlignment(), LLVMGO->canIncreaseAlignment());1072}1073 1074TEST_F(SandboxIRTest, GlobalIFunc) {1075 parseIR(C, R"IR(1076declare external void @bar()1077@ifunc0 = ifunc void(), ptr @foo1078@ifunc1 = ifunc void(), ptr @foo1079define void @foo() {1080 call void @ifunc0()1081 call void @ifunc1()1082 call void @bar()1083 ret void1084}1085)IR");1086 Function &LLVMF = *M->getFunction("foo");1087 auto *LLVMBB = &*LLVMF.begin();1088 auto LLVMIt = LLVMBB->begin();1089 auto *LLVMCall0 = cast<llvm::CallInst>(&*LLVMIt++);1090 auto *LLVMIFunc0 = cast<llvm::GlobalIFunc>(LLVMCall0->getCalledOperand());1091 1092 sandboxir::Context Ctx(C);1093 1094 auto &F = *Ctx.createFunction(&LLVMF);1095 auto *BB = &*F.begin();1096 auto It = BB->begin();1097 auto *Call0 = cast<sandboxir::CallInst>(&*It++);1098 auto *Call1 = cast<sandboxir::CallInst>(&*It++);1099 auto *CallBar = cast<sandboxir::CallInst>(&*It++);1100 // Check classof(), creation.1101 auto *IFunc0 = cast<sandboxir::GlobalIFunc>(Call0->getCalledOperand());1102 auto *IFunc1 = cast<sandboxir::GlobalIFunc>(Call1->getCalledOperand());1103 auto *Bar = cast<sandboxir::Function>(CallBar->getCalledOperand());1104 1105 // Check getIterator().1106 {1107 auto It0 = IFunc0->getIterator();1108 auto It1 = IFunc1->getIterator();1109 EXPECT_EQ(&*It0, IFunc0);1110 EXPECT_EQ(&*It1, IFunc1);1111 EXPECT_EQ(std::next(It0), It1);1112 EXPECT_EQ(std::prev(It1), It0);1113 EXPECT_EQ(&*std::next(It0), IFunc1);1114 EXPECT_EQ(&*std::prev(It1), IFunc0);1115 }1116 // Check getReverseIterator().1117 {1118 auto RevIt0 = IFunc0->getReverseIterator();1119 auto RevIt1 = IFunc1->getReverseIterator();1120 EXPECT_EQ(&*RevIt0, IFunc0);1121 EXPECT_EQ(&*RevIt1, IFunc1);1122 EXPECT_EQ(std::prev(RevIt0), RevIt1);1123 EXPECT_EQ(std::next(RevIt1), RevIt0);1124 EXPECT_EQ(&*std::prev(RevIt0), IFunc1);1125 EXPECT_EQ(&*std::next(RevIt1), IFunc0);1126 }1127 1128 // Check setResolver(), getResolver().1129 EXPECT_EQ(IFunc0->getResolver(), Ctx.getValue(LLVMIFunc0->getResolver()));1130 auto *OrigResolver = IFunc0->getResolver();1131 auto *NewResolver = Bar;1132 EXPECT_NE(NewResolver, OrigResolver);1133 IFunc0->setResolver(NewResolver);1134 EXPECT_EQ(IFunc0->getResolver(), NewResolver);1135 IFunc0->setResolver(OrigResolver);1136 EXPECT_EQ(IFunc0->getResolver(), OrigResolver);1137 // Check getResolverFunction().1138 EXPECT_EQ(IFunc0->getResolverFunction(),1139 Ctx.getValue(LLVMIFunc0->getResolverFunction()));1140 // Check isValidLinkage().1141 for (auto L :1142 {GlobalValue::ExternalLinkage, GlobalValue::AvailableExternallyLinkage,1143 GlobalValue::LinkOnceAnyLinkage, GlobalValue::LinkOnceODRLinkage,1144 GlobalValue::WeakAnyLinkage, GlobalValue::WeakODRLinkage,1145 GlobalValue::AppendingLinkage, GlobalValue::InternalLinkage,1146 GlobalValue::PrivateLinkage, GlobalValue::ExternalWeakLinkage,1147 GlobalValue::CommonLinkage}) {1148 EXPECT_EQ(IFunc0->isValidLinkage(L), LLVMIFunc0->isValidLinkage(L));1149 }1150}1151 1152TEST_F(SandboxIRTest, GlobalVariable) {1153 parseIR(C, R"IR(1154@glob0 = global i32 421155@glob1 = global i32 431156define void @foo() {1157 %ld0 = load i32, ptr @glob01158 %ld1 = load i32, ptr @glob11159 ret void1160}1161)IR");1162 Function &LLVMF = *M->getFunction("foo");1163 auto *LLVMBB = &*LLVMF.begin();1164 auto LLVMIt = LLVMBB->begin();1165 auto *LLVMLd0 = cast<llvm::LoadInst>(&*LLVMIt++);1166 auto *LLVMGV0 = cast<llvm::GlobalVariable>(LLVMLd0->getPointerOperand());1167 sandboxir::Context Ctx(C);1168 1169 auto &F = *Ctx.createFunction(&LLVMF);1170 auto *BB = &*F.begin();1171 auto It = BB->begin();1172 auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);1173 auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);1174 // Check classof(), creation.1175 auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());1176 auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());1177 // Check getIterator().1178 {1179 auto It0 = GV0->getIterator();1180 auto It1 = GV1->getIterator();1181 EXPECT_EQ(&*It0, GV0);1182 EXPECT_EQ(&*It1, GV1);1183 EXPECT_EQ(std::next(It0), It1);1184 EXPECT_EQ(std::prev(It1), It0);1185 EXPECT_EQ(&*std::next(It0), GV1);1186 EXPECT_EQ(&*std::prev(It1), GV0);1187 }1188 // Check getReverseIterator().1189 {1190 auto RevIt0 = GV0->getReverseIterator();1191 auto RevIt1 = GV1->getReverseIterator();1192 EXPECT_EQ(&*RevIt0, GV0);1193 EXPECT_EQ(&*RevIt1, GV1);1194 EXPECT_EQ(std::prev(RevIt0), RevIt1);1195 EXPECT_EQ(std::next(RevIt1), RevIt0);1196 EXPECT_EQ(&*std::prev(RevIt0), GV1);1197 EXPECT_EQ(&*std::next(RevIt1), GV0);1198 }1199 // Check hasInitializer().1200 EXPECT_EQ(GV0->hasInitializer(), LLVMGV0->hasInitializer());1201 // Check hasDefinitiveInitializer().1202 EXPECT_EQ(GV0->hasDefinitiveInitializer(),1203 LLVMGV0->hasDefinitiveInitializer());1204 // Check hasUniqueInitializer().1205 EXPECT_EQ(GV0->hasUniqueInitializer(), LLVMGV0->hasUniqueInitializer());1206 // Check getInitializer().1207 EXPECT_EQ(GV0->getInitializer(), Ctx.getValue(LLVMGV0->getInitializer()));1208 // Check setInitializer().1209 auto *OrigInitializer = GV0->getInitializer();1210 auto *NewInitializer = GV1->getInitializer();1211 EXPECT_NE(NewInitializer, OrigInitializer);1212 GV0->setInitializer(NewInitializer);1213 EXPECT_EQ(GV0->getInitializer(), NewInitializer);1214 GV0->setInitializer(OrigInitializer);1215 EXPECT_EQ(GV0->getInitializer(), OrigInitializer);1216 // Check isConstant().1217 EXPECT_EQ(GV0->isConstant(), LLVMGV0->isConstant());1218 // Check setConstant().1219 bool OrigIsConstant = GV0->isConstant();1220 bool NewIsConstant = !OrigIsConstant;1221 GV0->setConstant(NewIsConstant);1222 EXPECT_EQ(GV0->isConstant(), NewIsConstant);1223 GV0->setConstant(OrigIsConstant);1224 EXPECT_EQ(GV0->isConstant(), OrigIsConstant);1225 // Check isExternallyInitialized().1226 EXPECT_EQ(GV0->isExternallyInitialized(), LLVMGV0->isExternallyInitialized());1227 // Check setExternallyInitialized().1228 bool OrigIsExtInit = GV0->isExternallyInitialized();1229 bool NewIsExtInit = !OrigIsExtInit;1230 GV0->setExternallyInitialized(NewIsExtInit);1231 EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);1232 GV0->setExternallyInitialized(OrigIsExtInit);1233 EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);1234 for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {1235 // Check hasAttribute(AttrKind).1236 auto Kind = static_cast<Attribute::AttrKind>(KindIdx);1237 EXPECT_EQ(GV0->hasAttribute(Kind), LLVMGV0->hasAttribute(Kind));1238 // Check hasAttribute(StringRef).1239 StringRef KindStr = Attribute::getNameFromAttrKind(Kind);1240 EXPECT_EQ(GV0->hasAttribute(KindStr), LLVMGV0->hasAttribute(KindStr));1241 }1242 // Check hasAttributes().1243 EXPECT_EQ(GV0->hasAttributes(), LLVMGV0->hasAttributes());1244 1245 for (auto KindIdx : seq<int>(0, Attribute::AttrKind::EndAttrKinds)) {1246 // Check getAttribute(AttrKind).1247 auto Kind = static_cast<Attribute::AttrKind>(KindIdx);1248 EXPECT_EQ(GV0->getAttribute(Kind), LLVMGV0->getAttribute(Kind));1249 // Check getAttribute(StringRef).1250 StringRef KindStr = Attribute::getNameFromAttrKind(Kind);1251 EXPECT_EQ(GV0->getAttribute(KindStr), LLVMGV0->getAttribute(KindStr));1252 }1253 // Check getAttributes().1254 EXPECT_EQ(GV0->getAttributes(), LLVMGV0->getAttributes());1255 // Check getAttributesAsList().1256 EXPECT_THAT(GV0->getAttributesAsList(0u),1257 testing::ContainerEq(LLVMGV0->getAttributesAsList(0u)));1258 // Check hasImplicitSection().1259 EXPECT_EQ(GV0->hasImplicitSection(), LLVMGV0->hasImplicitSection());1260 // Check getCodeModelRaw().1261 EXPECT_EQ(GV0->getCodeModelRaw(), LLVMGV0->getCodeModelRaw());1262 // Check getCodeModel().1263 EXPECT_EQ(GV0->getCodeModel(), LLVMGV0->getCodeModel());1264 // Check getAlign().1265 EXPECT_EQ(GV0->getAlign(), LLVMGV0->getAlign());1266 // Check setAlignment().1267 auto OrigMaybeAlign = GV0->getAlign();1268 auto NewMaybeAlign = MaybeAlign(128);1269 EXPECT_NE(NewMaybeAlign, OrigMaybeAlign);1270 GV0->setAlignment(NewMaybeAlign);1271 EXPECT_EQ(GV0->getAlign(), NewMaybeAlign);1272 GV0->setAlignment(OrigMaybeAlign);1273 EXPECT_EQ(GV0->getAlign(), OrigMaybeAlign);1274}1275 1276TEST_F(SandboxIRTest, GlobalAlias) {1277 parseIR(C, R"IR(1278@alias0 = dso_local alias void(), ptr @foo1279@alias1 = dso_local alias void(), ptr @foo1280declare void @bar();1281define void @foo() {1282 call void @alias0()1283 call void @alias1()1284 call void @bar()1285 ret void1286}1287)IR");1288 Function &LLVMF = *M->getFunction("foo");1289 auto *LLVMBB = &*LLVMF.begin();1290 auto LLVMIt = LLVMBB->begin();1291 auto *LLVMCall0 = cast<llvm::CallInst>(&*LLVMIt++);1292 auto *LLVMAlias0 = cast<llvm::GlobalAlias>(LLVMCall0->getCalledOperand());1293 sandboxir::Context Ctx(C);1294 1295 auto &F = *Ctx.createFunction(&LLVMF);1296 auto *BB = &*F.begin();1297 auto It = BB->begin();1298 auto *Call0 = cast<sandboxir::CallInst>(&*It++);1299 auto *Call1 = cast<sandboxir::CallInst>(&*It++);1300 auto *CallBar = cast<sandboxir::CallInst>(&*It++);1301 auto *CalleeBar = cast<sandboxir::Constant>(CallBar->getCalledOperand());1302 // Check classof(), creation.1303 auto *Alias0 = cast<sandboxir::GlobalAlias>(Call0->getCalledOperand());1304 auto *Alias1 = cast<sandboxir::GlobalAlias>(Call1->getCalledOperand());1305 // Check getIterator().1306 {1307 auto It0 = Alias0->getIterator();1308 auto It1 = Alias1->getIterator();1309 EXPECT_EQ(&*It0, Alias0);1310 EXPECT_EQ(&*It1, Alias1);1311 EXPECT_EQ(std::next(It0), It1);1312 EXPECT_EQ(std::prev(It1), It0);1313 EXPECT_EQ(&*std::next(It0), Alias1);1314 EXPECT_EQ(&*std::prev(It1), Alias0);1315 }1316 // Check getReverseIterator().1317 {1318 auto RevIt0 = Alias0->getReverseIterator();1319 auto RevIt1 = Alias1->getReverseIterator();1320 EXPECT_EQ(&*RevIt0, Alias0);1321 EXPECT_EQ(&*RevIt1, Alias1);1322 EXPECT_EQ(std::prev(RevIt0), RevIt1);1323 EXPECT_EQ(std::next(RevIt1), RevIt0);1324 EXPECT_EQ(&*std::prev(RevIt0), Alias1);1325 EXPECT_EQ(&*std::next(RevIt1), Alias0);1326 }1327 // Check getAliasee().1328 EXPECT_EQ(Alias0->getAliasee(), Ctx.getValue(LLVMAlias0->getAliasee()));1329 // Check setAliasee().1330 auto *OrigAliasee = Alias0->getAliasee();1331 auto *NewAliasee = CalleeBar;1332 EXPECT_NE(NewAliasee, OrigAliasee);1333 Alias0->setAliasee(NewAliasee);1334 EXPECT_EQ(Alias0->getAliasee(), NewAliasee);1335 Alias0->setAliasee(OrigAliasee);1336 EXPECT_EQ(Alias0->getAliasee(), OrigAliasee);1337 // Check getAliaseeObject().1338 EXPECT_EQ(Alias0->getAliaseeObject(),1339 Ctx.getValue(LLVMAlias0->getAliaseeObject()));1340}1341 1342TEST_F(SandboxIRTest, NoCFIValue) {1343 parseIR(C, R"IR(1344define void @foo() {1345 call void no_cfi @foo()1346 ret void1347}1348)IR");1349 Function &LLVMF = *M->getFunction("foo");1350 sandboxir::Context Ctx(C);1351 1352 auto &F = *Ctx.createFunction(&LLVMF);1353 auto *BB = &*F.begin();1354 auto It = BB->begin();1355 auto *Call = cast<sandboxir::CallInst>(&*It++);1356 // Check classof(), creation.1357 auto *NoCFI = cast<sandboxir::NoCFIValue>(Call->getCalledOperand());1358 // Check get().1359 auto *NewNoCFI = sandboxir::NoCFIValue::get(&F);1360 EXPECT_EQ(NewNoCFI, NoCFI);1361 // Check getGlobalValue().1362 EXPECT_EQ(NoCFI->getGlobalValue(), &F);1363 // Check getType().1364 EXPECT_EQ(NoCFI->getType(), F.getType());1365}1366 1367TEST_F(SandboxIRTest, ConstantPtrAuth) {1368 parseIR(C, R"IR(1369define ptr @foo() {1370 ret ptr ptrauth (ptr @foo, i32 2, i64 1234)1371}1372)IR");1373 Function &LLVMF = *M->getFunction("foo");1374 auto *LLVMBB = &*LLVMF.begin();1375 auto *LLVMRet = cast<llvm::ReturnInst>(&*LLVMBB->begin());1376 auto *LLVMPtrAuth = cast<llvm::ConstantPtrAuth>(LLVMRet->getReturnValue());1377 sandboxir::Context Ctx(C);1378 1379 auto &F = *Ctx.createFunction(&LLVMF);1380 auto *BB = &*F.begin();1381 auto It = BB->begin();1382 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);1383 // Check classof(), creation.1384 auto *PtrAuth = cast<sandboxir::ConstantPtrAuth>(Ret->getReturnValue());1385 // Check get(), getKey(), getDiscriminator(), getAddrDiscriminator().1386 auto *NewPtrAuth = sandboxir::ConstantPtrAuth::get(1387 &F, PtrAuth->getKey(), PtrAuth->getDiscriminator(),1388 PtrAuth->getAddrDiscriminator(), PtrAuth->getDeactivationSymbol());1389 EXPECT_EQ(NewPtrAuth, PtrAuth);1390 // Check hasAddressDiscriminator().1391 EXPECT_EQ(PtrAuth->hasAddressDiscriminator(),1392 LLVMPtrAuth->hasAddressDiscriminator());1393 // Check hasSpecialAddressDiscriminator().1394 EXPECT_EQ(PtrAuth->hasSpecialAddressDiscriminator(0u),1395 LLVMPtrAuth->hasSpecialAddressDiscriminator(0u));1396 // Check isKnownCompatibleWith().1397 const DataLayout &DL = M->getDataLayout();1398 EXPECT_TRUE(PtrAuth->isKnownCompatibleWith(PtrAuth->getKey(),1399 PtrAuth->getDiscriminator(), DL));1400 // Check getWithSameSchema().1401 EXPECT_EQ(PtrAuth->getWithSameSchema(&F), PtrAuth);1402}1403 1404TEST_F(SandboxIRTest, ConstantExpr) {1405 parseIR(C, R"IR(1406define i32 @foo() {1407 ret i32 ptrtoint (ptr @foo to i32)1408}1409)IR");1410 Function &LLVMF = *M->getFunction("foo");1411 sandboxir::Context Ctx(C);1412 1413 auto &F = *Ctx.createFunction(&LLVMF);1414 auto *BB = &*F.begin();1415 auto It = BB->begin();1416 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);1417 // Check classof(), creation.1418 [[maybe_unused]] auto *ConstExpr =1419 cast<sandboxir::ConstantExpr>(Ret->getReturnValue());1420}1421 1422TEST_F(SandboxIRTest, BlockAddress) {1423 parseIR(C, R"IR(1424define void @foo(ptr %ptr) {1425bb0:1426 store ptr blockaddress(@foo, %bb0), ptr %ptr1427 ret void1428bb1:1429 ret void1430bb2:1431 ret void1432}1433)IR");1434 Function &LLVMF = *M->getFunction("foo");1435 sandboxir::Context Ctx(C);1436 1437 auto &F = *Ctx.createFunction(&LLVMF);1438 auto *BB0 = cast<sandboxir::BasicBlock>(1439 Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));1440 auto *BB1 = cast<sandboxir::BasicBlock>(1441 Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));1442 auto *BB2 = cast<sandboxir::BasicBlock>(1443 Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));1444 auto It = BB0->begin();1445 auto *SI = cast<sandboxir::StoreInst>(&*It++);1446 [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);1447 1448 // Check classof(), creation, getFunction(), getBasicBlock().1449 auto *BB0Addr = cast<sandboxir::BlockAddress>(SI->getValueOperand());1450 EXPECT_EQ(BB0Addr->getBasicBlock(), BB0);1451 EXPECT_EQ(BB0Addr->getFunction(), &F);1452 // Check get(F, BB).1453 auto *NewBB0Addr = sandboxir::BlockAddress::get(&F, BB0);1454 EXPECT_EQ(NewBB0Addr, BB0Addr);1455 // Check get(BB).1456 auto *NewBB0Addr2 = sandboxir::BlockAddress::get(BB0);1457 EXPECT_EQ(NewBB0Addr2, BB0Addr);1458 auto *BB1Addr = sandboxir::BlockAddress::get(BB1);1459 EXPECT_EQ(BB1Addr->getBasicBlock(), BB1);1460 EXPECT_NE(BB1Addr, BB0Addr);1461 // Check lookup().1462 auto *LookupBB0Addr = sandboxir::BlockAddress::lookup(BB0);1463 EXPECT_EQ(LookupBB0Addr, BB0Addr);1464 auto *LookupBB1Addr = sandboxir::BlockAddress::lookup(BB1);1465 EXPECT_EQ(LookupBB1Addr, BB1Addr);1466 auto *LookupBB2Addr = sandboxir::BlockAddress::lookup(BB2);1467 EXPECT_EQ(LookupBB2Addr, nullptr);1468}1469 1470TEST_F(SandboxIRTest, DSOLocalEquivalent) {1471 parseIR(C, R"IR(1472declare void @bar()1473define void @foo() {1474 call void dso_local_equivalent @bar()1475 ret void1476}1477)IR");1478 Function &LLVMF = *M->getFunction("foo");1479 sandboxir::Context Ctx(C);1480 1481 auto &F = *Ctx.createFunction(&LLVMF);1482 auto *BB = &*F.begin();1483 auto It = BB->begin();1484 auto *CI = cast<sandboxir::CallInst>(&*It++);1485 // Check classof().1486 auto *DSOLE = cast<sandboxir::DSOLocalEquivalent>(CI->getCalledOperand());1487 // Check getGlobalValue().1488 auto *GV = DSOLE->getGlobalValue();1489 // Check get().1490 auto *NewDSOLE = sandboxir::DSOLocalEquivalent::get(GV);1491 EXPECT_EQ(NewDSOLE, DSOLE);1492}1493 1494TEST_F(SandboxIRTest, ConstantTokenNone) {1495 parseIR(C, R"IR(1496define void @foo(ptr %ptr) {1497 bb0:1498 %cs = catchswitch within none [label %handler] unwind to caller1499 handler:1500 ret void1501}1502)IR");1503 Function &LLVMF = *M->getFunction("foo");1504 sandboxir::Context Ctx(C);1505 1506 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);1507 auto *BB0 = cast<sandboxir::BasicBlock>(1508 Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));1509 auto *CS = cast<sandboxir::CatchSwitchInst>(&*BB0->begin());1510 1511 // Check classof(), creation, getFunction(), getBasicBlock().1512 auto *CTN = cast<sandboxir::ConstantTokenNone>(CS->getParentPad());1513 // Check get().1514 auto *NewCTN = sandboxir::ConstantTokenNone::get(Ctx);1515 EXPECT_EQ(NewCTN, CTN);1516}1517 1518TEST_F(SandboxIRTest, Use) {1519 parseIR(C, R"IR(1520define i32 @foo(i32 %v0, i32 %v1) {1521 %add0 = add i32 %v0, %v11522 ret i32 %add01523}1524)IR");1525 Function &LLVMF = *M->getFunction("foo");1526 sandboxir::Context Ctx(C);1527 1528 BasicBlock *LLVMBB = &*LLVMF.begin();1529 auto LLVMBBIt = LLVMBB->begin();1530 Instruction *LLVMI0 = &*LLVMBBIt++;1531 Instruction *LLVMRet = &*LLVMBBIt++;1532 Argument *LLVMArg0 = LLVMF.getArg(0);1533 Argument *LLVMArg1 = LLVMF.getArg(1);1534 1535 auto &F = *Ctx.createFunction(&LLVMF);1536 auto &BB = *F.begin();1537 auto *Arg0 = F.getArg(0);1538 auto *Arg1 = F.getArg(1);1539 auto It = BB.begin();1540 auto *I0 = &*It++;1541 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);1542 1543 SmallVector<sandboxir::Argument *> Args{Arg0, Arg1};1544 unsigned OpIdx = 0;1545 for (sandboxir::Use Use : I0->operands()) {1546 // Check Use.getOperandNo().1547 EXPECT_EQ(Use.getOperandNo(), OpIdx);1548 // Check Use.getUser().1549 EXPECT_EQ(Use.getUser(), I0);1550 // Check Use.getContext().1551 EXPECT_EQ(Use.getContext(), &Ctx);1552 // Check Use.get().1553 sandboxir::Value *Op = Use.get();1554 EXPECT_EQ(Op, Ctx.getValue(LLVMI0->getOperand(OpIdx)));1555 // Check Use.getUser().1556 EXPECT_EQ(Use.getUser(), I0);1557 // Check implicit cast to Value.1558 sandboxir::Value *Cast = Use;1559 EXPECT_EQ(Cast, Op);1560 // Check that Use points to the correct operand.1561 EXPECT_EQ(Op, Args[OpIdx]);1562 // Check getOperand().1563 EXPECT_EQ(Op, I0->getOperand(OpIdx));1564 // Check getOperandUse().1565 EXPECT_EQ(Use, I0->getOperandUse(OpIdx));1566 ++OpIdx;1567 }1568 EXPECT_EQ(OpIdx, 2u);1569 1570 // Check Use.operator==() and Use.operator!=().1571 sandboxir::Use UseA = I0->getOperandUse(0);1572 sandboxir::Use UseB = I0->getOperandUse(0);1573 EXPECT_TRUE(UseA == UseB);1574 EXPECT_FALSE(UseA != UseB);1575 1576 // Check getNumOperands().1577 EXPECT_EQ(I0->getNumOperands(), 2u);1578 EXPECT_EQ(Ret->getNumOperands(), 1u);1579 1580 EXPECT_EQ(Ret->getOperand(0), I0);1581 1582#ifndef NDEBUG1583 // Check Use.dump(()1584 std::string Buff;1585 raw_string_ostream BS(Buff);1586 BS << "\n";1587 I0->getOperandUse(0).dumpOS(BS);1588 EXPECT_EQ(Buff, R"IR(1589Def: i32 %v0 ; SB2. (Argument)1590User: %add0 = add i32 %v0, %v1 ; SB5. (BinaryOperator)1591OperandNo: 01592)IR");1593#endif // NDEBUG1594 1595 // Check Value.user_begin().1596 sandboxir::Value::user_iterator UIt = I0->user_begin();1597 sandboxir::User *U = *UIt;1598 EXPECT_EQ(U, Ret);1599 // Check Value.uses().1600 EXPECT_EQ(range_size(I0->uses()), 1u);1601 EXPECT_EQ((*I0->uses().begin()).getUser(), Ret);1602 // Check Value.users().1603 EXPECT_EQ(range_size(I0->users()), 1u);1604 EXPECT_EQ(*I0->users().begin(), Ret);1605 // Check Value.getNumUses().1606 EXPECT_EQ(I0->getNumUses(), 1u);1607 // Check Value.hasNUsesOrMore().1608 EXPECT_TRUE(I0->hasNUsesOrMore(0u));1609 EXPECT_TRUE(I0->hasNUsesOrMore(1u));1610 EXPECT_FALSE(I0->hasNUsesOrMore(2u));1611 // Check Value.hasNUses().1612 EXPECT_FALSE(I0->hasNUses(0u));1613 EXPECT_TRUE(I0->hasNUses(1u));1614 EXPECT_FALSE(I0->hasNUses(2u));1615 1616 // Check Value.getExpectedType1617 1618 // Check User.setOperand().1619 Ret->setOperand(0, Arg0);1620 EXPECT_EQ(Ret->getOperand(0), Arg0);1621 EXPECT_EQ(Ret->getOperandUse(0).get(), Arg0);1622 EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg0);1623 1624 Ret->setOperand(0, Arg1);1625 EXPECT_EQ(Ret->getOperand(0), Arg1);1626 EXPECT_EQ(Ret->getOperandUse(0).get(), Arg1);1627 EXPECT_EQ(LLVMRet->getOperand(0), LLVMArg1);1628}1629 1630TEST_F(SandboxIRTest, RUOW) {1631 parseIR(C, R"IR(1632declare void @bar0()1633declare void @bar1()1634 1635@glob0 = global ptr @bar01636@glob1 = global ptr @bar11637 1638define i32 @foo(i32 %arg0, i32 %arg1) {1639 %add0 = add i32 %arg0, %arg11640 %gep1 = getelementptr i8, ptr @glob0, i32 11641 %gep2 = getelementptr i8, ptr @glob1, i32 11642 ret i32 %add01643}1644)IR");1645 llvm::Function &LLVMF = *M->getFunction("foo");1646 sandboxir::Context Ctx(C);1647 1648 auto &F = *Ctx.createFunction(&LLVMF);1649 auto &BB = *F.begin();1650 auto *Arg0 = F.getArg(0);1651 auto *Arg1 = F.getArg(1);1652 auto It = BB.begin();1653 auto *I0 = &*It++;1654 auto *I1 = &*It++;1655 auto *I2 = &*It++;1656 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);1657 1658 bool Replaced;1659 // Try to replace an operand that doesn't match.1660 Replaced = I0->replaceUsesOfWith(Ret, Arg1);1661 EXPECT_FALSE(Replaced);1662 EXPECT_EQ(I0->getOperand(0), Arg0);1663 EXPECT_EQ(I0->getOperand(1), Arg1);1664 1665 // Replace I0 operands when operands differ.1666 Replaced = I0->replaceUsesOfWith(Arg0, Arg1);1667 EXPECT_TRUE(Replaced);1668 EXPECT_EQ(I0->getOperand(0), Arg1);1669 EXPECT_EQ(I0->getOperand(1), Arg1);1670 1671 // Replace I0 operands when operands are the same.1672 Replaced = I0->replaceUsesOfWith(Arg1, Arg0);1673 EXPECT_TRUE(Replaced);1674 EXPECT_EQ(I0->getOperand(0), Arg0);1675 EXPECT_EQ(I0->getOperand(1), Arg0);1676 1677 // Replace Ret operand.1678 Replaced = Ret->replaceUsesOfWith(I0, Arg0);1679 EXPECT_TRUE(Replaced);1680 EXPECT_EQ(Ret->getOperand(0), Arg0);1681 // Check RAUW on constant.1682 auto *Glob0 = cast<sandboxir::Constant>(I1->getOperand(0));1683 auto *Glob1 = cast<sandboxir::Constant>(I2->getOperand(0));1684 auto *Glob0Op = Glob0->getOperand(0);1685 Glob0->replaceUsesOfWith(Glob0Op, Glob1);1686 EXPECT_EQ(Glob0->getOperand(0), Glob1);1687}1688 1689TEST_F(SandboxIRTest, RAUW_RUWIf) {1690 parseIR(C, R"IR(1691define void @foo(ptr %ptr) {1692 %ld0 = load float, ptr %ptr1693 %ld1 = load float, ptr %ptr1694 store float %ld0, ptr %ptr1695 store float %ld0, ptr %ptr1696 ret void1697}1698)IR");1699 llvm::Function &LLVMF = *M->getFunction("foo");1700 sandboxir::Context Ctx(C);1701 llvm::BasicBlock *LLVMBB = &*LLVMF.begin();1702 1703 Ctx.createFunction(&LLVMF);1704 auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));1705 auto It = BB->begin();1706 sandboxir::Instruction *Ld0 = &*It++;1707 sandboxir::Instruction *Ld1 = &*It++;1708 sandboxir::Instruction *St0 = &*It++;1709 sandboxir::Instruction *St1 = &*It++;1710 // Check RUWIf when the lambda returns false.1711 Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; });1712 EXPECT_EQ(St0->getOperand(0), Ld0);1713 EXPECT_EQ(St1->getOperand(0), Ld0);1714 // Check RUWIf when the lambda returns true.1715 Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; });1716 EXPECT_EQ(St0->getOperand(0), Ld1);1717 EXPECT_EQ(St1->getOperand(0), Ld1);1718 St0->setOperand(0, Ld0);1719 St1->setOperand(0, Ld0);1720 // Check RUWIf user == St0.1721 Ld0->replaceUsesWithIf(1722 Ld1, [St0](const sandboxir::Use &Use) { return Use.getUser() == St0; });1723 EXPECT_EQ(St0->getOperand(0), Ld1);1724 EXPECT_EQ(St1->getOperand(0), Ld0);1725 St0->setOperand(0, Ld0);1726 // Check RUWIf user == St1.1727 Ld0->replaceUsesWithIf(1728 Ld1, [St1](const sandboxir::Use &Use) { return Use.getUser() == St1; });1729 EXPECT_EQ(St0->getOperand(0), Ld0);1730 EXPECT_EQ(St1->getOperand(0), Ld1);1731 St1->setOperand(0, Ld0);1732 // Check RAUW.1733 Ld1->replaceAllUsesWith(Ld0);1734 EXPECT_EQ(St0->getOperand(0), Ld0);1735 EXPECT_EQ(St1->getOperand(0), Ld0);1736}1737 1738// Check that the operands/users are counted correctly.1739// I11740// / \1741// \ /1742// I21743TEST_F(SandboxIRTest, DuplicateUses) {1744 parseIR(C, R"IR(1745define void @foo(i8 %v) {1746 %I1 = add i8 %v, %v1747 %I2 = add i8 %I1, %I11748 ret void1749}1750)IR");1751 Function &LLVMF = *M->getFunction("foo");1752 sandboxir::Context Ctx(C);1753 auto *F = Ctx.createFunction(&LLVMF);1754 auto *BB = &*F->begin();1755 auto It = BB->begin();1756 auto *I1 = &*It++;1757 auto *I2 = &*It++;1758 EXPECT_EQ(range_size(I1->users()), 2u);1759 EXPECT_EQ(range_size(I2->operands()), 2u);1760}1761 1762TEST_F(SandboxIRTest, Function) {1763 parseIR(C, R"IR(1764define void @foo0(i32 %arg0, i32 %arg1) {1765bb0:1766 br label %bb11767bb1:1768 ret void1769}1770define void @foo1() {1771 ret void1772}1773 1774)IR");1775 llvm::Function *LLVMF0 = &*M->getFunction("foo0");1776 llvm::Function *LLVMF1 = &*M->getFunction("foo1");1777 llvm::Argument *LLVMArg0 = LLVMF0->getArg(0);1778 llvm::Argument *LLVMArg1 = LLVMF0->getArg(1);1779 1780 sandboxir::Context Ctx(C);1781 sandboxir::Function *F0 = Ctx.createFunction(LLVMF0);1782 sandboxir::Function *F1 = Ctx.createFunction(LLVMF1);1783 1784 // Check getIterator().1785 {1786 auto It0 = F0->getIterator();1787 auto It1 = F1->getIterator();1788 EXPECT_EQ(&*It0, F0);1789 EXPECT_EQ(&*It1, F1);1790 EXPECT_EQ(std::next(It0), It1);1791 EXPECT_EQ(std::prev(It1), It0);1792 EXPECT_EQ(&*std::next(It0), F1);1793 EXPECT_EQ(&*std::prev(It1), F0);1794 }1795 // Check getReverseIterator().1796 {1797 auto RevIt0 = F0->getReverseIterator();1798 auto RevIt1 = F1->getReverseIterator();1799 EXPECT_EQ(&*RevIt0, F0);1800 EXPECT_EQ(&*RevIt1, F1);1801 EXPECT_EQ(std::prev(RevIt0), RevIt1);1802 EXPECT_EQ(std::next(RevIt1), RevIt0);1803 EXPECT_EQ(&*std::prev(RevIt0), F1);1804 EXPECT_EQ(&*std::next(RevIt1), F0);1805 }1806 1807 // Check F arguments1808 EXPECT_EQ(F0->arg_size(), 2u);1809 EXPECT_FALSE(F0->arg_empty());1810 EXPECT_EQ(F0->getArg(0), Ctx.getValue(LLVMArg0));1811 EXPECT_EQ(F0->getArg(1), Ctx.getValue(LLVMArg1));1812 1813 // Check F.begin(), F.end(), Function::iterator1814 llvm::BasicBlock *LLVMBB = &*LLVMF0->begin();1815 for (sandboxir::BasicBlock &BB : *F0) {1816 EXPECT_EQ(&BB, Ctx.getValue(LLVMBB));1817 LLVMBB = LLVMBB->getNextNode();1818 }1819 1820#ifndef NDEBUG1821 {1822 // Check F.dumpNameAndArgs()1823 std::string Buff;1824 raw_string_ostream BS(Buff);1825 F0->dumpNameAndArgs(BS);1826 EXPECT_EQ(Buff, "void @foo0(i32 %arg0, i32 %arg1)");1827 }1828 {1829 // Check F.dump()1830 std::string Buff;1831 raw_string_ostream BS(Buff);1832 BS << "\n";1833 F0->dumpOS(BS);1834 EXPECT_EQ(Buff, R"IR(1835void @foo0(i32 %arg0, i32 %arg1) {1836bb0:1837 br label %bb1 ; SB4. (Br)1838 1839bb1:1840 ret void ; SB6. (Ret)1841}1842)IR");1843 }1844#endif // NDEBUG1845 1846 // Check getAlign().1847 EXPECT_EQ(F0->getAlign(), F0->getAlign());1848 // Check setAlignment().1849 auto OrigMaybeAlign = F0->getAlign();1850 auto NewMaybeAlign = MaybeAlign(128);1851 EXPECT_NE(NewMaybeAlign, OrigMaybeAlign);1852 F0->setAlignment(NewMaybeAlign);1853 EXPECT_EQ(F0->getAlign(), NewMaybeAlign);1854 F0->setAlignment(OrigMaybeAlign);1855 EXPECT_EQ(F0->getAlign(), OrigMaybeAlign);1856}1857 1858TEST_F(SandboxIRTest, Module) {1859 parseIR(C, R"IR(1860@glob0 = global i32 421861@glob1 = global i32 431862@internal0 = internal global i32 421863@const0 = constant i32 421864@alias0 = dso_local alias void(), ptr @foo1865@ifunc = ifunc void(), ptr @foo1866define void @foo() {1867 ret void1868}1869define void @bar() {1870 ret void1871}1872)IR");1873 llvm::Module *LLVMM = &*M;1874 llvm::Function *LLVMFFoo = &*M->getFunction("foo");1875 llvm::Function *LLVMFBar = &*M->getFunction("bar");1876 1877 sandboxir::Context Ctx(C);1878 auto *M = Ctx.createModule(LLVMM);1879 // Check getContext().1880 EXPECT_EQ(&M->getContext(), &Ctx);1881 // Check getFunction().1882 auto *FFoo = M->getFunction("foo");1883 auto *FBar = M->getFunction("bar");1884 EXPECT_EQ(FFoo, Ctx.getValue(LLVMFFoo));1885 EXPECT_EQ(FBar, Ctx.getValue(LLVMFBar));1886 // Check getDataLayout().1887 EXPECT_EQ(&M->getDataLayout(), &LLVMM->getDataLayout());1888 // Check getSourceFileName().1889 EXPECT_EQ(M->getSourceFileName(), LLVMM->getSourceFileName());1890 // Check getGlobalVariable().1891 for (const char *Name : {"global0", "global1", "internal0"})1892 EXPECT_EQ(M->getGlobalVariable(Name),1893 Ctx.getValue(LLVMM->getGlobalVariable(Name)));1894 // Check getGlobalVariable(AllowInternal).1895 {1896 auto *Internal0 = M->getGlobalVariable("internal0", /*AllowInternal=*/true);1897 EXPECT_TRUE(Internal0 != nullptr);1898 EXPECT_EQ(Internal0, Ctx.getValue(LLVMM->getNamedGlobal("internal0")));1899 }1900 // Check getNamedGlobal().1901 {1902 auto *Internal = M->getNamedGlobal("internal0");1903 EXPECT_TRUE(Internal != nullptr);1904 EXPECT_EQ(Internal, Ctx.getValue(LLVMM->getNamedGlobal("internal0")));1905 }1906 // Check getNamedAlias().1907 auto *Alias0 = M->getNamedAlias("alias0");1908 EXPECT_EQ(Alias0, Ctx.getValue(LLVMM->getNamedAlias("alias0")));1909 EXPECT_EQ(M->getNamedAlias("aliasFOO"), nullptr);1910 // Check getNamedIFunc().1911 auto *IFunc0 = M->getNamedIFunc("ifunc0");1912 EXPECT_EQ(IFunc0, Ctx.getValue(LLVMM->getNamedAlias("ifunc0")));1913 EXPECT_EQ(M->getNamedIFunc("ifuncFOO"), nullptr);1914}1915 1916TEST_F(SandboxIRTest, BasicBlock) {1917 parseIR(C, R"IR(1918define void @foo(i32 %v1) {1919bb0:1920 br label %bb11921bb1:1922 ret void1923}1924)IR");1925 llvm::Function *LLVMF = &*M->getFunction("foo");1926 llvm::BasicBlock *LLVMBB0 = getBasicBlockByName(*LLVMF, "bb0");1927 llvm::BasicBlock *LLVMBB1 = getBasicBlockByName(*LLVMF, "bb1");1928 1929 sandboxir::Context Ctx(C);1930 sandboxir::Function *F = Ctx.createFunction(LLVMF);1931 auto &BB0 = cast<sandboxir::BasicBlock>(*Ctx.getValue(LLVMBB0));1932 auto &BB1 = cast<sandboxir::BasicBlock>(*Ctx.getValue(LLVMBB1));1933 1934 // Check BB::classof()1935 EXPECT_TRUE(isa<sandboxir::Value>(BB0));1936 EXPECT_FALSE(isa<sandboxir::User>(BB0));1937 EXPECT_FALSE(isa<sandboxir::Instruction>(BB0));1938 EXPECT_FALSE(isa<sandboxir::Constant>(BB0));1939 EXPECT_FALSE(isa<sandboxir::Argument>(BB0));1940 1941 // Check BB.getParent()1942 EXPECT_EQ(BB0.getParent(), F);1943 EXPECT_EQ(BB1.getParent(), F);1944 1945 // Check BBIterator, BB.begin(), BB.end().1946 llvm::Instruction *LLVMI = &*LLVMBB0->begin();1947 for (sandboxir::Instruction &I : BB0) {1948 EXPECT_EQ(&I, Ctx.getValue(LLVMI));1949 LLVMI = LLVMI->getNextNode();1950 // Check getNodeParent().1951 EXPECT_EQ(I.getIterator().getNodeParent(), &BB0);1952 }1953 LLVMI = &*LLVMBB1->begin();1954 for (sandboxir::Instruction &I : BB1) {1955 EXPECT_EQ(&I, Ctx.getValue(LLVMI));1956 LLVMI = LLVMI->getNextNode();1957 }1958 // Check NodeParent() for BB::end().1959 EXPECT_EQ(BB0.end().getNodeParent(), &BB0);1960 1961 // Check BB.getTerminator()1962 EXPECT_EQ(BB0.getTerminator(), Ctx.getValue(LLVMBB0->getTerminator()));1963 EXPECT_EQ(BB1.getTerminator(), Ctx.getValue(LLVMBB1->getTerminator()));1964 1965 // Check BB.rbegin(), BB.rend()1966 EXPECT_EQ(&*BB0.rbegin(), BB0.getTerminator());1967 EXPECT_EQ(&*std::prev(BB0.rend()), &*BB0.begin());1968 1969#ifndef NDEBUG1970 {1971 // Check BB.dump()1972 std::string Buff;1973 raw_string_ostream BS(Buff);1974 BS << "\n";1975 BB0.dumpOS(BS);1976 EXPECT_EQ(Buff, R"IR(1977bb0:1978 br label %bb1 ; SB3. (Br)1979)IR");1980 }1981#endif // NDEBUG1982}1983 1984TEST_F(SandboxIRTest, Instruction) {1985 parseIR(C, R"IR(1986define void @foo(i8 %v1, ptr %ptr) {1987bb0:1988 %add0 = add i8 %v1, %v11989 %sub1 = sub i8 %add0, %v11990 ret void1991 1992bb1:1993 %add1 = add i8 %v1, %v11994 %sub2 = sub i8 %add1, %v11995 %ld0 = load i8, ptr %ptr1996 store i8 %ld0, ptr %ptr1997 store volatile i8 %ld0, ptr %ptr1998 %atomicrmw = atomicrmw add ptr %ptr, i8 %v1 acquire1999 %udiv = udiv i8 %ld0, %v12000 %urem = urem i8 %ld0, %v12001 call void @foo(), !dbg !12002 ret void, !tbaa !22003}2004 2005!1 = !{}2006!2 = !{}2007)IR");2008 llvm::Function *LLVMF = &*M->getFunction("foo");2009 llvm::BasicBlock *LLVMBB1 = getBasicBlockByName(*LLVMF, "bb1");2010 sandboxir::Context Ctx(C);2011 sandboxir::Function *F = Ctx.createFunction(LLVMF);2012 auto *Arg = F->getArg(0);2013 auto *BB = cast<sandboxir::BasicBlock>(2014 Ctx.getValue(getBasicBlockByName(*LLVMF, "bb0")));2015 auto It = BB->begin();2016 auto *I0 = &*It++;2017 auto *I1 = &*It++;2018 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);2019 2020 // Check getPrevNode().2021 EXPECT_EQ(Ret->getPrevNode(), I1);2022 EXPECT_EQ(I1->getPrevNode(), I0);2023 EXPECT_EQ(I0->getPrevNode(), nullptr);2024 2025 // Check getNextNode().2026 EXPECT_EQ(I0->getNextNode(), I1);2027 EXPECT_EQ(I1->getNextNode(), Ret);2028 EXPECT_EQ(Ret->getNextNode(), nullptr);2029 2030 // Check getIterator().2031 EXPECT_EQ(I0->getIterator(), std::next(BB->begin(), 0));2032 EXPECT_EQ(I1->getIterator(), std::next(BB->begin(), 1));2033 EXPECT_EQ(Ret->getIterator(), std::next(BB->begin(), 2));2034 2035 // Check getOpcode().2036 EXPECT_EQ(I0->getOpcode(), sandboxir::Instruction::Opcode::Add);2037 EXPECT_EQ(I1->getOpcode(), sandboxir::Instruction::Opcode::Sub);2038 EXPECT_EQ(Ret->getOpcode(), sandboxir::Instruction::Opcode::Ret);2039 2040 // Check getOpcodeName().2041 EXPECT_STREQ(I0->getOpcodeName(), "Add");2042 EXPECT_STREQ(I1->getOpcodeName(), "Sub");2043 EXPECT_STREQ(Ret->getOpcodeName(), "Ret");2044 2045 EXPECT_STREQ(sandboxir::Instruction::getOpcodeName(2046 sandboxir::Instruction::Opcode::Alloca),2047 "Alloca");2048 2049 // Check moveBefore(I).2050 I1->moveBefore(I0);2051 EXPECT_EQ(I0->getPrevNode(), I1);2052 EXPECT_EQ(I1->getNextNode(), I0);2053 2054 // Check moveAfter(I).2055 I1->moveAfter(I0);2056 EXPECT_EQ(I0->getNextNode(), I1);2057 EXPECT_EQ(I1->getPrevNode(), I0);2058 2059 // Check comesBefore(I).2060 EXPECT_TRUE(I0->comesBefore(I1));2061 EXPECT_FALSE(I1->comesBefore(I0));2062 2063 // Check moveBefore(BB, It).2064 I1->moveBefore(*BB, BB->begin());2065 EXPECT_EQ(I1->getPrevNode(), nullptr);2066 EXPECT_EQ(I1->getNextNode(), I0);2067 I1->moveBefore(*BB, BB->end());2068 EXPECT_EQ(I1->getNextNode(), nullptr);2069 EXPECT_EQ(Ret->getNextNode(), I1);2070 I1->moveBefore(*BB, std::next(BB->begin()));2071 EXPECT_EQ(I0->getNextNode(), I1);2072 EXPECT_EQ(I1->getNextNode(), Ret);2073 2074 // Check removeFromParent().2075 I0->removeFromParent();2076#ifndef NDEBUG2077 EXPECT_DEATH(I0->getPrevNode(), ".*Detached.*");2078 EXPECT_DEATH(I0->getNextNode(), ".*Detached.*");2079#endif // NDEBUG2080 EXPECT_EQ(I0->getParent(), nullptr);2081 EXPECT_EQ(I1->getPrevNode(), nullptr);2082 EXPECT_EQ(I0->getOperand(0), Arg);2083 2084 // Check insertBefore().2085 I0->insertBefore(I1);2086 EXPECT_EQ(I1->getPrevNode(), I0);2087 2088 // Check insertInto().2089 I0->removeFromParent();2090 I0->insertInto(BB, BB->end());2091 EXPECT_EQ(Ret->getNextNode(), I0);2092 I0->moveBefore(I1);2093 EXPECT_EQ(I0->getNextNode(), I1);2094 2095 // Check eraseFromParent().2096#ifndef NDEBUG2097 EXPECT_DEATH(I0->eraseFromParent(), "Still connected to users.*");2098#endif2099 I1->eraseFromParent();2100 EXPECT_EQ(I0->getNumUses(), 0u);2101 EXPECT_EQ(I0->getNextNode(), Ret);2102 2103 for (auto &LLVMI : *LLVMBB1) {2104 auto &I = cast<sandboxir::Instruction>(*Ctx.getValue(&LLVMI));2105 // Check isTerminator().2106 EXPECT_EQ(LLVMI.isTerminator(), I.isTerminator());2107 // Check isUnaryOp().2108 EXPECT_EQ(LLVMI.isUnaryOp(), I.isUnaryOp());2109 // Check isBinaryOp().2110 EXPECT_EQ(LLVMI.isBinaryOp(), I.isBinaryOp());2111 // Check isIntDivRem().2112 EXPECT_EQ(LLVMI.isIntDivRem(), I.isIntDivRem());2113 // Check isShift().2114 EXPECT_EQ(LLVMI.isShift(), I.isShift());2115 // Check isCast().2116 EXPECT_EQ(LLVMI.isCast(), I.isCast());2117 // Check isFuncletPad().2118 EXPECT_EQ(LLVMI.isFuncletPad(), I.isFuncletPad());2119 // Check isSpecialTerminator().2120 EXPECT_EQ(LLVMI.isSpecialTerminator(), I.isSpecialTerminator());2121 // Check isOnlyUserOfAnyOperand().2122 EXPECT_EQ(LLVMI.isOnlyUserOfAnyOperand(), I.isOnlyUserOfAnyOperand());2123 // Check isLogicalShift().2124 EXPECT_EQ(LLVMI.isLogicalShift(), I.isLogicalShift());2125 // Check hasMetadata().2126 EXPECT_EQ(LLVMI.hasMetadata(), I.hasMetadata());2127 // Check hasMetadataOtherThanDebugLoc().2128 EXPECT_EQ(LLVMI.hasMetadataOtherThanDebugLoc(),2129 I.hasMetadataOtherThanDebugLoc());2130 // Check isAssociative().2131 EXPECT_EQ(LLVMI.isAssociative(), I.isAssociative());2132 // Check isCommutative().2133 EXPECT_EQ(LLVMI.isCommutative(), I.isCommutative());2134 // Check isIdempotent().2135 EXPECT_EQ(LLVMI.isIdempotent(), I.isIdempotent());2136 // Check isNilpotent().2137 EXPECT_EQ(LLVMI.isNilpotent(), I.isNilpotent());2138 // Check mayWriteToMemory().2139 EXPECT_EQ(LLVMI.mayWriteToMemory(), I.mayWriteToMemory());2140 // Check mayReadFromMemory().2141 EXPECT_EQ(LLVMI.mayReadFromMemory(), I.mayReadFromMemory());2142 // Check mayReadOrWriteMemory().2143 EXPECT_EQ(LLVMI.mayReadOrWriteMemory(), I.mayReadOrWriteMemory());2144 // Check isAtomic().2145 EXPECT_EQ(LLVMI.isAtomic(), I.isAtomic());2146 if (I.isAtomic()) {2147 // Check hasAtomicLoad().2148 EXPECT_EQ(LLVMI.hasAtomicLoad(), I.hasAtomicLoad());2149 // Check hasAtomicStore().2150 EXPECT_EQ(LLVMI.hasAtomicStore(), I.hasAtomicStore());2151 }2152 // Check isVolatile().2153 EXPECT_EQ(LLVMI.isVolatile(), I.isVolatile());2154 // Check getAccessType().2155 EXPECT_EQ(Ctx.getType(LLVMI.getAccessType()), I.getAccessType());2156 // Check mayThrow().2157 EXPECT_EQ(LLVMI.mayThrow(), I.mayThrow());2158 // Check isFenceLike().2159 EXPECT_EQ(LLVMI.isFenceLike(), I.isFenceLike());2160 // Check mayHaveSideEffects().2161 EXPECT_EQ(LLVMI.mayHaveSideEffects(), I.mayHaveSideEffects());2162 }2163}2164 2165TEST_F(SandboxIRTest, VAArgInst) {2166 parseIR(C, R"IR(2167define void @foo(ptr %va) {2168 %va_arg = va_arg ptr %va, i322169 ret void2170}2171)IR");2172 llvm::Function *LLVMF = &*M->getFunction("foo");2173 2174 sandboxir::Context Ctx(C);2175 sandboxir::Function *F = Ctx.createFunction(LLVMF);2176 auto *Arg = F->getArg(0);2177 auto *BB = &*F->begin();2178 auto It = BB->begin();2179 auto *VA = cast<sandboxir::VAArgInst>(&*It++);2180 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);2181 2182 // Check getPointerOperand().2183 EXPECT_EQ(VA->getPointerOperand(), Arg);2184 // Check getPOinterOperandIndex().2185 EXPECT_EQ(sandboxir::VAArgInst::getPointerOperandIndex(),2186 llvm::VAArgInst::getPointerOperandIndex());2187 // Check create().2188 auto *NewVATy = sandboxir::Type::getInt8Ty(Ctx);2189 auto *NewVA = sandboxir::VAArgInst::create(Arg, NewVATy, Ret->getIterator(),2190 Ctx, "NewVA");2191 EXPECT_EQ(NewVA->getNextNode(), Ret);2192 EXPECT_EQ(NewVA->getType(), NewVATy);2193#ifndef NDEBUG2194 EXPECT_EQ(NewVA->getName(), "NewVA");2195#endif // NDEBUG2196}2197 2198TEST_F(SandboxIRTest, FreezeInst) {2199 parseIR(C, R"IR(2200define void @foo(i8 %arg) {2201 freeze i8 %arg2202 ret void2203}2204)IR");2205 llvm::Function *LLVMF = &*M->getFunction("foo");2206 2207 sandboxir::Context Ctx(C);2208 sandboxir::Function *F = Ctx.createFunction(LLVMF);2209 auto *Arg = F->getArg(0);2210 auto *BB = &*F->begin();2211 auto It = BB->begin();2212 auto *Freeze = cast<sandboxir::FreezeInst>(&*It++);2213 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);2214 2215 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Freeze));2216 EXPECT_EQ(Freeze->getOperand(0), Arg);2217 2218 // Check create().2219 auto *NewFreeze =2220 sandboxir::FreezeInst::create(Arg, Ret->getIterator(), Ctx, "NewFreeze");2221 EXPECT_EQ(NewFreeze->getNextNode(), Ret);2222#ifndef NDEBUG2223 EXPECT_EQ(NewFreeze->getName(), "NewFreeze");2224#endif // NDEBUG2225}2226 2227TEST_F(SandboxIRTest, FenceInst) {2228 parseIR(C, R"IR(2229define void @foo() {2230 fence syncscope("singlethread") seq_cst2231 ret void2232}2233)IR");2234 llvm::Function *LLVMF = &*M->getFunction("foo");2235 llvm::BasicBlock *LLVMBB = &*LLVMF->begin();2236 auto *LLVMFence = cast<llvm::FenceInst>(&*LLVMBB->begin());2237 sandboxir::Context Ctx(C);2238 sandboxir::Function *F = Ctx.createFunction(LLVMF);2239 auto *BB = &*F->begin();2240 auto It = BB->begin();2241 auto *Fence = cast<sandboxir::FenceInst>(&*It++);2242 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);2243 2244 // Check getOrdering().2245 EXPECT_EQ(Fence->getOrdering(), LLVMFence->getOrdering());2246 // Check setOrdering().2247 auto OrigOrdering = Fence->getOrdering();2248 auto NewOrdering = AtomicOrdering::Release;2249 EXPECT_NE(NewOrdering, OrigOrdering);2250 Fence->setOrdering(NewOrdering);2251 EXPECT_EQ(Fence->getOrdering(), NewOrdering);2252 Fence->setOrdering(OrigOrdering);2253 EXPECT_EQ(Fence->getOrdering(), OrigOrdering);2254 // Check getSyncScopeID().2255 EXPECT_EQ(Fence->getSyncScopeID(), LLVMFence->getSyncScopeID());2256 // Check setSyncScopeID().2257 auto OrigSSID = Fence->getSyncScopeID();2258 auto NewSSID = SyncScope::System;2259 EXPECT_NE(NewSSID, OrigSSID);2260 Fence->setSyncScopeID(NewSSID);2261 EXPECT_EQ(Fence->getSyncScopeID(), NewSSID);2262 Fence->setSyncScopeID(OrigSSID);2263 EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID);2264 // Check create().2265 auto *NewFence =2266 sandboxir::FenceInst::create(AtomicOrdering::Release, Ret->getIterator(),2267 Ctx, SyncScope::SingleThread);2268 EXPECT_EQ(NewFence->getNextNode(), Ret);2269 EXPECT_EQ(NewFence->getOrdering(), AtomicOrdering::Release);2270 EXPECT_EQ(NewFence->getSyncScopeID(), SyncScope::SingleThread);2271}2272 2273TEST_F(SandboxIRTest, SelectInst) {2274 parseIR(C, R"IR(2275define void @foo(i1 %c0, i8 %v0, i8 %v1, i1 %c1) {2276 %sel = select i1 %c0, i8 %v0, i8 %v12277 ret void2278}2279)IR");2280 llvm::Function *LLVMF = &*M->getFunction("foo");2281 sandboxir::Context Ctx(C);2282 sandboxir::Function *F = Ctx.createFunction(LLVMF);2283 auto *Cond0 = F->getArg(0);2284 auto *V0 = F->getArg(1);2285 auto *V1 = F->getArg(2);2286 auto *Cond1 = F->getArg(3);2287 auto *BB = &*F->begin();2288 auto It = BB->begin();2289 auto *Select = cast<sandboxir::SelectInst>(&*It++);2290 const auto *ConstSelect = Select; // To test the const getters.2291 auto *Ret = &*It++;2292 2293 // Check getCondition().2294 EXPECT_EQ(Select->getCondition(), Cond0);2295 EXPECT_EQ(ConstSelect->getCondition(), Cond0);2296 // Check getTrueValue().2297 EXPECT_EQ(Select->getTrueValue(), V0);2298 EXPECT_EQ(ConstSelect->getTrueValue(), V0);2299 // Check getFalseValue().2300 EXPECT_EQ(Select->getFalseValue(), V1);2301 EXPECT_EQ(ConstSelect->getFalseValue(), V1);2302 // Check setCondition().2303 Select->setCondition(Cond1);2304 EXPECT_EQ(Select->getCondition(), Cond1);2305 // Check setTrueValue().2306 Select->setTrueValue(V1);2307 EXPECT_EQ(Select->getTrueValue(), V1);2308 // Check setFalseValue().2309 Select->setFalseValue(V0);2310 EXPECT_EQ(Select->getFalseValue(), V0);2311 // Check swapValues().2312 Select->swapValues();2313 EXPECT_EQ(Select->getTrueValue(), V0);2314 EXPECT_EQ(Select->getFalseValue(), V1);2315 // Check areInvalidOperands.2316 EXPECT_EQ(sandboxir::SelectInst::areInvalidOperands(Cond0, V0, V1), nullptr);2317 EXPECT_NE(sandboxir::SelectInst::areInvalidOperands(V0, V1, Cond0), nullptr);2318 2319 {2320 // Check SelectInst::create() InsertBefore.2321 auto *NewSel = cast<sandboxir::SelectInst>(sandboxir::SelectInst::create(2322 Cond0, V0, V1, /*InsertBefore=*/Ret->getIterator(), Ctx));2323 EXPECT_EQ(NewSel->getCondition(), Cond0);2324 EXPECT_EQ(NewSel->getTrueValue(), V0);2325 EXPECT_EQ(NewSel->getFalseValue(), V1);2326 EXPECT_EQ(NewSel->getNextNode(), Ret);2327 }2328 {2329 // Check SelectInst::create() InsertAtEnd.2330 auto *NewSel = cast<sandboxir::SelectInst>(2331 sandboxir::SelectInst::create(Cond0, V0, V1, /*InsertAtEnd=*/BB, Ctx));2332 EXPECT_EQ(NewSel->getCondition(), Cond0);2333 EXPECT_EQ(NewSel->getTrueValue(), V0);2334 EXPECT_EQ(NewSel->getFalseValue(), V1);2335 EXPECT_EQ(NewSel->getPrevNode(), Ret);2336 }2337 {2338 // Check SelectInst::create() Folded.2339 auto *False = sandboxir::ConstantInt::get(sandboxir::Type::getInt1Ty(Ctx),2340 0, /*IsSigned=*/false);2341 auto *FortyTwo =2342 sandboxir::ConstantInt::get(sandboxir::Type::getInt1Ty(Ctx), 42,2343 /*IsSigned=*/false);2344 auto *NewSel = sandboxir::SelectInst::create(False, FortyTwo, FortyTwo,2345 Ret->getIterator(), Ctx);2346 EXPECT_TRUE(isa<sandboxir::Constant>(NewSel));2347 EXPECT_EQ(NewSel, FortyTwo);2348 }2349}2350 2351TEST_F(SandboxIRTest, ExtractElementInst) {2352 parseIR(C, R"IR(2353define void @foo(<2 x i8> %vec, i32 %idx) {2354 %ins0 = extractelement <2 x i8> %vec, i32 %idx2355 ret void2356}2357)IR");2358 Function &LLVMF = *M->getFunction("foo");2359 sandboxir::Context Ctx(C);2360 auto &F = *Ctx.createFunction(&LLVMF);2361 auto *ArgVec = F.getArg(0);2362 auto *ArgIdx = F.getArg(1);2363 auto *BB = &*F.begin();2364 auto It = BB->begin();2365 auto *EI = cast<sandboxir::ExtractElementInst>(&*It++);2366 auto *Ret = &*It++;2367 2368 EXPECT_EQ(EI->getOpcode(), sandboxir::Instruction::Opcode::ExtractElement);2369 EXPECT_EQ(EI->getOperand(0), ArgVec);2370 EXPECT_EQ(EI->getOperand(1), ArgIdx);2371 EXPECT_EQ(EI->getVectorOperand(), ArgVec);2372 EXPECT_EQ(EI->getIndexOperand(), ArgIdx);2373 EXPECT_EQ(EI->getVectorOperandType(), ArgVec->getType());2374 2375 auto *NewI1 =2376 cast<sandboxir::ExtractElementInst>(sandboxir::ExtractElementInst::create(2377 ArgVec, ArgIdx, Ret->getIterator(), Ctx, "NewExtrBeforeRet"));2378 EXPECT_EQ(NewI1->getOperand(0), ArgVec);2379 EXPECT_EQ(NewI1->getOperand(1), ArgIdx);2380 EXPECT_EQ(NewI1->getNextNode(), Ret);2381 2382 auto *NewI2 =2383 cast<sandboxir::ExtractElementInst>(sandboxir::ExtractElementInst::create(2384 ArgVec, ArgIdx, BB, Ctx, "NewExtrAtEndOfBB"));2385 EXPECT_EQ(NewI2->getPrevNode(), Ret);2386 2387 auto *LLVMArgVec = LLVMF.getArg(0);2388 auto *LLVMArgIdx = LLVMF.getArg(1);2389 EXPECT_EQ(sandboxir::ExtractElementInst::isValidOperands(ArgVec, ArgIdx),2390 llvm::ExtractElementInst::isValidOperands(LLVMArgVec, LLVMArgIdx));2391 EXPECT_EQ(sandboxir::ExtractElementInst::isValidOperands(ArgIdx, ArgVec),2392 llvm::ExtractElementInst::isValidOperands(LLVMArgIdx, LLVMArgVec));2393}2394 2395TEST_F(SandboxIRTest, InsertElementInst) {2396 parseIR(C, R"IR(2397define void @foo(i8 %v0, i8 %v1, <2 x i8> %vec) {2398 %ins0 = insertelement <2 x i8> poison, i8 %v0, i32 02399 %ins1 = insertelement <2 x i8> %ins0, i8 %v1, i32 12400 ret void2401}2402)IR");2403 Function &LLVMF = *M->getFunction("foo");2404 sandboxir::Context Ctx(C);2405 auto &F = *Ctx.createFunction(&LLVMF);2406 auto *Arg0 = F.getArg(0);2407 auto *Arg1 = F.getArg(1);2408 auto *ArgVec = F.getArg(2);2409 auto *BB = &*F.begin();2410 auto It = BB->begin();2411 auto *Ins0 = cast<sandboxir::InsertElementInst>(&*It++);2412 auto *Ins1 = cast<sandboxir::InsertElementInst>(&*It++);2413 auto *Ret = &*It++;2414 2415 EXPECT_EQ(Ins0->getOpcode(), sandboxir::Instruction::Opcode::InsertElement);2416 EXPECT_EQ(Ins0->getOperand(1), Arg0);2417 EXPECT_EQ(Ins1->getOperand(1), Arg1);2418 EXPECT_EQ(Ins1->getOperand(0), Ins0);2419 auto *Poison = Ins0->getOperand(0);2420 auto *Idx = Ins0->getOperand(2);2421 auto *NewI1 =2422 cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create(2423 Poison, Arg0, Idx, Ret->getIterator(), Ctx, "NewIns1"));2424 EXPECT_EQ(NewI1->getOperand(0), Poison);2425 EXPECT_EQ(NewI1->getNextNode(), Ret);2426 2427 auto *NewI2 =2428 cast<sandboxir::InsertElementInst>(sandboxir::InsertElementInst::create(2429 Poison, Arg0, Idx, BB, Ctx, "NewIns2"));2430 EXPECT_EQ(NewI2->getPrevNode(), Ret);2431 2432 auto *LLVMArg0 = LLVMF.getArg(0);2433 auto *LLVMArgVec = LLVMF.getArg(2);2434 auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt8Ty(Ctx), 0);2435 auto *LLVMZero = llvm::ConstantInt::get(Type::getInt8Ty(C), 0);2436 EXPECT_EQ(2437 sandboxir::InsertElementInst::isValidOperands(ArgVec, Arg0, Zero),2438 llvm::InsertElementInst::isValidOperands(LLVMArgVec, LLVMArg0, LLVMZero));2439 EXPECT_EQ(2440 sandboxir::InsertElementInst::isValidOperands(Arg0, ArgVec, Zero),2441 llvm::InsertElementInst::isValidOperands(LLVMArg0, LLVMArgVec, LLVMZero));2442}2443 2444TEST_F(SandboxIRTest, ShuffleVectorInst) {2445 parseIR(C, R"IR(2446define void @foo(<2 x i8> %v1, <2 x i8> %v2) {2447 %shuf = shufflevector <2 x i8> %v1, <2 x i8> %v2, <2 x i32> <i32 0, i32 2>2448 %extr = extractelement <2 x i8> <i8 0, i8 1>, i32 02449 ret void2450}2451)IR");2452 Function &LLVMF = *M->getFunction("foo");2453 sandboxir::Context Ctx(C);2454 auto &F = *Ctx.createFunction(&LLVMF);2455 auto *ArgV1 = F.getArg(0);2456 auto *ArgV2 = F.getArg(1);2457 auto *BB = &*F.begin();2458 auto It = BB->begin();2459 auto *SVI = cast<sandboxir::ShuffleVectorInst>(&*It++);2460 auto *EEI = cast<sandboxir::ExtractElementInst>(&*It++);2461 auto *Ret = &*It++;2462 2463 EXPECT_EQ(SVI->getOpcode(), sandboxir::Instruction::Opcode::ShuffleVector);2464 EXPECT_EQ(SVI->getOperand(0), ArgV1);2465 EXPECT_EQ(SVI->getOperand(1), ArgV2);2466 2467 // In order to test all the methods we need masks of different lengths, so we2468 // can't simply reuse one of the instructions created above. This helper2469 // creates a new `shufflevector %v1, %2, <mask>` with the given mask indices.2470 auto CreateShuffleWithMask = [&](auto &&...Indices) {2471 SmallVector<int, 4> Mask = {Indices...};2472 return cast<sandboxir::ShuffleVectorInst>(2473 sandboxir::ShuffleVectorInst::create(ArgV1, ArgV2, Mask,2474 Ret->getIterator(), Ctx));2475 };2476 2477 // create (InsertBefore)2478 auto *NewI1 =2479 cast<sandboxir::ShuffleVectorInst>(sandboxir::ShuffleVectorInst::create(2480 ArgV1, ArgV2, ArrayRef<int>({0, 2, 1, 3}), Ret->getIterator(), Ctx,2481 "NewShuffleBeforeRet"));2482 EXPECT_EQ(NewI1->getOperand(0), ArgV1);2483 EXPECT_EQ(NewI1->getOperand(1), ArgV2);2484 EXPECT_EQ(NewI1->getNextNode(), Ret);2485#ifndef NDEBUG2486 EXPECT_EQ(NewI1->getName(), "NewShuffleBeforeRet");2487#endif2488 2489 // create (InsertAtEnd)2490 auto *NewI2 =2491 cast<sandboxir::ShuffleVectorInst>(sandboxir::ShuffleVectorInst::create(2492 ArgV1, ArgV2, ArrayRef<int>({0, 1}), BB, Ctx, "NewShuffleAtEndOfBB"));2493 EXPECT_EQ(NewI2->getPrevNode(), Ret);2494 2495 // Test the path that creates a folded constant. We're currently using an2496 // extractelement instruction with a constant operand in the textual IR above2497 // to obtain a constant vector to work with.2498 // TODO: Refactor this once sandboxir::ConstantVector lands.2499 auto *ShouldBeConstant = sandboxir::ShuffleVectorInst::create(2500 EEI->getOperand(0), EEI->getOperand(0), ArrayRef<int>({0, 3}), BB, Ctx);2501 EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant));2502 2503 // isValidOperands2504 auto *LLVMArgV1 = LLVMF.getArg(0);2505 auto *LLVMArgV2 = LLVMF.getArg(1);2506 SmallVector<int, 2> Mask({1, 2});2507 EXPECT_EQ(2508 sandboxir::ShuffleVectorInst::isValidOperands(ArgV1, ArgV2, Mask),2509 llvm::ShuffleVectorInst::isValidOperands(LLVMArgV1, LLVMArgV2, Mask));2510 EXPECT_EQ(sandboxir::ShuffleVectorInst::isValidOperands(ArgV1, ArgV1, ArgV1),2511 llvm::ShuffleVectorInst::isValidOperands(LLVMArgV1, LLVMArgV1,2512 LLVMArgV1));2513 2514 // commute2515 {2516 auto *I = CreateShuffleWithMask(0, 2);2517 I->commute();2518 EXPECT_EQ(I->getOperand(0), ArgV2);2519 EXPECT_EQ(I->getOperand(1), ArgV1);2520 EXPECT_THAT(I->getShuffleMask(), testing::ElementsAre(2, 0));2521 }2522 2523 // getType2524 EXPECT_EQ(SVI->getType(), ArgV1->getType());2525 2526 // getMaskValue2527 EXPECT_EQ(SVI->getMaskValue(0), 0);2528 EXPECT_EQ(SVI->getMaskValue(1), 2);2529 2530 // getShuffleMask / getShuffleMaskForBitcode2531 {2532 EXPECT_THAT(SVI->getShuffleMask(), testing::ElementsAre(0, 2));2533 2534 SmallVector<int, 2> Result;2535 SVI->getShuffleMask(Result);2536 EXPECT_THAT(Result, testing::ElementsAre(0, 2));2537 2538 Result.clear();2539 sandboxir::ShuffleVectorInst::getShuffleMask(2540 SVI->getShuffleMaskForBitcode(), Result);2541 EXPECT_THAT(Result, testing::ElementsAre(0, 2));2542 }2543 2544 // convertShuffleMaskForBitcode2545 {2546 auto *C = sandboxir::ShuffleVectorInst::convertShuffleMaskForBitcode(2547 ArrayRef<int>({2, 3}), ArgV1->getType());2548 SmallVector<int, 2> Result;2549 sandboxir::ShuffleVectorInst::getShuffleMask(C, Result);2550 EXPECT_THAT(Result, testing::ElementsAre(2, 3));2551 }2552 2553 // setShuffleMask2554 {2555 auto *I = CreateShuffleWithMask(0, 1);2556 I->setShuffleMask(ArrayRef<int>({2, 3}));2557 EXPECT_THAT(I->getShuffleMask(), testing::ElementsAre(2, 3));2558 }2559 2560 // The following functions check different mask properties. Note that most2561 // of these come in three different flavors: a method that checks the mask2562 // in the current instructions and two static member functions that check2563 // a mask given as an ArrayRef<int> or Constant*, so there's quite a bit of2564 // repetition in order to check all of them.2565 2566 // changesLength / increasesLength2567 {2568 auto *I = CreateShuffleWithMask(1);2569 EXPECT_TRUE(I->changesLength());2570 EXPECT_FALSE(I->increasesLength());2571 }2572 {2573 auto *I = CreateShuffleWithMask(1, 1);2574 EXPECT_FALSE(I->changesLength());2575 EXPECT_FALSE(I->increasesLength());2576 }2577 {2578 auto *I = CreateShuffleWithMask(1, 1, 1);2579 EXPECT_TRUE(I->changesLength());2580 EXPECT_TRUE(I->increasesLength());2581 }2582 2583 // isSingleSource / isSingleSourceMask2584 {2585 auto *I = CreateShuffleWithMask(0, 1);2586 EXPECT_TRUE(I->isSingleSource());2587 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSingleSourceMask(2588 I->getShuffleMaskForBitcode(), 2));2589 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSingleSourceMask(2590 I->getShuffleMask(), 2));2591 }2592 {2593 auto *I = CreateShuffleWithMask(0, 2);2594 EXPECT_FALSE(I->isSingleSource());2595 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSingleSourceMask(2596 I->getShuffleMaskForBitcode(), 2));2597 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSingleSourceMask(2598 I->getShuffleMask(), 2));2599 }2600 2601 // isIdentity / isIdentityMask2602 {2603 auto *I = CreateShuffleWithMask(0, 1);2604 EXPECT_TRUE(I->isIdentity());2605 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isIdentityMask(2606 I->getShuffleMaskForBitcode(), 2));2607 EXPECT_TRUE(2608 sandboxir::ShuffleVectorInst::isIdentityMask(I->getShuffleMask(), 2));2609 }2610 {2611 auto *I = CreateShuffleWithMask(1, 0);2612 EXPECT_FALSE(I->isIdentity());2613 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isIdentityMask(2614 I->getShuffleMaskForBitcode(), 2));2615 EXPECT_FALSE(2616 sandboxir::ShuffleVectorInst::isIdentityMask(I->getShuffleMask(), 2));2617 }2618 2619 // isIdentityWithPadding2620 EXPECT_TRUE(CreateShuffleWithMask(0, 1, -1, -1)->isIdentityWithPadding());2621 EXPECT_FALSE(CreateShuffleWithMask(0, 1)->isIdentityWithPadding());2622 2623 // isIdentityWithExtract2624 EXPECT_TRUE(CreateShuffleWithMask(0)->isIdentityWithExtract());2625 EXPECT_FALSE(CreateShuffleWithMask(0, 1)->isIdentityWithExtract());2626 EXPECT_FALSE(CreateShuffleWithMask(0, 1, 2)->isIdentityWithExtract());2627 EXPECT_FALSE(CreateShuffleWithMask(1)->isIdentityWithExtract());2628 2629 // isConcat2630 EXPECT_TRUE(CreateShuffleWithMask(0, 1, 2, 3)->isConcat());2631 EXPECT_FALSE(CreateShuffleWithMask(0, 3)->isConcat());2632 2633 // isSelect / isSelectMask2634 {2635 auto *I = CreateShuffleWithMask(0, 3);2636 EXPECT_TRUE(I->isSelect());2637 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSelectMask(2638 I->getShuffleMaskForBitcode(), 2));2639 EXPECT_TRUE(2640 sandboxir::ShuffleVectorInst::isSelectMask(I->getShuffleMask(), 2));2641 }2642 {2643 auto *I = CreateShuffleWithMask(0, 2);2644 EXPECT_FALSE(I->isSelect());2645 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSelectMask(2646 I->getShuffleMaskForBitcode(), 2));2647 EXPECT_FALSE(2648 sandboxir::ShuffleVectorInst::isSelectMask(I->getShuffleMask(), 2));2649 }2650 2651 // isReverse / isReverseMask2652 {2653 auto *I = CreateShuffleWithMask(1, 0);2654 EXPECT_TRUE(I->isReverse());2655 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReverseMask(2656 I->getShuffleMaskForBitcode(), 2));2657 EXPECT_TRUE(2658 sandboxir::ShuffleVectorInst::isReverseMask(I->getShuffleMask(), 2));2659 }2660 {2661 auto *I = CreateShuffleWithMask(1, 2);2662 EXPECT_FALSE(I->isReverse());2663 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReverseMask(2664 I->getShuffleMaskForBitcode(), 2));2665 EXPECT_FALSE(2666 sandboxir::ShuffleVectorInst::isReverseMask(I->getShuffleMask(), 2));2667 }2668 2669 // isZeroEltSplat / isZeroEltSplatMask2670 {2671 auto *I = CreateShuffleWithMask(0, 0);2672 EXPECT_TRUE(I->isZeroEltSplat());2673 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask(2674 I->getShuffleMaskForBitcode(), 2));2675 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask(2676 I->getShuffleMask(), 2));2677 }2678 {2679 auto *I = CreateShuffleWithMask(1, 1);2680 EXPECT_FALSE(I->isZeroEltSplat());2681 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask(2682 I->getShuffleMaskForBitcode(), 2));2683 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isZeroEltSplatMask(2684 I->getShuffleMask(), 2));2685 }2686 2687 // isTranspose / isTransposeMask2688 {2689 auto *I = CreateShuffleWithMask(0, 2);2690 EXPECT_TRUE(I->isTranspose());2691 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isTransposeMask(2692 I->getShuffleMaskForBitcode(), 2));2693 EXPECT_TRUE(2694 sandboxir::ShuffleVectorInst::isTransposeMask(I->getShuffleMask(), 2));2695 }2696 {2697 auto *I = CreateShuffleWithMask(1, 1);2698 EXPECT_FALSE(I->isTranspose());2699 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isTransposeMask(2700 I->getShuffleMaskForBitcode(), 2));2701 EXPECT_FALSE(2702 sandboxir::ShuffleVectorInst::isTransposeMask(I->getShuffleMask(), 2));2703 }2704 2705 // isSplice / isSpliceMask2706 {2707 auto *I = CreateShuffleWithMask(1, 2);2708 int Index;2709 EXPECT_TRUE(I->isSplice(Index));2710 EXPECT_EQ(Index, 1);2711 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSpliceMask(2712 I->getShuffleMaskForBitcode(), 2, Index));2713 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isSpliceMask(I->getShuffleMask(),2714 2, Index));2715 }2716 {2717 auto *I = CreateShuffleWithMask(2, 1);2718 int Index;2719 EXPECT_FALSE(I->isSplice(Index));2720 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSpliceMask(2721 I->getShuffleMaskForBitcode(), 2, Index));2722 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isSpliceMask(I->getShuffleMask(),2723 2, Index));2724 }2725 2726 // isExtractSubvectorMask2727 {2728 auto *I = CreateShuffleWithMask(1);2729 int Index;2730 EXPECT_TRUE(I->isExtractSubvectorMask(Index));2731 EXPECT_EQ(Index, 1);2732 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask(2733 I->getShuffleMaskForBitcode(), 2, Index));2734 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask(2735 I->getShuffleMask(), 2, Index));2736 }2737 {2738 auto *I = CreateShuffleWithMask(1, 2);2739 int Index;2740 EXPECT_FALSE(I->isExtractSubvectorMask(Index));2741 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask(2742 I->getShuffleMaskForBitcode(), 2, Index));2743 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isExtractSubvectorMask(2744 I->getShuffleMask(), 2, Index));2745 }2746 2747 // isInsertSubvectorMask2748 {2749 auto *I = CreateShuffleWithMask(0, 2);2750 int NumSubElts, Index;2751 EXPECT_TRUE(I->isInsertSubvectorMask(NumSubElts, Index));2752 EXPECT_EQ(Index, 1);2753 EXPECT_EQ(NumSubElts, 1);2754 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask(2755 I->getShuffleMaskForBitcode(), 2, NumSubElts, Index));2756 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask(2757 I->getShuffleMask(), 2, NumSubElts, Index));2758 }2759 {2760 auto *I = CreateShuffleWithMask(0, 1);2761 int NumSubElts, Index;2762 EXPECT_FALSE(I->isInsertSubvectorMask(NumSubElts, Index));2763 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask(2764 I->getShuffleMaskForBitcode(), 2, NumSubElts, Index));2765 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInsertSubvectorMask(2766 I->getShuffleMask(), 2, NumSubElts, Index));2767 }2768 2769 // isReplicationMask2770 {2771 auto *I = CreateShuffleWithMask(0, 0, 0, 1, 1, 1);2772 int ReplicationFactor, VF;2773 EXPECT_TRUE(I->isReplicationMask(ReplicationFactor, VF));2774 EXPECT_EQ(ReplicationFactor, 3);2775 EXPECT_EQ(VF, 2);2776 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReplicationMask(2777 I->getShuffleMaskForBitcode(), ReplicationFactor, VF));2778 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isReplicationMask(2779 I->getShuffleMask(), ReplicationFactor, VF));2780 }2781 {2782 auto *I = CreateShuffleWithMask(1, 2);2783 int ReplicationFactor, VF;2784 EXPECT_FALSE(I->isReplicationMask(ReplicationFactor, VF));2785 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReplicationMask(2786 I->getShuffleMaskForBitcode(), ReplicationFactor, VF));2787 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isReplicationMask(2788 I->getShuffleMask(), ReplicationFactor, VF));2789 }2790 2791 // isOneUseSingleSourceMask2792 {2793 auto *I = CreateShuffleWithMask(0, 1, 1, 0);2794 EXPECT_TRUE(I->isOneUseSingleSourceMask(2));2795 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isOneUseSingleSourceMask(2796 I->getShuffleMask(), 2));2797 }2798 {2799 auto *I = CreateShuffleWithMask(0, 1, 0, 0);2800 EXPECT_FALSE(I->isOneUseSingleSourceMask(2));2801 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isOneUseSingleSourceMask(2802 I->getShuffleMask(), 2));2803 }2804 2805 // commuteShuffleMask2806 {2807 SmallVector<int, 4> M = {0, 2, 1, 3};2808 ShuffleVectorInst::commuteShuffleMask(M, 2);2809 EXPECT_THAT(M, testing::ElementsAre(2, 0, 3, 1));2810 }2811 2812 // isInterleave / isInterleaveMask2813 {2814 auto *I = CreateShuffleWithMask(0, 2, 1, 3);2815 EXPECT_TRUE(I->isInterleave(2));2816 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInterleaveMask(2817 I->getShuffleMask(), 2, 4));2818 SmallVector<unsigned, 4> StartIndexes;2819 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isInterleaveMask(2820 I->getShuffleMask(), 2, 4, StartIndexes));2821 EXPECT_THAT(StartIndexes, testing::ElementsAre(0, 2));2822 }2823 {2824 auto *I = CreateShuffleWithMask(0, 3, 1, 2);2825 EXPECT_FALSE(I->isInterleave(2));2826 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isInterleaveMask(2827 I->getShuffleMask(), 2, 4));2828 }2829 2830 // isDeInterleaveMaskOfFactor2831 {2832 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor(2833 ArrayRef<int>({0, 2}), 2));2834 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor(2835 ArrayRef<int>({0, 1}), 2));2836 2837 unsigned Index;2838 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isDeInterleaveMaskOfFactor(2839 ArrayRef<int>({1, 3}), 2, Index));2840 EXPECT_EQ(Index, 1u);2841 }2842 2843 // isBitRotateMask2844 {2845 unsigned NumSubElts, RotateAmt;2846 EXPECT_TRUE(sandboxir::ShuffleVectorInst::isBitRotateMask(2847 ArrayRef<int>({1, 0, 3, 2, 5, 4, 7, 6}), 8, 2, 2, NumSubElts,2848 RotateAmt));2849 EXPECT_EQ(NumSubElts, 2u);2850 EXPECT_EQ(RotateAmt, 8u);2851 2852 EXPECT_FALSE(sandboxir::ShuffleVectorInst::isBitRotateMask(2853 ArrayRef<int>({0, 7, 1, 6, 2, 5, 3, 4}), 8, 2, 2, NumSubElts,2854 RotateAmt));2855 }2856}2857 2858TEST_F(SandboxIRTest, ExtractValueInst) {2859 parseIR(C, R"IR(2860define void @foo({i32, float} %agg) {2861 %ext_simple = extractvalue {i32, float} %agg, 02862 %ext_nested = extractvalue {float, {i32}} undef, 1, 02863 %const1 = extractvalue {i32, float} {i32 0, float 99.0}, 02864 ret void2865}2866)IR");2867 Function &LLVMF = *M->getFunction("foo");2868 auto *LLVMBB = &*LLVMF.begin();2869 auto LLVMIt = LLVMBB->begin();2870 [[maybe_unused]] auto *LLVMExtSimple =2871 cast<llvm::ExtractValueInst>(&*LLVMIt++);2872 auto *LLVMExtNested = cast<llvm::ExtractValueInst>(&*LLVMIt++);2873 2874 sandboxir::Context Ctx(C);2875 auto &F = *Ctx.createFunction(&LLVMF);2876 auto *ArgAgg = F.getArg(0);2877 auto *BB = &*F.begin();2878 auto It = BB->begin();2879 auto *ExtSimple = cast<sandboxir::ExtractValueInst>(&*It++);2880 auto *ExtNested = cast<sandboxir::ExtractValueInst>(&*It++);2881 auto *Const1 = cast<sandboxir::ExtractValueInst>(&*It++);2882 auto *Ret = &*It++;2883 2884 EXPECT_EQ(ExtSimple->getOperand(0), ArgAgg);2885 2886 // create before instruction2887 auto *NewExtBeforeRet =2888 cast<sandboxir::ExtractValueInst>(sandboxir::ExtractValueInst::create(2889 ArgAgg, ArrayRef<unsigned>({0}), Ret->getIterator(), Ctx,2890 "NewExtBeforeRet"));2891 EXPECT_EQ(NewExtBeforeRet->getNextNode(), Ret);2892#ifndef NDEBUG2893 EXPECT_EQ(NewExtBeforeRet->getName(), "NewExtBeforeRet");2894#endif // NDEBUG2895 2896 // create at end of BB2897 auto *NewExtAtEnd =2898 cast<sandboxir::ExtractValueInst>(sandboxir::ExtractValueInst::create(2899 ArgAgg, ArrayRef<unsigned>({0}), BB->end(), Ctx, "NewExtAtEnd"));2900 EXPECT_EQ(NewExtAtEnd->getPrevNode(), Ret);2901#ifndef NDEBUG2902 EXPECT_EQ(NewExtAtEnd->getName(), "NewExtAtEnd");2903#endif // NDEBUG2904 2905 // Test the path that creates a folded constant.2906 auto *ShouldBeConstant = sandboxir::ExtractValueInst::create(2907 Const1->getOperand(0), ArrayRef<unsigned>({0}), BB->end(), Ctx);2908 EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant));2909 2910 auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);2911 EXPECT_EQ(ShouldBeConstant, Zero);2912 2913 // getIndexedType2914 sandboxir::Type *AggType = ExtNested->getAggregateOperand()->getType();2915 llvm::Type *LLVMAggType = LLVMExtNested->getAggregateOperand()->getType();2916 EXPECT_EQ(sandboxir::ExtractValueInst::getIndexedType(2917 AggType, ArrayRef<unsigned>({1, 0})),2918 Ctx.getType(llvm::ExtractValueInst::getIndexedType(2919 LLVMAggType, ArrayRef<unsigned>({1, 0}))));2920 2921 EXPECT_EQ(sandboxir::ExtractValueInst::getIndexedType(2922 AggType, ArrayRef<unsigned>({2})),2923 nullptr);2924 2925 // idx_begin / idx_end2926 {2927 SmallVector<int, 2> IndicesSimple(ExtSimple->idx_begin(),2928 ExtSimple->idx_end());2929 EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u));2930 2931 SmallVector<int, 2> IndicesNested(ExtNested->idx_begin(),2932 ExtNested->idx_end());2933 EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u));2934 }2935 2936 // indices2937 {2938 SmallVector<int, 2> IndicesSimple(ExtSimple->indices());2939 EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u));2940 2941 SmallVector<int, 2> IndicesNested(ExtNested->indices());2942 EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u));2943 }2944 2945 // getAggregateOperand2946 EXPECT_EQ(ExtSimple->getAggregateOperand(), ArgAgg);2947 const auto *ConstExtSimple = ExtSimple;2948 EXPECT_EQ(ConstExtSimple->getAggregateOperand(), ArgAgg);2949 2950 // getAggregateOperandIndex2951 EXPECT_EQ(sandboxir::ExtractValueInst::getAggregateOperandIndex(),2952 llvm::ExtractValueInst::getAggregateOperandIndex());2953 2954 // getIndices2955 EXPECT_EQ(ExtSimple->getIndices().size(), 1u);2956 EXPECT_EQ(ExtSimple->getIndices()[0], 0u);2957 2958 // getNumIndices2959 EXPECT_EQ(ExtSimple->getNumIndices(), 1u);2960 2961 // hasIndices2962 EXPECT_EQ(ExtSimple->hasIndices(), true);2963}2964 2965TEST_F(SandboxIRTest, InsertValueInst) {2966 parseIR(C, R"IR(2967define void @foo({i32, float} %agg, i32 %i) {2968 %ins_simple = insertvalue {i32, float} %agg, i32 %i, 02969 %ins_nested = insertvalue {float, {i32}} undef, i32 %i, 1, 02970 %const1 = insertvalue {i32, float} {i32 99, float 99.0}, i32 %i, 02971 %const2 = insertvalue {i32, float} {i32 0, float 99.0}, i32 %i, 02972 ret void2973}2974)IR");2975 Function &LLVMF = *M->getFunction("foo");2976 sandboxir::Context Ctx(C);2977 auto &F = *Ctx.createFunction(&LLVMF);2978 auto *ArgAgg = F.getArg(0);2979 auto *ArgInt = F.getArg(1);2980 auto *BB = &*F.begin();2981 auto It = BB->begin();2982 auto *InsSimple = cast<sandboxir::InsertValueInst>(&*It++);2983 auto *InsNested = cast<sandboxir::InsertValueInst>(&*It++);2984 // These "const" instructions are helpers to create constant struct operands.2985 // TODO: Remove them once sandboxir::ConstantStruct gets added.2986 auto *Const1 = cast<sandboxir::InsertValueInst>(&*It++);2987 auto *Const2 = cast<sandboxir::InsertValueInst>(&*It++);2988 auto *Ret = &*It++;2989 2990 EXPECT_EQ(InsSimple->getOperand(0), ArgAgg);2991 EXPECT_EQ(InsSimple->getOperand(1), ArgInt);2992 2993 // create before instruction2994 auto *NewInsBeforeRet =2995 cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create(2996 ArgAgg, ArgInt, ArrayRef<unsigned>({0}), Ret->getIterator(), Ctx,2997 "NewInsBeforeRet"));2998 EXPECT_EQ(NewInsBeforeRet->getNextNode(), Ret);2999#ifndef NDEBUG3000 EXPECT_EQ(NewInsBeforeRet->getName(), "NewInsBeforeRet");3001#endif // NDEBUG3002 3003 // create at end of BB3004 auto *NewInsAtEnd =3005 cast<sandboxir::InsertValueInst>(sandboxir::InsertValueInst::create(3006 ArgAgg, ArgInt, ArrayRef<unsigned>({0}), BB, Ctx, "NewInsAtEnd"));3007 EXPECT_EQ(NewInsAtEnd->getPrevNode(), Ret);3008#ifndef NDEBUG3009 EXPECT_EQ(NewInsAtEnd->getName(), "NewInsAtEnd");3010#endif // NDEBUG3011 3012 // Test the path that creates a folded constant.3013 auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);3014 auto *ShouldBeConstant = sandboxir::InsertValueInst::create(3015 Const1->getOperand(0), Zero, ArrayRef<unsigned>({0}), BB, Ctx);3016 auto *ExpectedConstant = Const2->getOperand(0);3017 EXPECT_TRUE(isa<sandboxir::Constant>(ShouldBeConstant));3018 EXPECT_EQ(ShouldBeConstant, ExpectedConstant);3019 3020 // idx_begin / idx_end3021 {3022 SmallVector<int, 2> IndicesSimple(InsSimple->idx_begin(),3023 InsSimple->idx_end());3024 EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u));3025 3026 SmallVector<int, 2> IndicesNested(InsNested->idx_begin(),3027 InsNested->idx_end());3028 EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u));3029 }3030 3031 // indices3032 {3033 SmallVector<int, 2> IndicesSimple(InsSimple->indices());3034 EXPECT_THAT(IndicesSimple, testing::ElementsAre(0u));3035 3036 SmallVector<int, 2> IndicesNested(InsNested->indices());3037 EXPECT_THAT(IndicesNested, testing::ElementsAre(1u, 0u));3038 }3039 3040 // getAggregateOperand3041 EXPECT_EQ(InsSimple->getAggregateOperand(), ArgAgg);3042 const auto *ConstInsSimple = InsSimple;3043 EXPECT_EQ(ConstInsSimple->getAggregateOperand(), ArgAgg);3044 3045 // getAggregateOperandIndex3046 EXPECT_EQ(sandboxir::InsertValueInst::getAggregateOperandIndex(),3047 llvm::InsertValueInst::getAggregateOperandIndex());3048 3049 // getInsertedValueOperand3050 EXPECT_EQ(InsSimple->getInsertedValueOperand(), ArgInt);3051 EXPECT_EQ(ConstInsSimple->getInsertedValueOperand(), ArgInt);3052 3053 // getInsertedValueOperandIndex3054 EXPECT_EQ(sandboxir::InsertValueInst::getInsertedValueOperandIndex(),3055 llvm::InsertValueInst::getInsertedValueOperandIndex());3056 3057 // getIndices3058 EXPECT_EQ(InsSimple->getIndices().size(), 1u);3059 EXPECT_EQ(InsSimple->getIndices()[0], 0u);3060 3061 // getNumIndices3062 EXPECT_EQ(InsSimple->getNumIndices(), 1u);3063 3064 // hasIndices3065 EXPECT_EQ(InsSimple->hasIndices(), true);3066}3067 3068TEST_F(SandboxIRTest, BranchInst) {3069 parseIR(C, R"IR(3070define void @foo(i1 %cond0, i1 %cond2) {3071 bb0:3072 br i1 %cond0, label %bb1, label %bb23073 bb1:3074 ret void3075 bb2:3076 ret void3077}3078)IR");3079 llvm::Function *LLVMF = &*M->getFunction("foo");3080 sandboxir::Context Ctx(C);3081 sandboxir::Function *F = Ctx.createFunction(LLVMF);3082 auto *Cond0 = F->getArg(0);3083 auto *Cond1 = F->getArg(1);3084 auto *BB0 = cast<sandboxir::BasicBlock>(3085 Ctx.getValue(getBasicBlockByName(*LLVMF, "bb0")));3086 auto *BB1 = cast<sandboxir::BasicBlock>(3087 Ctx.getValue(getBasicBlockByName(*LLVMF, "bb1")));3088 auto *Ret1 = BB1->getTerminator();3089 auto *BB2 = cast<sandboxir::BasicBlock>(3090 Ctx.getValue(getBasicBlockByName(*LLVMF, "bb2")));3091 auto *Ret2 = BB2->getTerminator();3092 auto It = BB0->begin();3093 auto *Br0 = cast<sandboxir::BranchInst>(&*It++);3094 // Check isUnconditional().3095 EXPECT_FALSE(Br0->isUnconditional());3096 // Check isConditional().3097 EXPECT_TRUE(Br0->isConditional());3098 // Check getCondition().3099 EXPECT_EQ(Br0->getCondition(), Cond0);3100 // Check setCondition().3101 Br0->setCondition(Cond1);3102 EXPECT_EQ(Br0->getCondition(), Cond1);3103 // Check getNumSuccessors().3104 EXPECT_EQ(Br0->getNumSuccessors(), 2u);3105 // Check getSuccessor().3106 EXPECT_EQ(Br0->getSuccessor(0), BB1);3107 EXPECT_EQ(Br0->getSuccessor(1), BB2);3108 // Check swapSuccessors().3109 Br0->swapSuccessors();3110 EXPECT_EQ(Br0->getSuccessor(0), BB2);3111 EXPECT_EQ(Br0->getSuccessor(1), BB1);3112 // Check successors().3113 EXPECT_EQ(range_size(Br0->successors()), 2u);3114 unsigned SuccIdx = 0;3115 SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1, BB2});3116 for (sandboxir::BasicBlock *Succ : Br0->successors())3117 EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);3118 3119 {3120 // Check unconditional BranchInst::create() InsertBefore.3121 auto *Br = sandboxir::BranchInst::create(BB1, Ret1->getIterator(), Ctx);3122 EXPECT_FALSE(Br->isConditional());3123 EXPECT_TRUE(Br->isUnconditional());3124#ifndef NDEBUG3125 EXPECT_DEATH(Br->getCondition(), ".*condition.*");3126#endif // NDEBUG3127 unsigned SuccIdx = 0;3128 SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1});3129 for (sandboxir::BasicBlock *Succ : Br->successors())3130 EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);3131 EXPECT_EQ(Br->getNextNode(), Ret1);3132 }3133 {3134 // Check unconditional BranchInst::create() InsertAtEnd.3135 auto *Br = sandboxir::BranchInst::create(BB1, /*InsertAtEnd=*/BB1, Ctx);3136 EXPECT_FALSE(Br->isConditional());3137 EXPECT_TRUE(Br->isUnconditional());3138#ifndef NDEBUG3139 EXPECT_DEATH(Br->getCondition(), ".*condition.*");3140#endif // NDEBUG3141 unsigned SuccIdx = 0;3142 SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB1});3143 for (sandboxir::BasicBlock *Succ : Br->successors())3144 EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);3145 EXPECT_EQ(Br->getPrevNode(), Ret1);3146 }3147 {3148 // Check conditional BranchInst::create() InsertBefore.3149 auto *Br = sandboxir::BranchInst::create(BB1, BB2, Cond0,3150 Ret1->getIterator(), Ctx);3151 EXPECT_TRUE(Br->isConditional());3152 EXPECT_EQ(Br->getCondition(), Cond0);3153 unsigned SuccIdx = 0;3154 SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1});3155 for (sandboxir::BasicBlock *Succ : Br->successors())3156 EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);3157 EXPECT_EQ(Br->getNextNode(), Ret1);3158 }3159 {3160 // Check conditional BranchInst::create() InsertAtEnd.3161 auto *Br = sandboxir::BranchInst::create(BB1, BB2, Cond0,3162 /*InsertAtEnd=*/BB2, Ctx);3163 EXPECT_TRUE(Br->isConditional());3164 EXPECT_EQ(Br->getCondition(), Cond0);3165 unsigned SuccIdx = 0;3166 SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1});3167 for (sandboxir::BasicBlock *Succ : Br->successors())3168 EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);3169 EXPECT_EQ(Br->getPrevNode(), Ret2);3170 }3171}3172 3173TEST_F(SandboxIRTest, LoadInst) {3174 parseIR(C, R"IR(3175define void @foo(ptr %arg0, ptr %arg1) {3176 %ld = load i8, ptr %arg0, align 643177 %vld = load volatile i8, ptr %arg0, align 643178 ret void3179}3180)IR");3181 llvm::Function *LLVMF = &*M->getFunction("foo");3182 sandboxir::Context Ctx(C);3183 sandboxir::Function *F = Ctx.createFunction(LLVMF);3184 auto *Arg0 = F->getArg(0);3185 auto *Arg1 = F->getArg(1);3186 auto *BB = &*F->begin();3187 auto It = BB->begin();3188 auto *Ld = cast<sandboxir::LoadInst>(&*It++);3189 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Ld));3190 auto *VLd = cast<sandboxir::LoadInst>(&*It++);3191 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);3192 bool OrigVolatileValue;3193 3194 // Check isVolatile()3195 EXPECT_FALSE(Ld->isVolatile());3196 // Check isVolatile()3197 EXPECT_TRUE(VLd->isVolatile());3198 // Check getPointerOperand()3199 EXPECT_EQ(Ld->getPointerOperand(), Arg0);3200 // Check getAlign()3201 EXPECT_EQ(Ld->getAlign(), 64);3202 // Check create(InsertBefore)3203 sandboxir::LoadInst *NewLd = sandboxir::LoadInst::create(3204 Ld->getType(), Arg1, Align(8), Ret->getIterator(), Ctx, "NewLd");3205 EXPECT_FALSE(NewLd->isVolatile());3206 OrigVolatileValue = NewLd->isVolatile();3207 NewLd->setVolatile(true);3208 EXPECT_TRUE(NewLd->isVolatile());3209 NewLd->setVolatile(OrigVolatileValue);3210 EXPECT_FALSE(NewLd->isVolatile());3211 EXPECT_EQ(NewLd->getType(), Ld->getType());3212 EXPECT_EQ(NewLd->getPointerOperand(), Arg1);3213 EXPECT_EQ(NewLd->getAlign(), 8);3214 EXPECT_EQ(NewLd->getName(), "NewLd");3215 // Check create(InsertBefore, IsVolatile=true)3216 sandboxir::LoadInst *NewVLd = sandboxir::LoadInst::create(3217 VLd->getType(), Arg1, Align(8), Ret->getIterator(),3218 /*IsVolatile=*/true, Ctx, "NewVLd");3219 3220 EXPECT_TRUE(NewVLd->isVolatile());3221 OrigVolatileValue = NewVLd->isVolatile();3222 NewVLd->setVolatile(false);3223 EXPECT_FALSE(NewVLd->isVolatile());3224 NewVLd->setVolatile(OrigVolatileValue);3225 EXPECT_TRUE(NewVLd->isVolatile());3226 EXPECT_EQ(NewVLd->getName(), "NewVLd");3227 // Check create(InsertAtEnd)3228 sandboxir::LoadInst *NewLdEnd =3229 sandboxir::LoadInst::create(Ld->getType(), Arg1, Align(8),3230 /*InsertAtEnd=*/BB, Ctx, "NewLdEnd");3231 EXPECT_FALSE(NewLdEnd->isVolatile());3232 EXPECT_EQ(NewLdEnd->getName(), "NewLdEnd");3233 EXPECT_EQ(NewLdEnd->getType(), Ld->getType());3234 EXPECT_EQ(NewLdEnd->getPointerOperand(), Arg1);3235 EXPECT_EQ(NewLdEnd->getAlign(), 8);3236 EXPECT_EQ(NewLdEnd->getParent(), BB);3237 EXPECT_EQ(NewLdEnd->getNextNode(), nullptr);3238 // Check create(InsertAtEnd, IsVolatile=true)3239 sandboxir::LoadInst *NewVLdEnd =3240 sandboxir::LoadInst::create(VLd->getType(), Arg1, Align(8),3241 /*InsertAtEnd=*/BB,3242 /*IsVolatile=*/true, Ctx, "NewVLdEnd");3243 EXPECT_TRUE(NewVLdEnd->isVolatile());3244 EXPECT_EQ(NewVLdEnd->getName(), "NewVLdEnd");3245 EXPECT_EQ(NewVLdEnd->getType(), VLd->getType());3246 EXPECT_EQ(NewVLdEnd->getPointerOperand(), Arg1);3247 EXPECT_EQ(NewVLdEnd->getAlign(), 8);3248 EXPECT_EQ(NewVLdEnd->getParent(), BB);3249 EXPECT_EQ(NewVLdEnd->getNextNode(), nullptr);3250}3251 3252TEST_F(SandboxIRTest, StoreInst) {3253 parseIR(C, R"IR(3254define void @foo(i8 %val, ptr %ptr) {3255 store i8 %val, ptr %ptr, align 643256 store volatile i8 %val, ptr %ptr, align 643257 ret void3258}3259)IR");3260 llvm::Function *LLVMF = &*M->getFunction("foo");3261 sandboxir::Context Ctx(C);3262 sandboxir::Function *F = Ctx.createFunction(LLVMF);3263 auto *Val = F->getArg(0);3264 auto *Ptr = F->getArg(1);3265 auto *BB = &*F->begin();3266 auto It = BB->begin();3267 auto *St = cast<sandboxir::StoreInst>(&*It++);3268 auto *VSt = cast<sandboxir::StoreInst>(&*It++);3269 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);3270 bool OrigVolatileValue;3271 3272 // Check that the StoreInst has been created correctly.3273 EXPECT_FALSE(St->isVolatile());3274 EXPECT_TRUE(VSt->isVolatile());3275 // Check getPointerOperand()3276 EXPECT_EQ(St->getValueOperand(), Val);3277 EXPECT_EQ(St->getPointerOperand(), Ptr);3278 // Check getAlign()3279 EXPECT_EQ(St->getAlign(), 64);3280 // Check create(InsertBefore)3281 sandboxir::StoreInst *NewSt =3282 sandboxir::StoreInst::create(Val, Ptr, Align(8), Ret->getIterator(), Ctx);3283 EXPECT_FALSE(NewSt->isVolatile());3284 OrigVolatileValue = NewSt->isVolatile();3285 NewSt->setVolatile(true);3286 EXPECT_TRUE(NewSt->isVolatile());3287 NewSt->setVolatile(OrigVolatileValue);3288 EXPECT_FALSE(NewSt->isVolatile());3289 EXPECT_EQ(NewSt->getType(), St->getType());3290 EXPECT_EQ(NewSt->getValueOperand(), Val);3291 EXPECT_EQ(NewSt->getPointerOperand(), Ptr);3292 EXPECT_EQ(NewSt->getAlign(), 8);3293 EXPECT_EQ(NewSt->getNextNode(), Ret);3294 // Check create(InsertBefore, IsVolatile=true)3295 sandboxir::StoreInst *NewVSt =3296 sandboxir::StoreInst::create(Val, Ptr, Align(8), Ret->getIterator(),3297 /*IsVolatile=*/true, Ctx);3298 EXPECT_TRUE(NewVSt->isVolatile());3299 OrigVolatileValue = NewVSt->isVolatile();3300 NewVSt->setVolatile(false);3301 EXPECT_FALSE(NewVSt->isVolatile());3302 NewVSt->setVolatile(OrigVolatileValue);3303 EXPECT_TRUE(NewVSt->isVolatile());3304 EXPECT_EQ(NewVSt->getType(), VSt->getType());3305 EXPECT_EQ(NewVSt->getValueOperand(), Val);3306 EXPECT_EQ(NewVSt->getPointerOperand(), Ptr);3307 EXPECT_EQ(NewVSt->getAlign(), 8);3308 EXPECT_EQ(NewVSt->getNextNode(), Ret);3309 // Check create(InsertAtEnd)3310 sandboxir::StoreInst *NewStEnd =3311 sandboxir::StoreInst::create(Val, Ptr, Align(8),3312 /*InsertAtEnd=*/BB, Ctx);3313 EXPECT_FALSE(NewStEnd->isVolatile());3314 EXPECT_EQ(NewStEnd->getType(), St->getType());3315 EXPECT_EQ(NewStEnd->getValueOperand(), Val);3316 EXPECT_EQ(NewStEnd->getPointerOperand(), Ptr);3317 EXPECT_EQ(NewStEnd->getAlign(), 8);3318 EXPECT_EQ(NewStEnd->getParent(), BB);3319 EXPECT_EQ(NewStEnd->getNextNode(), nullptr);3320 // Check create(InsertAtEnd, IsVolatile=true)3321 sandboxir::StoreInst *NewVStEnd =3322 sandboxir::StoreInst::create(Val, Ptr, Align(8),3323 /*InsertAtEnd=*/BB,3324 /*IsVolatile=*/true, Ctx);3325 EXPECT_TRUE(NewVStEnd->isVolatile());3326 EXPECT_EQ(NewVStEnd->getType(), VSt->getType());3327 EXPECT_EQ(NewVStEnd->getValueOperand(), Val);3328 EXPECT_EQ(NewVStEnd->getPointerOperand(), Ptr);3329 EXPECT_EQ(NewVStEnd->getAlign(), 8);3330 EXPECT_EQ(NewVStEnd->getParent(), BB);3331 EXPECT_EQ(NewVStEnd->getNextNode(), nullptr);3332}3333 3334TEST_F(SandboxIRTest, ReturnInst) {3335 parseIR(C, R"IR(3336define i8 @foo(i8 %val) {3337 %add = add i8 %val, 423338 ret i8 %val3339}3340)IR");3341 llvm::Function *LLVMF = &*M->getFunction("foo");3342 sandboxir::Context Ctx(C);3343 sandboxir::Function *F = Ctx.createFunction(LLVMF);3344 auto *Val = F->getArg(0);3345 auto *BB = &*F->begin();3346 auto It = BB->begin();3347 It++;3348 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);3349 3350 // Check that the ReturnInst has been created correctly.3351 // Check getReturnValue().3352 EXPECT_EQ(Ret->getReturnValue(), Val);3353 3354 // Check create(InsertBefore) a void ReturnInst.3355 auto *NewRet1 = cast<sandboxir::ReturnInst>(3356 sandboxir::ReturnInst::create(nullptr, Ret->getIterator(), Ctx));3357 EXPECT_EQ(NewRet1->getReturnValue(), nullptr);3358 // Check create(InsertBefore) a non-void ReturnInst.3359 auto *NewRet2 = cast<sandboxir::ReturnInst>(3360 sandboxir::ReturnInst::create(Val, Ret->getIterator(), Ctx));3361 EXPECT_EQ(NewRet2->getReturnValue(), Val);3362 3363 // Check create(InsertAtEnd) a void ReturnInst.3364 auto *NewRet3 = cast<sandboxir::ReturnInst>(3365 sandboxir::ReturnInst::create(nullptr, /*InsertAtEnd=*/BB, Ctx));3366 EXPECT_EQ(NewRet3->getReturnValue(), nullptr);3367 // Check create(InsertAtEnd) a non-void ReturnInst.3368 auto *NewRet4 = cast<sandboxir::ReturnInst>(3369 sandboxir::ReturnInst::create(Val, /*InsertAtEnd=*/BB, Ctx));3370 EXPECT_EQ(NewRet4->getReturnValue(), Val);3371}3372 3373TEST_F(SandboxIRTest, CallBase) {3374 parseIR(C, R"IR(3375declare void @bar1(i8)3376declare void @bar2()3377declare void @bar3()3378declare void @variadic(ptr, ...)3379 3380define i8 @foo(i8 %arg0, i32 %arg1, ptr %indirectFoo) {3381 %call = call i8 @foo(i8 %arg0, i32 %arg1)3382 call void @bar1(i8 %arg0)3383 call void @bar2()3384 call void %indirectFoo()3385 call void @bar2() noreturn3386 tail call fastcc void @bar2()3387 call void (ptr, ...) @variadic(ptr %indirectFoo, i32 1)3388 ret i8 %call3389}3390)IR");3391 llvm::Function &LLVMF = *M->getFunction("foo");3392 unsigned ArgIdx = 0;3393 llvm::Argument *LLVMArg0 = LLVMF.getArg(ArgIdx++);3394 llvm::Argument *LLVMArg1 = LLVMF.getArg(ArgIdx++);3395 llvm::BasicBlock *LLVMBB = &*LLVMF.begin();3396 SmallVector<llvm::CallBase *, 8> LLVMCalls;3397 auto LLVMIt = LLVMBB->begin();3398 while (isa<llvm::CallBase>(&*LLVMIt))3399 LLVMCalls.push_back(cast<llvm::CallBase>(&*LLVMIt++));3400 3401 sandboxir::Context Ctx(C);3402 sandboxir::Function &F = *Ctx.createFunction(&LLVMF);3403 3404 for (llvm::CallBase *LLVMCall : LLVMCalls) {3405 // Check classof(Instruction *).3406 auto *Call = cast<sandboxir::CallBase>(Ctx.getValue(LLVMCall));3407 // Check classof(Value *).3408 EXPECT_TRUE(isa<sandboxir::CallBase>((sandboxir::Value *)Call));3409 // Check getFunctionType().3410 EXPECT_EQ(Call->getFunctionType(),3411 Ctx.getType(LLVMCall->getFunctionType()));3412 // Check data_ops().3413 EXPECT_EQ(range_size(Call->data_ops()), range_size(LLVMCall->data_ops()));3414 auto DataOpIt = Call->data_operands_begin();3415 for (llvm::Use &LLVMUse : LLVMCall->data_ops()) {3416 Value *LLVMOp = LLVMUse.get();3417 sandboxir::Use Use = *DataOpIt++;3418 EXPECT_EQ(Ctx.getValue(LLVMOp), Use.get());3419 // Check isDataOperand().3420 EXPECT_EQ(Call->isDataOperand(Use), LLVMCall->isDataOperand(&LLVMUse));3421 // Check getDataOperandNo().3422 EXPECT_EQ(Call->getDataOperandNo(Use),3423 LLVMCall->getDataOperandNo(&LLVMUse));3424 // Check isArgOperand().3425 EXPECT_EQ(Call->isArgOperand(Use), LLVMCall->isArgOperand(&LLVMUse));3426 // Check isCallee().3427 EXPECT_EQ(Call->isCallee(Use), LLVMCall->isCallee(&LLVMUse));3428 }3429 // Check data_operands_empty().3430 EXPECT_EQ(Call->data_operands_empty(), LLVMCall->data_operands_empty());3431 // Check data_operands_size().3432 EXPECT_EQ(Call->data_operands_size(), LLVMCall->data_operands_size());3433 // Check getNumTotalBundleOperands().3434 EXPECT_EQ(Call->getNumTotalBundleOperands(),3435 LLVMCall->getNumTotalBundleOperands());3436 // Check args().3437 EXPECT_EQ(range_size(Call->args()), range_size(LLVMCall->args()));3438 auto ArgIt = Call->arg_begin();3439 for (llvm::Use &LLVMUse : LLVMCall->args()) {3440 Value *LLVMArg = LLVMUse.get();3441 sandboxir::Use Use = *ArgIt++;3442 EXPECT_EQ(Ctx.getValue(LLVMArg), Use.get());3443 }3444 // Check arg_empty().3445 EXPECT_EQ(Call->arg_empty(), LLVMCall->arg_empty());3446 // Check arg_size().3447 EXPECT_EQ(Call->arg_size(), LLVMCall->arg_size());3448 for (unsigned ArgIdx = 0, E = Call->arg_size(); ArgIdx != E; ++ArgIdx) {3449 // Check getArgOperand().3450 EXPECT_EQ(Call->getArgOperand(ArgIdx),3451 Ctx.getValue(LLVMCall->getArgOperand(ArgIdx)));3452 // Check getArgOperandUse().3453 sandboxir::Use Use = Call->getArgOperandUse(ArgIdx);3454 llvm::Use &LLVMUse = LLVMCall->getArgOperandUse(ArgIdx);3455 EXPECT_EQ(Use.get(), Ctx.getValue(LLVMUse.get()));3456 // Check getArgOperandNo().3457 EXPECT_EQ(Call->getArgOperandNo(Use),3458 LLVMCall->getArgOperandNo(&LLVMUse));3459 }3460 // Check hasArgument().3461 SmallVector<llvm::Value *> TestArgs(3462 {LLVMArg0, LLVMArg1, &LLVMF, LLVMBB, LLVMCall});3463 for (llvm::Value *LLVMV : TestArgs) {3464 sandboxir::Value *V = Ctx.getValue(LLVMV);3465 EXPECT_EQ(Call->hasArgument(V), LLVMCall->hasArgument(LLVMV));3466 }3467 // Check getCalledOperand().3468 EXPECT_EQ(Call->getCalledOperand(),3469 Ctx.getValue(LLVMCall->getCalledOperand()));3470 // Check getCalledOperandUse().3471 EXPECT_EQ(Call->getCalledOperandUse().get(),3472 Ctx.getValue(LLVMCall->getCalledOperandUse()));3473 // Check getCalledFunction().3474 if (LLVMCall->getCalledFunction() == nullptr)3475 EXPECT_EQ(Call->getCalledFunction(), nullptr);3476 else {3477 auto *LLVMCF = cast<llvm::Function>(LLVMCall->getCalledFunction());3478 (void)LLVMCF;3479 EXPECT_EQ(Call->getCalledFunction(),3480 cast<sandboxir::Function>(3481 Ctx.getValue(LLVMCall->getCalledFunction())));3482 }3483 // Check isIndirectCall().3484 EXPECT_EQ(Call->isIndirectCall(), LLVMCall->isIndirectCall());3485 // Check getCaller().3486 EXPECT_EQ(Call->getCaller(), Ctx.getValue(LLVMCall->getCaller()));3487 // Check isMustTailCall().3488 EXPECT_EQ(Call->isMustTailCall(), LLVMCall->isMustTailCall());3489 // Check isTailCall().3490 EXPECT_EQ(Call->isTailCall(), LLVMCall->isTailCall());3491 // Check getIntrinsicID().3492 EXPECT_EQ(Call->getIntrinsicID(), LLVMCall->getIntrinsicID());3493 // Check getCallingConv().3494 EXPECT_EQ(Call->getCallingConv(), LLVMCall->getCallingConv());3495 // Check isInlineAsm().3496 EXPECT_EQ(Call->isInlineAsm(), LLVMCall->isInlineAsm());3497 }3498 3499 auto *Arg0 = F.getArg(0);3500 auto *Arg1 = F.getArg(1);3501 auto *BB = &*F.begin();3502 auto It = BB->begin();3503 auto *Call0 = cast<sandboxir::CallBase>(&*It++);3504 [[maybe_unused]] auto *Call1 = cast<sandboxir::CallBase>(&*It++);3505 auto *Call2 = cast<sandboxir::CallBase>(&*It++);3506 // Check setArgOperand3507 Call0->setArgOperand(0, Arg1);3508 EXPECT_EQ(Call0->getArgOperand(0), Arg1);3509 Call0->setArgOperand(0, Arg0);3510 EXPECT_EQ(Call0->getArgOperand(0), Arg0);3511 3512 auto *Bar3F = Ctx.createFunction(M->getFunction("bar3"));3513 3514 // Check setCalledOperand3515 auto *SvOp = Call0->getCalledOperand();3516 Call0->setCalledOperand(Bar3F);3517 EXPECT_EQ(Call0->getCalledOperand(), Bar3F);3518 Call0->setCalledOperand(SvOp);3519 // Check setCalledFunction3520 Call2->setCalledFunction(Bar3F);3521 EXPECT_EQ(Call2->getCalledFunction(), Bar3F);3522}3523 3524TEST_F(SandboxIRTest, CallInst) {3525 parseIR(C, R"IR(3526define i8 @foo(i8 %arg) {3527 %call = call i8 @foo(i8 %arg)3528 ret i8 %call3529}3530)IR");3531 Function &LLVMF = *M->getFunction("foo");3532 sandboxir::Context Ctx(C);3533 auto &F = *Ctx.createFunction(&LLVMF);3534 unsigned ArgIdx = 0;3535 auto *Arg0 = F.getArg(ArgIdx++);3536 auto *BB = &*F.begin();3537 auto It = BB->begin();3538 auto *Call = cast<sandboxir::CallInst>(&*It++);3539 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);3540 EXPECT_EQ(Call->getNumOperands(), 2u);3541 EXPECT_EQ(Ret->getOpcode(), sandboxir::Instruction::Opcode::Ret);3542 sandboxir::FunctionType *FTy = F.getFunctionType();3543 SmallVector<sandboxir::Value *, 1> Args;3544 Args.push_back(Arg0);3545 {3546 // Check create() WhereIt.3547 auto *Call = cast<sandboxir::CallInst>(sandboxir::CallInst::create(3548 FTy, &F, Args, /*WhereIt=*/Ret->getIterator(), Ctx));3549 EXPECT_EQ(Call->getNextNode(), Ret);3550 EXPECT_EQ(Call->getCalledFunction(), &F);3551 EXPECT_EQ(range_size(Call->args()), 1u);3552 EXPECT_EQ(Call->getArgOperand(0), Arg0);3553 }3554 {3555 // Check create() InsertBefore.3556 auto *Call = cast<sandboxir::CallInst>(3557 sandboxir::CallInst::create(FTy, &F, Args, Ret->getIterator(), Ctx));3558 EXPECT_EQ(Call->getNextNode(), Ret);3559 EXPECT_EQ(Call->getCalledFunction(), &F);3560 EXPECT_EQ(range_size(Call->args()), 1u);3561 EXPECT_EQ(Call->getArgOperand(0), Arg0);3562 }3563 {3564 // Check create() InsertAtEnd.3565 auto *Call = cast<sandboxir::CallInst>(3566 sandboxir::CallInst::create(FTy, &F, Args, /*InsertAtEnd=*/BB, Ctx));3567 EXPECT_EQ(Call->getPrevNode(), Ret);3568 EXPECT_EQ(Call->getCalledFunction(), &F);3569 EXPECT_EQ(range_size(Call->args()), 1u);3570 EXPECT_EQ(Call->getArgOperand(0), Arg0);3571 }3572}3573 3574TEST_F(SandboxIRTest, InvokeInst) {3575 parseIR(C, R"IR(3576define void @foo(i8 %arg) {3577 bb0:3578 invoke i8 @foo(i8 %arg) to label %normal_bb3579 unwind label %exception_bb3580 normal_bb:3581 ret void3582 exception_bb:3583 %lpad = landingpad { ptr, i32}3584 cleanup3585 ret void3586 other_bb:3587 ret void3588}3589)IR");3590 Function &LLVMF = *M->getFunction("foo");3591 sandboxir::Context Ctx(C);3592 auto &F = *Ctx.createFunction(&LLVMF);3593 auto *Arg = F.getArg(0);3594 auto *BB0 = cast<sandboxir::BasicBlock>(3595 Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));3596 auto *NormalBB = cast<sandboxir::BasicBlock>(3597 Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));3598 auto *ExceptionBB = cast<sandboxir::BasicBlock>(3599 Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));3600 auto *LandingPad = &*ExceptionBB->begin();3601 auto *OtherBB = cast<sandboxir::BasicBlock>(3602 Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));3603 auto It = BB0->begin();3604 // Check classof(Instruction *).3605 auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);3606 3607 // Check getNormalDest().3608 EXPECT_EQ(Invoke->getNormalDest(), NormalBB);3609 // Check getUnwindDest().3610 EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);3611 // Check getSuccessor().3612 EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);3613 EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);3614 // Check setNormalDest().3615 Invoke->setNormalDest(OtherBB);3616 EXPECT_EQ(Invoke->getNormalDest(), OtherBB);3617 EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);3618 // Check setUnwindDest().3619 Invoke->setUnwindDest(OtherBB);3620 EXPECT_EQ(Invoke->getNormalDest(), OtherBB);3621 EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);3622 // Check setSuccessor().3623 Invoke->setSuccessor(0, NormalBB);3624 EXPECT_EQ(Invoke->getNormalDest(), NormalBB);3625 Invoke->setSuccessor(1, ExceptionBB);3626 EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);3627 // Check getLandingPadInst().3628 EXPECT_EQ(Invoke->getLandingPadInst(), LandingPad);3629 3630 {3631 // Check create() WhereIt, WhereBB.3632 SmallVector<sandboxir::Value *> Args({Arg});3633 auto *InsertBefore = &*BB0->begin();3634 auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create(3635 F.getFunctionType(), &F, NormalBB, ExceptionBB, Args,3636 InsertBefore->getIterator(), Ctx));3637 EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);3638 EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);3639 EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore);3640 }3641 {3642 // Check create() InsertBefore.3643 SmallVector<sandboxir::Value *> Args({Arg});3644 auto *InsertBefore = &*BB0->begin();3645 auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create(3646 F.getFunctionType(), &F, NormalBB, ExceptionBB, Args,3647 InsertBefore->getIterator(), Ctx));3648 EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);3649 EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);3650 EXPECT_EQ(NewInvoke->getNextNode(), InsertBefore);3651 }3652 {3653 // Check create() InsertAtEnd.3654 SmallVector<sandboxir::Value *> Args({Arg});3655 auto *NewInvoke = cast<sandboxir::InvokeInst>(sandboxir::InvokeInst::create(3656 F.getFunctionType(), &F, NormalBB, ExceptionBB, Args, BB0, Ctx));3657 EXPECT_EQ(NewInvoke->getNormalDest(), NormalBB);3658 EXPECT_EQ(NewInvoke->getUnwindDest(), ExceptionBB);3659 EXPECT_EQ(NewInvoke->getParent(), BB0);3660 EXPECT_EQ(NewInvoke->getNextNode(), nullptr);3661 }3662}3663 3664TEST_F(SandboxIRTest, CallBrInst) {3665 parseIR(C, R"IR(3666define void @foo(i8 %arg) {3667 bb0:3668 callbr void asm "", ""()3669 to label %bb1 [label %bb2]3670 bb1:3671 ret void3672 bb2:3673 ret void3674 other_bb:3675 ret void3676 bb3:3677 callbr void @foo(i8 %arg)3678 to label %bb1 [label %bb2]3679}3680)IR");3681 Function &LLVMF = *M->getFunction("foo");3682 auto *LLVMBB0 = getBasicBlockByName(LLVMF, "bb0");3683 auto *LLVMCallBr = cast<llvm::CallBrInst>(&*LLVMBB0->begin());3684 sandboxir::Context Ctx(C);3685 auto &F = *Ctx.createFunction(&LLVMF);3686 auto *Arg = F.getArg(0);3687 auto *BB0 = cast<sandboxir::BasicBlock>(3688 Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));3689 auto *BB1 = cast<sandboxir::BasicBlock>(3690 Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));3691 auto *BB2 = cast<sandboxir::BasicBlock>(3692 Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));3693 auto *BB3 = cast<sandboxir::BasicBlock>(3694 Ctx.getValue(getBasicBlockByName(LLVMF, "bb3")));3695 auto *OtherBB = cast<sandboxir::BasicBlock>(3696 Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));3697 auto It = BB0->begin();3698 // Check classof(Instruction *).3699 auto *CallBr0 = cast<sandboxir::CallBrInst>(&*It++);3700 3701 It = BB3->begin();3702 auto *CallBr1 = cast<sandboxir::CallBrInst>(&*It++);3703 for (sandboxir::CallBrInst *CallBr : {CallBr0, CallBr1}) {3704 // Check getNumIndirectDests().3705 EXPECT_EQ(CallBr->getNumIndirectDests(), 1u);3706 // Check getIndirectDestLabel().3707 EXPECT_EQ(CallBr->getIndirectDestLabel(0),3708 Ctx.getValue(LLVMCallBr->getIndirectDestLabel(0)));3709 // Check getIndirectDestLabelUse().3710 EXPECT_EQ(CallBr->getIndirectDestLabelUse(0),3711 Ctx.getValue(LLVMCallBr->getIndirectDestLabelUse(0)));3712 // Check getDefaultDest().3713 EXPECT_EQ(CallBr->getDefaultDest(),3714 Ctx.getValue(LLVMCallBr->getDefaultDest()));3715 // Check getIndirectDest().3716 EXPECT_EQ(CallBr->getIndirectDest(0),3717 Ctx.getValue(LLVMCallBr->getIndirectDest(0)));3718 // Check getIndirectDests().3719 auto Dests = CallBr->getIndirectDests();3720 EXPECT_EQ(Dests.size(), LLVMCallBr->getIndirectDests().size());3721 EXPECT_EQ(Dests[0], Ctx.getValue(LLVMCallBr->getIndirectDests()[0]));3722 // Check getNumSuccessors().3723 EXPECT_EQ(CallBr->getNumSuccessors(), LLVMCallBr->getNumSuccessors());3724 // Check getSuccessor().3725 for (unsigned SuccIdx = 0, E = CallBr->getNumSuccessors(); SuccIdx != E;3726 ++SuccIdx)3727 EXPECT_EQ(CallBr->getSuccessor(SuccIdx),3728 Ctx.getValue(LLVMCallBr->getSuccessor(SuccIdx)));3729 // Check setDefaultDest().3730 auto *SvDefaultDest = CallBr->getDefaultDest();3731 CallBr->setDefaultDest(OtherBB);3732 EXPECT_EQ(CallBr->getDefaultDest(), OtherBB);3733 CallBr->setDefaultDest(SvDefaultDest);3734 // Check setIndirectDest().3735 auto *SvIndirectDest = CallBr->getIndirectDest(0);3736 CallBr->setIndirectDest(0, OtherBB);3737 EXPECT_EQ(CallBr->getIndirectDest(0), OtherBB);3738 CallBr->setIndirectDest(0, SvIndirectDest);3739 }3740 3741 {3742 // Check create() WhereIt, WhereBB.3743 SmallVector<sandboxir::Value *> Args({Arg});3744 auto *NewCallBr = cast<sandboxir::CallBrInst>(sandboxir::CallBrInst::create(3745 F.getFunctionType(), &F, BB1, {BB2}, Args, BB0->end(), Ctx));3746 EXPECT_EQ(NewCallBr->getDefaultDest(), BB1);3747 EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u);3748 EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2);3749 EXPECT_EQ(NewCallBr->getNextNode(), nullptr);3750 EXPECT_EQ(NewCallBr->getParent(), BB0);3751 }3752 {3753 // Check create() InsertBefore3754 SmallVector<sandboxir::Value *> Args({Arg});3755 auto *InsertBefore = &*BB0->rbegin();3756 auto *NewCallBr = cast<sandboxir::CallBrInst>(3757 sandboxir::CallBrInst::create(F.getFunctionType(), &F, BB1, {BB2}, Args,3758 InsertBefore->getIterator(), Ctx));3759 EXPECT_EQ(NewCallBr->getDefaultDest(), BB1);3760 EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u);3761 EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2);3762 EXPECT_EQ(NewCallBr->getNextNode(), InsertBefore);3763 }3764 {3765 // Check create() InsertAtEnd.3766 SmallVector<sandboxir::Value *> Args({Arg});3767 auto *NewCallBr = cast<sandboxir::CallBrInst>(sandboxir::CallBrInst::create(3768 F.getFunctionType(), &F, BB1, {BB2}, Args, BB0, Ctx));3769 EXPECT_EQ(NewCallBr->getDefaultDest(), BB1);3770 EXPECT_EQ(NewCallBr->getIndirectDests().size(), 1u);3771 EXPECT_EQ(NewCallBr->getIndirectDests()[0], BB2);3772 EXPECT_EQ(NewCallBr->getNextNode(), nullptr);3773 EXPECT_EQ(NewCallBr->getParent(), BB0);3774 }3775}3776 3777TEST_F(SandboxIRTest, LandingPadInst) {3778 parseIR(C, R"IR(3779define void @foo() {3780entry:3781 invoke void @foo()3782 to label %bb unwind label %unwind3783unwind:3784 %lpad = landingpad { ptr, i32 }3785 catch ptr null3786 ret void3787bb:3788 ret void3789}3790)IR");3791 Function &LLVMF = *M->getFunction("foo");3792 auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");3793 auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMUnwind->begin());3794 3795 sandboxir::Context Ctx(C);3796 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);3797 auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));3798 auto *BB = cast<sandboxir::BasicBlock>(3799 Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));3800 auto It = Unwind->begin();3801 auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);3802 [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);3803 3804 // Check isCleanup().3805 EXPECT_EQ(LPad->isCleanup(), LLVMLPad->isCleanup());3806 // Check setCleanup().3807 auto OrigIsCleanup = LPad->isCleanup();3808 auto NewIsCleanup = true;3809 EXPECT_NE(NewIsCleanup, OrigIsCleanup);3810 LPad->setCleanup(NewIsCleanup);3811 EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);3812 LPad->setCleanup(OrigIsCleanup);3813 EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);3814 // Check getNumClauses().3815 EXPECT_EQ(LPad->getNumClauses(), LLVMLPad->getNumClauses());3816 // Check getClause().3817 for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))3818 EXPECT_EQ(LPad->getClause(Idx), Ctx.getValue(LLVMLPad->getClause(Idx)));3819 // Check isCatch().3820 for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))3821 EXPECT_EQ(LPad->isCatch(Idx), LLVMLPad->isCatch(Idx));3822 // Check isFilter().3823 for (auto Idx : seq<unsigned>(0, LPad->getNumClauses()))3824 EXPECT_EQ(LPad->isFilter(Idx), LLVMLPad->isFilter(Idx));3825 // Check create().3826 auto *BBRet = &*BB->begin();3827 auto *NewLPad = cast<sandboxir::LandingPadInst>(3828 sandboxir::LandingPadInst::create(sandboxir::Type::getInt8Ty(Ctx), 0,3829 BBRet->getIterator(), Ctx, "NewLPad"));3830 EXPECT_EQ(NewLPad->getNextNode(), BBRet);3831 EXPECT_FALSE(NewLPad->isCleanup());3832#ifndef NDEBUG3833 EXPECT_EQ(NewLPad->getName(), "NewLPad");3834#endif // NDEBUG3835}3836 3837TEST_F(SandboxIRTest, FuncletPadInst_CatchPadInst_CleanupPadInst) {3838 parseIR(C, R"IR(3839define void @foo() {3840dispatch:3841 %cs = catchswitch within none [label %handler0] unwind to caller3842handler0:3843 %catchpad = catchpad within %cs [ptr @foo]3844 ret void3845handler1:3846 %cleanuppad = cleanuppad within %cs [ptr @foo]3847 ret void3848bb:3849 ret void3850}3851)IR");3852 Function &LLVMF = *M->getFunction("foo");3853 BasicBlock *LLVMDispatch = getBasicBlockByName(LLVMF, "dispatch");3854 BasicBlock *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0");3855 BasicBlock *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1");3856 auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMHandler0->begin());3857 auto *LLVMCLP = cast<llvm::CleanupPadInst>(&*LLVMHandler1->begin());3858 3859 sandboxir::Context Ctx(C);3860 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);3861 auto *Dispatch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMDispatch));3862 auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0));3863 auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1));3864 auto *BB = cast<sandboxir::BasicBlock>(3865 Ctx.getValue(getBasicBlockByName(LLVMF, "bb")));3866 auto *BBRet = cast<sandboxir::ReturnInst>(&*BB->begin());3867 auto *CS = cast<sandboxir::CatchSwitchInst>(&*Dispatch->begin());3868 [[maybe_unused]] auto *CP =3869 cast<sandboxir::CatchPadInst>(&*Handler0->begin());3870 [[maybe_unused]] auto *CLP =3871 cast<sandboxir::CleanupPadInst>(&*Handler1->begin());3872 3873 // Check getCatchSwitch().3874 EXPECT_EQ(CP->getCatchSwitch(), CS);3875 EXPECT_EQ(CP->getCatchSwitch(), Ctx.getValue(LLVMCP->getCatchSwitch()));3876 3877 for (llvm::FuncletPadInst *LLVMFPI :3878 {static_cast<llvm::FuncletPadInst *>(LLVMCP),3879 static_cast<llvm::FuncletPadInst *>(LLVMCLP)}) {3880 auto *FPI = cast<sandboxir::FuncletPadInst>(Ctx.getValue(LLVMFPI));3881 // Check arg_size().3882 EXPECT_EQ(FPI->arg_size(), LLVMFPI->arg_size());3883 // Check getParentPad().3884 EXPECT_EQ(FPI->getParentPad(), Ctx.getValue(LLVMFPI->getParentPad()));3885 // Check setParentPad().3886 auto *OrigParentPad = FPI->getParentPad();3887 auto *NewParentPad = Dispatch;3888 EXPECT_NE(NewParentPad, OrigParentPad);3889 FPI->setParentPad(NewParentPad);3890 EXPECT_EQ(FPI->getParentPad(), NewParentPad);3891 FPI->setParentPad(OrigParentPad);3892 EXPECT_EQ(FPI->getParentPad(), OrigParentPad);3893 // Check getArgOperand().3894 for (auto Idx : seq<unsigned>(0, FPI->arg_size()))3895 EXPECT_EQ(FPI->getArgOperand(Idx),3896 Ctx.getValue(LLVMFPI->getArgOperand(Idx)));3897 // Check setArgOperand().3898 auto *OrigArgOperand = FPI->getArgOperand(0);3899 auto *NewArgOperand = Dispatch;3900 EXPECT_NE(NewArgOperand, OrigArgOperand);3901 FPI->setArgOperand(0, NewArgOperand);3902 EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);3903 FPI->setArgOperand(0, OrigArgOperand);3904 EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);3905 }3906 // Check CatchPadInst::create().3907 auto *NewCPI = cast<sandboxir::CatchPadInst>(sandboxir::CatchPadInst::create(3908 CS, {}, BBRet->getIterator(), Ctx, "NewCPI"));3909 EXPECT_EQ(NewCPI->getCatchSwitch(), CS);3910 EXPECT_EQ(NewCPI->arg_size(), 0u);3911 EXPECT_EQ(NewCPI->getNextNode(), BBRet);3912#ifndef NDEBUG3913 EXPECT_EQ(NewCPI->getName(), "NewCPI");3914#endif // NDEBUG3915 // Check CleanupPadInst::create().3916 auto *NewCLPI =3917 cast<sandboxir::CleanupPadInst>(sandboxir::CleanupPadInst::create(3918 CS, {}, BBRet->getIterator(), Ctx, "NewCLPI"));3919 EXPECT_EQ(NewCLPI->getParentPad(), CS);3920 EXPECT_EQ(NewCLPI->arg_size(), 0u);3921 EXPECT_EQ(NewCLPI->getNextNode(), BBRet);3922#ifndef NDEBUG3923 EXPECT_EQ(NewCLPI->getName(), "NewCLPI");3924#endif // NDEBUG3925}3926 3927TEST_F(SandboxIRTest, CatchReturnInst) {3928 parseIR(C, R"IR(3929define void @foo() {3930dispatch:3931 %cs = catchswitch within none [label %catch] unwind to caller3932catch:3933 %catchpad = catchpad within %cs [ptr @foo]3934 catchret from %catchpad to label %continue3935continue:3936 ret void3937catch2:3938 %catchpad2 = catchpad within %cs [ptr @foo]3939 ret void3940}3941)IR");3942 Function &LLVMF = *M->getFunction("foo");3943 BasicBlock *LLVMCatch = getBasicBlockByName(LLVMF, "catch");3944 auto LLVMIt = LLVMCatch->begin();3945 [[maybe_unused]] auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMIt++);3946 auto *LLVMCR = cast<llvm::CatchReturnInst>(&*LLVMIt++);3947 3948 sandboxir::Context Ctx(C);3949 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);3950 auto *Catch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCatch));3951 auto *Catch2 = cast<sandboxir::BasicBlock>(3952 Ctx.getValue(getBasicBlockByName(LLVMF, "catch2")));3953 auto It = Catch->begin();3954 [[maybe_unused]] auto *CP = cast<sandboxir::CatchPadInst>(&*It++);3955 auto *CR = cast<sandboxir::CatchReturnInst>(&*It++);3956 auto *CP2 = cast<sandboxir::CatchPadInst>(&*Catch2->begin());3957 3958 // Check getCatchPad().3959 EXPECT_EQ(CR->getCatchPad(), Ctx.getValue(LLVMCR->getCatchPad()));3960 // Check setCatchPad().3961 auto *OrigCP = CR->getCatchPad();3962 auto *NewCP = CP2;3963 EXPECT_NE(NewCP, OrigCP);3964 CR->setCatchPad(NewCP);3965 EXPECT_EQ(CR->getCatchPad(), NewCP);3966 CR->setCatchPad(OrigCP);3967 EXPECT_EQ(CR->getCatchPad(), OrigCP);3968 // Check getSuccessor().3969 EXPECT_EQ(CR->getSuccessor(), Ctx.getValue(LLVMCR->getSuccessor()));3970 // Check setSuccessor().3971 auto *OrigSucc = CR->getSuccessor();3972 auto *NewSucc = Catch;3973 EXPECT_NE(NewSucc, OrigSucc);3974 CR->setSuccessor(NewSucc);3975 EXPECT_EQ(CR->getSuccessor(), NewSucc);3976 CR->setSuccessor(OrigSucc);3977 EXPECT_EQ(CR->getSuccessor(), OrigSucc);3978 // Check getNumSuccessors().3979 EXPECT_EQ(CR->getNumSuccessors(), LLVMCR->getNumSuccessors());3980 // Check getCatchSwitchParentPad().3981 EXPECT_EQ(CR->getCatchSwitchParentPad(),3982 Ctx.getValue(LLVMCR->getCatchSwitchParentPad()));3983 // Check create().3984 auto *CRI = cast<sandboxir::CatchReturnInst>(3985 sandboxir::CatchReturnInst::create(CP, Catch, CP->getIterator(), Ctx));3986 EXPECT_EQ(CRI->getNextNode(), CP);3987 EXPECT_EQ(CRI->getCatchPad(), CP);3988 EXPECT_EQ(CRI->getSuccessor(), Catch);3989}3990 3991TEST_F(SandboxIRTest, CleanupReturnInst) {3992 parseIR(C, R"IR(3993define void @foo() {3994dispatch:3995 invoke void @foo()3996 to label %throw unwind label %cleanup3997throw:3998 ret void3999cleanup:4000 %cleanuppad = cleanuppad within none []4001 cleanupret from %cleanuppad unwind label %cleanup24002cleanup2:4003 %cleanuppad2 = cleanuppad within none []4004 ret void4005}4006)IR");4007 Function &LLVMF = *M->getFunction("foo");4008 BasicBlock *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup");4009 auto LLVMIt = LLVMCleanup->begin();4010 [[maybe_unused]] auto *LLVMCP = cast<llvm::CleanupPadInst>(&*LLVMIt++);4011 auto *LLVMCRI = cast<llvm::CleanupReturnInst>(&*LLVMIt++);4012 4013 sandboxir::Context Ctx(C);4014 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);4015 auto *Throw = cast<sandboxir::BasicBlock>(4016 Ctx.getValue(getBasicBlockByName(LLVMF, "throw")));4017 auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup));4018 auto *Cleanup2 = cast<sandboxir::BasicBlock>(4019 Ctx.getValue(getBasicBlockByName(LLVMF, "cleanup2")));4020 auto It = Cleanup->begin();4021 [[maybe_unused]] auto *CP = cast<sandboxir::CleanupPadInst>(&*It++);4022 auto *CRI = cast<sandboxir::CleanupReturnInst>(&*It++);4023 It = Cleanup2->begin();4024 auto *CP2 = cast<sandboxir::CleanupPadInst>(&*It++);4025 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);4026 4027 // Check hasUnwindDest().4028 EXPECT_EQ(CRI->hasUnwindDest(), LLVMCRI->hasUnwindDest());4029 // Check unwindsToCaller().4030 EXPECT_EQ(CRI->unwindsToCaller(), LLVMCRI->unwindsToCaller());4031 // Check getCleanupPad().4032 EXPECT_EQ(CRI->getCleanupPad(), Ctx.getValue(LLVMCRI->getCleanupPad()));4033 // Check setCleanupPad().4034 auto *OrigCleanupPad = CRI->getCleanupPad();4035 auto *NewCleanupPad = CP2;4036 EXPECT_NE(NewCleanupPad, OrigCleanupPad);4037 CRI->setCleanupPad(NewCleanupPad);4038 EXPECT_EQ(CRI->getCleanupPad(), NewCleanupPad);4039 CRI->setCleanupPad(OrigCleanupPad);4040 EXPECT_EQ(CRI->getCleanupPad(), OrigCleanupPad);4041 // Check setNumSuccessors().4042 EXPECT_EQ(CRI->getNumSuccessors(), LLVMCRI->getNumSuccessors());4043 // Check getUnwindDest().4044 EXPECT_EQ(CRI->getUnwindDest(), Ctx.getValue(LLVMCRI->getUnwindDest()));4045 // Check setUnwindDest().4046 auto *OrigUnwindDest = CRI->getUnwindDest();4047 auto *NewUnwindDest = Throw;4048 EXPECT_NE(NewUnwindDest, OrigUnwindDest);4049 CRI->setUnwindDest(NewUnwindDest);4050 EXPECT_EQ(CRI->getUnwindDest(), NewUnwindDest);4051 CRI->setUnwindDest(OrigUnwindDest);4052 EXPECT_EQ(CRI->getUnwindDest(), OrigUnwindDest);4053 // Check create().4054 auto *UnwindBB = Cleanup;4055 auto *NewCRI = sandboxir::CleanupReturnInst::create(CP2, UnwindBB,4056 Ret->getIterator(), Ctx);4057 EXPECT_EQ(NewCRI->getCleanupPad(), CP2);4058 EXPECT_EQ(NewCRI->getUnwindDest(), UnwindBB);4059 EXPECT_EQ(NewCRI->getNextNode(), Ret);4060}4061 4062TEST_F(SandboxIRTest, GetElementPtrInstruction) {4063 parseIR(C, R"IR(4064define void @foo(ptr %ptr, <2 x ptr> %ptrs) {4065 %gep0 = getelementptr i8, ptr %ptr, i32 04066 %gep1 = getelementptr nusw i8, ptr %ptr, i32 04067 %gep2 = getelementptr nuw i8, ptr %ptr, i32 04068 %gep3 = getelementptr inbounds {i32, {i32, i8}}, ptr %ptr, i32 1, i32 04069 %gep4 = getelementptr inbounds {i8, i8, {i32, i16}}, <2 x ptr> %ptrs, i32 2, <2 x i32> <i32 0, i32 0>4070 ret void4071}4072)IR");4073 Function &LLVMF = *M->getFunction("foo");4074 BasicBlock *LLVMBB = &*LLVMF.begin();4075 auto LLVMIt = LLVMBB->begin();4076 SmallVector<llvm::GetElementPtrInst *, 4> LLVMGEPs;4077 while (isa<llvm::GetElementPtrInst>(&*LLVMIt))4078 LLVMGEPs.push_back(cast<llvm::GetElementPtrInst>(&*LLVMIt++));4079 auto *LLVMRet = cast<llvm::ReturnInst>(&*LLVMIt++);4080 sandboxir::Context Ctx(C);4081 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);4082 4083 for (llvm::GetElementPtrInst *LLVMGEP : LLVMGEPs) {4084 // Check classof().4085 auto *GEP = cast<sandboxir::GetElementPtrInst>(Ctx.getValue(LLVMGEP));4086 // Check getSourceElementType().4087 EXPECT_EQ(GEP->getSourceElementType(),4088 Ctx.getType(LLVMGEP->getSourceElementType()));4089 // Check getResultElementType().4090 EXPECT_EQ(GEP->getResultElementType(),4091 Ctx.getType(LLVMGEP->getResultElementType()));4092 // Check getAddressSpace().4093 EXPECT_EQ(GEP->getAddressSpace(), LLVMGEP->getAddressSpace());4094 // Check indices().4095 EXPECT_EQ(range_size(GEP->indices()), range_size(LLVMGEP->indices()));4096 auto IdxIt = GEP->idx_begin();4097 for (llvm::Value *LLVMIdxV : LLVMGEP->indices()) {4098 sandboxir::Value *IdxV = *IdxIt++;4099 EXPECT_EQ(IdxV, Ctx.getValue(LLVMIdxV));4100 }4101 // Check getPointerOperand().4102 EXPECT_EQ(GEP->getPointerOperand(),4103 Ctx.getValue(LLVMGEP->getPointerOperand()));4104 // Check getPointerOperandIndex().4105 EXPECT_EQ(GEP->getPointerOperandIndex(), LLVMGEP->getPointerOperandIndex());4106 // Check getPointerOperandType().4107 EXPECT_EQ(GEP->getPointerOperandType(),4108 Ctx.getType(LLVMGEP->getPointerOperandType()));4109 // Check getPointerAddressSpace().4110 EXPECT_EQ(GEP->getPointerAddressSpace(), LLVMGEP->getPointerAddressSpace());4111 // Check getNumIndices().4112 EXPECT_EQ(GEP->getNumIndices(), LLVMGEP->getNumIndices());4113 // Check hasIndices().4114 EXPECT_EQ(GEP->hasIndices(), LLVMGEP->hasIndices());4115 // Check hasAllConstantIndices().4116 EXPECT_EQ(GEP->hasAllConstantIndices(), LLVMGEP->hasAllConstantIndices());4117 // Check getNoWrapFlags().4118 EXPECT_EQ(GEP->getNoWrapFlags(), LLVMGEP->getNoWrapFlags());4119 // Check isInBounds().4120 EXPECT_EQ(GEP->isInBounds(), LLVMGEP->isInBounds());4121 // Check hasNoUnsignedWrap().4122 EXPECT_EQ(GEP->hasNoUnsignedWrap(), LLVMGEP->hasNoUnsignedWrap());4123 // Check accumulateConstantOffset().4124 const DataLayout &DL = M->getDataLayout();4125 APInt Offset1 =4126 APInt::getZero(DL.getIndexSizeInBits(GEP->getPointerAddressSpace()));4127 APInt Offset2 =4128 APInt::getZero(DL.getIndexSizeInBits(GEP->getPointerAddressSpace()));4129 EXPECT_EQ(GEP->accumulateConstantOffset(DL, Offset1),4130 LLVMGEP->accumulateConstantOffset(DL, Offset2));4131 EXPECT_EQ(Offset1, Offset2);4132 }4133 4134 auto *BB = &*F.begin();4135 auto *GEP0 = cast<sandboxir::GetElementPtrInst>(&*BB->begin());4136 auto *Ret = cast<sandboxir::ReturnInst>(Ctx.getValue(LLVMRet));4137 SmallVector<sandboxir::Value *> Indices(GEP0->indices());4138 4139 // Check create() WhereIt, WhereBB.4140 auto *NewGEP0 =4141 cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create(4142 GEP0->getType(), GEP0->getPointerOperand(), Indices,4143 Ret->getIterator(), Ctx, "NewGEP0"));4144 EXPECT_EQ(NewGEP0->getName(), "NewGEP0");4145 EXPECT_EQ(NewGEP0->getType(), GEP0->getType());4146 EXPECT_EQ(NewGEP0->getPointerOperand(), GEP0->getPointerOperand());4147 EXPECT_EQ(range_size(NewGEP0->indices()), range_size(GEP0->indices()));4148 for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(),4149 OldIt = GEP0->idx_begin();4150 NewIt != NewItE; ++NewIt) {4151 sandboxir::Value *NewIdxV = *NewIt;4152 sandboxir::Value *OldIdxV = *OldIt;4153 EXPECT_EQ(NewIdxV, OldIdxV);4154 }4155 EXPECT_EQ(NewGEP0->getNextNode(), Ret);4156 4157 // Check create() InsertBefore.4158 auto *NewGEP1 =4159 cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create(4160 GEP0->getType(), GEP0->getPointerOperand(), Indices,4161 Ret->getIterator(), Ctx, "NewGEP1"));4162 EXPECT_EQ(NewGEP1->getName(), "NewGEP1");4163 EXPECT_EQ(NewGEP1->getType(), GEP0->getType());4164 EXPECT_EQ(NewGEP1->getPointerOperand(), GEP0->getPointerOperand());4165 EXPECT_EQ(range_size(NewGEP1->indices()), range_size(GEP0->indices()));4166 for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(),4167 OldIt = GEP0->idx_begin();4168 NewIt != NewItE; ++NewIt) {4169 sandboxir::Value *NewIdxV = *NewIt;4170 sandboxir::Value *OldIdxV = *OldIt;4171 EXPECT_EQ(NewIdxV, OldIdxV);4172 }4173 EXPECT_EQ(NewGEP1->getNextNode(), Ret);4174 4175 // Check create() InsertAtEnd.4176 auto *NewGEP2 =4177 cast<sandboxir::GetElementPtrInst>(sandboxir::GetElementPtrInst::create(4178 GEP0->getType(), GEP0->getPointerOperand(), Indices, BB, Ctx,4179 "NewGEP2"));4180 EXPECT_EQ(NewGEP2->getName(), "NewGEP2");4181 EXPECT_EQ(NewGEP2->getType(), GEP0->getType());4182 EXPECT_EQ(NewGEP2->getPointerOperand(), GEP0->getPointerOperand());4183 EXPECT_EQ(range_size(NewGEP2->indices()), range_size(GEP0->indices()));4184 for (auto NewIt = NewGEP0->idx_begin(), NewItE = NewGEP0->idx_end(),4185 OldIt = GEP0->idx_begin();4186 NewIt != NewItE; ++NewIt) {4187 sandboxir::Value *NewIdxV = *NewIt;4188 sandboxir::Value *OldIdxV = *OldIt;4189 EXPECT_EQ(NewIdxV, OldIdxV);4190 }4191 EXPECT_EQ(NewGEP2->getPrevNode(), Ret);4192 EXPECT_EQ(NewGEP2->getNextNode(), nullptr);4193}4194 4195TEST_F(SandboxIRTest, Flags) {4196 parseIR(C, R"IR(4197define void @foo(i32 %arg, float %farg) {4198 %add = add i32 %arg, %arg4199 %fadd = fadd float %farg, %farg4200 %udiv = udiv i32 %arg, %arg4201 ret void4202}4203)IR");4204 Function &LLVMF = *M->getFunction("foo");4205 BasicBlock *LLVMBB = &*LLVMF.begin();4206 auto LLVMIt = LLVMBB->begin();4207 auto *LLVMAdd = &*LLVMIt++;4208 auto *LLVMFAdd = &*LLVMIt++;4209 auto *LLVMUDiv = &*LLVMIt++;4210 4211 sandboxir::Context Ctx(C);4212 auto &F = *Ctx.createFunction(&LLVMF);4213 auto *BB = &*F.begin();4214 auto It = BB->begin();4215 auto *Add = &*It++;4216 auto *FAdd = &*It++;4217 auto *UDiv = &*It++;4218 4219#define CHECK_FLAG(I, LLVMI, GETTER, SETTER) \4220 { \4221 EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \4222 bool NewFlagVal = !I->GETTER(); \4223 I->SETTER(NewFlagVal); \4224 EXPECT_EQ(I->GETTER(), NewFlagVal); \4225 EXPECT_EQ(I->GETTER(), LLVMI->GETTER()); \4226 }4227 4228 CHECK_FLAG(Add, LLVMAdd, hasNoUnsignedWrap, setHasNoUnsignedWrap);4229 CHECK_FLAG(Add, LLVMAdd, hasNoSignedWrap, setHasNoSignedWrap);4230 CHECK_FLAG(FAdd, LLVMFAdd, isFast, setFast);4231 CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReassoc, setHasAllowReassoc);4232 CHECK_FLAG(UDiv, LLVMUDiv, isExact, setIsExact);4233 CHECK_FLAG(FAdd, LLVMFAdd, hasNoNaNs, setHasNoNaNs);4234 CHECK_FLAG(FAdd, LLVMFAdd, hasNoInfs, setHasNoInfs);4235 CHECK_FLAG(FAdd, LLVMFAdd, hasNoSignedZeros, setHasNoSignedZeros);4236 CHECK_FLAG(FAdd, LLVMFAdd, hasAllowReciprocal, setHasAllowReciprocal);4237 CHECK_FLAG(FAdd, LLVMFAdd, hasAllowContract, setHasAllowContract);4238 CHECK_FLAG(FAdd, LLVMFAdd, hasApproxFunc, setHasApproxFunc);4239 4240 // Check getFastMathFlags(), copyFastMathFlags().4241 FAdd->setFastMathFlags(FastMathFlags::getFast());4242 EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());4243 FastMathFlags OrigFMF = FAdd->getFastMathFlags();4244 FastMathFlags NewFMF;4245 NewFMF.setAllowReassoc(true);4246 EXPECT_TRUE(NewFMF != OrigFMF);4247 FAdd->setFastMathFlags(NewFMF);4248 EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);4249 FAdd->copyFastMathFlags(NewFMF);4250 EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);4251 EXPECT_FALSE(FAdd->getFastMathFlags() != LLVMFAdd->getFastMathFlags());4252}4253 4254TEST_F(SandboxIRTest, CatchSwitchInst) {4255 parseIR(C, R"IR(4256define void @foo(i32 %cond0, i32 %cond1) {4257 bb0:4258 %cs0 = catchswitch within none [label %handler0, label %handler1] unwind to caller4259 bb1:4260 %cs1 = catchswitch within %cs0 [label %handler0, label %handler1] unwind label %cleanup4261 handler0:4262 ret void4263 handler1:4264 ret void4265 cleanup:4266 ret void4267}4268)IR");4269 Function &LLVMF = *M->getFunction("foo");4270 auto *LLVMBB0 = getBasicBlockByName(LLVMF, "bb0");4271 auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1");4272 auto *LLVMHandler0 = getBasicBlockByName(LLVMF, "handler0");4273 auto *LLVMHandler1 = getBasicBlockByName(LLVMF, "handler1");4274 auto *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup");4275 auto *LLVMCS0 = cast<llvm::CatchSwitchInst>(&*LLVMBB0->begin());4276 auto *LLVMCS1 = cast<llvm::CatchSwitchInst>(&*LLVMBB1->begin());4277 4278 sandboxir::Context Ctx(C);4279 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);4280 auto *BB0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB0));4281 auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1));4282 auto *Handler0 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler0));4283 auto *Handler1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMHandler1));4284 auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup));4285 auto *CS0 = cast<sandboxir::CatchSwitchInst>(&*BB0->begin());4286 auto *CS1 = cast<sandboxir::CatchSwitchInst>(&*BB1->begin());4287 4288 // Check getParentPad().4289 EXPECT_EQ(CS0->getParentPad(), Ctx.getValue(LLVMCS0->getParentPad()));4290 EXPECT_EQ(CS1->getParentPad(), Ctx.getValue(LLVMCS1->getParentPad()));4291 // Check setParentPad().4292 auto *OrigPad = CS0->getParentPad();4293 auto *NewPad = CS1;4294 EXPECT_NE(NewPad, OrigPad);4295 CS0->setParentPad(NewPad);4296 EXPECT_EQ(CS0->getParentPad(), NewPad);4297 CS0->setParentPad(OrigPad);4298 EXPECT_EQ(CS0->getParentPad(), OrigPad);4299 // Check hasUnwindDest().4300 EXPECT_EQ(CS0->hasUnwindDest(), LLVMCS0->hasUnwindDest());4301 EXPECT_EQ(CS1->hasUnwindDest(), LLVMCS1->hasUnwindDest());4302 // Check unwindsToCaller().4303 EXPECT_EQ(CS0->unwindsToCaller(), LLVMCS0->unwindsToCaller());4304 EXPECT_EQ(CS1->unwindsToCaller(), LLVMCS1->unwindsToCaller());4305 // Check getUnwindDest().4306 EXPECT_EQ(CS0->getUnwindDest(), Ctx.getValue(LLVMCS0->getUnwindDest()));4307 EXPECT_EQ(CS1->getUnwindDest(), Ctx.getValue(LLVMCS1->getUnwindDest()));4308 // Check setUnwindDest().4309 auto *OrigUnwindDest = CS1->getUnwindDest();4310 auto *NewUnwindDest = BB0;4311 EXPECT_NE(NewUnwindDest, OrigUnwindDest);4312 CS1->setUnwindDest(NewUnwindDest);4313 EXPECT_EQ(CS1->getUnwindDest(), NewUnwindDest);4314 CS1->setUnwindDest(OrigUnwindDest);4315 EXPECT_EQ(CS1->getUnwindDest(), OrigUnwindDest);4316 // Check getNumHandlers().4317 EXPECT_EQ(CS0->getNumHandlers(), LLVMCS0->getNumHandlers());4318 EXPECT_EQ(CS1->getNumHandlers(), LLVMCS1->getNumHandlers());4319 // Check handler_begin(), handler_end().4320 auto It = CS0->handler_begin();4321 EXPECT_EQ(*It++, Handler0);4322 EXPECT_EQ(*It++, Handler1);4323 EXPECT_EQ(It, CS0->handler_end());4324 // Check handlers().4325 SmallVector<sandboxir::BasicBlock *, 2> Handlers;4326 for (sandboxir::BasicBlock *Handler : CS0->handlers())4327 Handlers.push_back(Handler);4328 EXPECT_EQ(Handlers.size(), 2u);4329 EXPECT_EQ(Handlers[0], Handler0);4330 EXPECT_EQ(Handlers[1], Handler1);4331 // Check addHandler().4332 CS0->addHandler(BB0);4333 EXPECT_EQ(CS0->getNumHandlers(), 3u);4334 EXPECT_EQ(*std::next(CS0->handler_begin(), 2), BB0);4335 // Check getNumSuccessors().4336 EXPECT_EQ(CS0->getNumSuccessors(), LLVMCS0->getNumSuccessors());4337 EXPECT_EQ(CS1->getNumSuccessors(), LLVMCS1->getNumSuccessors());4338 // Check getSuccessor().4339 for (auto SuccIdx : seq<unsigned>(0, CS0->getNumSuccessors()))4340 EXPECT_EQ(CS0->getSuccessor(SuccIdx),4341 Ctx.getValue(LLVMCS0->getSuccessor(SuccIdx)));4342 // Check setSuccessor().4343 auto *OrigSuccessor = CS0->getSuccessor(0);4344 auto *NewSuccessor = BB0;4345 EXPECT_NE(NewSuccessor, OrigSuccessor);4346 CS0->setSuccessor(0, NewSuccessor);4347 EXPECT_EQ(CS0->getSuccessor(0), NewSuccessor);4348 CS0->setSuccessor(0, OrigSuccessor);4349 EXPECT_EQ(CS0->getSuccessor(0), OrigSuccessor);4350 // Check create().4351 CS1->eraseFromParent();4352 auto *NewCSI = sandboxir::CatchSwitchInst::create(4353 CS0, Cleanup, 2, BB1->begin(), Ctx, "NewCSI");4354 EXPECT_TRUE(isa<sandboxir::CatchSwitchInst>(NewCSI));4355 EXPECT_EQ(NewCSI->getParentPad(), CS0);4356}4357 4358TEST_F(SandboxIRTest, ResumeInst) {4359 parseIR(C, R"IR(4360define void @foo() {4361entry:4362 invoke void @foo()4363 to label %bb unwind label %unwind4364bb:4365 ret void4366unwind:4367 %lpad = landingpad { ptr, i32 }4368 cleanup4369 resume { ptr, i32 } %lpad4370}4371)IR");4372 Function &LLVMF = *M->getFunction("foo");4373 auto *LLVMUnwindBB = getBasicBlockByName(LLVMF, "unwind");4374 auto LLVMIt = LLVMUnwindBB->begin();4375 [[maybe_unused]] auto *LLVMLPad = cast<llvm::LandingPadInst>(&*LLVMIt++);4376 auto *LLVMResume = cast<llvm::ResumeInst>(&*LLVMIt++);4377 4378 sandboxir::Context Ctx(C);4379 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);4380 auto *UnwindBB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwindBB));4381 auto It = UnwindBB->begin();4382 auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);4383 auto *Resume = cast<sandboxir::ResumeInst>(&*It++);4384 // Check getValue().4385 EXPECT_EQ(Resume->getValue(), LPad);4386 EXPECT_EQ(Resume->getValue(), Ctx.getValue(LLVMResume->getValue()));4387 // Check getNumSuccessors().4388 EXPECT_EQ(Resume->getNumSuccessors(), LLVMResume->getNumSuccessors());4389 // Check create().4390 auto *NewResume = sandboxir::ResumeInst::create(LPad, UnwindBB->end(), Ctx);4391 EXPECT_EQ(NewResume->getValue(), LPad);4392 EXPECT_EQ(NewResume->getParent(), UnwindBB);4393 EXPECT_EQ(NewResume->getNextNode(), nullptr);4394}4395 4396TEST_F(SandboxIRTest, SwitchInst) {4397 parseIR(C, R"IR(4398define void @foo(i32 %cond0, i32 %cond1) {4399 entry:4400 switch i32 %cond0, label %default [ i32 0, label %bb04401 i32 1, label %bb1 ]4402 bb0:4403 ret void4404 bb1:4405 ret void4406 default:4407 ret void4408}4409)IR");4410 Function &LLVMF = *M->getFunction("foo");4411 auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry");4412 auto *LLVMSwitch = cast<llvm::SwitchInst>(&*LLVMEntry->begin());4413 4414 sandboxir::Context Ctx(C);4415 auto &F = *Ctx.createFunction(&LLVMF);4416 auto *Cond1 = F.getArg(1);4417 auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry));4418 auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin());4419 auto *BB0 = cast<sandboxir::BasicBlock>(4420 Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));4421 auto *BB1 = cast<sandboxir::BasicBlock>(4422 Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));4423 auto *Default = cast<sandboxir::BasicBlock>(4424 Ctx.getValue(getBasicBlockByName(LLVMF, "default")));4425 4426 // Check getCondition().4427 EXPECT_EQ(Switch->getCondition(), Ctx.getValue(LLVMSwitch->getCondition()));4428 // Check setCondition().4429 auto *OrigCond = Switch->getCondition();4430 auto *NewCond = Cond1;4431 EXPECT_NE(NewCond, OrigCond);4432 Switch->setCondition(NewCond);4433 EXPECT_EQ(Switch->getCondition(), NewCond);4434 Switch->setCondition(OrigCond);4435 EXPECT_EQ(Switch->getCondition(), OrigCond);4436 // Check getDefaultDest().4437 EXPECT_EQ(Switch->getDefaultDest(),4438 Ctx.getValue(LLVMSwitch->getDefaultDest()));4439 EXPECT_EQ(Switch->getDefaultDest(), Default);4440 // Check defaultDestUnreachable().4441 EXPECT_EQ(Switch->defaultDestUnreachable(),4442 LLVMSwitch->defaultDestUnreachable());4443 // Check setDefaultDest().4444 auto *OrigDefaultDest = Switch->getDefaultDest();4445 auto *NewDefaultDest = Entry;4446 EXPECT_NE(NewDefaultDest, OrigDefaultDest);4447 Switch->setDefaultDest(NewDefaultDest);4448 EXPECT_EQ(Switch->getDefaultDest(), NewDefaultDest);4449 Switch->setDefaultDest(OrigDefaultDest);4450 EXPECT_EQ(Switch->getDefaultDest(), OrigDefaultDest);4451 // Check getNumCases().4452 EXPECT_EQ(Switch->getNumCases(), LLVMSwitch->getNumCases());4453 // Check getNumSuccessors().4454 EXPECT_EQ(Switch->getNumSuccessors(), LLVMSwitch->getNumSuccessors());4455 // Check getSuccessor().4456 for (auto SuccIdx : seq<unsigned>(0, Switch->getNumSuccessors()))4457 EXPECT_EQ(Switch->getSuccessor(SuccIdx),4458 Ctx.getValue(LLVMSwitch->getSuccessor(SuccIdx)));4459 // Check setSuccessor().4460 auto *OrigSucc = Switch->getSuccessor(0);4461 auto *NewSucc = Entry;4462 EXPECT_NE(NewSucc, OrigSucc);4463 Switch->setSuccessor(0, NewSucc);4464 EXPECT_EQ(Switch->getSuccessor(0), NewSucc);4465 Switch->setSuccessor(0, OrigSucc);4466 EXPECT_EQ(Switch->getSuccessor(0), OrigSucc);4467 // Check case_begin(), case_end(), CaseIt.4468 auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);4469 auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1);4470 auto CaseIt = Switch->case_begin();4471 {4472 sandboxir::SwitchInst::CaseHandle Case = *CaseIt++;4473 EXPECT_EQ(Case.getCaseValue(), Zero);4474 EXPECT_EQ(Case.getCaseSuccessor(), BB0);4475 EXPECT_EQ(Case.getCaseIndex(), 0u);4476 EXPECT_EQ(Case.getSuccessorIndex(), 1u);4477 }4478 {4479 sandboxir::SwitchInst::CaseHandle Case = *CaseIt++;4480 EXPECT_EQ(Case.getCaseValue(), One);4481 EXPECT_EQ(Case.getCaseSuccessor(), BB1);4482 EXPECT_EQ(Case.getCaseIndex(), 1u);4483 EXPECT_EQ(Case.getSuccessorIndex(), 2u);4484 }4485 EXPECT_EQ(CaseIt, Switch->case_end());4486 // Check cases().4487 unsigned CntCase = 0;4488 for (auto &Case : Switch->cases()) {4489 EXPECT_EQ(Case.getCaseIndex(), CntCase);4490 ++CntCase;4491 }4492 EXPECT_EQ(CntCase, 2u);4493 // Check case_default().4494 auto CaseDefault = *Switch->case_default();4495 EXPECT_EQ(CaseDefault.getCaseSuccessor(), Default);4496 EXPECT_EQ(CaseDefault.getCaseIndex(),4497 sandboxir::SwitchInst::DefaultPseudoIndex);4498 // Check findCaseValue().4499 EXPECT_EQ(Switch->findCaseValue(Zero)->getCaseIndex(), 0u);4500 EXPECT_EQ(Switch->findCaseValue(One)->getCaseIndex(), 1u);4501 // Check findCaseDest().4502 EXPECT_EQ(Switch->findCaseDest(BB0), Zero);4503 EXPECT_EQ(Switch->findCaseDest(BB1), One);4504 EXPECT_EQ(Switch->findCaseDest(Entry), nullptr);4505 // Check addCase().4506 auto *Two = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 2);4507 Switch->addCase(Two, Entry);4508 auto CaseTwoIt = Switch->findCaseValue(Two);4509 auto CaseTwo = *CaseTwoIt;4510 EXPECT_EQ(CaseTwo.getCaseValue(), Two);4511 EXPECT_EQ(CaseTwo.getCaseSuccessor(), Entry);4512 EXPECT_EQ(Switch->getNumCases(), 3u);4513 // Check removeCase().4514 auto RemovedIt = Switch->removeCase(CaseTwoIt);4515 EXPECT_EQ(RemovedIt, Switch->case_end());4516 EXPECT_EQ(Switch->getNumCases(), 2u);4517 // Check create().4518 auto NewSwitch = sandboxir::SwitchInst::create(4519 Cond1, Default, 1, Default->begin(), Ctx, "NewSwitch");4520 EXPECT_TRUE(isa<sandboxir::SwitchInst>(NewSwitch));4521 EXPECT_EQ(NewSwitch->getCondition(), Cond1);4522 EXPECT_EQ(NewSwitch->getDefaultDest(), Default);4523}4524 4525TEST_F(SandboxIRTest, UnaryOperator) {4526 parseIR(C, R"IR(4527define void @foo(float %arg0) {4528 %fneg = fneg float %arg04529 %copyfrom = fadd reassoc float %arg0, 42.04530 ret void4531}4532)IR");4533 Function &LLVMF = *M->getFunction("foo");4534 sandboxir::Context Ctx(C);4535 4536 auto &F = *Ctx.createFunction(&LLVMF);4537 auto *Arg0 = F.getArg(0);4538 auto *BB = &*F.begin();4539 auto It = BB->begin();4540 auto *I = cast<sandboxir::UnaryOperator>(&*It++);4541 auto *CopyFrom = cast<sandboxir::BinaryOperator>(&*It++);4542 auto *Ret = &*It++;4543 EXPECT_EQ(I->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4544 EXPECT_EQ(I->getOperand(0), Arg0);4545 4546 {4547 // Check create() WhereIt, WhereBB.4548 auto *NewI =4549 cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create(4550 sandboxir::Instruction::Opcode::FNeg, Arg0, Ret->getIterator(), Ctx,4551 "New1"));4552 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4553 EXPECT_EQ(NewI->getOperand(0), Arg0);4554#ifndef NDEBUG4555 EXPECT_EQ(NewI->getName(), "New1");4556#endif // NDEBUG4557 EXPECT_EQ(NewI->getNextNode(), Ret);4558 }4559 {4560 // Check create() InsertBefore.4561 auto *NewI =4562 cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create(4563 sandboxir::Instruction::Opcode::FNeg, Arg0, Ret->getIterator(), Ctx,4564 "New2"));4565 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4566 EXPECT_EQ(NewI->getOperand(0), Arg0);4567#ifndef NDEBUG4568 EXPECT_EQ(NewI->getName(), "New2");4569#endif // NDEBUG4570 EXPECT_EQ(NewI->getNextNode(), Ret);4571 }4572 {4573 // Check create() InsertAtEnd.4574 auto *NewI =4575 cast<sandboxir::UnaryOperator>(sandboxir::UnaryOperator::create(4576 sandboxir::Instruction::Opcode::FNeg, Arg0, BB, Ctx, "New3"));4577 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4578 EXPECT_EQ(NewI->getOperand(0), Arg0);4579#ifndef NDEBUG4580 EXPECT_EQ(NewI->getName(), "New3");4581#endif // NDEBUG4582 EXPECT_EQ(NewI->getParent(), BB);4583 EXPECT_EQ(NewI->getNextNode(), nullptr);4584 }4585 {4586 // Check create() when it gets folded.4587 auto *FortyTwo = CopyFrom->getOperand(1);4588 auto *NewV = sandboxir::UnaryOperator::create(4589 sandboxir::Instruction::Opcode::FNeg, FortyTwo, Ret->getIterator(), Ctx,4590 "Folded");4591 EXPECT_TRUE(isa<sandboxir::Constant>(NewV));4592 }4593 4594 {4595 // Check createWithCopiedFlags() WhereIt, WhereBB.4596 auto *NewI = cast<sandboxir::UnaryOperator>(4597 sandboxir::UnaryOperator::createWithCopiedFlags(4598 sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom,4599 Ret->getIterator(), Ctx, "NewCopyFrom1"));4600 EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc());4601 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4602 EXPECT_EQ(NewI->getOperand(0), Arg0);4603#ifndef NDEBUG4604 EXPECT_EQ(NewI->getName(), "NewCopyFrom1");4605#endif // NDEBUG4606 EXPECT_EQ(NewI->getNextNode(), Ret);4607 }4608 {4609 // Check createWithCopiedFlags() InsertBefore,4610 auto *NewI = cast<sandboxir::UnaryOperator>(4611 sandboxir::UnaryOperator::createWithCopiedFlags(4612 sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom,4613 Ret->getIterator(), Ctx, "NewCopyFrom2"));4614 EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc());4615 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4616 EXPECT_EQ(NewI->getOperand(0), Arg0);4617#ifndef NDEBUG4618 EXPECT_EQ(NewI->getName(), "NewCopyFrom2");4619#endif // NDEBUG4620 EXPECT_EQ(NewI->getNextNode(), Ret);4621 }4622 {4623 // Check createWithCopiedFlags() InsertAtEnd,4624 auto *NewI = cast<sandboxir::UnaryOperator>(4625 sandboxir::UnaryOperator::createWithCopiedFlags(4626 sandboxir::Instruction::Opcode::FNeg, Arg0, CopyFrom, BB, Ctx,4627 "NewCopyFrom3"));4628 EXPECT_EQ(NewI->hasAllowReassoc(), CopyFrom->hasAllowReassoc());4629 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::FNeg);4630 EXPECT_EQ(NewI->getOperand(0), Arg0);4631#ifndef NDEBUG4632 EXPECT_EQ(NewI->getName(), "NewCopyFrom3");4633#endif // NDEBUG4634 EXPECT_EQ(NewI->getParent(), BB);4635 EXPECT_EQ(NewI->getNextNode(), nullptr);4636 }4637 {4638 // Check createWithCopiedFlags() when it gets folded.4639 auto *FortyTwo = CopyFrom->getOperand(1);4640 auto *NewV = sandboxir::UnaryOperator::createWithCopiedFlags(4641 sandboxir::Instruction::Opcode::FNeg, FortyTwo, CopyFrom, BB, Ctx,4642 "Folded");4643 EXPECT_TRUE(isa<sandboxir::Constant>(NewV));4644 }4645}4646 4647TEST_F(SandboxIRTest, BinaryOperator) {4648 parseIR(C, R"IR(4649define void @foo(i8 %arg0, i8 %arg1, float %farg0, float %farg1) {4650 %add = add i8 %arg0, %arg14651 %fadd = fadd float %farg0, %farg14652 %sub = sub i8 %arg0, %arg14653 %fsub = fsub float %farg0, %farg14654 %mul = mul i8 %arg0, %arg14655 %fmul = fmul float %farg0, %farg14656 %udiv = udiv i8 %arg0, %arg14657 %sdiv = sdiv i8 %arg0, %arg14658 %fdiv = fdiv float %farg0, %farg14659 %urem = urem i8 %arg0, %arg14660 %srem = srem i8 %arg0, %arg14661 %frem = frem float %farg0, %farg14662 %shl = shl i8 %arg0, %arg14663 %lshr = lshr i8 %arg0, %arg14664 %ashr = ashr i8 %arg0, %arg14665 %and = and i8 %arg0, %arg14666 %or = or i8 %arg0, %arg14667 %xor = xor i8 %arg0, %arg14668 4669 %copyfrom = add nsw i8 %arg0, %arg14670 ret void4671}4672)IR");4673 Function &LLVMF = *M->getFunction("foo");4674 sandboxir::Context Ctx(C);4675 4676 auto &F = *Ctx.createFunction(&LLVMF);4677 auto *Arg0 = F.getArg(0);4678 auto *Arg1 = F.getArg(1);4679 auto *FArg0 = F.getArg(2);4680 auto *FArg1 = F.getArg(3);4681 auto *BB = &*F.begin();4682 auto It = BB->begin();4683 4684#define CHECK_IBINOP(OPCODE) \4685 { \4686 auto *I = cast<sandboxir::BinaryOperator>(&*It++); \4687 EXPECT_EQ(I->getOpcode(), OPCODE); \4688 EXPECT_EQ(I->getOperand(0), Arg0); \4689 EXPECT_EQ(I->getOperand(1), Arg1); \4690 }4691#define CHECK_FBINOP(OPCODE) \4692 { \4693 auto *I = cast<sandboxir::BinaryOperator>(&*It++); \4694 EXPECT_EQ(I->getOpcode(), OPCODE); \4695 EXPECT_EQ(I->getOperand(0), FArg0); \4696 EXPECT_EQ(I->getOperand(1), FArg1); \4697 }4698 4699 CHECK_IBINOP(sandboxir::Instruction::Opcode::Add);4700 CHECK_FBINOP(sandboxir::Instruction::Opcode::FAdd);4701 CHECK_IBINOP(sandboxir::Instruction::Opcode::Sub);4702 CHECK_FBINOP(sandboxir::Instruction::Opcode::FSub);4703 CHECK_IBINOP(sandboxir::Instruction::Opcode::Mul);4704 CHECK_FBINOP(sandboxir::Instruction::Opcode::FMul);4705 CHECK_IBINOP(sandboxir::Instruction::Opcode::UDiv);4706 CHECK_IBINOP(sandboxir::Instruction::Opcode::SDiv);4707 CHECK_FBINOP(sandboxir::Instruction::Opcode::FDiv);4708 CHECK_IBINOP(sandboxir::Instruction::Opcode::URem);4709 CHECK_IBINOP(sandboxir::Instruction::Opcode::SRem);4710 CHECK_FBINOP(sandboxir::Instruction::Opcode::FRem);4711 CHECK_IBINOP(sandboxir::Instruction::Opcode::Shl);4712 CHECK_IBINOP(sandboxir::Instruction::Opcode::LShr);4713 CHECK_IBINOP(sandboxir::Instruction::Opcode::AShr);4714 CHECK_IBINOP(sandboxir::Instruction::Opcode::And);4715 CHECK_IBINOP(sandboxir::Instruction::Opcode::Or);4716 CHECK_IBINOP(sandboxir::Instruction::Opcode::Xor);4717 4718 auto *CopyFrom = cast<sandboxir::BinaryOperator>(&*It++);4719 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);4720 4721 {4722 // Check create() WhereIt, WhereBB.4723 auto *NewI =4724 cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create(4725 sandboxir::Instruction::Opcode::Add, Arg0, Arg1, Ret->getIterator(),4726 Ctx, "New1"));4727 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4728 EXPECT_EQ(NewI->getOperand(0), Arg0);4729 EXPECT_EQ(NewI->getOperand(1), Arg1);4730#ifndef NDEBUG4731 EXPECT_EQ(NewI->getName(), "New1");4732#endif // NDEBUG4733 EXPECT_EQ(NewI->getNextNode(), Ret);4734 }4735 {4736 // Check create() InsertBefore.4737 auto *NewI =4738 cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create(4739 sandboxir::Instruction::Opcode::Add, Arg0, Arg1, Ret->getIterator(),4740 Ctx, "New2"));4741 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4742 EXPECT_EQ(NewI->getOperand(0), Arg0);4743 EXPECT_EQ(NewI->getOperand(1), Arg1);4744#ifndef NDEBUG4745 EXPECT_EQ(NewI->getName(), "New2");4746#endif // NDEBUG4747 EXPECT_EQ(NewI->getNextNode(), Ret);4748 }4749 {4750 // Check create() InsertAtEnd.4751 auto *NewI =4752 cast<sandboxir::BinaryOperator>(sandboxir::BinaryOperator::create(4753 sandboxir::Instruction::Opcode::Add, Arg0, Arg1,4754 /*InsertAtEnd=*/BB, Ctx, "New3"));4755 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4756 EXPECT_EQ(NewI->getOperand(0), Arg0);4757 EXPECT_EQ(NewI->getOperand(1), Arg1);4758#ifndef NDEBUG4759 EXPECT_EQ(NewI->getName(), "New3");4760#endif // NDEBUG4761 EXPECT_EQ(NewI->getNextNode(), nullptr);4762 EXPECT_EQ(NewI->getParent(), BB);4763 }4764 {4765 // Check create() when it gets folded.4766 auto *FortyTwo =4767 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);4768 auto *NewV = sandboxir::BinaryOperator::create(4769 sandboxir::Instruction::Opcode::Add, FortyTwo, FortyTwo,4770 Ret->getIterator(), Ctx, "Folded");4771 EXPECT_TRUE(isa<sandboxir::Constant>(NewV));4772 }4773 4774 {4775 // Check createWithCopiedFlags() WhereIt, WhereBB.4776 auto *NewI = cast<sandboxir::BinaryOperator>(4777 sandboxir::BinaryOperator::createWithCopiedFlags(4778 sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom,4779 Ret->getIterator(), Ctx, "NewNSW1"));4780 EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap());4781 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4782 EXPECT_EQ(NewI->getOperand(0), Arg0);4783 EXPECT_EQ(NewI->getOperand(1), Arg1);4784#ifndef NDEBUG4785 EXPECT_EQ(NewI->getName(), "NewNSW1");4786#endif // NDEBUG4787 EXPECT_EQ(NewI->getNextNode(), Ret);4788 }4789 {4790 // Check createWithCopiedFlags() InsertBefore.4791 auto *NewI = cast<sandboxir::BinaryOperator>(4792 sandboxir::BinaryOperator::createWithCopiedFlags(4793 sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom,4794 Ret->getIterator(), Ctx, "NewNSW2"));4795 EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap());4796 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4797 EXPECT_EQ(NewI->getOperand(0), Arg0);4798 EXPECT_EQ(NewI->getOperand(1), Arg1);4799#ifndef NDEBUG4800 EXPECT_EQ(NewI->getName(), "NewNSW2");4801#endif // NDEBUG4802 EXPECT_EQ(NewI->getNextNode(), Ret);4803 }4804 {4805 // Check createWithCopiedFlags() InsertAtEnd.4806 auto *NewI = cast<sandboxir::BinaryOperator>(4807 sandboxir::BinaryOperator::createWithCopiedFlags(4808 sandboxir::Instruction::Opcode::Add, Arg0, Arg1, CopyFrom, BB, Ctx,4809 "NewNSW3"));4810 EXPECT_EQ(NewI->hasNoSignedWrap(), CopyFrom->hasNoSignedWrap());4811 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Add);4812 EXPECT_EQ(NewI->getOperand(0), Arg0);4813 EXPECT_EQ(NewI->getOperand(1), Arg1);4814#ifndef NDEBUG4815 EXPECT_EQ(NewI->getName(), "NewNSW3");4816#endif // NDEBUG4817 EXPECT_EQ(NewI->getParent(), BB);4818 EXPECT_EQ(NewI->getNextNode(), nullptr);4819 }4820 {4821 // Check createWithCopiedFlags() when it gets folded.4822 auto *FortyTwo =4823 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);4824 auto *NewV = sandboxir::BinaryOperator::createWithCopiedFlags(4825 sandboxir::Instruction::Opcode::Add, FortyTwo, FortyTwo, CopyFrom,4826 Ret->getIterator(), Ctx, "Folded");4827 EXPECT_TRUE(isa<sandboxir::Constant>(NewV));4828 }4829}4830 4831TEST_F(SandboxIRTest, PossiblyDisjointInst) {4832 parseIR(C, R"IR(4833define void @foo(i8 %arg0, i8 %arg1) {4834 %or = or i8 %arg0, %arg14835 ret void4836}4837)IR");4838 Function &LLVMF = *M->getFunction("foo");4839 sandboxir::Context Ctx(C);4840 4841 auto &F = *Ctx.createFunction(&LLVMF);4842 auto *BB = &*F.begin();4843 auto It = BB->begin();4844 auto *PDI = cast<sandboxir::PossiblyDisjointInst>(&*It++);4845 4846 // Check setIsDisjoint(), isDisjoint().4847 auto OrigIsDisjoint = PDI->isDisjoint();4848 auto NewIsDisjoint = true;4849 EXPECT_NE(NewIsDisjoint, OrigIsDisjoint);4850 PDI->setIsDisjoint(NewIsDisjoint);4851 EXPECT_EQ(PDI->isDisjoint(), NewIsDisjoint);4852 PDI->setIsDisjoint(OrigIsDisjoint);4853 EXPECT_EQ(PDI->isDisjoint(), OrigIsDisjoint);4854}4855 4856TEST_F(SandboxIRTest, AtomicRMWInst) {4857 parseIR(C, R"IR(4858define void @foo(ptr %ptr, i8 %arg) {4859 %atomicrmw = atomicrmw add ptr %ptr, i8 %arg acquire, align 1284860 ret void4861}4862)IR");4863 llvm::Function &LLVMF = *M->getFunction("foo");4864 llvm::BasicBlock *LLVMBB = &*LLVMF.begin();4865 auto LLVMIt = LLVMBB->begin();4866 auto *LLVMRMW = cast<llvm::AtomicRMWInst>(&*LLVMIt++);4867 4868 sandboxir::Context Ctx(C);4869 sandboxir::Function *F = Ctx.createFunction(&LLVMF);4870 auto *Ptr = F->getArg(0);4871 auto *Arg = F->getArg(1);4872 auto *BB = &*F->begin();4873 auto It = BB->begin();4874 auto *RMW = cast<sandboxir::AtomicRMWInst>(&*It++);4875 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);4876 4877 // Check getOperationName().4878 EXPECT_EQ(4879 sandboxir::AtomicRMWInst::getOperationName(4880 sandboxir::AtomicRMWInst::BinOp::Add),4881 llvm::AtomicRMWInst::getOperationName(llvm::AtomicRMWInst::BinOp::Add));4882 // Check isFPOperation().4883 EXPECT_EQ(4884 sandboxir::AtomicRMWInst::isFPOperation(4885 sandboxir::AtomicRMWInst::BinOp::Add),4886 llvm::AtomicRMWInst::isFPOperation(llvm::AtomicRMWInst::BinOp::Add));4887 EXPECT_FALSE(sandboxir::AtomicRMWInst::isFPOperation(4888 sandboxir::AtomicRMWInst::BinOp::Add));4889 EXPECT_TRUE(sandboxir::AtomicRMWInst::isFPOperation(4890 sandboxir::AtomicRMWInst::BinOp::FAdd));4891 // Check setOperation(), getOperation().4892 EXPECT_EQ(RMW->getOperation(), LLVMRMW->getOperation());4893 RMW->setOperation(sandboxir::AtomicRMWInst::BinOp::Sub);4894 EXPECT_EQ(RMW->getOperation(), sandboxir::AtomicRMWInst::BinOp::Sub);4895 RMW->setOperation(sandboxir::AtomicRMWInst::BinOp::Add);4896 // Check getAlign().4897 EXPECT_EQ(RMW->getAlign(), LLVMRMW->getAlign());4898 auto OrigAlign = RMW->getAlign();4899 Align NewAlign(256);4900 EXPECT_NE(NewAlign, OrigAlign);4901 RMW->setAlignment(NewAlign);4902 EXPECT_EQ(RMW->getAlign(), NewAlign);4903 RMW->setAlignment(OrigAlign);4904 EXPECT_EQ(RMW->getAlign(), OrigAlign);4905 // Check isVolatile(), setVolatile().4906 EXPECT_EQ(RMW->isVolatile(), LLVMRMW->isVolatile());4907 bool OrigV = RMW->isVolatile();4908 bool NewV = true;4909 EXPECT_NE(NewV, OrigV);4910 RMW->setVolatile(NewV);4911 EXPECT_EQ(RMW->isVolatile(), NewV);4912 RMW->setVolatile(OrigV);4913 EXPECT_EQ(RMW->isVolatile(), OrigV);4914 // Check getOrdering(), setOrdering().4915 EXPECT_EQ(RMW->getOrdering(), LLVMRMW->getOrdering());4916 auto OldOrdering = RMW->getOrdering();4917 auto NewOrdering = AtomicOrdering::Monotonic;4918 EXPECT_NE(NewOrdering, OldOrdering);4919 RMW->setOrdering(NewOrdering);4920 EXPECT_EQ(RMW->getOrdering(), NewOrdering);4921 RMW->setOrdering(OldOrdering);4922 EXPECT_EQ(RMW->getOrdering(), OldOrdering);4923 // Check getSyncScopeID(), setSyncScopeID().4924 EXPECT_EQ(RMW->getSyncScopeID(), LLVMRMW->getSyncScopeID());4925 auto OrigSSID = RMW->getSyncScopeID();4926 SyncScope::ID NewSSID = SyncScope::SingleThread;4927 EXPECT_NE(NewSSID, OrigSSID);4928 RMW->setSyncScopeID(NewSSID);4929 EXPECT_EQ(RMW->getSyncScopeID(), NewSSID);4930 RMW->setSyncScopeID(OrigSSID);4931 EXPECT_EQ(RMW->getSyncScopeID(), OrigSSID);4932 // Check getPointerOperand().4933 EXPECT_EQ(RMW->getPointerOperand(),4934 Ctx.getValue(LLVMRMW->getPointerOperand()));4935 // Check getValOperand().4936 EXPECT_EQ(RMW->getValOperand(), Ctx.getValue(LLVMRMW->getValOperand()));4937 // Check getPointerAddressSpace().4938 EXPECT_EQ(RMW->getPointerAddressSpace(), LLVMRMW->getPointerAddressSpace());4939 // Check isFloatingPointOperation().4940 EXPECT_EQ(RMW->isFloatingPointOperation(),4941 LLVMRMW->isFloatingPointOperation());4942 4943 Align Align(1024);4944 auto Ordering = AtomicOrdering::Acquire;4945 auto SSID = SyncScope::System;4946 {4947 // Check create() WhereIt, WhereBB.4948 auto *NewI =4949 cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create(4950 sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering,4951 Ret->getIterator(), Ctx, SSID, "NewAtomicRMW1"));4952 // Check getOpcode().4953 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW);4954 // Check getAlign().4955 EXPECT_EQ(NewI->getAlign(), Align);4956 // Check getSuccessOrdering().4957 EXPECT_EQ(NewI->getOrdering(), Ordering);4958 // Check instr position.4959 EXPECT_EQ(NewI->getNextNode(), Ret);4960 // Check getPointerOperand().4961 EXPECT_EQ(NewI->getPointerOperand(), Ptr);4962 // Check getValOperand().4963 EXPECT_EQ(NewI->getValOperand(), Arg);4964#ifndef NDEBUG4965 // Check getName().4966 EXPECT_EQ(NewI->getName(), "NewAtomicRMW1");4967#endif // NDEBUG4968 }4969 {4970 // Check create() InsertBefore.4971 auto *NewI =4972 cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create(4973 sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering,4974 Ret->getIterator(), Ctx, SSID, "NewAtomicRMW2"));4975 // Check getOpcode().4976 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW);4977 // Check getAlign().4978 EXPECT_EQ(NewI->getAlign(), Align);4979 // Check getSuccessOrdering().4980 EXPECT_EQ(NewI->getOrdering(), Ordering);4981 // Check instr position.4982 EXPECT_EQ(NewI->getNextNode(), Ret);4983 // Check getPointerOperand().4984 EXPECT_EQ(NewI->getPointerOperand(), Ptr);4985 // Check getValOperand().4986 EXPECT_EQ(NewI->getValOperand(), Arg);4987#ifndef NDEBUG4988 // Check getName().4989 EXPECT_EQ(NewI->getName(), "NewAtomicRMW2");4990#endif // NDEBUG4991 }4992 {4993 // Check create() InsertAtEnd.4994 auto *NewI =4995 cast<sandboxir::AtomicRMWInst>(sandboxir::AtomicRMWInst::create(4996 sandboxir::AtomicRMWInst::BinOp::Sub, Ptr, Arg, Align, Ordering, BB,4997 Ctx, SSID, "NewAtomicRMW3"));4998 // Check getOpcode().4999 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicRMW);5000 // Check getAlign().5001 EXPECT_EQ(NewI->getAlign(), Align);5002 // Check getSuccessOrdering().5003 EXPECT_EQ(NewI->getOrdering(), Ordering);5004 // Check instr position.5005 EXPECT_EQ(NewI->getParent(), BB);5006 EXPECT_EQ(NewI->getNextNode(), nullptr);5007 // Check getPointerOperand().5008 EXPECT_EQ(NewI->getPointerOperand(), Ptr);5009 // Check getValOperand().5010 EXPECT_EQ(NewI->getValOperand(), Arg);5011#ifndef NDEBUG5012 // Check getName().5013 EXPECT_EQ(NewI->getName(), "NewAtomicRMW3");5014#endif // NDEBUG5015 }5016}5017 5018TEST_F(SandboxIRTest, AtomicCmpXchgInst) {5019 parseIR(C, R"IR(5020define void @foo(ptr %ptr, i8 %cmp, i8 %new) {5021 %cmpxchg = cmpxchg ptr %ptr, i8 %cmp, i8 %new monotonic monotonic, align 1285022 ret void5023}5024)IR");5025 llvm::Function &LLVMF = *M->getFunction("foo");5026 llvm::BasicBlock *LLVMBB = &*LLVMF.begin();5027 auto LLVMIt = LLVMBB->begin();5028 auto *LLVMCmpXchg = cast<llvm::AtomicCmpXchgInst>(&*LLVMIt++);5029 5030 sandboxir::Context Ctx(C);5031 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5032 auto *Ptr = F->getArg(0);5033 auto *Cmp = F->getArg(1);5034 auto *New = F->getArg(2);5035 auto *BB = &*F->begin();5036 auto It = BB->begin();5037 auto *CmpXchg = cast<sandboxir::AtomicCmpXchgInst>(&*It++);5038 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);5039 5040 // Check getAlign(), setAlignment().5041 EXPECT_EQ(CmpXchg->getAlign(), LLVMCmpXchg->getAlign());5042 auto OrigAlign = CmpXchg->getAlign();5043 Align NewAlign(256);5044 EXPECT_NE(NewAlign, OrigAlign);5045 CmpXchg->setAlignment(NewAlign);5046 EXPECT_EQ(CmpXchg->getAlign(), NewAlign);5047 CmpXchg->setAlignment(OrigAlign);5048 EXPECT_EQ(CmpXchg->getAlign(), OrigAlign);5049 // Check isVolatile(), setVolatile().5050 EXPECT_EQ(CmpXchg->isVolatile(), LLVMCmpXchg->isVolatile());5051 bool OrigV = CmpXchg->isVolatile();5052 bool NewV = true;5053 EXPECT_NE(NewV, OrigV);5054 CmpXchg->setVolatile(NewV);5055 EXPECT_EQ(CmpXchg->isVolatile(), NewV);5056 CmpXchg->setVolatile(OrigV);5057 EXPECT_EQ(CmpXchg->isVolatile(), OrigV);5058 // Check isWeak(), setWeak().5059 EXPECT_EQ(CmpXchg->isWeak(), LLVMCmpXchg->isWeak());5060 bool OrigWeak = CmpXchg->isWeak();5061 bool NewWeak = true;5062 EXPECT_NE(NewWeak, OrigWeak);5063 CmpXchg->setWeak(NewWeak);5064 EXPECT_EQ(CmpXchg->isWeak(), NewWeak);5065 CmpXchg->setWeak(OrigWeak);5066 EXPECT_EQ(CmpXchg->isWeak(), OrigWeak);5067 // Check isValidSuccessOrdering(), isValidFailureOrdering().5068 SmallVector<AtomicOrdering> AllOrderings(5069 {AtomicOrdering::NotAtomic, AtomicOrdering::Unordered,5070 AtomicOrdering::Monotonic, AtomicOrdering::Acquire,5071 AtomicOrdering::Release, AtomicOrdering::AcquireRelease,5072 AtomicOrdering::SequentiallyConsistent});5073 for (auto Ordering : AllOrderings) {5074 EXPECT_EQ(sandboxir::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering),5075 llvm::AtomicCmpXchgInst::isValidSuccessOrdering(Ordering));5076 EXPECT_EQ(sandboxir::AtomicCmpXchgInst::isValidFailureOrdering(Ordering),5077 llvm::AtomicCmpXchgInst::isValidFailureOrdering(Ordering));5078 }5079 // Check getSuccessOrdering(), setSuccessOrdering().5080 EXPECT_EQ(CmpXchg->getSuccessOrdering(), LLVMCmpXchg->getSuccessOrdering());5081 auto OldSuccOrdering = CmpXchg->getSuccessOrdering();5082 auto NewSuccOrdering = AtomicOrdering::Acquire;5083 EXPECT_NE(NewSuccOrdering, OldSuccOrdering);5084 CmpXchg->setSuccessOrdering(NewSuccOrdering);5085 EXPECT_EQ(CmpXchg->getSuccessOrdering(), NewSuccOrdering);5086 CmpXchg->setSuccessOrdering(OldSuccOrdering);5087 EXPECT_EQ(CmpXchg->getSuccessOrdering(), OldSuccOrdering);5088 // Check getFailureOrdering(), setFailureOrdering().5089 EXPECT_EQ(CmpXchg->getFailureOrdering(), LLVMCmpXchg->getFailureOrdering());5090 auto OldFailOrdering = CmpXchg->getFailureOrdering();5091 auto NewFailOrdering = AtomicOrdering::Acquire;5092 EXPECT_NE(NewFailOrdering, OldFailOrdering);5093 CmpXchg->setFailureOrdering(NewFailOrdering);5094 EXPECT_EQ(CmpXchg->getFailureOrdering(), NewFailOrdering);5095 CmpXchg->setFailureOrdering(OldFailOrdering);5096 EXPECT_EQ(CmpXchg->getFailureOrdering(), OldFailOrdering);5097 // Check getMergedOrdering().5098 EXPECT_EQ(CmpXchg->getMergedOrdering(), LLVMCmpXchg->getMergedOrdering());5099 // Check getSyncScopeID(), setSyncScopeID().5100 EXPECT_EQ(CmpXchg->getSyncScopeID(), LLVMCmpXchg->getSyncScopeID());5101 auto OrigSSID = CmpXchg->getSyncScopeID();5102 SyncScope::ID NewSSID = SyncScope::SingleThread;5103 EXPECT_NE(NewSSID, OrigSSID);5104 CmpXchg->setSyncScopeID(NewSSID);5105 EXPECT_EQ(CmpXchg->getSyncScopeID(), NewSSID);5106 CmpXchg->setSyncScopeID(OrigSSID);5107 EXPECT_EQ(CmpXchg->getSyncScopeID(), OrigSSID);5108 // Check getPointerOperand().5109 EXPECT_EQ(CmpXchg->getPointerOperand(),5110 Ctx.getValue(LLVMCmpXchg->getPointerOperand()));5111 // Check getCompareOperand().5112 EXPECT_EQ(CmpXchg->getCompareOperand(),5113 Ctx.getValue(LLVMCmpXchg->getCompareOperand()));5114 // Check getNewValOperand().5115 EXPECT_EQ(CmpXchg->getNewValOperand(),5116 Ctx.getValue(LLVMCmpXchg->getNewValOperand()));5117 // Check getPointerAddressSpace().5118 EXPECT_EQ(CmpXchg->getPointerAddressSpace(),5119 LLVMCmpXchg->getPointerAddressSpace());5120 5121 Align Align(1024);5122 auto SuccOrdering = AtomicOrdering::Acquire;5123 auto FailOrdering = AtomicOrdering::Monotonic;5124 auto SSID = SyncScope::System;5125 {5126 // Check create() WhereIt, WhereBB.5127 auto *NewI =5128 cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create(5129 Ptr, Cmp, New, Align, SuccOrdering, FailOrdering,5130 Ret->getIterator(), Ctx, SSID, "NewAtomicCmpXchg1"));5131 // Check getOpcode().5132 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg);5133 // Check getAlign().5134 EXPECT_EQ(NewI->getAlign(), Align);5135 // Check getSuccessOrdering().5136 EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering);5137 // Check getFailureOrdering().5138 EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering);5139 // Check instr position.5140 EXPECT_EQ(NewI->getNextNode(), Ret);5141 // Check getPointerOperand().5142 EXPECT_EQ(NewI->getPointerOperand(), Ptr);5143 // Check getCompareOperand().5144 EXPECT_EQ(NewI->getCompareOperand(), Cmp);5145 // Check getNewValOperand().5146 EXPECT_EQ(NewI->getNewValOperand(), New);5147#ifndef NDEBUG5148 // Check getName().5149 EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg1");5150#endif // NDEBUG5151 }5152 {5153 // Check create() InsertBefore.5154 auto *NewI =5155 cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create(5156 Ptr, Cmp, New, Align, SuccOrdering, FailOrdering,5157 Ret->getIterator(), Ctx, SSID, "NewAtomicCmpXchg2"));5158 // Check getOpcode().5159 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg);5160 // Check getAlign().5161 EXPECT_EQ(NewI->getAlign(), Align);5162 // Check getSuccessOrdering().5163 EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering);5164 // Check getFailureOrdering().5165 EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering);5166 // Check instr position.5167 EXPECT_EQ(NewI->getNextNode(), Ret);5168 // Check getPointerOperand().5169 EXPECT_EQ(NewI->getPointerOperand(), Ptr);5170 // Check getCompareOperand().5171 EXPECT_EQ(NewI->getCompareOperand(), Cmp);5172 // Check getNewValOperand().5173 EXPECT_EQ(NewI->getNewValOperand(), New);5174#ifndef NDEBUG5175 // Check getName().5176 EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg2");5177#endif // NDEBUG5178 }5179 {5180 // Check create() InsertAtEnd.5181 auto *NewI =5182 cast<sandboxir::AtomicCmpXchgInst>(sandboxir::AtomicCmpXchgInst::create(5183 Ptr, Cmp, New, Align, SuccOrdering, FailOrdering, BB, Ctx, SSID,5184 "NewAtomicCmpXchg3"));5185 // Check getOpcode().5186 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::AtomicCmpXchg);5187 // Check getAlign().5188 EXPECT_EQ(NewI->getAlign(), Align);5189 // Check getSuccessOrdering().5190 EXPECT_EQ(NewI->getSuccessOrdering(), SuccOrdering);5191 // Check getFailureOrdering().5192 EXPECT_EQ(NewI->getFailureOrdering(), FailOrdering);5193 // Check instr position.5194 EXPECT_EQ(NewI->getParent(), BB);5195 EXPECT_EQ(NewI->getNextNode(), nullptr);5196 // Check getPointerOperand().5197 EXPECT_EQ(NewI->getPointerOperand(), Ptr);5198 // Check getCompareOperand().5199 EXPECT_EQ(NewI->getCompareOperand(), Cmp);5200 // Check getNewValOperand().5201 EXPECT_EQ(NewI->getNewValOperand(), New);5202#ifndef NDEBUG5203 // Check getName().5204 EXPECT_EQ(NewI->getName(), "NewAtomicCmpXchg3");5205#endif // NDEBUG5206 }5207}5208 5209TEST_F(SandboxIRTest, AllocaInst) {5210 parseIR(C, R"IR(5211define void @foo() {5212 %allocaScalar = alloca i32, align 10245213 %allocaArray = alloca i32, i32 425214 ret void5215}5216)IR");5217 const DataLayout &DL = M->getDataLayout();5218 llvm::Function &LLVMF = *M->getFunction("foo");5219 llvm::BasicBlock *LLVMBB = &*LLVMF.begin();5220 auto LLVMIt = LLVMBB->begin();5221 auto *LLVMAllocaScalar = cast<llvm::AllocaInst>(&*LLVMIt++);5222 auto *LLVMAllocaArray = cast<llvm::AllocaInst>(&*LLVMIt++);5223 5224 sandboxir::Context Ctx(C);5225 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5226 auto *BB = &*F->begin();5227 auto It = BB->begin();5228 auto *AllocaScalar = cast<sandboxir::AllocaInst>(&*It++);5229 auto *AllocaArray = cast<sandboxir::AllocaInst>(&*It++);5230 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);5231 5232 // Check isArrayAllocation().5233 EXPECT_EQ(AllocaScalar->isArrayAllocation(),5234 LLVMAllocaScalar->isArrayAllocation());5235 EXPECT_EQ(AllocaArray->isArrayAllocation(),5236 LLVMAllocaArray->isArrayAllocation());5237 // Check getArraySize().5238 EXPECT_EQ(AllocaScalar->getArraySize(),5239 Ctx.getValue(LLVMAllocaScalar->getArraySize()));5240 EXPECT_EQ(AllocaArray->getArraySize(),5241 Ctx.getValue(LLVMAllocaArray->getArraySize()));5242 // Check getType().5243 EXPECT_EQ(AllocaScalar->getType(), Ctx.getType(LLVMAllocaScalar->getType()));5244 EXPECT_EQ(AllocaArray->getType(), Ctx.getType(LLVMAllocaArray->getType()));5245 // Check getAddressSpace().5246 EXPECT_EQ(AllocaScalar->getAddressSpace(),5247 LLVMAllocaScalar->getAddressSpace());5248 EXPECT_EQ(AllocaArray->getAddressSpace(), LLVMAllocaArray->getAddressSpace());5249 // Check getAllocationSize().5250 EXPECT_EQ(AllocaScalar->getAllocationSize(DL),5251 LLVMAllocaScalar->getAllocationSize(DL));5252 EXPECT_EQ(AllocaArray->getAllocationSize(DL),5253 LLVMAllocaArray->getAllocationSize(DL));5254 // Check getAllocationSizeInBits().5255 EXPECT_EQ(AllocaScalar->getAllocationSizeInBits(DL),5256 LLVMAllocaScalar->getAllocationSizeInBits(DL));5257 EXPECT_EQ(AllocaArray->getAllocationSizeInBits(DL),5258 LLVMAllocaArray->getAllocationSizeInBits(DL));5259 // Check getAllocatedType().5260 EXPECT_EQ(AllocaScalar->getAllocatedType(),5261 Ctx.getType(LLVMAllocaScalar->getAllocatedType()));5262 EXPECT_EQ(AllocaArray->getAllocatedType(),5263 Ctx.getType(LLVMAllocaArray->getAllocatedType()));5264 // Check setAllocatedType().5265 auto *OrigType = AllocaScalar->getAllocatedType();5266 auto *NewType = sandboxir::PointerType::get(Ctx, 0);5267 EXPECT_NE(NewType, OrigType);5268 AllocaScalar->setAllocatedType(NewType);5269 EXPECT_EQ(AllocaScalar->getAllocatedType(), NewType);5270 AllocaScalar->setAllocatedType(OrigType);5271 EXPECT_EQ(AllocaScalar->getAllocatedType(), OrigType);5272 // Check getAlign().5273 EXPECT_EQ(AllocaScalar->getAlign(), LLVMAllocaScalar->getAlign());5274 EXPECT_EQ(AllocaArray->getAlign(), LLVMAllocaArray->getAlign());5275 // Check setAlignment().5276 Align OrigAlign = AllocaScalar->getAlign();5277 Align NewAlign(16);5278 EXPECT_NE(NewAlign, OrigAlign);5279 AllocaScalar->setAlignment(NewAlign);5280 EXPECT_EQ(AllocaScalar->getAlign(), NewAlign);5281 AllocaScalar->setAlignment(OrigAlign);5282 EXPECT_EQ(AllocaScalar->getAlign(), OrigAlign);5283 // Check isStaticAlloca().5284 EXPECT_EQ(AllocaScalar->isStaticAlloca(), LLVMAllocaScalar->isStaticAlloca());5285 EXPECT_EQ(AllocaArray->isStaticAlloca(), LLVMAllocaArray->isStaticAlloca());5286 // Check isUsedWithInAlloca(), setUsedWithInAlloca().5287 EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(),5288 LLVMAllocaScalar->isUsedWithInAlloca());5289 bool OrigUsedWithInAlloca = AllocaScalar->isUsedWithInAlloca();5290 bool NewUsedWithInAlloca = true;5291 EXPECT_NE(NewUsedWithInAlloca, OrigUsedWithInAlloca);5292 AllocaScalar->setUsedWithInAlloca(NewUsedWithInAlloca);5293 EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), NewUsedWithInAlloca);5294 AllocaScalar->setUsedWithInAlloca(OrigUsedWithInAlloca);5295 EXPECT_EQ(AllocaScalar->isUsedWithInAlloca(), OrigUsedWithInAlloca);5296 5297 auto *Ty = sandboxir::Type::getInt32Ty(Ctx);5298 unsigned AddrSpace = 42;5299 auto *PtrTy = sandboxir::PointerType::get(Ctx, AddrSpace);5300 auto *ArraySize = sandboxir::ConstantInt::get(Ty, 43);5301 {5302 // Check create() WhereIt, WhereBB.5303 auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(5304 Ty, AddrSpace, Ret->getIterator(), Ctx, ArraySize, "NewAlloca1"));5305 // Check getOpcode().5306 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);5307 // Check getType().5308 EXPECT_EQ(NewI->getType(), PtrTy);5309 // Check getArraySize().5310 EXPECT_EQ(NewI->getArraySize(), ArraySize);5311 // Check getAddrSpace().5312 EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);5313 // Check instr position.5314 EXPECT_EQ(NewI->getNextNode(), Ret);5315 }5316 {5317 // Check create() InsertBefore.5318 auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(5319 Ty, AddrSpace, Ret->getIterator(), Ctx, ArraySize, "NewAlloca2"));5320 // Check getOpcode().5321 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);5322 // Check getType().5323 EXPECT_EQ(NewI->getType(), PtrTy);5324 // Check getArraySize().5325 EXPECT_EQ(NewI->getArraySize(), ArraySize);5326 // Check getAddrSpace().5327 EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);5328 // Check instr position.5329 EXPECT_EQ(NewI->getNextNode(), Ret);5330 }5331 {5332 // Check create() InsertAtEnd.5333 auto *NewI = cast<sandboxir::AllocaInst>(sandboxir::AllocaInst::create(5334 Ty, AddrSpace, BB, Ctx, ArraySize, "NewAlloca3"));5335 // Check getOpcode().5336 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::Alloca);5337 // Check getType().5338 EXPECT_EQ(NewI->getType(), PtrTy);5339 // Check getArraySize().5340 EXPECT_EQ(NewI->getArraySize(), ArraySize);5341 // Check getAddrSpace().5342 EXPECT_EQ(NewI->getAddressSpace(), AddrSpace);5343 // Check instr position.5344 EXPECT_EQ(NewI->getParent(), BB);5345 EXPECT_EQ(NewI->getNextNode(), nullptr);5346 }5347}5348 5349TEST_F(SandboxIRTest, CastInst) {5350 parseIR(C, R"IR(5351define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) {5352 %zext = zext i32 %arg to i645353 %sext = sext i32 %arg to i645354 %fptoui = fptoui float %farg to i325355 %fptosi = fptosi float %farg to i325356 %fpext = fpext float %farg to double5357 %ptrtoint = ptrtoint ptr %ptr to i325358 %inttoptr = inttoptr i32 %arg to ptr5359 %sitofp = sitofp i32 %arg to float5360 %uitofp = uitofp i32 %arg to float5361 %trunc = trunc i32 %arg to i165362 %fptrunc = fptrunc double %darg to float5363 %bitcast = bitcast i32 %arg to float5364 %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1)5365 ret void5366}5367)IR");5368 Function &LLVMF = *M->getFunction("foo");5369 sandboxir::Context Ctx(C);5370 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5371 unsigned ArgIdx = 0;5372 auto *Arg = F->getArg(ArgIdx++);5373 auto *BB = &*F->begin();5374 auto It = BB->begin();5375 5376 auto *Ti64 = sandboxir::Type::getInt64Ty(Ctx);5377 auto *Ti32 = sandboxir::Type::getInt32Ty(Ctx);5378 auto *Ti16 = sandboxir::Type::getInt16Ty(Ctx);5379 auto *Tdouble = sandboxir::Type::getDoubleTy(Ctx);5380 auto *Tfloat = sandboxir::Type::getFloatTy(Ctx);5381 auto *Tptr = sandboxir::PointerType::get(Ctx, 0);5382 auto *Tptr1 = sandboxir::PointerType::get(Ctx, 1);5383 5384 // Check classof(), getOpcode(), getSrcTy(), getDstTy()5385 auto *ZExt = cast<sandboxir::CastInst>(&*It++);5386 auto *ZExtI = cast<sandboxir::ZExtInst>(ZExt);5387 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(ZExtI));5388 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(ZExtI));5389 EXPECT_EQ(ZExt->getOpcode(), sandboxir::Instruction::Opcode::ZExt);5390 EXPECT_EQ(ZExt->getSrcTy(), Ti32);5391 EXPECT_EQ(ZExt->getDestTy(), Ti64);5392 5393 auto *SExt = cast<sandboxir::CastInst>(&*It++);5394 auto *SExtI = cast<sandboxir::SExtInst>(SExt);5395 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SExt));5396 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SExtI));5397 EXPECT_EQ(SExt->getOpcode(), sandboxir::Instruction::Opcode::SExt);5398 EXPECT_EQ(SExt->getSrcTy(), Ti32);5399 EXPECT_EQ(SExt->getDestTy(), Ti64);5400 5401 auto *FPToUI = cast<sandboxir::CastInst>(&*It++);5402 auto *FPToUII = cast<sandboxir::FPToUIInst>(FPToUI);5403 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToUI));5404 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToUII));5405 EXPECT_EQ(FPToUI->getOpcode(), sandboxir::Instruction::Opcode::FPToUI);5406 EXPECT_EQ(FPToUI->getSrcTy(), Tfloat);5407 EXPECT_EQ(FPToUI->getDestTy(), Ti32);5408 5409 auto *FPToSI = cast<sandboxir::CastInst>(&*It++);5410 auto *FPToSII = cast<sandboxir::FPToSIInst>(FPToSI);5411 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToSI));5412 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPToSII));5413 EXPECT_EQ(FPToSI->getOpcode(), sandboxir::Instruction::Opcode::FPToSI);5414 EXPECT_EQ(FPToSI->getSrcTy(), Tfloat);5415 EXPECT_EQ(FPToSI->getDestTy(), Ti32);5416 5417 auto *FPExt = cast<sandboxir::CastInst>(&*It++);5418 auto *FPExtI = cast<sandboxir::FPExtInst>(FPExt);5419 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPExt));5420 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPExtI));5421 EXPECT_EQ(FPExt->getOpcode(), sandboxir::Instruction::Opcode::FPExt);5422 EXPECT_EQ(FPExt->getSrcTy(), Tfloat);5423 EXPECT_EQ(FPExt->getDestTy(), Tdouble);5424 5425 auto *PtrToInt = cast<sandboxir::CastInst>(&*It++);5426 auto *PtrToIntI = cast<sandboxir::PtrToIntInst>(PtrToInt);5427 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(PtrToInt));5428 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(PtrToIntI));5429 EXPECT_EQ(PtrToInt->getOpcode(), sandboxir::Instruction::Opcode::PtrToInt);5430 EXPECT_EQ(PtrToInt->getSrcTy(), Tptr);5431 EXPECT_EQ(PtrToInt->getDestTy(), Ti32);5432 5433 auto *IntToPtr = cast<sandboxir::CastInst>(&*It++);5434 auto *IntToPtrI = cast<sandboxir::IntToPtrInst>(IntToPtr);5435 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(IntToPtr));5436 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(IntToPtrI));5437 EXPECT_EQ(IntToPtr->getOpcode(), sandboxir::Instruction::Opcode::IntToPtr);5438 EXPECT_EQ(IntToPtr->getSrcTy(), Ti32);5439 EXPECT_EQ(IntToPtr->getDestTy(), Tptr);5440 5441 auto *SIToFP = cast<sandboxir::CastInst>(&*It++);5442 auto *SIToFPI = cast<sandboxir::SIToFPInst>(SIToFP);5443 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SIToFP));5444 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(SIToFPI));5445 EXPECT_EQ(SIToFP->getOpcode(), sandboxir::Instruction::Opcode::SIToFP);5446 EXPECT_EQ(SIToFP->getSrcTy(), Ti32);5447 EXPECT_EQ(SIToFP->getDestTy(), Tfloat);5448 5449 auto *UIToFP = cast<sandboxir::CastInst>(&*It++);5450 auto *UIToFPI = cast<sandboxir::UIToFPInst>(UIToFP);5451 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(UIToFP));5452 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(UIToFPI));5453 EXPECT_EQ(UIToFP->getOpcode(), sandboxir::Instruction::Opcode::UIToFP);5454 EXPECT_EQ(UIToFP->getSrcTy(), Ti32);5455 EXPECT_EQ(UIToFP->getDestTy(), Tfloat);5456 5457 auto *Trunc = cast<sandboxir::CastInst>(&*It++);5458 auto *TruncI = cast<sandboxir::TruncInst>(Trunc);5459 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(Trunc));5460 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(TruncI));5461 EXPECT_EQ(Trunc->getOpcode(), sandboxir::Instruction::Opcode::Trunc);5462 EXPECT_EQ(Trunc->getSrcTy(), Ti32);5463 EXPECT_EQ(Trunc->getDestTy(), Ti16);5464 5465 auto *FPTrunc = cast<sandboxir::CastInst>(&*It++);5466 auto *FPTruncI = cast<sandboxir::FPTruncInst>(FPTrunc);5467 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPTrunc));5468 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(FPTruncI));5469 EXPECT_EQ(FPTrunc->getOpcode(), sandboxir::Instruction::Opcode::FPTrunc);5470 EXPECT_EQ(FPTrunc->getSrcTy(), Tdouble);5471 EXPECT_EQ(FPTrunc->getDestTy(), Tfloat);5472 5473 auto *BitCast = cast<sandboxir::CastInst>(&*It++);5474 auto *BitCastI = cast<sandboxir::BitCastInst>(BitCast);5475 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(BitCast));5476 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(BitCastI));5477 EXPECT_EQ(BitCast->getOpcode(), sandboxir::Instruction::Opcode::BitCast);5478 EXPECT_EQ(BitCast->getSrcTy(), Ti32);5479 EXPECT_EQ(BitCast->getDestTy(), Tfloat);5480 5481 auto *AddrSpaceCast = cast<sandboxir::CastInst>(&*It++);5482 auto *AddrSpaceCastI = cast<sandboxir::AddrSpaceCastInst>(AddrSpaceCast);5483 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(AddrSpaceCast));5484 EXPECT_TRUE(isa<sandboxir::UnaryInstruction>(AddrSpaceCastI));5485 EXPECT_EQ(AddrSpaceCast->getOpcode(),5486 sandboxir::Instruction::Opcode::AddrSpaceCast);5487 EXPECT_EQ(AddrSpaceCast->getSrcTy(), Tptr);5488 EXPECT_EQ(AddrSpaceCast->getDestTy(), Tptr1);5489 5490 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);5491 5492 {5493 // Check create() WhereIt, WhereBB5494 auto *NewI = cast<sandboxir::CastInst>(5495 sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::SExt,5496 Arg, BB->end(), Ctx, "SExt"));5497 // Check getOpcode().5498 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::SExt);5499 // Check getSrcTy().5500 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5501 // Check getDestTy().5502 EXPECT_EQ(NewI->getDestTy(), Ti64);5503 // Check instr position.5504 EXPECT_EQ(NewI->getNextNode(), nullptr);5505 EXPECT_EQ(NewI->getPrevNode(), Ret);5506 }5507 5508 {5509 // Check create() InsertBefore.5510 auto *NewI = cast<sandboxir::CastInst>(5511 sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::ZExt,5512 Arg, Ret->getIterator(), Ctx, "ZExt"));5513 // Check getOpcode().5514 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt);5515 // Check getSrcTy().5516 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5517 // Check getDestTy().5518 EXPECT_EQ(NewI->getDestTy(), Ti64);5519 // Check instr position.5520 EXPECT_EQ(NewI->getNextNode(), Ret);5521 }5522 {5523 // Check create() InsertAtEnd.5524 auto *NewI = cast<sandboxir::CastInst>(sandboxir::CastInst::create(5525 Ti64, sandboxir::Instruction::Opcode::ZExt, Arg, BB, Ctx, "ZExt"));5526 // Check getOpcode().5527 EXPECT_EQ(NewI->getOpcode(), sandboxir::Instruction::Opcode::ZExt);5528 // Check getSrcTy().5529 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5530 // Check getDestTy().5531 EXPECT_EQ(NewI->getDestTy(), Ti64);5532 // Check instr position.5533 EXPECT_EQ(NewI->getNextNode(), nullptr);5534 EXPECT_EQ(NewI->getParent(), BB);5535 }5536 5537 {5538#ifndef NDEBUG5539 // Check that passing a non-cast opcode crashes.5540 EXPECT_DEATH(5541 sandboxir::CastInst::create(Ti64, sandboxir::Instruction::Opcode::Store,5542 Arg, Ret->getIterator(), Ctx, "Bad"),5543 ".*Opcode.*");5544#endif // NDEBUG5545 }5546}5547 5548TEST_F(SandboxIRTest, PossiblyNonNegInst) {5549 parseIR(C, R"IR(5550define void @foo(i32 %arg, float %farg, double %darg, ptr %ptr) {5551 %zext = zext i32 %arg to i645552 %uitofp = uitofp i32 %arg to float5553 5554 %sext = sext i32 %arg to i645555 %fptoui = fptoui float %farg to i325556 %fptosi = fptosi float %farg to i325557 %fpext = fpext float %farg to double5558 %ptrtoint = ptrtoint ptr %ptr to i325559 %inttoptr = inttoptr i32 %arg to ptr5560 %sitofp = sitofp i32 %arg to float5561 %trunc = trunc i32 %arg to i165562 %fptrunc = fptrunc double %darg to float5563 %bitcast = bitcast i32 %arg to float5564 %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1)5565 ret void5566}5567)IR");5568 Function &LLVMF = *M->getFunction("foo");5569 sandboxir::Context Ctx(C);5570 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5571 auto *BB = &*F->begin();5572 auto It = BB->begin();5573 auto *PNNI0 = cast<sandboxir::PossiblyNonNegInst>(&*It++);5574 auto *PNNI1 = cast<sandboxir::PossiblyNonNegInst>(&*It++);5575 for (auto ItE = BB->end(); It != ItE; ++It)5576 EXPECT_FALSE(isa<sandboxir::PossiblyNonNegInst>(&*It++));5577 5578 for (auto *PNNI : {PNNI0, PNNI1}) {5579 // Check setNonNeg(), hasNonNeg().5580 auto OrigNonNeg = PNNI->hasNonNeg();5581 auto NewNonNeg = true;5582 EXPECT_NE(NewNonNeg, OrigNonNeg);5583 PNNI->setNonNeg(NewNonNeg);5584 EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg);5585 PNNI->setNonNeg(OrigNonNeg);5586 EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg);5587 }5588}5589 5590/// CastInst's subclasses are very similar so we can use a common test function5591/// for them.5592template <typename SubclassT, sandboxir::Instruction::Opcode OpcodeT>5593void testCastInst(llvm::Module &M, llvm::Type *LLVMSrcTy,5594 llvm::Type *LLVMDstTy) {5595 Function &LLVMF = *M.getFunction("foo");5596 sandboxir::Context Ctx(M.getContext());5597 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5598 sandboxir::Type *SrcTy = Ctx.getType(LLVMSrcTy);5599 sandboxir::Type *DstTy = Ctx.getType(LLVMDstTy);5600 unsigned ArgIdx = 0;5601 auto *Arg = F->getArg(ArgIdx++);5602 auto *BB = &*F->begin();5603 auto It = BB->begin();5604 5605 auto *CI = cast<SubclassT>(&*It++);5606 EXPECT_EQ(CI->getOpcode(), OpcodeT);5607 EXPECT_EQ(CI->getSrcTy(), SrcTy);5608 EXPECT_EQ(CI->getDestTy(), DstTy);5609 auto *Ret = cast<sandboxir::ReturnInst>(&*It++);5610 5611 {5612 // Check create() WhereIt, WhereBB5613 auto *NewI =5614 cast<SubclassT>(SubclassT::create(Arg, DstTy, BB->end(), Ctx, "NewCI"));5615 // Check getOpcode().5616 EXPECT_EQ(NewI->getOpcode(), OpcodeT);5617 // Check getSrcTy().5618 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5619 // Check getDestTy().5620 EXPECT_EQ(NewI->getDestTy(), DstTy);5621 // Check instr position.5622 EXPECT_EQ(NewI->getNextNode(), nullptr);5623 EXPECT_EQ(NewI->getPrevNode(), Ret);5624 // Check instr name.5625 EXPECT_EQ(NewI->getName(), "NewCI");5626 }5627 {5628 // Check create() InsertBefore.5629 auto *NewI = cast<SubclassT>(5630 SubclassT::create(Arg, DstTy, Ret->getIterator(), Ctx, "NewCI"));5631 // Check getOpcode().5632 EXPECT_EQ(NewI->getOpcode(), OpcodeT);5633 // Check getSrcTy().5634 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5635 // Check getDestTy().5636 EXPECT_EQ(NewI->getDestTy(), DstTy);5637 // Check instr position.5638 EXPECT_EQ(NewI->getNextNode(), Ret);5639 }5640 {5641 // Check create() InsertAtEnd.5642 auto *NewI =5643 cast<SubclassT>(SubclassT::create(Arg, DstTy,5644 /*InsertAtEnd=*/BB, Ctx, "NewCI"));5645 // Check getOpcode().5646 EXPECT_EQ(NewI->getOpcode(), OpcodeT);5647 // Check getSrcTy().5648 EXPECT_EQ(NewI->getSrcTy(), Arg->getType());5649 // Check getDestTy().5650 EXPECT_EQ(NewI->getDestTy(), DstTy);5651 // Check instr position.5652 EXPECT_EQ(NewI->getNextNode(), nullptr);5653 EXPECT_EQ(NewI->getParent(), BB);5654 }5655}5656 5657TEST_F(SandboxIRTest, TruncInst) {5658 parseIR(C, R"IR(5659define void @foo(i64 %arg) {5660 %trunc = trunc i64 %arg to i325661 ret void5662}5663)IR");5664 testCastInst<sandboxir::TruncInst, sandboxir::Instruction::Opcode::Trunc>(5665 *M,5666 /*SrcTy=*/Type::getInt64Ty(C), /*DstTy=*/Type::getInt32Ty(C));5667}5668 5669TEST_F(SandboxIRTest, ZExtInst) {5670 parseIR(C, R"IR(5671define void @foo(i32 %arg) {5672 %zext = zext i32 %arg to i645673 ret void5674}5675)IR");5676 testCastInst<sandboxir::ZExtInst, sandboxir::Instruction::Opcode::ZExt>(5677 *M,5678 /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getInt64Ty(C));5679}5680 5681TEST_F(SandboxIRTest, SExtInst) {5682 parseIR(C, R"IR(5683define void @foo(i32 %arg) {5684 %sext = sext i32 %arg to i645685 ret void5686}5687)IR");5688 testCastInst<sandboxir::SExtInst, sandboxir::Instruction::Opcode::SExt>(5689 *M,5690 /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getInt64Ty(C));5691}5692 5693TEST_F(SandboxIRTest, FPTruncInst) {5694 parseIR(C, R"IR(5695define void @foo(double %arg) {5696 %fptrunc = fptrunc double %arg to float5697 ret void5698}5699)IR");5700 testCastInst<sandboxir::FPTruncInst, sandboxir::Instruction::Opcode::FPTrunc>(5701 *M,5702 /*SrcTy=*/Type::getDoubleTy(C), /*DstTy=*/Type::getFloatTy(C));5703}5704 5705TEST_F(SandboxIRTest, FPExtInst) {5706 parseIR(C, R"IR(5707define void @foo(float %arg) {5708 %fpext = fpext float %arg to double5709 ret void5710}5711)IR");5712 testCastInst<sandboxir::FPExtInst, sandboxir::Instruction::Opcode::FPExt>(5713 *M,5714 /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getDoubleTy(C));5715}5716 5717TEST_F(SandboxIRTest, UIToFPInst) {5718 parseIR(C, R"IR(5719define void @foo(i32 %arg) {5720 %uitofp = uitofp i32 %arg to float5721 ret void5722}5723)IR");5724 testCastInst<sandboxir::UIToFPInst, sandboxir::Instruction::Opcode::UIToFP>(5725 *M,5726 /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getFloatTy(C));5727}5728 5729TEST_F(SandboxIRTest, SIToFPInst) {5730 parseIR(C, R"IR(5731define void @foo(i32 %arg) {5732 %sitofp = sitofp i32 %arg to float5733 ret void5734}5735)IR");5736 testCastInst<sandboxir::SIToFPInst, sandboxir::Instruction::Opcode::SIToFP>(5737 *M,5738 /*SrcTy=*/Type::getInt32Ty(C),5739 /*DstTy=*/Type::getFloatTy(C));5740}5741 5742TEST_F(SandboxIRTest, FPToUIInst) {5743 parseIR(C, R"IR(5744define void @foo(float %arg) {5745 %fptoui = fptoui float %arg to i325746 ret void5747}5748)IR");5749 testCastInst<sandboxir::FPToUIInst, sandboxir::Instruction::Opcode::FPToUI>(5750 5751 *M, /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getInt32Ty(C));5752}5753 5754TEST_F(SandboxIRTest, FPToSIInst) {5755 parseIR(C, R"IR(5756define void @foo(float %arg) {5757 %fptosi = fptosi float %arg to i325758 ret void5759}5760)IR");5761 testCastInst<sandboxir::FPToSIInst, sandboxir::Instruction::Opcode::FPToSI>(5762 *M, /*SrcTy=*/Type::getFloatTy(C), /*DstTy=*/Type::getInt32Ty(C));5763}5764 5765TEST_F(SandboxIRTest, IntToPtrInst) {5766 parseIR(C, R"IR(5767define void @foo(i32 %arg) {5768 %inttoptr = inttoptr i32 %arg to ptr5769 ret void5770}5771)IR");5772 testCastInst<sandboxir::IntToPtrInst,5773 sandboxir::Instruction::Opcode::IntToPtr>(5774 *M,5775 /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/PointerType::get(C, 0));5776}5777 5778TEST_F(SandboxIRTest, PtrToIntInst) {5779 parseIR(C, R"IR(5780define void @foo(ptr %ptr) {5781 %ptrtoint = ptrtoint ptr %ptr to i325782 ret void5783}5784)IR");5785 testCastInst<sandboxir::PtrToIntInst,5786 sandboxir::Instruction::Opcode::PtrToInt>(5787 *M, /*SrcTy=*/PointerType::get(C, 0), /*DstTy=*/Type::getInt32Ty(C));5788}5789 5790TEST_F(SandboxIRTest, BitCastInst) {5791 parseIR(C, R"IR(5792define void @foo(i32 %arg) {5793 %bitcast = bitcast i32 %arg to float5794 ret void5795}5796)IR");5797 testCastInst<sandboxir::BitCastInst, sandboxir::Instruction::Opcode::BitCast>(5798 *M,5799 /*SrcTy=*/Type::getInt32Ty(C), /*DstTy=*/Type::getFloatTy(C));5800}5801 5802TEST_F(SandboxIRTest, AddrSpaceCastInst) {5803 parseIR(C, R"IR(5804define void @foo(ptr %ptr) {5805 %addrspacecast = addrspacecast ptr %ptr to ptr addrspace(1)5806 ret void5807}5808)IR");5809 Type *Tptr0 = PointerType::get(C, 0);5810 Type *Tptr1 = PointerType::get(C, 1);5811 testCastInst<sandboxir::AddrSpaceCastInst,5812 sandboxir::Instruction::Opcode::AddrSpaceCast>(*M,5813 /*SrcTy=*/Tptr0,5814 /*DstTy=*/Tptr1);5815 Function &LLVMF = *M->getFunction("foo");5816 sandboxir::Context Ctx(C);5817 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5818 unsigned ArgIdx = 0;5819 auto *Arg = F->getArg(ArgIdx++);5820 auto *BB = &*F->begin();5821 auto It = BB->begin();5822 5823 auto *AddrSpaceCast = cast<sandboxir::AddrSpaceCastInst>(&*It++);5824 EXPECT_EQ(AddrSpaceCast->getOpcode(),5825 sandboxir::Instruction::Opcode::AddrSpaceCast);5826 EXPECT_EQ(AddrSpaceCast->getPointerOperand(), Arg);5827 EXPECT_EQ(sandboxir::AddrSpaceCastInst::getPointerOperandIndex(), 0u);5828 EXPECT_EQ(AddrSpaceCast->getSrcAddressSpace(),5829 cast<PointerType>(Tptr0)->getPointerAddressSpace());5830 EXPECT_EQ(AddrSpaceCast->getDestAddressSpace(),5831 cast<PointerType>(Tptr1)->getPointerAddressSpace());5832}5833 5834TEST_F(SandboxIRTest, PHINode) {5835 parseIR(C, R"IR(5836define void @foo(i32 %arg) {5837bb1:5838 br label %bb25839 5840bb2:5841 %phi = phi i32 [ %arg, %bb1 ], [ 0, %bb2 ], [ 1, %bb3 ], [ 2, %bb4 ], [ 3, %bb5 ]5842 br label %bb25843 5844bb3:5845 br label %bb25846 5847bb4:5848 br label %bb25849 5850bb5:5851 br label %bb25852 ret void5853}5854)IR");5855 Function &LLVMF = *M->getFunction("foo");5856 auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1");5857 auto *LLVMBB2 = getBasicBlockByName(LLVMF, "bb2");5858 auto *LLVMBB3 = getBasicBlockByName(LLVMF, "bb3");5859 auto LLVMIt = LLVMBB2->begin();5860 auto *LLVMPHI = cast<llvm::PHINode>(&*LLVMIt++);5861 sandboxir::Context Ctx(C);5862 sandboxir::Function *F = Ctx.createFunction(&LLVMF);5863 auto *Arg = F->getArg(0);5864 auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1));5865 auto *BB2 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB2));5866 auto *BB3 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB3));5867 auto It = BB2->begin();5868 // Check classof().5869 auto *PHI = cast<sandboxir::PHINode>(&*It++);5870 auto *Br = cast<sandboxir::BranchInst>(&*It++);5871 // Check blocks().5872 EXPECT_EQ(range_size(PHI->blocks()), range_size(LLVMPHI->blocks()));5873 auto BlockIt = PHI->block_begin();5874 for (llvm::BasicBlock *LLVMBB : LLVMPHI->blocks()) {5875 sandboxir::BasicBlock *BB = *BlockIt++;5876 EXPECT_EQ(BB, Ctx.getValue(LLVMBB));5877 }5878 // Check incoming_values().5879 EXPECT_EQ(range_size(PHI->incoming_values()),5880 range_size(LLVMPHI->incoming_values()));5881 auto IncIt = PHI->incoming_values().begin();5882 for (llvm::Value *LLVMV : LLVMPHI->incoming_values()) {5883 sandboxir::Value *IncV = *IncIt++;5884 EXPECT_EQ(IncV, Ctx.getValue(LLVMV));5885 }5886 // Check getNumIncomingValues().5887 EXPECT_EQ(PHI->getNumIncomingValues(), LLVMPHI->getNumIncomingValues());5888 // Check getIncomingValue().5889 EXPECT_EQ(PHI->getIncomingValue(0),5890 Ctx.getValue(LLVMPHI->getIncomingValue(0)));5891 EXPECT_EQ(PHI->getIncomingValue(1),5892 Ctx.getValue(LLVMPHI->getIncomingValue(1)));5893 // Check setIncomingValue().5894 auto *OrigV = PHI->getIncomingValue(0);5895 PHI->setIncomingValue(0, PHI);5896 EXPECT_EQ(PHI->getIncomingValue(0), PHI);5897 PHI->setIncomingValue(0, OrigV);5898 // Check getOperandNumForIncomingValue().5899 EXPECT_EQ(sandboxir::PHINode::getOperandNumForIncomingValue(0),5900 llvm::PHINode::getOperandNumForIncomingValue(0));5901 // Check getIncomingValueNumForOperand().5902 EXPECT_EQ(sandboxir::PHINode::getIncomingValueNumForOperand(0),5903 llvm::PHINode::getIncomingValueNumForOperand(0));5904 // Check getIncomingBlock(unsigned).5905 EXPECT_EQ(PHI->getIncomingBlock(0),5906 Ctx.getValue(LLVMPHI->getIncomingBlock(0)));5907 // Check getIncomingBlock(Use).5908 llvm::Use &LLVMUse = LLVMPHI->getOperandUse(0);5909 sandboxir::Use Use = PHI->getOperandUse(0);5910 EXPECT_EQ(PHI->getIncomingBlock(Use),5911 Ctx.getValue(LLVMPHI->getIncomingBlock(LLVMUse)));5912 // Check setIncomingBlock().5913 sandboxir::BasicBlock *OrigBB = PHI->getIncomingBlock(0);5914 EXPECT_NE(OrigBB, BB2);5915 PHI->setIncomingBlock(0, BB2);5916 EXPECT_EQ(PHI->getIncomingBlock(0), BB2);5917 PHI->setIncomingBlock(0, OrigBB);5918 EXPECT_EQ(PHI->getIncomingBlock(0), OrigBB);5919 // Check addIncoming().5920 unsigned OrigNumIncoming = PHI->getNumIncomingValues();5921 PHI->addIncoming(Arg, BB3);5922 EXPECT_EQ(PHI->getNumIncomingValues(), LLVMPHI->getNumIncomingValues());5923 EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming + 1);5924 EXPECT_EQ(PHI->getIncomingValue(OrigNumIncoming), Arg);5925 EXPECT_EQ(PHI->getIncomingBlock(OrigNumIncoming), BB3);5926 // Check removeIncomingValue(unsigned).5927 PHI->removeIncomingValue(OrigNumIncoming);5928 EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming);5929 // Check removeIncomingValue(BasicBlock *).5930 PHI->addIncoming(Arg, BB3);5931 PHI->removeIncomingValue(BB3);5932 EXPECT_EQ(PHI->getNumIncomingValues(), OrigNumIncoming);5933 // Check getBasicBlockIndex().5934 EXPECT_EQ(PHI->getBasicBlockIndex(BB1), LLVMPHI->getBasicBlockIndex(LLVMBB1));5935 // Check getIncomingValueForBlock().5936 EXPECT_EQ(PHI->getIncomingValueForBlock(BB1),5937 Ctx.getValue(LLVMPHI->getIncomingValueForBlock(LLVMBB1)));5938 // Check hasConstantValue().5939 llvm::Value *ConstV = LLVMPHI->hasConstantValue();5940 EXPECT_EQ(PHI->hasConstantValue(),5941 ConstV != nullptr ? Ctx.getValue(ConstV) : nullptr);5942 // Check hasConstantOrUndefValue().5943 EXPECT_EQ(PHI->hasConstantOrUndefValue(), LLVMPHI->hasConstantOrUndefValue());5944 // Check isComplete().5945 EXPECT_EQ(PHI->isComplete(), LLVMPHI->isComplete());5946 // Check replaceIncomingValueIf5947 EXPECT_EQ(PHI->getNumIncomingValues(), 5u);5948 auto *RemainBB0 = PHI->getIncomingBlock(0);5949 auto *RemoveBB0 = PHI->getIncomingBlock(1);5950 auto *RemainBB1 = PHI->getIncomingBlock(2);5951 auto *RemoveBB1 = PHI->getIncomingBlock(3);5952 auto *RemainBB2 = PHI->getIncomingBlock(4);5953 PHI->removeIncomingValueIf([&](unsigned Idx) {5954 return PHI->getIncomingBlock(Idx) == RemoveBB0 ||5955 PHI->getIncomingBlock(Idx) == RemoveBB1;5956 });5957 EXPECT_EQ(PHI->getNumIncomingValues(), 3u);5958 EXPECT_EQ(PHI->getIncomingBlock(0), RemainBB0);5959 EXPECT_EQ(PHI->getIncomingBlock(1), RemainBB1);5960 EXPECT_EQ(PHI->getIncomingBlock(2), RemainBB2);5961 // Check replaceIncomingBlockWith5962 OrigBB = RemainBB0;5963 auto *NewBB = RemainBB1;5964 EXPECT_NE(NewBB, OrigBB);5965 PHI->replaceIncomingBlockWith(OrigBB, NewBB);5966 EXPECT_EQ(PHI->getIncomingBlock(0), NewBB);5967 EXPECT_EQ(PHI->getIncomingBlock(1), RemainBB1);5968 EXPECT_EQ(PHI->getIncomingBlock(2), RemainBB2);5969 // Check create().5970 auto *NewPHI = cast<sandboxir::PHINode>(sandboxir::PHINode::create(5971 PHI->getType(), 0, Br->getIterator(), Ctx, "NewPHI"));5972 EXPECT_EQ(NewPHI->getType(), PHI->getType());5973 EXPECT_EQ(NewPHI->getNextNode(), Br);5974 EXPECT_EQ(NewPHI->getName(), "NewPHI");5975 EXPECT_EQ(NewPHI->getNumIncomingValues(), 0u);5976 for (auto [Idx, V] : enumerate(PHI->incoming_values())) {5977 sandboxir::BasicBlock *IncBB = PHI->getIncomingBlock(Idx);5978 NewPHI->addIncoming(V, IncBB);5979 }5980 EXPECT_EQ(NewPHI->getNumIncomingValues(), PHI->getNumIncomingValues());5981}5982 5983static void checkSwapOperands(sandboxir::Context &Ctx,5984 llvm::sandboxir::CmpInst *Cmp,5985 llvm::CmpInst *LLVMCmp) {5986 auto OrigOp0 = Cmp->getOperand(0);5987 auto OrigOp1 = Cmp->getOperand(1);5988 EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(0)), OrigOp0);5989 EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(1)), OrigOp1);5990 // This checks the dispatch mechanism in CmpInst, as well as5991 // the specific implementations.5992 Cmp->swapOperands();5993 EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(1)), OrigOp0);5994 EXPECT_EQ(Ctx.getValue(LLVMCmp->getOperand(0)), OrigOp1);5995 EXPECT_EQ(Cmp->getOperand(0), OrigOp1);5996 EXPECT_EQ(Cmp->getOperand(1), OrigOp0);5997 // Undo it to keep the rest of the test consistent5998 Cmp->swapOperands();5999}6000 6001static void checkCommonPredicates(sandboxir::CmpInst *Cmp,6002 llvm::CmpInst *LLVMCmp) {6003 // Check proper creation6004 auto Pred = Cmp->getPredicate();6005 auto LLVMPred = LLVMCmp->getPredicate();6006 EXPECT_EQ(Pred, LLVMPred);6007 // Check setPredicate6008 Cmp->setPredicate(llvm::CmpInst::FCMP_FALSE);6009 EXPECT_EQ(Cmp->getPredicate(), llvm::CmpInst::FCMP_FALSE);6010 EXPECT_EQ(LLVMCmp->getPredicate(), llvm::CmpInst::FCMP_FALSE);6011 Cmp->setPredicate(Pred);6012 EXPECT_EQ(LLVMCmp->getPredicate(), Pred);6013 // Ensure the accessors properly forward to the underlying implementation6014 EXPECT_STREQ(sandboxir::CmpInst::getPredicateName(Pred).data(),6015 llvm::CmpInst::getPredicateName(LLVMPred).data());6016 EXPECT_EQ(Cmp->isFPPredicate(), LLVMCmp->isFPPredicate());6017 EXPECT_EQ(Cmp->isIntPredicate(), LLVMCmp->isIntPredicate());6018 EXPECT_EQ(Cmp->getInversePredicate(), LLVMCmp->getInversePredicate());6019 EXPECT_EQ(Cmp->getOrderedPredicate(), LLVMCmp->getOrderedPredicate());6020 EXPECT_EQ(Cmp->getUnorderedPredicate(), LLVMCmp->getUnorderedPredicate());6021 EXPECT_EQ(Cmp->getSwappedPredicate(), LLVMCmp->getSwappedPredicate());6022 EXPECT_EQ(Cmp->isStrictPredicate(), LLVMCmp->isStrictPredicate());6023 EXPECT_EQ(Cmp->isNonStrictPredicate(), LLVMCmp->isNonStrictPredicate());6024 EXPECT_EQ(Cmp->isRelational(), LLVMCmp->isRelational());6025 if (Cmp->isRelational()) {6026 EXPECT_EQ(Cmp->getFlippedStrictnessPredicate(),6027 LLVMCmp->getFlippedStrictnessPredicate());6028 }6029 EXPECT_EQ(Cmp->isCommutative(), LLVMCmp->isCommutative());6030 EXPECT_EQ(Cmp->isTrueWhenEqual(), LLVMCmp->isTrueWhenEqual());6031 EXPECT_EQ(Cmp->isFalseWhenEqual(), LLVMCmp->isFalseWhenEqual());6032 EXPECT_EQ(sandboxir::CmpInst::isOrdered(Pred),6033 llvm::CmpInst::isOrdered(LLVMPred));6034 EXPECT_EQ(sandboxir::CmpInst::isUnordered(Pred),6035 llvm::CmpInst::isUnordered(LLVMPred));6036}6037 6038TEST_F(SandboxIRTest, ICmpInst) {6039 SCOPED_TRACE("SandboxIRTest sandboxir::ICmpInst tests");6040 parseIR(C, R"IR(6041define void @foo(i32 %i0, i32 %i1) {6042 bb:6043 %ine = icmp ne i32 %i0, %i16044 %iugt = icmp ugt i32 %i0, %i16045 %iuge = icmp uge i32 %i0, %i16046 %iult = icmp ult i32 %i0, %i16047 %iule = icmp ule i32 %i0, %i16048 %isgt = icmp sgt i32 %i0, %i16049 %isle = icmp sle i32 %i0, %i16050 %ieg = icmp eq i32 %i0, %i16051 ret void6052}6053)IR");6054 Function &LLVMF = *M->getFunction("foo");6055 sandboxir::Context Ctx(C);6056 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);6057 6058 auto *LLVMBB = getBasicBlockByName(LLVMF, "bb");6059 auto LLVMIt = LLVMBB->begin();6060 auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));6061 auto It = BB->begin();6062 // Check classof()6063 while (auto *ICmp = dyn_cast<sandboxir::ICmpInst>(&*It++)) {6064 auto *LLVMICmp = cast<llvm::ICmpInst>(&*LLVMIt++);6065 checkSwapOperands(Ctx, ICmp, LLVMICmp);6066 checkCommonPredicates(ICmp, LLVMICmp);6067 EXPECT_EQ(ICmp->isSigned(), LLVMICmp->isSigned());6068 EXPECT_EQ(ICmp->isUnsigned(), LLVMICmp->isUnsigned());6069 EXPECT_EQ(ICmp->getSignedPredicate(), LLVMICmp->getSignedPredicate());6070 EXPECT_EQ(ICmp->getUnsignedPredicate(), LLVMICmp->getUnsignedPredicate());6071 }6072 auto *NewCmp = cast<sandboxir::CmpInst>(6073 sandboxir::CmpInst::create(llvm::CmpInst::ICMP_ULE, F.getArg(0),6074 F.getArg(1), BB->begin(), Ctx, "NewCmp"));6075 EXPECT_EQ(NewCmp, &*BB->begin());6076 EXPECT_EQ(NewCmp->getPredicate(), llvm::CmpInst::ICMP_ULE);6077 EXPECT_EQ(NewCmp->getOperand(0), F.getArg(0));6078 EXPECT_EQ(NewCmp->getOperand(1), F.getArg(1));6079#ifndef NDEBUG6080 EXPECT_EQ(NewCmp->getName(), "NewCmp");6081#endif // NDEBUG6082 // TODO: Improve this test when sandboxir::VectorType is more completely6083 // implemented.6084 sandboxir::Type *RT =6085 sandboxir::CmpInst::makeCmpResultType(F.getArg(0)->getType());6086 EXPECT_TRUE(RT->isIntegerTy(1)); // Only one bit in a single comparison6087 6088 {6089 // Check create() when operands are constant.6090 auto *Const42 =6091 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);6092 auto *NewConstCmp =6093 sandboxir::CmpInst::create(llvm::CmpInst::ICMP_ULE, Const42, Const42,6094 BB->begin(), Ctx, "NewConstCmp");6095 EXPECT_TRUE(isa<sandboxir::Constant>(NewConstCmp));6096 }6097}6098 6099TEST_F(SandboxIRTest, FCmpInst) {6100 SCOPED_TRACE("SandboxIRTest sandboxir::FCmpInst tests");6101 parseIR(C, R"IR(6102define void @foo(float %f0, float %f1) {6103bb:6104 %ffalse = fcmp false float %f0, %f16105 %foeq = fcmp oeq float %f0, %f16106 %fogt = fcmp ogt float %f0, %f16107 %folt = fcmp olt float %f0, %f16108 %fole = fcmp ole float %f0, %f16109 %fone = fcmp one float %f0, %f16110 %ford = fcmp ord float %f0, %f16111 %funo = fcmp uno float %f0, %f16112 %fueq = fcmp ueq float %f0, %f16113 %fugt = fcmp ugt float %f0, %f16114 %fuge = fcmp uge float %f0, %f16115 %fult = fcmp ult float %f0, %f16116 %fule = fcmp ule float %f0, %f16117 %fune = fcmp une float %f0, %f16118 %ftrue = fcmp true float %f0, %f16119 ret void6120bb1:6121 %copyfrom = fadd reassoc float %f0, 42.06122 ret void6123}6124)IR");6125 Function &LLVMF = *M->getFunction("foo");6126 sandboxir::Context Ctx(C);6127 [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);6128 6129 auto *LLVMBB = getBasicBlockByName(LLVMF, "bb");6130 auto LLVMIt = LLVMBB->begin();6131 auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));6132 auto It = BB->begin();6133 // Check classof()6134 while (auto *FCmp = dyn_cast<sandboxir::ICmpInst>(&*It++)) {6135 auto *LLVMFCmp = cast<llvm::ICmpInst>(&*LLVMIt++);6136 checkSwapOperands(Ctx, FCmp, LLVMFCmp);6137 checkCommonPredicates(FCmp, LLVMFCmp);6138 }6139 6140 auto *LLVMBB1 = getBasicBlockByName(LLVMF, "bb1");6141 auto *BB1 = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB1));6142 auto It1 = BB1->begin();6143 auto *CopyFrom = &*It1++;6144 CopyFrom->setFastMathFlags(FastMathFlags::getFast());6145 6146 // create with default flags6147 auto *NewFCmp = cast<sandboxir::CmpInst>(sandboxir::CmpInst::create(6148 llvm::CmpInst::FCMP_ONE, F.getArg(0), F.getArg(1), It1, Ctx, "NewFCmp"));6149 EXPECT_EQ(NewFCmp->getPredicate(), llvm::CmpInst::FCMP_ONE);6150 EXPECT_EQ(NewFCmp->getOperand(0), F.getArg(0));6151 EXPECT_EQ(NewFCmp->getOperand(1), F.getArg(1));6152#ifndef NDEBUG6153 EXPECT_EQ(NewFCmp->getName(), "NewFCmp");6154#endif // NDEBUG6155 FastMathFlags DefaultFMF = NewFCmp->getFastMathFlags();6156 EXPECT_TRUE(CopyFrom->getFastMathFlags() != DefaultFMF);6157 // create with copied flags6158 auto *NewFCmpFlags =6159 cast<sandboxir::CmpInst>(sandboxir::CmpInst::createWithCopiedFlags(6160 llvm::CmpInst::FCMP_ONE, F.getArg(0), F.getArg(1), CopyFrom, It1, Ctx,6161 "NewFCmpFlags"));6162 EXPECT_FALSE(NewFCmpFlags->getFastMathFlags() !=6163 CopyFrom->getFastMathFlags());6164 EXPECT_EQ(NewFCmpFlags->getPredicate(), llvm::CmpInst::FCMP_ONE);6165 EXPECT_EQ(NewFCmpFlags->getOperand(0), F.getArg(0));6166 EXPECT_EQ(NewFCmpFlags->getOperand(1), F.getArg(1));6167#ifndef NDEBUG6168 EXPECT_EQ(NewFCmpFlags->getName(), "NewFCmpFlags");6169#endif // NDEBUG6170 6171 {6172 // Check create() when operands are constant.6173 auto *Const42 =6174 sandboxir::ConstantFP::get(sandboxir::Type::getFloatTy(Ctx), 42.0);6175 auto *NewConstCmp =6176 sandboxir::CmpInst::create(llvm::CmpInst::FCMP_ULE, Const42, Const42,6177 BB->begin(), Ctx, "NewConstCmp");6178 EXPECT_TRUE(isa<sandboxir::Constant>(NewConstCmp));6179 }6180}6181 6182TEST_F(SandboxIRTest, UnreachableInst) {6183 parseIR(C, R"IR(6184define void @foo() {6185 unreachable6186}6187)IR");6188 llvm::Function *LLVMF = &*M->getFunction("foo");6189 sandboxir::Context Ctx(C);6190 sandboxir::Function *F = Ctx.createFunction(LLVMF);6191 auto *BB = &*F->begin();6192 auto It = BB->begin();6193 auto *UI = cast<sandboxir::UnreachableInst>(&*It++);6194 6195 EXPECT_EQ(UI->getNumSuccessors(), 0u);6196 EXPECT_EQ(UI->getNumOfIRInstrs(), 1u);6197 // Check create(InsertBefore)6198 sandboxir::UnreachableInst *NewUI =6199 sandboxir::UnreachableInst::create(UI->getIterator(), Ctx);6200 EXPECT_EQ(NewUI->getNextNode(), UI);6201 // Check create(InsertAtEnd)6202 sandboxir::UnreachableInst *NewUIEnd =6203 sandboxir::UnreachableInst::create(/*InsertAtEnd=*/BB, Ctx);6204 EXPECT_EQ(NewUIEnd->getParent(), BB);6205 EXPECT_EQ(NewUIEnd->getNextNode(), nullptr);6206}6207 6208/// Makes sure that all Instruction sub-classes have a classof().6209TEST_F(SandboxIRTest, CheckClassof) {6210#define DEF_INSTR(ID, OPC, CLASS) \6211 EXPECT_NE(&sandboxir::CLASS::classof, &sandboxir::Instruction::classof);6212#include "llvm/SandboxIR/Values.def"6213}6214 6215TEST_F(SandboxIRTest, InstructionCallbacks) {6216 parseIR(C, R"IR(6217 define void @foo(ptr %ptr, i8 %val) {6218 ret void6219 }6220 )IR");6221 Function &LLVMF = *M->getFunction("foo");6222 sandboxir::Context Ctx(C);6223 6224 auto &F = *Ctx.createFunction(&LLVMF);6225 auto &BB = *F.begin();6226 sandboxir::Argument *Ptr = F.getArg(0);6227 sandboxir::Argument *Val = F.getArg(1);6228 sandboxir::Instruction *Ret = &BB.front();6229 6230 SmallVector<sandboxir::Instruction *> Inserted;6231 auto InsertCbId = Ctx.registerCreateInstrCallback(6232 [&Inserted](sandboxir::Instruction *I) { Inserted.push_back(I); });6233 6234 SmallVector<sandboxir::Instruction *> Removed;6235 auto RemoveCbId = Ctx.registerEraseInstrCallback(6236 [&Removed](sandboxir::Instruction *I) { Removed.push_back(I); });6237 6238 // Keep the moved instruction and the instruction pointed by the Where6239 // iterator so we can check both callback arguments work as expected.6240 SmallVector<std::pair<sandboxir::Instruction *, sandboxir::Instruction *>>6241 Moved;6242 auto MoveCbId = Ctx.registerMoveInstrCallback(6243 [&Moved](sandboxir::Instruction *I, const sandboxir::BBIterator &Where) {6244 // Use a nullptr to signal "move to end" to keep it single. We only6245 // have a basic block in this test case anyway.6246 if (Where == Where.getNodeParent()->end())6247 Moved.push_back(std::make_pair(I, nullptr));6248 else6249 Moved.push_back(std::make_pair(I, &*Where));6250 });6251 6252 // Two more insertion callbacks, to check that they're called in registration6253 // order.6254 SmallVector<int> Order;6255 auto CheckOrderInsertCbId1 = Ctx.registerCreateInstrCallback(6256 [&Order](sandboxir::Instruction *I) { Order.push_back(1); });6257 6258 auto CheckOrderInsertCbId2 = Ctx.registerCreateInstrCallback(6259 [&Order](sandboxir::Instruction *I) { Order.push_back(2); });6260 6261 Ctx.save();6262 auto *NewI = sandboxir::StoreInst::create(Val, Ptr, /*Align=*/std::nullopt,6263 Ret->getIterator(), Ctx);6264 EXPECT_THAT(Inserted, testing::ElementsAre(NewI));6265 EXPECT_THAT(Removed, testing::IsEmpty());6266 EXPECT_THAT(Moved, testing::IsEmpty());6267 EXPECT_THAT(Order, testing::ElementsAre(1, 2));6268 6269 Ret->moveBefore(NewI);6270 EXPECT_THAT(Inserted, testing::ElementsAre(NewI));6271 EXPECT_THAT(Removed, testing::IsEmpty());6272 EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI)));6273 6274 Ret->eraseFromParent();6275 EXPECT_THAT(Inserted, testing::ElementsAre(NewI));6276 EXPECT_THAT(Removed, testing::ElementsAre(Ret));6277 EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI)));6278 6279 NewI->eraseFromParent();6280 EXPECT_THAT(Inserted, testing::ElementsAre(NewI));6281 EXPECT_THAT(Removed, testing::ElementsAre(Ret, NewI));6282 EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI)));6283 6284 // Check that after revert the callbacks have been called for the inverse6285 // operations of the changes made so far.6286 Ctx.revert();6287 EXPECT_THAT(Inserted, testing::ElementsAre(NewI, NewI, Ret));6288 EXPECT_THAT(Removed, testing::ElementsAre(Ret, NewI, NewI));6289 EXPECT_THAT(Moved, testing::ElementsAre(std::make_pair(Ret, NewI),6290 std::make_pair(Ret, nullptr)));6291 EXPECT_THAT(Order, testing::ElementsAre(1, 2, 1, 2, 1, 2));6292 6293 // Check that deregistration works. Do an operation of each type after6294 // deregistering callbacks and check.6295 Inserted.clear();6296 Removed.clear();6297 Moved.clear();6298 Ctx.unregisterCreateInstrCallback(InsertCbId);6299 Ctx.unregisterEraseInstrCallback(RemoveCbId);6300 Ctx.unregisterMoveInstrCallback(MoveCbId);6301 Ctx.unregisterCreateInstrCallback(CheckOrderInsertCbId1);6302 Ctx.unregisterCreateInstrCallback(CheckOrderInsertCbId2);6303 auto *NewI2 = sandboxir::StoreInst::create(Val, Ptr, /*Align=*/std::nullopt,6304 Ret->getIterator(), Ctx);6305 Ret->moveBefore(NewI2);6306 Ret->eraseFromParent();6307 EXPECT_THAT(Inserted, testing::IsEmpty());6308 EXPECT_THAT(Removed, testing::IsEmpty());6309 EXPECT_THAT(Moved, testing::IsEmpty());6310}6311 6312// Check callbacks when we set a Use.6313TEST_F(SandboxIRTest, SetUseCallbacks) {6314 parseIR(C, R"IR(6315define void @foo(i8 %v0, i8 %v1) {6316 %add0 = add i8 %v0, %v16317 %add1 = add i8 %add0, %v16318 ret void6319}6320)IR");6321 llvm::Function *LLVMF = &*M->getFunction("foo");6322 sandboxir::Context Ctx(C);6323 auto *F = Ctx.createFunction(LLVMF);6324 auto *Arg0 = F->getArg(0);6325 auto *BB = &*F->begin();6326 auto It = BB->begin();6327 auto *Add0 = cast<sandboxir::BinaryOperator>(&*It++);6328 auto *Add1 = cast<sandboxir::BinaryOperator>(&*It++);6329 6330 SmallVector<std::pair<sandboxir::Use, sandboxir::Value *>> UsesSet;6331 auto Id = Ctx.registerSetUseCallback(6332 [&UsesSet](sandboxir::Use U, sandboxir::Value *NewSrc) {6333 UsesSet.push_back({U, NewSrc});6334 });6335 6336 // Now change %add1 operand to not use %add0.6337 Add1->setOperand(0, Arg0);6338 EXPECT_EQ(UsesSet.size(), 1u);6339 EXPECT_EQ(UsesSet[0].first.get(), Add1->getOperandUse(0).get());6340 EXPECT_EQ(UsesSet[0].second, Arg0);6341 // Restore to previous state.6342 Add1->setOperand(0, Add0);6343 UsesSet.clear();6344 6345 // RAUW6346 Add0->replaceAllUsesWith(Arg0);6347 EXPECT_EQ(UsesSet.size(), 1u);6348 EXPECT_EQ(UsesSet[0].first.get(), Add1->getOperandUse(0).get());6349 EXPECT_EQ(UsesSet[0].second, Arg0);6350 // Restore to previous state.6351 Add1->setOperand(0, Add0);6352 UsesSet.clear();6353 6354 // RUWIf6355 Add0->replaceUsesWithIf(Arg0, [](const auto &U) { return true; });6356 EXPECT_EQ(UsesSet.size(), 1u);6357 EXPECT_EQ(UsesSet[0].first.get(), Add1->getOperandUse(0).get());6358 EXPECT_EQ(UsesSet[0].second, Arg0);6359 // Restore to previous state.6360 Add1->setOperand(0, Add0);6361 UsesSet.clear();6362 6363 // RUOW6364 Add1->replaceUsesOfWith(Add0, Arg0);6365 EXPECT_EQ(UsesSet.size(), 1u);6366 EXPECT_EQ(UsesSet[0].first.get(), Add1->getOperandUse(0).get());6367 EXPECT_EQ(UsesSet[0].second, Arg0);6368 // Restore to previous state.6369 Add1->setOperand(0, Add0);6370 UsesSet.clear();6371 6372 // Check unregister.6373 Ctx.unregisterSetUseCallback(Id);6374 Add0->replaceAllUsesWith(Arg0);6375 EXPECT_TRUE(UsesSet.empty());6376}6377 6378TEST_F(SandboxIRTest, FunctionObjectAlreadyExists) {6379 parseIR(C, R"IR(6380define void @foo() {6381 call void @bar()6382 ret void6383}6384define void @bar() {6385 ret void6386}6387)IR");6388 Function &LLVMFoo = *M->getFunction("foo");6389 Function &LLVMBar = *M->getFunction("bar");6390 sandboxir::Context Ctx(C);6391 // This will create a Function object for @bar().6392 Ctx.createFunction(&LLVMFoo);6393 EXPECT_NE(Ctx.getValue(&LLVMBar), nullptr);6394 // This should not crash, even though there is already a value for LLVMBar.6395 Ctx.createFunction(&LLVMBar);6396}6397 6398TEST_F(SandboxIRTest, OpaqueValue) {6399 parseIR(C, R"IR(6400declare void @bar(metadata)6401define void @foo() {6402 call void @bar(metadata !1)6403 call void asm "asm", ""()6404 ret void6405}6406!1 = !{}6407)IR");6408 Function &LLVMFoo = *M->getFunction("foo");6409 sandboxir::Context Ctx(C);6410 auto *F = Ctx.createFunction(&LLVMFoo);6411 auto *BB = &*F->begin();6412 auto It = BB->begin();6413 auto *Call = cast<sandboxir::CallInst>(&*It++);6414 auto *Op0 = Call->getOperand(0);6415 EXPECT_TRUE(isa<sandboxir::OpaqueValue>(Op0));6416 auto *Asm = cast<sandboxir::CallInst>(&*It++);6417 auto *AsmOp0 = Asm->getOperand(0);6418 EXPECT_TRUE(isa<sandboxir::OpaqueValue>(AsmOp0));6419}6420