brintos

brintos / llvm-project-archived public Read only

0
0
Text · 56.0 KiB · 9c18247 Raw
1921 lines · cpp
1//===- TrackerTest.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/Function.h"12#include "llvm/IR/Instruction.h"13#include "llvm/IR/Module.h"14#include "llvm/SandboxIR/Function.h"15#include "llvm/SandboxIR/Instruction.h"16#include "llvm/Support/SourceMgr.h"17#include "gmock/gmock-matchers.h"18#include "gtest/gtest.h"19 20using namespace llvm;21 22struct TrackerTest : public testing::Test {23  LLVMContext C;24  std::unique_ptr<Module> M;25 26  void parseIR(LLVMContext &C, const char *IR) {27    SMDiagnostic Err;28    M = parseAssemblyString(IR, Err, C);29    if (!M)30      Err.print("TrackerTest", errs());31  }32  BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {33    for (BasicBlock &BB : F)34      if (BB.getName() == Name)35        return &BB;36    llvm_unreachable("Expected to find basic block!");37  }38};39 40TEST_F(TrackerTest, SetOperand) {41  parseIR(C, R"IR(42define void @foo(ptr %ptr) {43  %gep0 = getelementptr float, ptr %ptr, i32 044  %gep1 = getelementptr float, ptr %ptr, i32 145  %ld0 = load float, ptr %gep046  store float undef, ptr %gep047  ret void48}49)IR");50  Function &LLVMF = *M->getFunction("foo");51  sandboxir::Context Ctx(C);52  auto *F = Ctx.createFunction(&LLVMF);53  auto *BB = &*F->begin();54  auto &Tracker = Ctx.getTracker();55  // Check empty().56  EXPECT_TRUE(Ctx.getTracker().empty());57 58  Tracker.save();59  auto It = BB->begin();60  auto *Gep0 = &*It++;61  auto *Gep1 = &*It++;62  auto *Ld = &*It++;63  auto *St = &*It++;64  St->setOperand(0, Ld);65  St->setOperand(1, Gep1);66  Ld->setOperand(0, Gep1);67  EXPECT_EQ(St->getOperand(0), Ld);68  EXPECT_EQ(St->getOperand(1), Gep1);69  EXPECT_EQ(Ld->getOperand(0), Gep1);70 71  // Check empty().72  EXPECT_FALSE(Ctx.getTracker().empty());73 74  Ctx.getTracker().revert();75  EXPECT_NE(St->getOperand(0), Ld);76  EXPECT_EQ(St->getOperand(1), Gep0);77  EXPECT_EQ(Ld->getOperand(0), Gep0);78}79 80TEST_F(TrackerTest, SetUse) {81  parseIR(C, R"IR(82define void @foo(ptr %ptr, i8 %arg) {83  %ld = load i8, ptr %ptr84  %add = add i8 %ld, %arg85  ret void86}87)IR");88  Function &LLVMF = *M->getFunction("foo");89  sandboxir::Context Ctx(C);90  auto *F = Ctx.createFunction(&LLVMF);91  unsigned ArgIdx = 0;92  auto *Arg0 = F->getArg(ArgIdx++);93  auto *BB = &*F->begin();94  auto &Tracker = Ctx.getTracker();95  Tracker.save();96  auto It = BB->begin();97  auto *Ld = &*It++;98  auto *Add = &*It++;99 100  Ctx.save();101  sandboxir::Use Use = Add->getOperandUse(0);102  Use.set(Arg0);103  EXPECT_EQ(Add->getOperand(0), Arg0);104  Ctx.revert();105  EXPECT_EQ(Add->getOperand(0), Ld);106}107 108TEST_F(TrackerTest, SwapOperands) {109  parseIR(C, R"IR(110define void @foo(i1 %cond) {111 bb0:112   br i1 %cond, label %bb1, label %bb2113 bb1:114   ret void115 bb2:116   ret void117}118)IR");119  Function &LLVMF = *M->getFunction("foo");120  sandboxir::Context Ctx(C);121  Ctx.createFunction(&LLVMF);122  auto *BB0 = cast<sandboxir::BasicBlock>(123      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));124  auto *BB1 = cast<sandboxir::BasicBlock>(125      Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));126  auto *BB2 = cast<sandboxir::BasicBlock>(127      Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));128  auto &Tracker = Ctx.getTracker();129  Tracker.save();130  auto It = BB0->begin();131  auto *Br = cast<sandboxir::BranchInst>(&*It++);132 133  unsigned SuccIdx = 0;134  SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1});135  for (auto *Succ : Br->successors())136    EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);137 138  // This calls User::swapOperandsInternal() internally.139  Br->swapSuccessors();140 141  SuccIdx = 0;142  for (auto *Succ : reverse(Br->successors()))143    EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);144 145  Ctx.getTracker().revert();146  SuccIdx = 0;147  for (auto *Succ : Br->successors())148    EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);149}150 151TEST_F(TrackerTest, RUWIf_RAUW_RUOW) {152  parseIR(C, R"IR(153define void @foo(ptr %ptr) {154  %ld0 = load float, ptr %ptr155  %ld1 = load float, ptr %ptr156  store float %ld0, ptr %ptr157  store float %ld0, ptr %ptr158  ret void159}160)IR");161  llvm::Function &LLVMF = *M->getFunction("foo");162  sandboxir::Context Ctx(C);163  llvm::BasicBlock *LLVMBB = &*LLVMF.begin();164  Ctx.createFunction(&LLVMF);165  auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));166  auto It = BB->begin();167  sandboxir::Instruction *Ld0 = &*It++;168  sandboxir::Instruction *Ld1 = &*It++;169  sandboxir::Instruction *St0 = &*It++;170  sandboxir::Instruction *St1 = &*It++;171  Ctx.save();172  // Check RUWIf when the lambda returns false.173  Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; });174  EXPECT_EQ(St0->getOperand(0), Ld0);175  EXPECT_EQ(St1->getOperand(0), Ld0);176 177  // Check RUWIf when the lambda returns true.178  Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; });179  EXPECT_EQ(St0->getOperand(0), Ld1);180  EXPECT_EQ(St1->getOperand(0), Ld1);181  Ctx.revert();182  EXPECT_EQ(St0->getOperand(0), Ld0);183  EXPECT_EQ(St1->getOperand(0), Ld0);184 185  // Check RUWIf user == St0.186  Ctx.save();187  Ld0->replaceUsesWithIf(188      Ld1, [St0](const sandboxir::Use &Use) { return Use.getUser() == St0; });189  EXPECT_EQ(St0->getOperand(0), Ld1);190  EXPECT_EQ(St1->getOperand(0), Ld0);191  Ctx.revert();192  EXPECT_EQ(St0->getOperand(0), Ld0);193  EXPECT_EQ(St1->getOperand(0), Ld0);194 195  // Check RUWIf user == St1.196  Ctx.save();197  Ld0->replaceUsesWithIf(198      Ld1, [St1](const sandboxir::Use &Use) { return Use.getUser() == St1; });199  EXPECT_EQ(St0->getOperand(0), Ld0);200  EXPECT_EQ(St1->getOperand(0), Ld1);201  Ctx.revert();202  EXPECT_EQ(St0->getOperand(0), Ld0);203  EXPECT_EQ(St1->getOperand(0), Ld0);204 205  // Check RAUW.206  Ctx.save();207  Ld1->replaceAllUsesWith(Ld0);208  EXPECT_EQ(St0->getOperand(0), Ld0);209  EXPECT_EQ(St1->getOperand(0), Ld0);210  Ctx.revert();211  EXPECT_EQ(St0->getOperand(0), Ld0);212  EXPECT_EQ(St1->getOperand(0), Ld0);213 214  // Check RUOW.215  Ctx.save();216  St0->replaceUsesOfWith(Ld0, Ld1);217  EXPECT_EQ(St0->getOperand(0), Ld1);218  Ctx.revert();219  EXPECT_EQ(St0->getOperand(0), Ld0);220 221  // Check accept().222  Ctx.save();223  St0->replaceUsesOfWith(Ld0, Ld1);224  EXPECT_EQ(St0->getOperand(0), Ld1);225  Ctx.accept();226  EXPECT_EQ(St0->getOperand(0), Ld1);227}228 229// TODO: Test multi-instruction patterns.230TEST_F(TrackerTest, EraseFromParent) {231  parseIR(C, R"IR(232define void @foo(i32 %v1) {233  %add0 = add i32 %v1, %v1234  %add1 = add i32 %add0, %v1235  ret void236}237)IR");238  Function &LLVMF = *M->getFunction("foo");239  sandboxir::Context Ctx(C);240 241  auto *F = Ctx.createFunction(&LLVMF);242  auto *BB = &*F->begin();243  auto It = BB->begin();244  sandboxir::Instruction *Add0 = &*It++;245  sandboxir::Instruction *Add1 = &*It++;246  sandboxir::Instruction *Ret = &*It++;247 248  Ctx.save();249  // Check erase.250  Add1->eraseFromParent();251  It = BB->begin();252  EXPECT_EQ(&*It++, Add0);253  EXPECT_EQ(&*It++, Ret);254  EXPECT_EQ(It, BB->end());255  EXPECT_EQ(Add0->getNumUses(), 0u);256 257  // Check revert().258  Ctx.revert();259  It = BB->begin();260  EXPECT_EQ(&*It++, Add0);261  EXPECT_EQ(&*It++, Add1);262  EXPECT_EQ(&*It++, Ret);263  EXPECT_EQ(It, BB->end());264  EXPECT_EQ(Add1->getOperand(0), Add0);265 266  // Same for the last instruction in the block.267  Ctx.save();268  Ret->eraseFromParent();269  It = BB->begin();270  EXPECT_EQ(&*It++, Add0);271  EXPECT_EQ(&*It++, Add1);272  EXPECT_EQ(It, BB->end());273  Ctx.revert();274  It = BB->begin();275  EXPECT_EQ(&*It++, Add0);276  EXPECT_EQ(&*It++, Add1);277  EXPECT_EQ(&*It++, Ret);278  EXPECT_EQ(It, BB->end());279}280 281// TODO: Test multi-instruction patterns.282TEST_F(TrackerTest, RemoveFromParent) {283  parseIR(C, R"IR(284define i32 @foo(i32 %arg) {285  %add0 = add i32 %arg, %arg286  %add1 = add i32 %add0, %arg287  ret i32 %add1288}289)IR");290  Function &LLVMF = *M->getFunction("foo");291  sandboxir::Context Ctx(C);292 293  auto *F = Ctx.createFunction(&LLVMF);294  auto *Arg = F->getArg(0);295  auto *BB = &*F->begin();296  auto It = BB->begin();297  sandboxir::Instruction *Add0 = &*It++;298  sandboxir::Instruction *Add1 = &*It++;299  sandboxir::Instruction *Ret = &*It++;300 301  Ctx.save();302  // Check removeFromParent().303  Add1->removeFromParent();304  It = BB->begin();305  EXPECT_EQ(&*It++, Add0);306  EXPECT_EQ(&*It++, Ret);307  EXPECT_EQ(It, BB->end());308  // Removed instruction still be connected to operands and users.309  EXPECT_EQ(Add1->getOperand(0), Add0);310  EXPECT_EQ(Add1->getOperand(1), Arg);311  EXPECT_EQ(Add0->getNumUses(), 1u);312 313  // Check revert().314  Ctx.revert();315  It = BB->begin();316  EXPECT_EQ(&*It++, Add0);317  EXPECT_EQ(&*It++, Add1);318  EXPECT_EQ(&*It++, Ret);319  EXPECT_EQ(It, BB->end());320  EXPECT_EQ(Add1->getOperand(0), Add0);321 322  // Same for the last instruction in the block.323  Ctx.save();324  Ret->removeFromParent();325  It = BB->begin();326  EXPECT_EQ(&*It++, Add0);327  EXPECT_EQ(&*It++, Add1);328  EXPECT_EQ(It, BB->end());329  EXPECT_EQ(Ret->getOperand(0), Add1);330  Ctx.revert();331  It = BB->begin();332  EXPECT_EQ(&*It++, Add0);333  EXPECT_EQ(&*It++, Add1);334  EXPECT_EQ(&*It++, Ret);335  EXPECT_EQ(It, BB->end());336}337 338// TODO: Test multi-instruction patterns.339TEST_F(TrackerTest, MoveInstr) {340  parseIR(C, R"IR(341define i32 @foo(i32 %arg) {342  %add0 = add i32 %arg, %arg343  %add1 = add i32 %add0, %arg344  ret i32 %add1345}346)IR");347  Function &LLVMF = *M->getFunction("foo");348  sandboxir::Context Ctx(C);349 350  auto *F = Ctx.createFunction(&LLVMF);351  auto *BB = &*F->begin();352  auto It = BB->begin();353  sandboxir::Instruction *Add0 = &*It++;354  sandboxir::Instruction *Add1 = &*It++;355  sandboxir::Instruction *Ret = &*It++;356 357  // Check moveBefore(Instruction *) with tracking enabled.358  Ctx.save();359  Add1->moveBefore(Add0);360  It = BB->begin();361  EXPECT_EQ(&*It++, Add1);362  EXPECT_EQ(&*It++, Add0);363  EXPECT_EQ(&*It++, Ret);364  EXPECT_EQ(It, BB->end());365  // Check revert().366  Ctx.revert();367  It = BB->begin();368  EXPECT_EQ(&*It++, Add0);369  EXPECT_EQ(&*It++, Add1);370  EXPECT_EQ(&*It++, Ret);371  EXPECT_EQ(It, BB->end());372 373  // Same for the last instruction in the block.374  Ctx.save();375  Ret->moveBefore(Add0);376  It = BB->begin();377  EXPECT_EQ(&*It++, Ret);378  EXPECT_EQ(&*It++, Add0);379  EXPECT_EQ(&*It++, Add1);380  EXPECT_EQ(It, BB->end());381  Ctx.revert();382  It = BB->begin();383  EXPECT_EQ(&*It++, Add0);384  EXPECT_EQ(&*It++, Add1);385  EXPECT_EQ(&*It++, Ret);386  EXPECT_EQ(It, BB->end());387 388  // Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.389  Ctx.save();390  Add1->moveBefore(*BB, Add0->getIterator());391  It = BB->begin();392  EXPECT_EQ(&*It++, Add1);393  EXPECT_EQ(&*It++, Add0);394  EXPECT_EQ(&*It++, Ret);395  EXPECT_EQ(It, BB->end());396  // Check revert().397  Ctx.revert();398  It = BB->begin();399  EXPECT_EQ(&*It++, Add0);400  EXPECT_EQ(&*It++, Add1);401  EXPECT_EQ(&*It++, Ret);402  EXPECT_EQ(It, BB->end());403 404  // Same for the last instruction in the block.405  Ctx.save();406  Ret->moveBefore(*BB, Add0->getIterator());407  It = BB->begin();408  EXPECT_EQ(&*It++, Ret);409  EXPECT_EQ(&*It++, Add0);410  EXPECT_EQ(&*It++, Add1);411  EXPECT_EQ(It, BB->end());412  // Check revert().413  Ctx.revert();414  It = BB->begin();415  EXPECT_EQ(&*It++, Add0);416  EXPECT_EQ(&*It++, Add1);417  EXPECT_EQ(&*It++, Ret);418  EXPECT_EQ(It, BB->end());419 420  // Check moveAfter(Instruction *) with tracking enabled.421  Ctx.save();422  Add0->moveAfter(Add1);423  It = BB->begin();424  EXPECT_EQ(&*It++, Add1);425  EXPECT_EQ(&*It++, Add0);426  EXPECT_EQ(&*It++, Ret);427  EXPECT_EQ(It, BB->end());428  // Check revert().429  Ctx.revert();430  It = BB->begin();431  EXPECT_EQ(&*It++, Add0);432  EXPECT_EQ(&*It++, Add1);433  EXPECT_EQ(&*It++, Ret);434  EXPECT_EQ(It, BB->end());435 436  // Same for the last instruction in the block.437  Ctx.save();438  Ret->moveAfter(Add0);439  It = BB->begin();440  EXPECT_EQ(&*It++, Add0);441  EXPECT_EQ(&*It++, Ret);442  EXPECT_EQ(&*It++, Add1);443  EXPECT_EQ(It, BB->end());444  // Check revert().445  Ctx.revert();446  It = BB->begin();447  EXPECT_EQ(&*It++, Add0);448  EXPECT_EQ(&*It++, Add1);449  EXPECT_EQ(&*It++, Ret);450  EXPECT_EQ(It, BB->end());451}452 453// TODO: Test multi-instruction patterns.454TEST_F(TrackerTest, InsertIntoBB) {455  parseIR(C, R"IR(456define void @foo(i32 %arg) {457  %add0 = add i32 %arg, %arg458  ret void459}460)IR");461  Function &LLVMF = *M->getFunction("foo");462  sandboxir::Context Ctx(C);463 464  auto *F = Ctx.createFunction(&LLVMF);465  auto *BB = &*F->begin();466  auto It = BB->begin();467  sandboxir::Instruction *Add0 = &*It++;468  sandboxir::Instruction *Ret = &*It++;469  // Detach `Add0` before we save.470  Add0->removeFromParent();471 472  // Check insertBefore(Instruction *) with tracking enabled.473  Ctx.save();474  Add0->insertBefore(Ret);475  It = BB->begin();476  EXPECT_EQ(&*It++, Add0);477  EXPECT_EQ(&*It++, Ret);478  EXPECT_EQ(It, BB->end());479  // Check revert().480  Ctx.revert();481  It = BB->begin();482  EXPECT_EQ(&*It++, Ret);483  EXPECT_EQ(It, BB->end());484 485  // Check insertAfter(Instruction *) with tracking enabled.486  Ctx.save();487  Add0->insertAfter(Ret);488  It = BB->begin();489  EXPECT_EQ(&*It++, Ret);490  EXPECT_EQ(&*It++, Add0);491  EXPECT_EQ(It, BB->end());492  // Check revert().493  Ctx.revert();494  It = BB->begin();495  EXPECT_EQ(&*It++, Ret);496  EXPECT_EQ(It, BB->end());497 498  // Check insertInto(BasicBlock *, BasicBlock::iterator) with tracking enabled.499  Ctx.save();500  Add0->insertInto(BB, Ret->getIterator());501  It = BB->begin();502  EXPECT_EQ(&*It++, Add0);503  EXPECT_EQ(&*It++, Ret);504  EXPECT_EQ(It, BB->end());505  // Check revert().506  Ctx.revert();507  It = BB->begin();508  EXPECT_EQ(&*It++, Ret);509  EXPECT_EQ(It, BB->end());510 511  // To make sure we don't leak memory insert `Add0` back into the BB before the512  // end of the test.513  Add0->insertBefore(Ret);514}515 516// TODO: Test multi-instruction patterns.517TEST_F(TrackerTest, CreateAndInsertInst) {518  parseIR(C, R"IR(519define void @foo(ptr %ptr) {520  %ld = load i8, ptr %ptr, align 64521  ret void522}523)IR");524  Function &LLVMF = *M->getFunction("foo");525  sandboxir::Context Ctx(C);526 527  auto *F = Ctx.createFunction(&LLVMF);528  auto *Ptr = F->getArg(0);529  auto *BB = &*F->begin();530  auto It = BB->begin();531  auto *Ld = cast<sandboxir::LoadInst>(&*It++);532  auto *Ret = &*It++;533 534  Ctx.save();535  // Check create(InsertBefore) with tracking enabled.536  sandboxir::LoadInst *NewLd = sandboxir::LoadInst::create(537      Ld->getType(), Ptr, Align(8),538      /*InsertBefore=*/Ld->getIterator(), Ctx, "NewLd");539  It = BB->begin();540  EXPECT_EQ(&*It++, NewLd);541  EXPECT_EQ(&*It++, Ld);542  EXPECT_EQ(&*It++, Ret);543  EXPECT_EQ(It, BB->end());544  // Check revert().545  Ctx.revert();546  It = BB->begin();547  EXPECT_EQ(&*It++, Ld);548  EXPECT_EQ(&*It++, Ret);549  EXPECT_EQ(It, BB->end());550}551 552TEST_F(TrackerTest, FenceInstSetters) {553  parseIR(C, R"IR(554define void @foo() {555  fence syncscope("singlethread") seq_cst556  ret void557}558)IR");559  llvm::Function *LLVMF = &*M->getFunction("foo");560  sandboxir::Context Ctx(C);561  sandboxir::Function *F = Ctx.createFunction(LLVMF);562  auto *BB = &*F->begin();563  auto It = BB->begin();564  auto *Fence = cast<sandboxir::FenceInst>(&*It++);565 566  // Check setOrdering().567  auto OrigOrdering = Fence->getOrdering();568  auto NewOrdering = AtomicOrdering::Release;569  EXPECT_NE(NewOrdering, OrigOrdering);570  Ctx.save();571  Fence->setOrdering(NewOrdering);572  EXPECT_EQ(Fence->getOrdering(), NewOrdering);573  Ctx.revert();574  EXPECT_EQ(Fence->getOrdering(), OrigOrdering);575  // Check setSyncScopeID().576  auto OrigSSID = Fence->getSyncScopeID();577  auto NewSSID = SyncScope::System;578  EXPECT_NE(NewSSID, OrigSSID);579  Ctx.save();580  Fence->setSyncScopeID(NewSSID);581  EXPECT_EQ(Fence->getSyncScopeID(), NewSSID);582  Ctx.revert();583  EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID);584}585 586TEST_F(TrackerTest, CallBaseSetters) {587  parseIR(C, R"IR(588declare void @bar1(i8)589declare void @bar2(i8)590 591define void @foo(i8 %arg0, i8 %arg1) {592  call void @bar1(i8 %arg0)593  ret void594}595)IR");596  Function &LLVMF = *M->getFunction("foo");597  sandboxir::Context Ctx(C);598 599  auto *F = Ctx.createFunction(&LLVMF);600  unsigned ArgIdx = 0;601  auto *Arg0 = F->getArg(ArgIdx++);602  auto *Arg1 = F->getArg(ArgIdx++);603  auto *BB = &*F->begin();604  auto It = BB->begin();605  auto *Call = cast<sandboxir::CallBase>(&*It++);606  [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);607 608  // Check setArgOperand().609  Ctx.save();610  Call->setArgOperand(0, Arg1);611  EXPECT_EQ(Call->getArgOperand(0), Arg1);612  Ctx.revert();613  EXPECT_EQ(Call->getArgOperand(0), Arg0);614 615  auto *Bar1F = Call->getCalledFunction();616  auto *Bar2F = Ctx.createFunction(M->getFunction("bar2"));617 618  // Check setCalledOperand().619  Ctx.save();620  Call->setCalledOperand(Bar2F);621  EXPECT_EQ(Call->getCalledOperand(), Bar2F);622  Ctx.revert();623  EXPECT_EQ(Call->getCalledOperand(), Bar1F);624 625  // Check setCalledFunction().626  Ctx.save();627  Call->setCalledFunction(Bar2F);628  EXPECT_EQ(Call->getCalledFunction(), Bar2F);629  Ctx.revert();630  EXPECT_EQ(Call->getCalledFunction(), Bar1F);631}632 633TEST_F(TrackerTest, InvokeSetters) {634  parseIR(C, R"IR(635define void @foo(i8 %arg) {636 bb0:637   invoke i8 @foo(i8 %arg) to label %normal_bb638                       unwind label %exception_bb639 normal_bb:640   ret void641 exception_bb:642   ret void643 other_bb:644   ret void645}646)IR");647  Function &LLVMF = *M->getFunction("foo");648  sandboxir::Context Ctx(C);649  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);650  auto *BB0 = cast<sandboxir::BasicBlock>(651      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));652  auto *NormalBB = cast<sandboxir::BasicBlock>(653      Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));654  auto *ExceptionBB = cast<sandboxir::BasicBlock>(655      Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));656  auto *OtherBB = cast<sandboxir::BasicBlock>(657      Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));658  auto It = BB0->begin();659  auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);660 661  // Check setNormalDest().662  Ctx.save();663  Invoke->setNormalDest(OtherBB);664  EXPECT_EQ(Invoke->getNormalDest(), OtherBB);665  Ctx.revert();666  EXPECT_EQ(Invoke->getNormalDest(), NormalBB);667 668  // Check setUnwindDest().669  Ctx.save();670  Invoke->setUnwindDest(OtherBB);671  EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);672  Ctx.revert();673  EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);674 675  // Check setSuccessor().676  Ctx.save();677  Invoke->setSuccessor(0, OtherBB);678  EXPECT_EQ(Invoke->getSuccessor(0), OtherBB);679  Ctx.revert();680  EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);681 682  Ctx.save();683  Invoke->setSuccessor(1, OtherBB);684  EXPECT_EQ(Invoke->getSuccessor(1), OtherBB);685  Ctx.revert();686  EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);687}688 689TEST_F(TrackerTest, CatchSwitchInst) {690  parseIR(C, R"IR(691define void @foo(i32 %cond0, i32 %cond1) {692  bb0:693    %cs0 = catchswitch within none [label %handler0, label %handler1] unwind to caller694  bb1:695    %cs1 = catchswitch within %cs0 [label %handler0, label %handler1] unwind label %cleanup696  handler0:697    ret void698  handler1:699    ret void700  cleanup:701    ret void702}703)IR");704  Function &LLVMF = *M->getFunction("foo");705 706  sandboxir::Context Ctx(C);707  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);708  auto *BB0 = cast<sandboxir::BasicBlock>(709      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));710  auto *BB1 = cast<sandboxir::BasicBlock>(711      Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));712  auto *Handler0 = cast<sandboxir::BasicBlock>(713      Ctx.getValue(getBasicBlockByName(LLVMF, "handler0")));714  auto *Handler1 = cast<sandboxir::BasicBlock>(715      Ctx.getValue(getBasicBlockByName(LLVMF, "handler1")));716  auto *CS0 = cast<sandboxir::CatchSwitchInst>(&*BB0->begin());717  auto *CS1 = cast<sandboxir::CatchSwitchInst>(&*BB1->begin());718 719  // Check setParentPad().720  auto *OrigPad = CS0->getParentPad();721  auto *NewPad = CS1;722  EXPECT_NE(NewPad, OrigPad);723  Ctx.save();724  CS0->setParentPad(NewPad);725  EXPECT_EQ(CS0->getParentPad(), NewPad);726  Ctx.revert();727  EXPECT_EQ(CS0->getParentPad(), OrigPad);728  // Check setUnwindDest().729  auto *OrigUnwindDest = CS1->getUnwindDest();730  auto *NewUnwindDest = BB0;731  EXPECT_NE(NewUnwindDest, OrigUnwindDest);732  Ctx.save();733  CS1->setUnwindDest(NewUnwindDest);734  EXPECT_EQ(CS1->getUnwindDest(), NewUnwindDest);735  Ctx.revert();736  EXPECT_EQ(CS1->getUnwindDest(), OrigUnwindDest);737  // Check setSuccessor().738  auto *OrigSuccessor = CS0->getSuccessor(0);739  auto *NewSuccessor = BB0;740  EXPECT_NE(NewSuccessor, OrigSuccessor);741  Ctx.save();742  CS0->setSuccessor(0, NewSuccessor);743  EXPECT_EQ(CS0->getSuccessor(0), NewSuccessor);744  Ctx.revert();745  EXPECT_EQ(CS0->getSuccessor(0), OrigSuccessor);746  // Check addHandler().747  Ctx.save();748  CS0->addHandler(BB0);749  EXPECT_EQ(CS0->getNumHandlers(), 3u);750  Ctx.revert();751  EXPECT_EQ(CS0->getNumHandlers(), 2u);752  auto HIt = CS0->handler_begin();753  EXPECT_EQ(*HIt++, Handler0);754  EXPECT_EQ(*HIt++, Handler1);755}756 757TEST_F(TrackerTest, LandingPadInstSetters) {758  parseIR(C, R"IR(759define void @foo() {760entry:761  invoke void @foo()762      to label %bb unwind label %unwind763unwind:764  %lpad = landingpad { ptr, i32 }765            catch ptr null766  ret void767bb:768  ret void769}770)IR");771  Function &LLVMF = *M->getFunction("foo");772  auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");773 774  sandboxir::Context Ctx(C);775  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);776  auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));777  auto It = Unwind->begin();778  auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);779  [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);780 781  // Check setCleanup().782  auto OrigIsCleanup = LPad->isCleanup();783  auto NewIsCleanup = true;784  EXPECT_NE(NewIsCleanup, OrigIsCleanup);785  Ctx.save();786  LPad->setCleanup(NewIsCleanup);787  EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);788  Ctx.revert();789  EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);790}791 792TEST_F(TrackerTest, CatchReturnInstSetters) {793  parseIR(C, R"IR(794define void @foo() {795dispatch:796  %cs = catchswitch within none [label %catch] unwind to caller797catch:798  %catchpad = catchpad within %cs [ptr @foo]799  catchret from %catchpad to label %continue800continue:801  ret void802catch2:803  %catchpad2 = catchpad within %cs [ptr @foo]804  ret void805}806)IR");807  Function &LLVMF = *M->getFunction("foo");808  BasicBlock *LLVMCatch = getBasicBlockByName(LLVMF, "catch");809  auto LLVMIt = LLVMCatch->begin();810  [[maybe_unused]] auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMIt++);811 812  sandboxir::Context Ctx(C);813  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);814  auto *Catch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCatch));815  auto *Catch2 = cast<sandboxir::BasicBlock>(816      Ctx.getValue(getBasicBlockByName(LLVMF, "catch2")));817  auto It = Catch->begin();818  [[maybe_unused]] auto *CP = cast<sandboxir::CatchPadInst>(&*It++);819  auto *CR = cast<sandboxir::CatchReturnInst>(&*It++);820  auto *CP2 = cast<sandboxir::CatchPadInst>(&*Catch2->begin());821 822  // Check setCatchPad().823  auto *OrigCP = CR->getCatchPad();824  auto *NewCP = CP2;825  EXPECT_NE(NewCP, OrigCP);826  Ctx.save();827  CR->setCatchPad(NewCP);828  EXPECT_EQ(CR->getCatchPad(), NewCP);829  Ctx.revert();830  EXPECT_EQ(CR->getCatchPad(), OrigCP);831  // Check setSuccessor().832  auto *OrigSucc = CR->getSuccessor();833  auto *NewSucc = Catch;834  EXPECT_NE(NewSucc, OrigSucc);835  Ctx.save();836  CR->setSuccessor(NewSucc);837  EXPECT_EQ(CR->getSuccessor(), NewSucc);838  Ctx.revert();839  EXPECT_EQ(CR->getSuccessor(), OrigSucc);840}841 842TEST_F(TrackerTest, CleanupReturnInstSetters) {843  parseIR(C, R"IR(844define void @foo() {845dispatch:846  invoke void @foo()847              to label %throw unwind label %cleanup848throw:849  ret void850cleanup:851  %cleanuppad = cleanuppad within none []852  cleanupret from %cleanuppad unwind label %cleanup2853cleanup2:854  %cleanuppad2 = cleanuppad within none []855  ret void856}857)IR");858  Function &LLVMF = *M->getFunction("foo");859  BasicBlock *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup");860 861  sandboxir::Context Ctx(C);862  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);863  auto *Throw = cast<sandboxir::BasicBlock>(864      Ctx.getValue(getBasicBlockByName(LLVMF, "throw")));865  auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup));866  auto *Cleanup2 = cast<sandboxir::BasicBlock>(867      Ctx.getValue(getBasicBlockByName(LLVMF, "cleanup2")));868  auto It = Cleanup->begin();869  [[maybe_unused]] auto *CP = cast<sandboxir::CleanupPadInst>(&*It++);870  auto *CRI = cast<sandboxir::CleanupReturnInst>(&*It++);871  auto *CP2 = cast<sandboxir::CleanupPadInst>(&*Cleanup2->begin());872 873  // Check setCleanupPad().874  auto *OrigCleanupPad = CRI->getCleanupPad();875  auto *NewCleanupPad = CP2;876  EXPECT_NE(NewCleanupPad, OrigCleanupPad);877  Ctx.save();878  CRI->setCleanupPad(NewCleanupPad);879  EXPECT_EQ(CRI->getCleanupPad(), NewCleanupPad);880  Ctx.revert();881  EXPECT_EQ(CRI->getCleanupPad(), OrigCleanupPad);882  // Check setUnwindDest().883  auto *OrigUnwindDest = CRI->getUnwindDest();884  auto *NewUnwindDest = Throw;885  EXPECT_NE(NewUnwindDest, OrigUnwindDest);886  Ctx.save();887  CRI->setUnwindDest(NewUnwindDest);888  EXPECT_EQ(CRI->getUnwindDest(), NewUnwindDest);889  Ctx.revert();890  EXPECT_EQ(CRI->getUnwindDest(), OrigUnwindDest);891}892 893TEST_F(TrackerTest, SwitchInstSetters) {894  parseIR(C, R"IR(895define void @foo(i32 %cond0, i32 %cond1) {896  entry:897    switch i32 %cond0, label %default [ i32 0, label %bb0898                                        i32 1, label %bb1 ]899  bb0:900    ret void901  bb1:902    ret void903  default:904    ret void905}906)IR");907  Function &LLVMF = *M->getFunction("foo");908  auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry");909 910  sandboxir::Context Ctx(C);911  auto &F = *Ctx.createFunction(&LLVMF);912  auto *Cond1 = F.getArg(1);913  auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry));914  auto *BB0 = cast<sandboxir::BasicBlock>(915      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));916  auto *BB1 = cast<sandboxir::BasicBlock>(917      Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));918  auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin());919 920  // Check setCondition().921  auto *OrigCond = Switch->getCondition();922  auto *NewCond = Cond1;923  EXPECT_NE(NewCond, OrigCond);924  Ctx.save();925  Switch->setCondition(NewCond);926  EXPECT_EQ(Switch->getCondition(), NewCond);927  Ctx.revert();928  EXPECT_EQ(Switch->getCondition(), OrigCond);929  // Check setDefaultDest().930  auto *OrigDefaultDest = Switch->getDefaultDest();931  auto *NewDefaultDest = Entry;932  EXPECT_NE(NewDefaultDest, OrigDefaultDest);933  Ctx.save();934  Switch->setDefaultDest(NewDefaultDest);935  EXPECT_EQ(Switch->getDefaultDest(), NewDefaultDest);936  Ctx.revert();937  EXPECT_EQ(Switch->getDefaultDest(), OrigDefaultDest);938  // Check setSuccessor().939  auto *OrigSucc = Switch->getSuccessor(0);940  auto *NewSucc = Entry;941  EXPECT_NE(NewSucc, OrigSucc);942  Ctx.save();943  Switch->setSuccessor(0, NewSucc);944  EXPECT_EQ(Switch->getSuccessor(0), NewSucc);945  Ctx.revert();946  EXPECT_EQ(Switch->getSuccessor(0), OrigSucc);947  // Check addCase().948  auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);949  auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1);950  auto *FortyTwo =951      sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);952  Ctx.save();953  Switch->addCase(FortyTwo, Entry);954  EXPECT_EQ(Switch->getNumCases(), 3u);955  EXPECT_EQ(Switch->findCaseDest(Entry), FortyTwo);956  EXPECT_EQ(Switch->findCaseValue(FortyTwo)->getCaseSuccessor(), Entry);957  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);958  EXPECT_EQ(Switch->findCaseDest(BB1), One);959  Ctx.revert();960  EXPECT_EQ(Switch->getNumCases(), 2u);961  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);962  EXPECT_EQ(Switch->findCaseDest(BB1), One);963  // Check removeCase().964  Ctx.save();965  Switch->removeCase(Switch->findCaseValue(Zero));966  EXPECT_EQ(Switch->getNumCases(), 1u);967  EXPECT_EQ(Switch->findCaseDest(BB1), One);968  Ctx.revert();969  EXPECT_EQ(Switch->getNumCases(), 2u);970  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);971  EXPECT_EQ(Switch->findCaseDest(BB1), One);972}973 974TEST_F(TrackerTest, SwitchInstPreservesSuccesorOrder) {975  parseIR(C, R"IR(976define void @foo(i32 %cond0) {977  entry:978    switch i32 %cond0, label %default [ i32 0, label %bb0979                                        i32 1, label %bb1980                                        i32 2, label %bb2 ]981  bb0:982    ret void983  bb1:984    ret void985  bb2:986    ret void987  default:988    ret void989}990)IR");991  Function &LLVMF = *M->getFunction("foo");992  auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry");993 994  sandboxir::Context Ctx(C);995  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);996  auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry));997  auto *BB0 = cast<sandboxir::BasicBlock>(998      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));999  auto *BB1 = cast<sandboxir::BasicBlock>(1000      Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));1001  auto *BB2 = cast<sandboxir::BasicBlock>(1002      Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));1003  auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin());1004 1005  auto *DefaultDest = Switch->getDefaultDest();1006  auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);1007  auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1);1008  auto *Two = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 2);1009 1010  // Check that we can properly revert a removeCase multiple positions apart1011  // from the end of the operand list.1012  Ctx.save();1013  Switch->removeCase(Switch->findCaseValue(Zero));1014  EXPECT_EQ(Switch->getNumCases(), 2u);1015  Ctx.revert();1016  EXPECT_EQ(Switch->getNumCases(), 3u);1017  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);1018  EXPECT_EQ(Switch->findCaseDest(BB1), One);1019  EXPECT_EQ(Switch->findCaseDest(BB2), Two);1020  EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);1021  EXPECT_EQ(Switch->getSuccessor(1), BB0);1022  EXPECT_EQ(Switch->getSuccessor(2), BB1);1023  EXPECT_EQ(Switch->getSuccessor(3), BB2);1024 1025  // Check that we can properly revert a removeCase of the last case.1026  Ctx.save();1027  Switch->removeCase(Switch->findCaseValue(Two));1028  EXPECT_EQ(Switch->getNumCases(), 2u);1029  Ctx.revert();1030  EXPECT_EQ(Switch->getNumCases(), 3u);1031  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);1032  EXPECT_EQ(Switch->findCaseDest(BB1), One);1033  EXPECT_EQ(Switch->findCaseDest(BB2), Two);1034  EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);1035  EXPECT_EQ(Switch->getSuccessor(1), BB0);1036  EXPECT_EQ(Switch->getSuccessor(2), BB1);1037  EXPECT_EQ(Switch->getSuccessor(3), BB2);1038 1039  // Check order is preserved after reverting multiple removeCase invocations.1040  Ctx.save();1041  Switch->removeCase(Switch->findCaseValue(One));1042  Switch->removeCase(Switch->findCaseValue(Zero));1043  Switch->removeCase(Switch->findCaseValue(Two));1044  EXPECT_EQ(Switch->getNumCases(), 0u);1045  Ctx.revert();1046  EXPECT_EQ(Switch->getNumCases(), 3u);1047  EXPECT_EQ(Switch->findCaseDest(BB0), Zero);1048  EXPECT_EQ(Switch->findCaseDest(BB1), One);1049  EXPECT_EQ(Switch->findCaseDest(BB2), Two);1050  EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);1051  EXPECT_EQ(Switch->getSuccessor(1), BB0);1052  EXPECT_EQ(Switch->getSuccessor(2), BB1);1053  EXPECT_EQ(Switch->getSuccessor(3), BB2);1054}1055 1056TEST_F(TrackerTest, SelectInst) {1057  parseIR(C, R"IR(1058define void @foo(i1 %c0, i8 %v0, i8 %v1) {1059  %sel = select i1 %c0, i8 %v0, i8 %v11060  ret void1061}1062)IR");1063  llvm::Function *LLVMF = &*M->getFunction("foo");1064  sandboxir::Context Ctx(C);1065  sandboxir::Function *F = Ctx.createFunction(LLVMF);1066  auto *V0 = F->getArg(1);1067  auto *V1 = F->getArg(2);1068  auto *BB = &*F->begin();1069  auto It = BB->begin();1070  auto *Select = cast<sandboxir::SelectInst>(&*It++);1071 1072  // Check tracking for swapValues.1073  Ctx.save();1074  Select->swapValues();1075  EXPECT_EQ(Select->getTrueValue(), V1);1076  EXPECT_EQ(Select->getFalseValue(), V0);1077  Ctx.revert();1078  EXPECT_EQ(Select->getTrueValue(), V0);1079  EXPECT_EQ(Select->getFalseValue(), V1);1080}1081 1082TEST_F(TrackerTest, ShuffleVectorInst) {1083  parseIR(C, R"IR(1084define void @foo(<2 x i8> %v1, <2 x i8> %v2) {1085  %shuf = shufflevector <2 x i8> %v1, <2 x i8> %v2, <2 x i32> <i32 1, i32 2>1086  ret void1087}1088)IR");1089  Function &LLVMF = *M->getFunction("foo");1090  sandboxir::Context Ctx(C);1091 1092  auto *F = Ctx.createFunction(&LLVMF);1093  auto *BB = &*F->begin();1094  auto It = BB->begin();1095  auto *SVI = cast<sandboxir::ShuffleVectorInst>(&*It++);1096 1097  // Check setShuffleMask.1098  SmallVector<int, 2> OrigMask(SVI->getShuffleMask());1099  Ctx.save();1100  SVI->setShuffleMask(ArrayRef<int>({0, 0}));1101  EXPECT_NE(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));1102  Ctx.revert();1103  EXPECT_EQ(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));1104 1105  // Check commute.1106  auto *Op0 = SVI->getOperand(0);1107  auto *Op1 = SVI->getOperand(1);1108  Ctx.save();1109  SVI->commute();1110  EXPECT_EQ(SVI->getOperand(0), Op1);1111  EXPECT_EQ(SVI->getOperand(1), Op0);1112  EXPECT_NE(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));1113  Ctx.revert();1114  EXPECT_EQ(SVI->getOperand(0), Op0);1115  EXPECT_EQ(SVI->getOperand(1), Op1);1116  EXPECT_EQ(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));1117}1118 1119TEST_F(TrackerTest, PossiblyDisjointInstSetters) {1120  parseIR(C, R"IR(1121define void @foo(i8 %arg0, i8 %arg1) {1122  %or = or i8 %arg0, %arg11123  ret void1124}1125)IR");1126  Function &LLVMF = *M->getFunction("foo");1127  sandboxir::Context Ctx(C);1128 1129  auto &F = *Ctx.createFunction(&LLVMF);1130  auto *BB = &*F.begin();1131  auto It = BB->begin();1132  auto *PDI = cast<sandboxir::PossiblyDisjointInst>(&*It++);1133 1134  // Check setIsDisjoint().1135  auto OrigIsDisjoint = PDI->isDisjoint();1136  auto NewIsDisjoint = true;1137  EXPECT_NE(NewIsDisjoint, OrigIsDisjoint);1138  Ctx.save();1139  PDI->setIsDisjoint(NewIsDisjoint);1140  EXPECT_EQ(PDI->isDisjoint(), NewIsDisjoint);1141  Ctx.revert();1142  EXPECT_EQ(PDI->isDisjoint(), OrigIsDisjoint);1143}1144 1145TEST_F(TrackerTest, PossiblyNonNegInstSetters) {1146  parseIR(C, R"IR(1147define void @foo(i32 %arg) {1148  %zext = zext i32 %arg to i641149  ret void1150}1151)IR");1152  Function &LLVMF = *M->getFunction("foo");1153  sandboxir::Context Ctx(C);1154 1155  auto &F = *Ctx.createFunction(&LLVMF);1156  auto *BB = &*F.begin();1157  auto It = BB->begin();1158  auto *PNNI = cast<sandboxir::PossiblyNonNegInst>(&*It++);1159 1160  // Check setNonNeg().1161  auto OrigNonNeg = PNNI->hasNonNeg();1162  auto NewNonNeg = true;1163  EXPECT_NE(NewNonNeg, OrigNonNeg);1164  Ctx.save();1165  PNNI->setNonNeg(NewNonNeg);1166  EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg);1167  Ctx.revert();1168  EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg);1169}1170 1171TEST_F(TrackerTest, AtomicRMWSetters) {1172  parseIR(C, R"IR(1173define void @foo(ptr %ptr, i8 %arg) {1174  %atomicrmw = atomicrmw add ptr %ptr, i8 %arg acquire, align 1281175  ret void1176}1177)IR");1178  Function &LLVMF = *M->getFunction("foo");1179  sandboxir::Context Ctx(C);1180  auto &F = *Ctx.createFunction(&LLVMF);1181  auto *BB = &*F.begin();1182  auto It = BB->begin();1183  auto *RMW = cast<sandboxir::AtomicRMWInst>(&*It++);1184 1185  // Check setAlignment().1186  Ctx.save();1187  auto OrigAlign = RMW->getAlign();1188  Align NewAlign(1024);1189  EXPECT_NE(NewAlign, OrigAlign);1190  RMW->setAlignment(NewAlign);1191  EXPECT_EQ(RMW->getAlign(), NewAlign);1192  Ctx.revert();1193  EXPECT_EQ(RMW->getAlign(), OrigAlign);1194 1195  // Check setVolatile().1196  Ctx.save();1197  auto OrigIsVolatile = RMW->isVolatile();1198  bool NewIsVolatile = true;1199  EXPECT_NE(NewIsVolatile, OrigIsVolatile);1200  RMW->setVolatile(NewIsVolatile);1201  EXPECT_EQ(RMW->isVolatile(), NewIsVolatile);1202  Ctx.revert();1203  EXPECT_EQ(RMW->isVolatile(), OrigIsVolatile);1204 1205  // Check setOrdering().1206  Ctx.save();1207  auto OrigOrdering = RMW->getOrdering();1208  auto NewOrdering = AtomicOrdering::SequentiallyConsistent;1209  EXPECT_NE(NewOrdering, OrigOrdering);1210  RMW->setOrdering(NewOrdering);1211  EXPECT_EQ(RMW->getOrdering(), NewOrdering);1212  Ctx.revert();1213  EXPECT_EQ(RMW->getOrdering(), OrigOrdering);1214 1215  // Check setSyncScopeID().1216  Ctx.save();1217  auto OrigSSID = RMW->getSyncScopeID();1218  auto NewSSID = SyncScope::SingleThread;1219  EXPECT_NE(NewSSID, OrigSSID);1220  RMW->setSyncScopeID(NewSSID);1221  EXPECT_EQ(RMW->getSyncScopeID(), NewSSID);1222  Ctx.revert();1223  EXPECT_EQ(RMW->getSyncScopeID(), OrigSSID);1224}1225 1226TEST_F(TrackerTest, AtomicCmpXchgSetters) {1227  parseIR(C, R"IR(1228define void @foo(ptr %ptr, i8 %cmp, i8 %new) {1229  %cmpxchg = cmpxchg ptr %ptr, i8 %cmp, i8 %new monotonic monotonic, align 1281230  ret void1231}1232)IR");1233  Function &LLVMF = *M->getFunction("foo");1234  sandboxir::Context Ctx(C);1235  auto &F = *Ctx.createFunction(&LLVMF);1236  auto *BB = &*F.begin();1237  auto It = BB->begin();1238  auto *CmpXchg = cast<sandboxir::AtomicCmpXchgInst>(&*It++);1239 1240  // Check setAlignment().1241  Ctx.save();1242  auto OrigAlign = CmpXchg->getAlign();1243  Align NewAlign(1024);1244  EXPECT_NE(NewAlign, OrigAlign);1245  CmpXchg->setAlignment(NewAlign);1246  EXPECT_EQ(CmpXchg->getAlign(), NewAlign);1247  Ctx.revert();1248  EXPECT_EQ(CmpXchg->getAlign(), OrigAlign);1249 1250  // Check setVolatile().1251  Ctx.save();1252  auto OrigIsVolatile = CmpXchg->isVolatile();1253  bool NewIsVolatile = true;1254  EXPECT_NE(NewIsVolatile, OrigIsVolatile);1255  CmpXchg->setVolatile(NewIsVolatile);1256  EXPECT_EQ(CmpXchg->isVolatile(), NewIsVolatile);1257  Ctx.revert();1258  EXPECT_EQ(CmpXchg->isVolatile(), OrigIsVolatile);1259 1260  // Check setWeak().1261  Ctx.save();1262  auto OrigIsWeak = CmpXchg->isWeak();1263  bool NewIsWeak = true;1264  EXPECT_NE(NewIsWeak, OrigIsWeak);1265  CmpXchg->setWeak(NewIsWeak);1266  EXPECT_EQ(CmpXchg->isWeak(), NewIsWeak);1267  Ctx.revert();1268  EXPECT_EQ(CmpXchg->isWeak(), OrigIsWeak);1269 1270  // Check setSuccessOrdering().1271  Ctx.save();1272  auto OrigSuccessOrdering = CmpXchg->getSuccessOrdering();1273  auto NewSuccessOrdering = AtomicOrdering::SequentiallyConsistent;1274  EXPECT_NE(NewSuccessOrdering, OrigSuccessOrdering);1275  CmpXchg->setSuccessOrdering(NewSuccessOrdering);1276  EXPECT_EQ(CmpXchg->getSuccessOrdering(), NewSuccessOrdering);1277  Ctx.revert();1278  EXPECT_EQ(CmpXchg->getSuccessOrdering(), OrigSuccessOrdering);1279 1280  // Check setFailureOrdering().1281  Ctx.save();1282  auto OrigFailureOrdering = CmpXchg->getFailureOrdering();1283  auto NewFailureOrdering = AtomicOrdering::SequentiallyConsistent;1284  EXPECT_NE(NewFailureOrdering, OrigFailureOrdering);1285  CmpXchg->setFailureOrdering(NewFailureOrdering);1286  EXPECT_EQ(CmpXchg->getFailureOrdering(), NewFailureOrdering);1287  Ctx.revert();1288  EXPECT_EQ(CmpXchg->getFailureOrdering(), OrigFailureOrdering);1289 1290  // Check setSyncScopeID().1291  Ctx.save();1292  auto OrigSSID = CmpXchg->getSyncScopeID();1293  auto NewSSID = SyncScope::SingleThread;1294  EXPECT_NE(NewSSID, OrigSSID);1295  CmpXchg->setSyncScopeID(NewSSID);1296  EXPECT_EQ(CmpXchg->getSyncScopeID(), NewSSID);1297  Ctx.revert();1298  EXPECT_EQ(CmpXchg->getSyncScopeID(), OrigSSID);1299}1300 1301TEST_F(TrackerTest, AllocaInstSetters) {1302  parseIR(C, R"IR(1303define void @foo(i8 %arg) {1304  %alloca = alloca i32, align 641305  ret void1306}1307)IR");1308  Function &LLVMF = *M->getFunction("foo");1309  sandboxir::Context Ctx(C);1310  auto &F = *Ctx.createFunction(&LLVMF);1311  auto *BB = &*F.begin();1312  auto It = BB->begin();1313  auto *Alloca = cast<sandboxir::AllocaInst>(&*It++);1314 1315  // Check setAllocatedType().1316  Ctx.save();1317  auto *OrigTy = Alloca->getAllocatedType();1318  auto *NewTy = sandboxir::Type::getInt64Ty(Ctx);1319  EXPECT_NE(NewTy, OrigTy);1320  Alloca->setAllocatedType(NewTy);1321  EXPECT_EQ(Alloca->getAllocatedType(), NewTy);1322  Ctx.revert();1323  EXPECT_EQ(Alloca->getAllocatedType(), OrigTy);1324 1325  // Check setAlignment().1326  Ctx.save();1327  auto OrigAlign = Alloca->getAlign();1328  Align NewAlign(128);1329  EXPECT_NE(NewAlign, OrigAlign);1330  Alloca->setAlignment(NewAlign);1331  EXPECT_EQ(Alloca->getAlign(), NewAlign);1332  Ctx.revert();1333  EXPECT_EQ(Alloca->getAlign(), OrigAlign);1334 1335  // Check setUsedWithInAlloca().1336  Ctx.save();1337  auto OrigWIA = Alloca->isUsedWithInAlloca();1338  bool NewWIA = true;1339  EXPECT_NE(NewWIA, OrigWIA);1340  Alloca->setUsedWithInAlloca(NewWIA);1341  EXPECT_EQ(Alloca->isUsedWithInAlloca(), NewWIA);1342  Ctx.revert();1343  EXPECT_EQ(Alloca->isUsedWithInAlloca(), OrigWIA);1344}1345 1346TEST_F(TrackerTest, CallBrSetters) {1347  parseIR(C, R"IR(1348define void @foo(i8 %arg) {1349 bb0:1350   callbr void @foo(i8 %arg)1351               to label %bb1 [label %bb2]1352 bb1:1353   ret void1354 bb2:1355   ret void1356 other_bb:1357   ret void1358}1359)IR");1360  Function &LLVMF = *M->getFunction("foo");1361  sandboxir::Context Ctx(C);1362  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);1363  auto *BB0 = cast<sandboxir::BasicBlock>(1364      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));1365  auto *OtherBB = cast<sandboxir::BasicBlock>(1366      Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));1367  auto It = BB0->begin();1368  auto *CallBr = cast<sandboxir::CallBrInst>(&*It++);1369  // Check setDefaultDest().1370  Ctx.save();1371  auto *OrigDefaultDest = CallBr->getDefaultDest();1372  CallBr->setDefaultDest(OtherBB);1373  EXPECT_EQ(CallBr->getDefaultDest(), OtherBB);1374  Ctx.revert();1375  EXPECT_EQ(CallBr->getDefaultDest(), OrigDefaultDest);1376 1377  // Check setIndirectDest().1378  Ctx.save();1379  auto *OrigIndirectDest = CallBr->getIndirectDest(0);1380  CallBr->setIndirectDest(0, OtherBB);1381  EXPECT_EQ(CallBr->getIndirectDest(0), OtherBB);1382  Ctx.revert();1383  EXPECT_EQ(CallBr->getIndirectDest(0), OrigIndirectDest);1384}1385 1386TEST_F(TrackerTest, FuncletPadInstSetters) {1387  parseIR(C, R"IR(1388define void @foo() {1389dispatch:1390  %cs = catchswitch within none [label %handler0] unwind to caller1391handler0:1392  %catchpad = catchpad within %cs [ptr @foo]1393  ret void1394handler1:1395  %cleanuppad = cleanuppad within %cs [ptr @foo]1396  ret void1397bb:1398  ret void1399}1400)IR");1401  Function &LLVMF = *M->getFunction("foo");1402  sandboxir::Context Ctx(C);1403  [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);1404  auto *Dispatch = cast<sandboxir::BasicBlock>(1405      Ctx.getValue(getBasicBlockByName(LLVMF, "dispatch")));1406  auto *Handler0 = cast<sandboxir::BasicBlock>(1407      Ctx.getValue(getBasicBlockByName(LLVMF, "handler0")));1408  auto *Handler1 = cast<sandboxir::BasicBlock>(1409      Ctx.getValue(getBasicBlockByName(LLVMF, "handler1")));1410  auto *CP = cast<sandboxir::CatchPadInst>(&*Handler0->begin());1411  auto *CLP = cast<sandboxir::CleanupPadInst>(&*Handler1->begin());1412 1413  for (auto *FPI : {static_cast<sandboxir::FuncletPadInst *>(CP),1414                    static_cast<sandboxir::FuncletPadInst *>(CLP)}) {1415    // Check setParentPad().1416    auto *OrigParentPad = FPI->getParentPad();1417    auto *NewParentPad = Dispatch;1418    EXPECT_NE(NewParentPad, OrigParentPad);1419    Ctx.save();1420    FPI->setParentPad(NewParentPad);1421    EXPECT_EQ(FPI->getParentPad(), NewParentPad);1422    Ctx.revert();1423    EXPECT_EQ(FPI->getParentPad(), OrigParentPad);1424 1425    // Check setArgOperand().1426    auto *OrigArgOperand = FPI->getArgOperand(0);1427    auto *NewArgOperand = Dispatch;1428    EXPECT_NE(NewArgOperand, OrigArgOperand);1429    Ctx.save();1430    FPI->setArgOperand(0, NewArgOperand);1431    EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);1432    Ctx.revert();1433    EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);1434  }1435}1436 1437TEST_F(TrackerTest, PHINodeSetters) {1438  parseIR(C, R"IR(1439define void @foo(i8 %arg0, i8 %arg1, i8 %arg2) {1440bb0:1441  br label %bb21442 1443bb1:1444  %phi = phi i8 [ %arg0, %bb0 ], [ %arg1, %bb1 ]1445  br label %bb11446 1447bb2:1448  ret void1449}1450)IR");1451  Function &LLVMF = *M->getFunction("foo");1452  sandboxir::Context Ctx(C);1453  auto &F = *Ctx.createFunction(&LLVMF);1454  unsigned ArgIdx = 0;1455  auto *Arg0 = F.getArg(ArgIdx++);1456  auto *Arg1 = F.getArg(ArgIdx++);1457  auto *Arg2 = F.getArg(ArgIdx++);1458  auto *BB0 = cast<sandboxir::BasicBlock>(1459      Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));1460  auto *BB1 = cast<sandboxir::BasicBlock>(1461      Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));1462  auto *BB2 = cast<sandboxir::BasicBlock>(1463      Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));1464  auto *PHI = cast<sandboxir::PHINode>(&*BB1->begin());1465 1466  // Check setIncomingValue().1467  Ctx.save();1468  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1469  PHI->setIncomingValue(0, Arg2);1470  EXPECT_EQ(PHI->getIncomingValue(0), Arg2);1471  Ctx.revert();1472  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1473  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1474  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1475  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1476  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1477  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1478 1479  // Check setIncomingBlock().1480  Ctx.save();1481  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1482  PHI->setIncomingBlock(0, BB2);1483  EXPECT_EQ(PHI->getIncomingBlock(0), BB2);1484  Ctx.revert();1485  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1486  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1487  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1488  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1489  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1490  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1491 1492  // Check addIncoming().1493  Ctx.save();1494  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1495  PHI->addIncoming(Arg1, BB2);1496  EXPECT_EQ(PHI->getNumIncomingValues(), 3u);1497  EXPECT_EQ(PHI->getIncomingBlock(2), BB2);1498  EXPECT_EQ(PHI->getIncomingValue(2), Arg1);1499  Ctx.revert();1500  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1501  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1502  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1503  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1504  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1505 1506  // Check removeIncomingValue(1).1507  Ctx.save();1508  PHI->removeIncomingValue(1);1509  EXPECT_EQ(PHI->getNumIncomingValues(), 1u);1510  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1511  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1512  Ctx.revert();1513  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1514  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1515  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1516  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1517  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1518 1519  // Check removeIncomingValue(0).1520  Ctx.save();1521  PHI->removeIncomingValue(0u);1522  EXPECT_EQ(PHI->getNumIncomingValues(), 1u);1523  EXPECT_EQ(PHI->getIncomingBlock(0), BB1);1524  EXPECT_EQ(PHI->getIncomingValue(0), Arg1);1525  Ctx.revert();1526  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1527  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1528  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1529  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1530  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1531 1532  // Check removeIncomingValueIf(FromBB1).1533  Ctx.save();1534  PHI->removeIncomingValueIf(1535      [&](unsigned Idx) { return PHI->getIncomingBlock(Idx) == BB1; });1536  EXPECT_EQ(PHI->getNumIncomingValues(), 1u);1537  Ctx.revert();1538  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1539  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1540  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1541  // Check removeIncomingValue() remove all.1542  Ctx.save();1543  PHI->removeIncomingValue(0u);1544  EXPECT_EQ(PHI->getNumIncomingValues(), 1u);1545  EXPECT_EQ(PHI->getIncomingBlock(0), BB1);1546  EXPECT_EQ(PHI->getIncomingValue(0), Arg1);1547  PHI->removeIncomingValue(0u);1548  EXPECT_EQ(PHI->getNumIncomingValues(), 0u);1549  Ctx.revert();1550  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1551  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1552  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1553  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1554  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1555 1556  // Check removeIncomingValue(BasicBlock *).1557  Ctx.save();1558  PHI->removeIncomingValue(BB1);1559  EXPECT_EQ(PHI->getNumIncomingValues(), 1u);1560  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1561  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1562  Ctx.revert();1563  EXPECT_EQ(PHI->getNumIncomingValues(), 2u);1564  EXPECT_EQ(PHI->getIncomingBlock(0), BB0);1565  EXPECT_EQ(PHI->getIncomingValue(0), Arg0);1566  EXPECT_EQ(PHI->getIncomingBlock(1), BB1);1567  EXPECT_EQ(PHI->getIncomingValue(1), Arg1);1568}1569 1570void checkCmpInst(sandboxir::Context &Ctx, sandboxir::CmpInst *Cmp) {1571  Ctx.save();1572  auto OrigP = Cmp->getPredicate();1573  auto NewP = Cmp->getSwappedPredicate();1574  Cmp->setPredicate(NewP);1575  EXPECT_EQ(Cmp->getPredicate(), NewP);1576  Ctx.revert();1577  EXPECT_EQ(Cmp->getPredicate(), OrigP);1578 1579  Ctx.save();1580  auto OrigOp0 = Cmp->getOperand(0);1581  auto OrigOp1 = Cmp->getOperand(1);1582  Cmp->swapOperands();1583  EXPECT_EQ(Cmp->getPredicate(), NewP);1584  EXPECT_EQ(Cmp->getOperand(0), OrigOp1);1585  EXPECT_EQ(Cmp->getOperand(1), OrigOp0);1586  Ctx.revert();1587  EXPECT_EQ(Cmp->getPredicate(), OrigP);1588  EXPECT_EQ(Cmp->getOperand(0), OrigOp0);1589  EXPECT_EQ(Cmp->getOperand(1), OrigOp1);1590}1591 1592TEST_F(TrackerTest, CmpInst) {1593  SCOPED_TRACE("TrackerTest sandboxir::CmpInst tests");1594  parseIR(C, R"IR(1595define void @foo(i64 %i0, i64 %i1, float %f0, float %f1) {1596  %foeq = fcmp ogt float %f0, %f11597  %ioeq = icmp uge i64 %i0, %i11598 1599  ret void1600}1601)IR");1602  Function &LLVMF = *M->getFunction("foo");1603  sandboxir::Context Ctx(C);1604  auto &F = *Ctx.createFunction(&LLVMF);1605  auto *BB = &*F.begin();1606  auto It = BB->begin();1607  auto *FCmp = cast<sandboxir::CmpInst>(&*It++);1608  checkCmpInst(Ctx, FCmp);1609  auto *ICmp = cast<sandboxir::CmpInst>(&*It++);1610  checkCmpInst(Ctx, ICmp);1611}1612 1613TEST_F(TrackerTest, GlobalValueSetters) {1614  parseIR(C, R"IR(1615define void @foo() {1616  call void @foo()1617  ret void1618}1619)IR");1620  Function &LLVMF = *M->getFunction("foo");1621  sandboxir::Context Ctx(C);1622 1623  auto &F = *Ctx.createFunction(&LLVMF);1624  auto *BB = &*F.begin();1625  auto *Call = cast<sandboxir::CallInst>(&*BB->begin());1626 1627  auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand());1628  // Check setUnnamedAddr().1629  auto OrigUnnamedAddr = GV->getUnnamedAddr();1630  auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global;1631  EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr);1632  Ctx.save();1633  GV->setUnnamedAddr(NewUnnamedAddr);1634  EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr);1635  Ctx.revert();1636  EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr);1637 1638  // Check setVisibility().1639  auto OrigVisibility = GV->getVisibility();1640  auto NewVisibility =1641      sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility;1642  EXPECT_NE(NewVisibility, OrigVisibility);1643  Ctx.save();1644  GV->setVisibility(NewVisibility);1645  EXPECT_EQ(GV->getVisibility(), NewVisibility);1646  Ctx.revert();1647  EXPECT_EQ(GV->getVisibility(), OrigVisibility);1648}1649 1650TEST_F(TrackerTest, GlobalIFuncSetters) {1651  parseIR(C, R"IR(1652declare external void @bar()1653@ifunc = ifunc void(), ptr @foo1654define void @foo() {1655  call void @ifunc()1656  call void @bar()1657  ret void1658}1659)IR");1660  Function &LLVMF = *M->getFunction("foo");1661  sandboxir::Context Ctx(C);1662 1663  auto &F = *Ctx.createFunction(&LLVMF);1664  auto *BB = &*F.begin();1665  auto It = BB->begin();1666  auto *Call0 = cast<sandboxir::CallInst>(&*It++);1667  auto *Call1 = cast<sandboxir::CallInst>(&*It++);1668  // Check classof(), creation.1669  auto *IFunc = cast<sandboxir::GlobalIFunc>(Call0->getCalledOperand());1670  auto *Bar = cast<sandboxir::Function>(Call1->getCalledOperand());1671  // Check setResolver().1672  auto *OrigResolver = IFunc->getResolver();1673  auto *NewResolver = Bar;1674  EXPECT_NE(NewResolver, OrigResolver);1675  Ctx.save();1676  IFunc->setResolver(NewResolver);1677  EXPECT_EQ(IFunc->getResolver(), NewResolver);1678  Ctx.revert();1679  EXPECT_EQ(IFunc->getResolver(), OrigResolver);1680}1681 1682TEST_F(TrackerTest, GlobalVariableSetters) {1683  parseIR(C, R"IR(1684@glob0 = global i32 421685@glob1 = global i32 431686define void @foo() {1687  %ld0 = load i32, ptr @glob01688  %ld1 = load i32, ptr @glob11689  ret void1690}1691)IR");1692  Function &LLVMF = *M->getFunction("foo");1693  sandboxir::Context Ctx(C);1694 1695  auto &F = *Ctx.createFunction(&LLVMF);1696  auto *BB = &*F.begin();1697  auto It = BB->begin();1698  auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);1699  auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);1700  // Check classof(), creation.1701  auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());1702  auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());1703  // Check setInitializer().1704  auto *OrigInitializer = GV0->getInitializer();1705  auto *NewInitializer = GV1->getInitializer();1706  EXPECT_NE(NewInitializer, OrigInitializer);1707  Ctx.save();1708  GV0->setInitializer(NewInitializer);1709  EXPECT_EQ(GV0->getInitializer(), NewInitializer);1710  Ctx.revert();1711  EXPECT_EQ(GV0->getInitializer(), OrigInitializer);1712  // Check setConstant().1713  bool OrigIsConstant = GV0->isConstant();1714  bool NewIsConstant = !OrigIsConstant;1715  Ctx.save();1716  GV0->setConstant(NewIsConstant);1717  EXPECT_EQ(GV0->isConstant(), NewIsConstant);1718  Ctx.revert();1719  EXPECT_EQ(GV0->isConstant(), OrigIsConstant);1720  // Check setExternallyInitialized().1721  bool OrigIsExtInit = GV0->isExternallyInitialized();1722  bool NewIsExtInit = !OrigIsExtInit;1723  Ctx.save();1724  GV0->setExternallyInitialized(NewIsExtInit);1725  EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);1726  Ctx.revert();1727  EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);1728}1729 1730TEST_F(TrackerTest, GlobalAliasSetters) {1731  parseIR(C, R"IR(1732@alias = dso_local alias void(), ptr @foo1733declare void @bar();1734define void @foo() {1735  call void @alias()1736  call void @bar()1737  ret void1738}1739)IR");1740  Function &LLVMF = *M->getFunction("foo");1741  sandboxir::Context Ctx(C);1742 1743  auto &F = *Ctx.createFunction(&LLVMF);1744  auto *BB = &*F.begin();1745  auto It = BB->begin();1746  auto *Call0 = cast<sandboxir::CallInst>(&*It++);1747  auto *Call1 = cast<sandboxir::CallInst>(&*It++);1748  auto *Callee1 = cast<sandboxir::Constant>(Call1->getCalledOperand());1749  auto *Alias = cast<sandboxir::GlobalAlias>(Call0->getCalledOperand());1750  // Check setAliasee().1751  auto *OrigAliasee = Alias->getAliasee();1752  auto *NewAliasee = Callee1;1753  EXPECT_NE(NewAliasee, OrigAliasee);1754  Ctx.save();1755  Alias->setAliasee(NewAliasee);1756  EXPECT_EQ(Alias->getAliasee(), NewAliasee);1757  Ctx.revert();1758  EXPECT_EQ(Alias->getAliasee(), OrigAliasee);1759}1760 1761TEST_F(TrackerTest, SetVolatile) {1762  parseIR(C, R"IR(1763define void @foo(ptr %arg0, i8 %val) {1764  %ld = load i8, ptr %arg0, align 641765  store i8 %val, ptr %arg0, align 641766  ret void1767}1768)IR");1769  Function &LLVMF = *M->getFunction("foo");1770  sandboxir::Context Ctx(C);1771 1772  auto *F = Ctx.createFunction(&LLVMF);1773  auto *BB = &*F->begin();1774  auto It = BB->begin();1775  auto *Load = cast<sandboxir::LoadInst>(&*It++);1776  auto *Store = cast<sandboxir::StoreInst>(&*It++);1777 1778  EXPECT_FALSE(Load->isVolatile());1779  Ctx.save();1780  Load->setVolatile(true);1781  EXPECT_TRUE(Load->isVolatile());1782  Ctx.revert();1783  EXPECT_FALSE(Load->isVolatile());1784 1785  EXPECT_FALSE(Store->isVolatile());1786  Ctx.save();1787  Store->setVolatile(true);1788  EXPECT_TRUE(Store->isVolatile());1789  Ctx.revert();1790  EXPECT_FALSE(Store->isVolatile());1791}1792 1793TEST_F(TrackerTest, Flags) {1794  parseIR(C, R"IR(1795define void @foo(i32 %arg, float %farg) {1796  %add = add i32 %arg, %arg1797  %fadd = fadd float %farg, %farg1798  %udiv = udiv i32 %arg, %arg1799  ret void1800}1801)IR");1802  Function &LLVMF = *M->getFunction("foo");1803  sandboxir::Context Ctx(C);1804  auto &F = *Ctx.createFunction(&LLVMF);1805  auto *BB = &*F.begin();1806  auto It = BB->begin();1807  auto *Add = &*It++;1808  auto *FAdd = &*It++;1809  auto *UDiv = &*It++;1810 1811#define CHECK_FLAG(I, GETTER, SETTER)                                          \1812  {                                                                            \1813    Ctx.save();                                                                \1814    bool OrigFlag = I->GETTER();                                               \1815    bool NewFlag = !OrigFlag;                                                  \1816    I->SETTER(NewFlag);                                                        \1817    EXPECT_EQ(I->GETTER(), NewFlag);                                           \1818    Ctx.revert();                                                              \1819    EXPECT_EQ(I->GETTER(), OrigFlag);                                          \1820  }1821 1822  CHECK_FLAG(Add, hasNoUnsignedWrap, setHasNoUnsignedWrap);1823  CHECK_FLAG(Add, hasNoSignedWrap, setHasNoSignedWrap);1824  CHECK_FLAG(FAdd, isFast, setFast);1825  CHECK_FLAG(FAdd, hasAllowReassoc, setHasAllowReassoc);1826  CHECK_FLAG(UDiv, isExact, setIsExact);1827  CHECK_FLAG(FAdd, hasNoNaNs, setHasNoNaNs);1828  CHECK_FLAG(FAdd, hasNoInfs, setHasNoInfs);1829  CHECK_FLAG(FAdd, hasNoSignedZeros, setHasNoSignedZeros);1830  CHECK_FLAG(FAdd, hasAllowReciprocal, setHasAllowReciprocal);1831  CHECK_FLAG(FAdd, hasAllowContract, setHasAllowContract);1832  CHECK_FLAG(FAdd, hasApproxFunc, setHasApproxFunc);1833 1834  // Check setFastMathFlags().1835  FastMathFlags OrigFMF = FAdd->getFastMathFlags();1836  FastMathFlags NewFMF;1837  NewFMF.setAllowReassoc(true);1838  EXPECT_TRUE(NewFMF != OrigFMF);1839 1840  Ctx.save();1841  FAdd->setFastMathFlags(NewFMF);1842  EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);1843  Ctx.revert();1844  EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);1845 1846  // Check copyFastMathFlags().1847  Ctx.save();1848  FAdd->copyFastMathFlags(NewFMF);1849  EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);1850  Ctx.revert();1851  EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);1852}1853 1854// IRSnapshotChecker is only defined in debug mode.1855#ifndef NDEBUG1856 1857TEST_F(TrackerTest, IRSnapshotCheckerNoChanges) {1858  parseIR(C, R"IR(1859define i32 @foo(i32 %arg) {1860  %add0 = add i32 %arg, %arg1861  ret i32 %add01862}1863)IR");1864  Function &LLVMF = *M->getFunction("foo");1865  sandboxir::Context Ctx(C);1866 1867  [[maybe_unused]] auto *F = Ctx.createFunction(&LLVMF);1868  sandboxir::IRSnapshotChecker Checker(Ctx);1869  Checker.save();1870  Checker.expectNoDiff();1871}1872 1873TEST_F(TrackerTest, IRSnapshotCheckerDiesWithUnexpectedChanges) {1874  parseIR(C, R"IR(1875define i32 @foo(i32 %arg) {1876  %add0 = add i32 %arg, %arg1877  %add1 = add i32 %add0, %arg1878  ret i32 %add11879}1880)IR");1881  Function &LLVMF = *M->getFunction("foo");1882  sandboxir::Context Ctx(C);1883 1884  auto *F = Ctx.createFunction(&LLVMF);1885  auto *BB = &*F->begin();1886  auto It = BB->begin();1887  sandboxir::Instruction *Add0 = &*It++;1888  sandboxir::Instruction *Add1 = &*It++;1889  sandboxir::IRSnapshotChecker Checker(Ctx);1890  Checker.save();1891  Add1->setOperand(1, Add0);1892  EXPECT_DEATH(Checker.expectNoDiff(), "Found IR difference");1893}1894 1895TEST_F(TrackerTest, IRSnapshotCheckerSaveMultipleTimes) {1896  parseIR(C, R"IR(1897define i32 @foo(i32 %arg) {1898  %add0 = add i32 %arg, %arg1899  %add1 = add i32 %add0, %arg1900  ret i32 %add11901}1902)IR");1903  Function &LLVMF = *M->getFunction("foo");1904  sandboxir::Context Ctx(C);1905 1906  auto *F = Ctx.createFunction(&LLVMF);1907  auto *BB = &*F->begin();1908  auto It = BB->begin();1909  sandboxir::Instruction *Add0 = &*It++;1910  sandboxir::Instruction *Add1 = &*It++;1911  sandboxir::IRSnapshotChecker Checker(Ctx);1912  Checker.save();1913  Add1->setOperand(1, Add0);1914  // Now IR differs from the last snapshot. Let's take a new snapshot.1915  Checker.save();1916  // The new snapshot should have replaced the old one, so this should succeed.1917  Checker.expectNoDiff();1918}1919 1920#endif // NDEBUG1921