xref: /llvm-project/llvm/unittests/SandboxIR/TrackerTest.cpp (revision 3b8606be547acbc7ae93d943645e6d6c83f66983)
15338bd3cSvporpo //===- TrackerTest.cpp ----------------------------------------------------===//
25338bd3cSvporpo //
35338bd3cSvporpo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45338bd3cSvporpo // See https://llvm.org/LICENSE.txt for license information.
55338bd3cSvporpo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65338bd3cSvporpo //
75338bd3cSvporpo //===----------------------------------------------------------------------===//
85338bd3cSvporpo 
95338bd3cSvporpo #include "llvm/AsmParser/Parser.h"
105338bd3cSvporpo #include "llvm/IR/BasicBlock.h"
115338bd3cSvporpo #include "llvm/IR/Function.h"
125338bd3cSvporpo #include "llvm/IR/Instruction.h"
135338bd3cSvporpo #include "llvm/IR/Module.h"
14e22b07e7Svporpo #include "llvm/SandboxIR/Function.h"
15eba106d4Svporpo #include "llvm/SandboxIR/Instruction.h"
165338bd3cSvporpo #include "llvm/Support/SourceMgr.h"
17b5ba7265SJorge Gorbe Moya #include "gmock/gmock-matchers.h"
185338bd3cSvporpo #include "gtest/gtest.h"
195338bd3cSvporpo 
205338bd3cSvporpo using namespace llvm;
215338bd3cSvporpo 
225338bd3cSvporpo struct TrackerTest : public testing::Test {
235338bd3cSvporpo   LLVMContext C;
245338bd3cSvporpo   std::unique_ptr<Module> M;
255338bd3cSvporpo 
265338bd3cSvporpo   void parseIR(LLVMContext &C, const char *IR) {
275338bd3cSvporpo     SMDiagnostic Err;
285338bd3cSvporpo     M = parseAssemblyString(IR, Err, C);
295338bd3cSvporpo     if (!M)
305338bd3cSvporpo       Err.print("TrackerTest", errs());
315338bd3cSvporpo   }
325338bd3cSvporpo   BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
335338bd3cSvporpo     for (BasicBlock &BB : F)
345338bd3cSvporpo       if (BB.getName() == Name)
355338bd3cSvporpo         return &BB;
365338bd3cSvporpo     llvm_unreachable("Expected to find basic block!");
375338bd3cSvporpo   }
385338bd3cSvporpo };
395338bd3cSvporpo 
405338bd3cSvporpo TEST_F(TrackerTest, SetOperand) {
415338bd3cSvporpo   parseIR(C, R"IR(
425338bd3cSvporpo define void @foo(ptr %ptr) {
435338bd3cSvporpo   %gep0 = getelementptr float, ptr %ptr, i32 0
445338bd3cSvporpo   %gep1 = getelementptr float, ptr %ptr, i32 1
455338bd3cSvporpo   %ld0 = load float, ptr %gep0
465338bd3cSvporpo   store float undef, ptr %gep0
475338bd3cSvporpo   ret void
485338bd3cSvporpo }
495338bd3cSvporpo )IR");
505338bd3cSvporpo   Function &LLVMF = *M->getFunction("foo");
515338bd3cSvporpo   sandboxir::Context Ctx(C);
525338bd3cSvporpo   auto *F = Ctx.createFunction(&LLVMF);
535338bd3cSvporpo   auto *BB = &*F->begin();
545338bd3cSvporpo   auto &Tracker = Ctx.getTracker();
555338bd3cSvporpo   Tracker.save();
565338bd3cSvporpo   auto It = BB->begin();
575338bd3cSvporpo   auto *Gep0 = &*It++;
585338bd3cSvporpo   auto *Gep1 = &*It++;
595338bd3cSvporpo   auto *Ld = &*It++;
605338bd3cSvporpo   auto *St = &*It++;
615338bd3cSvporpo   St->setOperand(0, Ld);
625338bd3cSvporpo   St->setOperand(1, Gep1);
635338bd3cSvporpo   Ld->setOperand(0, Gep1);
645338bd3cSvporpo   EXPECT_EQ(St->getOperand(0), Ld);
655338bd3cSvporpo   EXPECT_EQ(St->getOperand(1), Gep1);
665338bd3cSvporpo   EXPECT_EQ(Ld->getOperand(0), Gep1);
675338bd3cSvporpo 
685338bd3cSvporpo   Ctx.getTracker().revert();
695338bd3cSvporpo   EXPECT_NE(St->getOperand(0), Ld);
705338bd3cSvporpo   EXPECT_EQ(St->getOperand(1), Gep0);
715338bd3cSvporpo   EXPECT_EQ(Ld->getOperand(0), Gep0);
725338bd3cSvporpo }
735338bd3cSvporpo 
74372a6beaSvporpo TEST_F(TrackerTest, SetUse) {
75372a6beaSvporpo   parseIR(C, R"IR(
76372a6beaSvporpo define void @foo(ptr %ptr, i8 %arg) {
77372a6beaSvporpo   %ld = load i8, ptr %ptr
78372a6beaSvporpo   %add = add i8 %ld, %arg
79372a6beaSvporpo   ret void
80372a6beaSvporpo }
81372a6beaSvporpo )IR");
82372a6beaSvporpo   Function &LLVMF = *M->getFunction("foo");
83372a6beaSvporpo   sandboxir::Context Ctx(C);
84372a6beaSvporpo   auto *F = Ctx.createFunction(&LLVMF);
85372a6beaSvporpo   unsigned ArgIdx = 0;
86372a6beaSvporpo   auto *Arg0 = F->getArg(ArgIdx++);
87372a6beaSvporpo   auto *BB = &*F->begin();
88372a6beaSvporpo   auto &Tracker = Ctx.getTracker();
89372a6beaSvporpo   Tracker.save();
90372a6beaSvporpo   auto It = BB->begin();
91372a6beaSvporpo   auto *Ld = &*It++;
92372a6beaSvporpo   auto *Add = &*It++;
93372a6beaSvporpo 
94372a6beaSvporpo   Ctx.save();
95372a6beaSvporpo   sandboxir::Use Use = Add->getOperandUse(0);
96372a6beaSvporpo   Use.set(Arg0);
97372a6beaSvporpo   EXPECT_EQ(Add->getOperand(0), Arg0);
98372a6beaSvporpo   Ctx.revert();
99372a6beaSvporpo   EXPECT_EQ(Add->getOperand(0), Ld);
100372a6beaSvporpo }
101372a6beaSvporpo 
102c444548bSVasileios Porpodas TEST_F(TrackerTest, SwapOperands) {
103c444548bSVasileios Porpodas   parseIR(C, R"IR(
104c444548bSVasileios Porpodas define void @foo(i1 %cond) {
105c444548bSVasileios Porpodas  bb0:
106c444548bSVasileios Porpodas    br i1 %cond, label %bb1, label %bb2
107c444548bSVasileios Porpodas  bb1:
108c444548bSVasileios Porpodas    ret void
109c444548bSVasileios Porpodas  bb2:
110c444548bSVasileios Porpodas    ret void
111c444548bSVasileios Porpodas }
112c444548bSVasileios Porpodas )IR");
113c444548bSVasileios Porpodas   Function &LLVMF = *M->getFunction("foo");
114c444548bSVasileios Porpodas   sandboxir::Context Ctx(C);
115c444548bSVasileios Porpodas   Ctx.createFunction(&LLVMF);
116c444548bSVasileios Porpodas   auto *BB0 = cast<sandboxir::BasicBlock>(
117c444548bSVasileios Porpodas       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
118c444548bSVasileios Porpodas   auto *BB1 = cast<sandboxir::BasicBlock>(
119c444548bSVasileios Porpodas       Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
120c444548bSVasileios Porpodas   auto *BB2 = cast<sandboxir::BasicBlock>(
121c444548bSVasileios Porpodas       Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));
122c444548bSVasileios Porpodas   auto &Tracker = Ctx.getTracker();
123c444548bSVasileios Porpodas   Tracker.save();
124c444548bSVasileios Porpodas   auto It = BB0->begin();
125c444548bSVasileios Porpodas   auto *Br = cast<sandboxir::BranchInst>(&*It++);
126c444548bSVasileios Porpodas 
127c444548bSVasileios Porpodas   unsigned SuccIdx = 0;
128c444548bSVasileios Porpodas   SmallVector<sandboxir::BasicBlock *> ExpectedSuccs({BB2, BB1});
129c444548bSVasileios Porpodas   for (auto *Succ : Br->successors())
130c444548bSVasileios Porpodas     EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);
131c444548bSVasileios Porpodas 
132c444548bSVasileios Porpodas   // This calls User::swapOperandsInternal() internally.
133c444548bSVasileios Porpodas   Br->swapSuccessors();
134c444548bSVasileios Porpodas 
135c444548bSVasileios Porpodas   SuccIdx = 0;
136c444548bSVasileios Porpodas   for (auto *Succ : reverse(Br->successors()))
137c444548bSVasileios Porpodas     EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);
138c444548bSVasileios Porpodas 
139c444548bSVasileios Porpodas   Ctx.getTracker().revert();
140c444548bSVasileios Porpodas   SuccIdx = 0;
141c444548bSVasileios Porpodas   for (auto *Succ : Br->successors())
142c444548bSVasileios Porpodas     EXPECT_EQ(Succ, ExpectedSuccs[SuccIdx++]);
143c444548bSVasileios Porpodas }
144c444548bSVasileios Porpodas 
1455338bd3cSvporpo TEST_F(TrackerTest, RUWIf_RAUW_RUOW) {
1465338bd3cSvporpo   parseIR(C, R"IR(
1475338bd3cSvporpo define void @foo(ptr %ptr) {
1485338bd3cSvporpo   %ld0 = load float, ptr %ptr
1495338bd3cSvporpo   %ld1 = load float, ptr %ptr
1505338bd3cSvporpo   store float %ld0, ptr %ptr
1515338bd3cSvporpo   store float %ld0, ptr %ptr
1525338bd3cSvporpo   ret void
1535338bd3cSvporpo }
1545338bd3cSvporpo )IR");
1555338bd3cSvporpo   llvm::Function &LLVMF = *M->getFunction("foo");
1565338bd3cSvporpo   sandboxir::Context Ctx(C);
1575338bd3cSvporpo   llvm::BasicBlock *LLVMBB = &*LLVMF.begin();
1585338bd3cSvporpo   Ctx.createFunction(&LLVMF);
1595338bd3cSvporpo   auto *BB = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMBB));
1605338bd3cSvporpo   auto It = BB->begin();
1615338bd3cSvporpo   sandboxir::Instruction *Ld0 = &*It++;
1625338bd3cSvporpo   sandboxir::Instruction *Ld1 = &*It++;
1635338bd3cSvporpo   sandboxir::Instruction *St0 = &*It++;
1645338bd3cSvporpo   sandboxir::Instruction *St1 = &*It++;
1655338bd3cSvporpo   Ctx.save();
1665338bd3cSvporpo   // Check RUWIf when the lambda returns false.
1675338bd3cSvporpo   Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return false; });
1685338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
1695338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
1705338bd3cSvporpo 
1715338bd3cSvporpo   // Check RUWIf when the lambda returns true.
1725338bd3cSvporpo   Ld0->replaceUsesWithIf(Ld1, [](const sandboxir::Use &Use) { return true; });
1735338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld1);
1745338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld1);
1755338bd3cSvporpo   Ctx.revert();
1765338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
1775338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
1785338bd3cSvporpo 
1795338bd3cSvporpo   // Check RUWIf user == St0.
1805338bd3cSvporpo   Ctx.save();
1815338bd3cSvporpo   Ld0->replaceUsesWithIf(
1825338bd3cSvporpo       Ld1, [St0](const sandboxir::Use &Use) { return Use.getUser() == St0; });
1835338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld1);
1845338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
1855338bd3cSvporpo   Ctx.revert();
1865338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
1875338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
1885338bd3cSvporpo 
1895338bd3cSvporpo   // Check RUWIf user == St1.
1905338bd3cSvporpo   Ctx.save();
1915338bd3cSvporpo   Ld0->replaceUsesWithIf(
1925338bd3cSvporpo       Ld1, [St1](const sandboxir::Use &Use) { return Use.getUser() == St1; });
1935338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
1945338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld1);
1955338bd3cSvporpo   Ctx.revert();
1965338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
1975338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
1985338bd3cSvporpo 
1995338bd3cSvporpo   // Check RAUW.
2005338bd3cSvporpo   Ctx.save();
2015338bd3cSvporpo   Ld1->replaceAllUsesWith(Ld0);
2025338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
2035338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
2045338bd3cSvporpo   Ctx.revert();
2055338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
2065338bd3cSvporpo   EXPECT_EQ(St1->getOperand(0), Ld0);
2075338bd3cSvporpo 
2085338bd3cSvporpo   // Check RUOW.
2095338bd3cSvporpo   Ctx.save();
2105338bd3cSvporpo   St0->replaceUsesOfWith(Ld0, Ld1);
2115338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld1);
2125338bd3cSvporpo   Ctx.revert();
2135338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld0);
2145338bd3cSvporpo 
2155338bd3cSvporpo   // Check accept().
2165338bd3cSvporpo   Ctx.save();
2175338bd3cSvporpo   St0->replaceUsesOfWith(Ld0, Ld1);
2185338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld1);
2195338bd3cSvporpo   Ctx.accept();
2205338bd3cSvporpo   EXPECT_EQ(St0->getOperand(0), Ld1);
2215338bd3cSvporpo }
222c5432d31Svporpo 
223c5432d31Svporpo // TODO: Test multi-instruction patterns.
224c5432d31Svporpo TEST_F(TrackerTest, EraseFromParent) {
225c5432d31Svporpo   parseIR(C, R"IR(
226c5432d31Svporpo define void @foo(i32 %v1) {
227c5432d31Svporpo   %add0 = add i32 %v1, %v1
228c5432d31Svporpo   %add1 = add i32 %add0, %v1
229c5432d31Svporpo   ret void
230c5432d31Svporpo }
231c5432d31Svporpo )IR");
232c5432d31Svporpo   Function &LLVMF = *M->getFunction("foo");
233c5432d31Svporpo   sandboxir::Context Ctx(C);
234c5432d31Svporpo 
235c5432d31Svporpo   auto *F = Ctx.createFunction(&LLVMF);
236c5432d31Svporpo   auto *BB = &*F->begin();
237c5432d31Svporpo   auto It = BB->begin();
238c5432d31Svporpo   sandboxir::Instruction *Add0 = &*It++;
239c5432d31Svporpo   sandboxir::Instruction *Add1 = &*It++;
240c5432d31Svporpo   sandboxir::Instruction *Ret = &*It++;
241c5432d31Svporpo 
242c5432d31Svporpo   Ctx.save();
243c5432d31Svporpo   // Check erase.
244c5432d31Svporpo   Add1->eraseFromParent();
245c5432d31Svporpo   It = BB->begin();
246c5432d31Svporpo   EXPECT_EQ(&*It++, Add0);
247c5432d31Svporpo   EXPECT_EQ(&*It++, Ret);
248c5432d31Svporpo   EXPECT_EQ(It, BB->end());
249c5432d31Svporpo   EXPECT_EQ(Add0->getNumUses(), 0u);
250c5432d31Svporpo 
251c5432d31Svporpo   // Check revert().
252c5432d31Svporpo   Ctx.revert();
253c5432d31Svporpo   It = BB->begin();
254c5432d31Svporpo   EXPECT_EQ(&*It++, Add0);
255c5432d31Svporpo   EXPECT_EQ(&*It++, Add1);
256c5432d31Svporpo   EXPECT_EQ(&*It++, Ret);
257c5432d31Svporpo   EXPECT_EQ(It, BB->end());
258c5432d31Svporpo   EXPECT_EQ(Add1->getOperand(0), Add0);
259c5432d31Svporpo 
260c5432d31Svporpo   // Same for the last instruction in the block.
261c5432d31Svporpo   Ctx.save();
262c5432d31Svporpo   Ret->eraseFromParent();
263c5432d31Svporpo   It = BB->begin();
264c5432d31Svporpo   EXPECT_EQ(&*It++, Add0);
265c5432d31Svporpo   EXPECT_EQ(&*It++, Add1);
266c5432d31Svporpo   EXPECT_EQ(It, BB->end());
267c5432d31Svporpo   Ctx.revert();
268c5432d31Svporpo   It = BB->begin();
269c5432d31Svporpo   EXPECT_EQ(&*It++, Add0);
270c5432d31Svporpo   EXPECT_EQ(&*It++, Add1);
271c5432d31Svporpo   EXPECT_EQ(&*It++, Ret);
272c5432d31Svporpo   EXPECT_EQ(It, BB->end());
273c5432d31Svporpo }
2744f786c68Svporpo 
2754f786c68Svporpo // TODO: Test multi-instruction patterns.
2764f786c68Svporpo TEST_F(TrackerTest, RemoveFromParent) {
2774f786c68Svporpo   parseIR(C, R"IR(
2784f786c68Svporpo define i32 @foo(i32 %arg) {
2794f786c68Svporpo   %add0 = add i32 %arg, %arg
2804f786c68Svporpo   %add1 = add i32 %add0, %arg
2814f786c68Svporpo   ret i32 %add1
2824f786c68Svporpo }
2834f786c68Svporpo )IR");
2844f786c68Svporpo   Function &LLVMF = *M->getFunction("foo");
2854f786c68Svporpo   sandboxir::Context Ctx(C);
2864f786c68Svporpo 
2874f786c68Svporpo   auto *F = Ctx.createFunction(&LLVMF);
2884f786c68Svporpo   auto *Arg = F->getArg(0);
2894f786c68Svporpo   auto *BB = &*F->begin();
2904f786c68Svporpo   auto It = BB->begin();
2914f786c68Svporpo   sandboxir::Instruction *Add0 = &*It++;
2924f786c68Svporpo   sandboxir::Instruction *Add1 = &*It++;
2934f786c68Svporpo   sandboxir::Instruction *Ret = &*It++;
2944f786c68Svporpo 
2954f786c68Svporpo   Ctx.save();
2964f786c68Svporpo   // Check removeFromParent().
2974f786c68Svporpo   Add1->removeFromParent();
2984f786c68Svporpo   It = BB->begin();
2994f786c68Svporpo   EXPECT_EQ(&*It++, Add0);
3004f786c68Svporpo   EXPECT_EQ(&*It++, Ret);
3014f786c68Svporpo   EXPECT_EQ(It, BB->end());
3024f786c68Svporpo   // Removed instruction still be connected to operands and users.
3034f786c68Svporpo   EXPECT_EQ(Add1->getOperand(0), Add0);
3044f786c68Svporpo   EXPECT_EQ(Add1->getOperand(1), Arg);
3054f786c68Svporpo   EXPECT_EQ(Add0->getNumUses(), 1u);
3064f786c68Svporpo 
3074f786c68Svporpo   // Check revert().
3084f786c68Svporpo   Ctx.revert();
3094f786c68Svporpo   It = BB->begin();
3104f786c68Svporpo   EXPECT_EQ(&*It++, Add0);
3114f786c68Svporpo   EXPECT_EQ(&*It++, Add1);
3124f786c68Svporpo   EXPECT_EQ(&*It++, Ret);
3134f786c68Svporpo   EXPECT_EQ(It, BB->end());
3144f786c68Svporpo   EXPECT_EQ(Add1->getOperand(0), Add0);
3154f786c68Svporpo 
3164f786c68Svporpo   // Same for the last instruction in the block.
3174f786c68Svporpo   Ctx.save();
3184f786c68Svporpo   Ret->removeFromParent();
3194f786c68Svporpo   It = BB->begin();
3204f786c68Svporpo   EXPECT_EQ(&*It++, Add0);
3214f786c68Svporpo   EXPECT_EQ(&*It++, Add1);
3224f786c68Svporpo   EXPECT_EQ(It, BB->end());
3234f786c68Svporpo   EXPECT_EQ(Ret->getOperand(0), Add1);
3244f786c68Svporpo   Ctx.revert();
3254f786c68Svporpo   It = BB->begin();
3264f786c68Svporpo   EXPECT_EQ(&*It++, Add0);
3274f786c68Svporpo   EXPECT_EQ(&*It++, Add1);
3284f786c68Svporpo   EXPECT_EQ(&*It++, Ret);
3294f786c68Svporpo   EXPECT_EQ(It, BB->end());
3304f786c68Svporpo }
331cbbd1532Svporpo 
332cbbd1532Svporpo // TODO: Test multi-instruction patterns.
333cbbd1532Svporpo TEST_F(TrackerTest, MoveInstr) {
334cbbd1532Svporpo   parseIR(C, R"IR(
335cbbd1532Svporpo define i32 @foo(i32 %arg) {
336cbbd1532Svporpo   %add0 = add i32 %arg, %arg
337cbbd1532Svporpo   %add1 = add i32 %add0, %arg
338cbbd1532Svporpo   ret i32 %add1
339cbbd1532Svporpo }
340cbbd1532Svporpo )IR");
341cbbd1532Svporpo   Function &LLVMF = *M->getFunction("foo");
342cbbd1532Svporpo   sandboxir::Context Ctx(C);
343cbbd1532Svporpo 
344cbbd1532Svporpo   auto *F = Ctx.createFunction(&LLVMF);
345cbbd1532Svporpo   auto *BB = &*F->begin();
346cbbd1532Svporpo   auto It = BB->begin();
347cbbd1532Svporpo   sandboxir::Instruction *Add0 = &*It++;
348cbbd1532Svporpo   sandboxir::Instruction *Add1 = &*It++;
349cbbd1532Svporpo   sandboxir::Instruction *Ret = &*It++;
350cbbd1532Svporpo 
351cbbd1532Svporpo   // Check moveBefore(Instruction *) with tracking enabled.
352cbbd1532Svporpo   Ctx.save();
353cbbd1532Svporpo   Add1->moveBefore(Add0);
354cbbd1532Svporpo   It = BB->begin();
355cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
356cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
357cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
358cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
359cbbd1532Svporpo   // Check revert().
360cbbd1532Svporpo   Ctx.revert();
361cbbd1532Svporpo   It = BB->begin();
362cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
363cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
364cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
365cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
366cbbd1532Svporpo 
367cbbd1532Svporpo   // Same for the last instruction in the block.
368cbbd1532Svporpo   Ctx.save();
369cbbd1532Svporpo   Ret->moveBefore(Add0);
370cbbd1532Svporpo   It = BB->begin();
371cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
372cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
373cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
374cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
375cbbd1532Svporpo   Ctx.revert();
376cbbd1532Svporpo   It = BB->begin();
377cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
378cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
379cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
380cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
381cbbd1532Svporpo 
382cbbd1532Svporpo   // Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.
383cbbd1532Svporpo   Ctx.save();
384cbbd1532Svporpo   Add1->moveBefore(*BB, Add0->getIterator());
385cbbd1532Svporpo   It = BB->begin();
386cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
387cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
388cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
389cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
390cbbd1532Svporpo   // Check revert().
391cbbd1532Svporpo   Ctx.revert();
392cbbd1532Svporpo   It = BB->begin();
393cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
394cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
395cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
396cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
397cbbd1532Svporpo 
398cbbd1532Svporpo   // Same for the last instruction in the block.
399cbbd1532Svporpo   Ctx.save();
400cbbd1532Svporpo   Ret->moveBefore(*BB, Add0->getIterator());
401cbbd1532Svporpo   It = BB->begin();
402cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
403cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
404cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
405cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
406cbbd1532Svporpo   // Check revert().
407cbbd1532Svporpo   Ctx.revert();
408cbbd1532Svporpo   It = BB->begin();
409cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
410cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
411cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
412cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
413cbbd1532Svporpo 
414cbbd1532Svporpo   // Check moveAfter(Instruction *) with tracking enabled.
415cbbd1532Svporpo   Ctx.save();
416cbbd1532Svporpo   Add0->moveAfter(Add1);
417cbbd1532Svporpo   It = BB->begin();
418cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
419cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
420cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
421cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
422cbbd1532Svporpo   // Check revert().
423cbbd1532Svporpo   Ctx.revert();
424cbbd1532Svporpo   It = BB->begin();
425cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
426cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
427cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
428cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
429cbbd1532Svporpo 
430cbbd1532Svporpo   // Same for the last instruction in the block.
431cbbd1532Svporpo   Ctx.save();
432cbbd1532Svporpo   Ret->moveAfter(Add0);
433cbbd1532Svporpo   It = BB->begin();
434cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
435cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
436cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
437cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
438cbbd1532Svporpo   // Check revert().
439cbbd1532Svporpo   Ctx.revert();
440cbbd1532Svporpo   It = BB->begin();
441cbbd1532Svporpo   EXPECT_EQ(&*It++, Add0);
442cbbd1532Svporpo   EXPECT_EQ(&*It++, Add1);
443cbbd1532Svporpo   EXPECT_EQ(&*It++, Ret);
444cbbd1532Svporpo   EXPECT_EQ(It, BB->end());
445cbbd1532Svporpo }
446372a6beaSvporpo 
44785da9611Svporpo // TODO: Test multi-instruction patterns.
44885da9611Svporpo TEST_F(TrackerTest, InsertIntoBB) {
44985da9611Svporpo   parseIR(C, R"IR(
45085da9611Svporpo define void @foo(i32 %arg) {
45185da9611Svporpo   %add0 = add i32 %arg, %arg
45285da9611Svporpo   ret void
45385da9611Svporpo }
45485da9611Svporpo )IR");
45585da9611Svporpo   Function &LLVMF = *M->getFunction("foo");
45685da9611Svporpo   sandboxir::Context Ctx(C);
45785da9611Svporpo 
45885da9611Svporpo   auto *F = Ctx.createFunction(&LLVMF);
45985da9611Svporpo   auto *BB = &*F->begin();
46085da9611Svporpo   auto It = BB->begin();
46185da9611Svporpo   sandboxir::Instruction *Add0 = &*It++;
46285da9611Svporpo   sandboxir::Instruction *Ret = &*It++;
46385da9611Svporpo   // Detach `Add0` before we save.
46485da9611Svporpo   Add0->removeFromParent();
46585da9611Svporpo 
46685da9611Svporpo   // Check insertBefore(Instruction *) with tracking enabled.
46785da9611Svporpo   Ctx.save();
46885da9611Svporpo   Add0->insertBefore(Ret);
46985da9611Svporpo   It = BB->begin();
47085da9611Svporpo   EXPECT_EQ(&*It++, Add0);
47185da9611Svporpo   EXPECT_EQ(&*It++, Ret);
47285da9611Svporpo   EXPECT_EQ(It, BB->end());
47385da9611Svporpo   // Check revert().
47485da9611Svporpo   Ctx.revert();
47585da9611Svporpo   It = BB->begin();
47685da9611Svporpo   EXPECT_EQ(&*It++, Ret);
47785da9611Svporpo   EXPECT_EQ(It, BB->end());
47885da9611Svporpo 
47985da9611Svporpo   // Check insertAfter(Instruction *) with tracking enabled.
48085da9611Svporpo   Ctx.save();
48185da9611Svporpo   Add0->insertAfter(Ret);
48285da9611Svporpo   It = BB->begin();
48385da9611Svporpo   EXPECT_EQ(&*It++, Ret);
48485da9611Svporpo   EXPECT_EQ(&*It++, Add0);
48585da9611Svporpo   EXPECT_EQ(It, BB->end());
48685da9611Svporpo   // Check revert().
48785da9611Svporpo   Ctx.revert();
48885da9611Svporpo   It = BB->begin();
48985da9611Svporpo   EXPECT_EQ(&*It++, Ret);
49085da9611Svporpo   EXPECT_EQ(It, BB->end());
49185da9611Svporpo 
49285da9611Svporpo   // Check insertInto(BasicBlock *, BasicBlock::iterator) with tracking enabled.
49385da9611Svporpo   Ctx.save();
49485da9611Svporpo   Add0->insertInto(BB, Ret->getIterator());
49585da9611Svporpo   It = BB->begin();
49685da9611Svporpo   EXPECT_EQ(&*It++, Add0);
49785da9611Svporpo   EXPECT_EQ(&*It++, Ret);
49885da9611Svporpo   EXPECT_EQ(It, BB->end());
49985da9611Svporpo   // Check revert().
50085da9611Svporpo   Ctx.revert();
50185da9611Svporpo   It = BB->begin();
50285da9611Svporpo   EXPECT_EQ(&*It++, Ret);
50385da9611Svporpo   EXPECT_EQ(It, BB->end());
50485da9611Svporpo 
50585da9611Svporpo   // To make sure we don't leak memory insert `Add0` back into the BB before the
50685da9611Svporpo   // end of the test.
50785da9611Svporpo   Add0->insertBefore(Ret);
50885da9611Svporpo }
50985da9611Svporpo 
5100959e58fSvporpo // TODO: Test multi-instruction patterns.
5110959e58fSvporpo TEST_F(TrackerTest, CreateAndInsertInst) {
5120959e58fSvporpo   parseIR(C, R"IR(
5130959e58fSvporpo define void @foo(ptr %ptr) {
5140959e58fSvporpo   %ld = load i8, ptr %ptr, align 64
5150959e58fSvporpo   ret void
5160959e58fSvporpo }
5170959e58fSvporpo )IR");
5180959e58fSvporpo   Function &LLVMF = *M->getFunction("foo");
5190959e58fSvporpo   sandboxir::Context Ctx(C);
5200959e58fSvporpo 
5210959e58fSvporpo   auto *F = Ctx.createFunction(&LLVMF);
5220959e58fSvporpo   auto *Ptr = F->getArg(0);
5230959e58fSvporpo   auto *BB = &*F->begin();
5240959e58fSvporpo   auto It = BB->begin();
5250959e58fSvporpo   auto *Ld = cast<sandboxir::LoadInst>(&*It++);
5260959e58fSvporpo   auto *Ret = &*It++;
5270959e58fSvporpo 
5280959e58fSvporpo   Ctx.save();
5290959e58fSvporpo   // Check create(InsertBefore) with tracking enabled.
530e1434a87Svporpo   sandboxir::LoadInst *NewLd = sandboxir::LoadInst::create(
531e1434a87Svporpo       Ld->getType(), Ptr, Align(8),
532e1434a87Svporpo       /*InsertBefore=*/Ld->getIterator(), Ctx, "NewLd");
5330959e58fSvporpo   It = BB->begin();
5340959e58fSvporpo   EXPECT_EQ(&*It++, NewLd);
5350959e58fSvporpo   EXPECT_EQ(&*It++, Ld);
5360959e58fSvporpo   EXPECT_EQ(&*It++, Ret);
5370959e58fSvporpo   EXPECT_EQ(It, BB->end());
5380959e58fSvporpo   // Check revert().
5390959e58fSvporpo   Ctx.revert();
5400959e58fSvporpo   It = BB->begin();
5410959e58fSvporpo   EXPECT_EQ(&*It++, Ld);
5420959e58fSvporpo   EXPECT_EQ(&*It++, Ret);
5430959e58fSvporpo   EXPECT_EQ(It, BB->end());
5440959e58fSvporpo }
5450959e58fSvporpo 
546d88876e7Svporpo TEST_F(TrackerTest, FenceInstSetters) {
547d88876e7Svporpo   parseIR(C, R"IR(
548d88876e7Svporpo define void @foo() {
549d88876e7Svporpo   fence syncscope("singlethread") seq_cst
550d88876e7Svporpo   ret void
551d88876e7Svporpo }
552d88876e7Svporpo )IR");
553d88876e7Svporpo   llvm::Function *LLVMF = &*M->getFunction("foo");
554d88876e7Svporpo   sandboxir::Context Ctx(C);
555d88876e7Svporpo   sandboxir::Function *F = Ctx.createFunction(LLVMF);
556d88876e7Svporpo   auto *BB = &*F->begin();
557d88876e7Svporpo   auto It = BB->begin();
558d88876e7Svporpo   auto *Fence = cast<sandboxir::FenceInst>(&*It++);
559d88876e7Svporpo 
560d88876e7Svporpo   // Check setOrdering().
561d88876e7Svporpo   auto OrigOrdering = Fence->getOrdering();
562d88876e7Svporpo   auto NewOrdering = AtomicOrdering::Release;
563d88876e7Svporpo   EXPECT_NE(NewOrdering, OrigOrdering);
564d88876e7Svporpo   Ctx.save();
565d88876e7Svporpo   Fence->setOrdering(NewOrdering);
566d88876e7Svporpo   EXPECT_EQ(Fence->getOrdering(), NewOrdering);
567d88876e7Svporpo   Ctx.revert();
568d88876e7Svporpo   EXPECT_EQ(Fence->getOrdering(), OrigOrdering);
569d88876e7Svporpo   // Check setSyncScopeID().
570d88876e7Svporpo   auto OrigSSID = Fence->getSyncScopeID();
571d88876e7Svporpo   auto NewSSID = SyncScope::System;
572d88876e7Svporpo   EXPECT_NE(NewSSID, OrigSSID);
573d88876e7Svporpo   Ctx.save();
574d88876e7Svporpo   Fence->setSyncScopeID(NewSSID);
575d88876e7Svporpo   EXPECT_EQ(Fence->getSyncScopeID(), NewSSID);
576d88876e7Svporpo   Ctx.revert();
577d88876e7Svporpo   EXPECT_EQ(Fence->getSyncScopeID(), OrigSSID);
578d88876e7Svporpo }
579d88876e7Svporpo 
580372a6beaSvporpo TEST_F(TrackerTest, CallBaseSetters) {
581372a6beaSvporpo   parseIR(C, R"IR(
582372a6beaSvporpo declare void @bar1(i8)
583372a6beaSvporpo declare void @bar2(i8)
584372a6beaSvporpo 
585372a6beaSvporpo define void @foo(i8 %arg0, i8 %arg1) {
586372a6beaSvporpo   call void @bar1(i8 %arg0)
587372a6beaSvporpo   ret void
588372a6beaSvporpo }
589372a6beaSvporpo )IR");
590372a6beaSvporpo   Function &LLVMF = *M->getFunction("foo");
591372a6beaSvporpo   sandboxir::Context Ctx(C);
592372a6beaSvporpo 
593372a6beaSvporpo   auto *F = Ctx.createFunction(&LLVMF);
594372a6beaSvporpo   unsigned ArgIdx = 0;
595372a6beaSvporpo   auto *Arg0 = F->getArg(ArgIdx++);
596372a6beaSvporpo   auto *Arg1 = F->getArg(ArgIdx++);
597372a6beaSvporpo   auto *BB = &*F->begin();
598372a6beaSvporpo   auto It = BB->begin();
599372a6beaSvporpo   auto *Call = cast<sandboxir::CallBase>(&*It++);
600372a6beaSvporpo   [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
601372a6beaSvporpo 
602372a6beaSvporpo   // Check setArgOperand().
603372a6beaSvporpo   Ctx.save();
604372a6beaSvporpo   Call->setArgOperand(0, Arg1);
605372a6beaSvporpo   EXPECT_EQ(Call->getArgOperand(0), Arg1);
606372a6beaSvporpo   Ctx.revert();
607372a6beaSvporpo   EXPECT_EQ(Call->getArgOperand(0), Arg0);
608372a6beaSvporpo 
609372a6beaSvporpo   auto *Bar1F = Call->getCalledFunction();
610372a6beaSvporpo   auto *Bar2F = Ctx.createFunction(M->getFunction("bar2"));
611372a6beaSvporpo 
612372a6beaSvporpo   // Check setCalledOperand().
613372a6beaSvporpo   Ctx.save();
614372a6beaSvporpo   Call->setCalledOperand(Bar2F);
615372a6beaSvporpo   EXPECT_EQ(Call->getCalledOperand(), Bar2F);
616372a6beaSvporpo   Ctx.revert();
617372a6beaSvporpo   EXPECT_EQ(Call->getCalledOperand(), Bar1F);
618372a6beaSvporpo 
619372a6beaSvporpo   // Check setCalledFunction().
620372a6beaSvporpo   Ctx.save();
621372a6beaSvporpo   Call->setCalledFunction(Bar2F);
622372a6beaSvporpo   EXPECT_EQ(Call->getCalledFunction(), Bar2F);
623372a6beaSvporpo   Ctx.revert();
624372a6beaSvporpo   EXPECT_EQ(Call->getCalledFunction(), Bar1F);
625372a6beaSvporpo }
626db2aa50eSvporpo 
627db2aa50eSvporpo TEST_F(TrackerTest, InvokeSetters) {
628db2aa50eSvporpo   parseIR(C, R"IR(
629db2aa50eSvporpo define void @foo(i8 %arg) {
630db2aa50eSvporpo  bb0:
631db2aa50eSvporpo    invoke i8 @foo(i8 %arg) to label %normal_bb
632db2aa50eSvporpo                        unwind label %exception_bb
633db2aa50eSvporpo  normal_bb:
634db2aa50eSvporpo    ret void
635db2aa50eSvporpo  exception_bb:
636db2aa50eSvporpo    ret void
637db2aa50eSvporpo  other_bb:
638db2aa50eSvporpo    ret void
639db2aa50eSvporpo }
640db2aa50eSvporpo )IR");
641db2aa50eSvporpo   Function &LLVMF = *M->getFunction("foo");
642db2aa50eSvporpo   sandboxir::Context Ctx(C);
643db2aa50eSvporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
644db2aa50eSvporpo   auto *BB0 = cast<sandboxir::BasicBlock>(
645db2aa50eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
646db2aa50eSvporpo   auto *NormalBB = cast<sandboxir::BasicBlock>(
647db2aa50eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "normal_bb")));
648db2aa50eSvporpo   auto *ExceptionBB = cast<sandboxir::BasicBlock>(
649db2aa50eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "exception_bb")));
650db2aa50eSvporpo   auto *OtherBB = cast<sandboxir::BasicBlock>(
651db2aa50eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));
652db2aa50eSvporpo   auto It = BB0->begin();
653db2aa50eSvporpo   auto *Invoke = cast<sandboxir::InvokeInst>(&*It++);
654db2aa50eSvporpo 
655db2aa50eSvporpo   // Check setNormalDest().
656db2aa50eSvporpo   Ctx.save();
657db2aa50eSvporpo   Invoke->setNormalDest(OtherBB);
658db2aa50eSvporpo   EXPECT_EQ(Invoke->getNormalDest(), OtherBB);
659db2aa50eSvporpo   Ctx.revert();
660db2aa50eSvporpo   EXPECT_EQ(Invoke->getNormalDest(), NormalBB);
661db2aa50eSvporpo 
662db2aa50eSvporpo   // Check setUnwindDest().
663db2aa50eSvporpo   Ctx.save();
664db2aa50eSvporpo   Invoke->setUnwindDest(OtherBB);
665db2aa50eSvporpo   EXPECT_EQ(Invoke->getUnwindDest(), OtherBB);
666db2aa50eSvporpo   Ctx.revert();
667db2aa50eSvporpo   EXPECT_EQ(Invoke->getUnwindDest(), ExceptionBB);
668db2aa50eSvporpo 
669db2aa50eSvporpo   // Check setSuccessor().
670db2aa50eSvporpo   Ctx.save();
671db2aa50eSvporpo   Invoke->setSuccessor(0, OtherBB);
672db2aa50eSvporpo   EXPECT_EQ(Invoke->getSuccessor(0), OtherBB);
673db2aa50eSvporpo   Ctx.revert();
674db2aa50eSvporpo   EXPECT_EQ(Invoke->getSuccessor(0), NormalBB);
675db2aa50eSvporpo 
676db2aa50eSvporpo   Ctx.save();
677db2aa50eSvporpo   Invoke->setSuccessor(1, OtherBB);
678db2aa50eSvporpo   EXPECT_EQ(Invoke->getSuccessor(1), OtherBB);
679db2aa50eSvporpo   Ctx.revert();
680db2aa50eSvporpo   EXPECT_EQ(Invoke->getSuccessor(1), ExceptionBB);
681db2aa50eSvporpo }
682cfb92be0Svporpo 
6836e8c9703Svporpo TEST_F(TrackerTest, CatchSwitchInst) {
6846e8c9703Svporpo   parseIR(C, R"IR(
6856e8c9703Svporpo define void @foo(i32 %cond0, i32 %cond1) {
6866e8c9703Svporpo   bb0:
6876e8c9703Svporpo     %cs0 = catchswitch within none [label %handler0, label %handler1] unwind to caller
6886e8c9703Svporpo   bb1:
6896e8c9703Svporpo     %cs1 = catchswitch within %cs0 [label %handler0, label %handler1] unwind label %cleanup
6906e8c9703Svporpo   handler0:
6916e8c9703Svporpo     ret void
6926e8c9703Svporpo   handler1:
6936e8c9703Svporpo     ret void
6946e8c9703Svporpo   cleanup:
6956e8c9703Svporpo     ret void
6966e8c9703Svporpo }
6976e8c9703Svporpo )IR");
6986e8c9703Svporpo   Function &LLVMF = *M->getFunction("foo");
6996e8c9703Svporpo 
7006e8c9703Svporpo   sandboxir::Context Ctx(C);
7016e8c9703Svporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
7026e8c9703Svporpo   auto *BB0 = cast<sandboxir::BasicBlock>(
7036e8c9703Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
7046e8c9703Svporpo   auto *BB1 = cast<sandboxir::BasicBlock>(
7056e8c9703Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
7066e8c9703Svporpo   auto *Handler0 = cast<sandboxir::BasicBlock>(
7076e8c9703Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "handler0")));
7086e8c9703Svporpo   auto *Handler1 = cast<sandboxir::BasicBlock>(
7096e8c9703Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "handler1")));
7106e8c9703Svporpo   auto *CS0 = cast<sandboxir::CatchSwitchInst>(&*BB0->begin());
7116e8c9703Svporpo   auto *CS1 = cast<sandboxir::CatchSwitchInst>(&*BB1->begin());
7126e8c9703Svporpo 
7136e8c9703Svporpo   // Check setParentPad().
7146e8c9703Svporpo   auto *OrigPad = CS0->getParentPad();
7156e8c9703Svporpo   auto *NewPad = CS1;
7166e8c9703Svporpo   EXPECT_NE(NewPad, OrigPad);
7176e8c9703Svporpo   Ctx.save();
7186e8c9703Svporpo   CS0->setParentPad(NewPad);
7196e8c9703Svporpo   EXPECT_EQ(CS0->getParentPad(), NewPad);
7206e8c9703Svporpo   Ctx.revert();
7216e8c9703Svporpo   EXPECT_EQ(CS0->getParentPad(), OrigPad);
7226e8c9703Svporpo   // Check setUnwindDest().
7236e8c9703Svporpo   auto *OrigUnwindDest = CS1->getUnwindDest();
7246e8c9703Svporpo   auto *NewUnwindDest = BB0;
7256e8c9703Svporpo   EXPECT_NE(NewUnwindDest, OrigUnwindDest);
7266e8c9703Svporpo   Ctx.save();
7276e8c9703Svporpo   CS1->setUnwindDest(NewUnwindDest);
7286e8c9703Svporpo   EXPECT_EQ(CS1->getUnwindDest(), NewUnwindDest);
7296e8c9703Svporpo   Ctx.revert();
7306e8c9703Svporpo   EXPECT_EQ(CS1->getUnwindDest(), OrigUnwindDest);
7316e8c9703Svporpo   // Check setSuccessor().
7326e8c9703Svporpo   auto *OrigSuccessor = CS0->getSuccessor(0);
7336e8c9703Svporpo   auto *NewSuccessor = BB0;
7346e8c9703Svporpo   EXPECT_NE(NewSuccessor, OrigSuccessor);
7356e8c9703Svporpo   Ctx.save();
7366e8c9703Svporpo   CS0->setSuccessor(0, NewSuccessor);
7376e8c9703Svporpo   EXPECT_EQ(CS0->getSuccessor(0), NewSuccessor);
7386e8c9703Svporpo   Ctx.revert();
7396e8c9703Svporpo   EXPECT_EQ(CS0->getSuccessor(0), OrigSuccessor);
7406e8c9703Svporpo   // Check addHandler().
7416e8c9703Svporpo   Ctx.save();
7426e8c9703Svporpo   CS0->addHandler(BB0);
7436e8c9703Svporpo   EXPECT_EQ(CS0->getNumHandlers(), 3u);
7446e8c9703Svporpo   Ctx.revert();
7456e8c9703Svporpo   EXPECT_EQ(CS0->getNumHandlers(), 2u);
7466e8c9703Svporpo   auto HIt = CS0->handler_begin();
7476e8c9703Svporpo   EXPECT_EQ(*HIt++, Handler0);
7486e8c9703Svporpo   EXPECT_EQ(*HIt++, Handler1);
7496e8c9703Svporpo }
7506e8c9703Svporpo 
751e8b93ce2Svporpo TEST_F(TrackerTest, LandingPadInstSetters) {
752e8b93ce2Svporpo   parseIR(C, R"IR(
753e8b93ce2Svporpo define void @foo() {
754e8b93ce2Svporpo entry:
755e8b93ce2Svporpo   invoke void @foo()
756e8b93ce2Svporpo       to label %bb unwind label %unwind
757e8b93ce2Svporpo unwind:
758e8b93ce2Svporpo   %lpad = landingpad { ptr, i32 }
759e8b93ce2Svporpo             catch ptr null
760e8b93ce2Svporpo   ret void
761e8b93ce2Svporpo bb:
762e8b93ce2Svporpo   ret void
763e8b93ce2Svporpo }
764e8b93ce2Svporpo )IR");
765e8b93ce2Svporpo   Function &LLVMF = *M->getFunction("foo");
766e8b93ce2Svporpo   auto *LLVMUnwind = getBasicBlockByName(LLVMF, "unwind");
767e8b93ce2Svporpo 
768e8b93ce2Svporpo   sandboxir::Context Ctx(C);
769e8b93ce2Svporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
770e8b93ce2Svporpo   auto *Unwind = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMUnwind));
771e8b93ce2Svporpo   auto It = Unwind->begin();
772e8b93ce2Svporpo   auto *LPad = cast<sandboxir::LandingPadInst>(&*It++);
773e8b93ce2Svporpo   [[maybe_unused]] auto *Ret = cast<sandboxir::ReturnInst>(&*It++);
774e8b93ce2Svporpo 
775e8b93ce2Svporpo   // Check setCleanup().
776e8b93ce2Svporpo   auto OrigIsCleanup = LPad->isCleanup();
777e8b93ce2Svporpo   auto NewIsCleanup = true;
778e8b93ce2Svporpo   EXPECT_NE(NewIsCleanup, OrigIsCleanup);
779e8b93ce2Svporpo   Ctx.save();
780e8b93ce2Svporpo   LPad->setCleanup(NewIsCleanup);
781e8b93ce2Svporpo   EXPECT_EQ(LPad->isCleanup(), NewIsCleanup);
782e8b93ce2Svporpo   Ctx.revert();
783e8b93ce2Svporpo   EXPECT_EQ(LPad->isCleanup(), OrigIsCleanup);
784e8b93ce2Svporpo }
785e8b93ce2Svporpo 
7860d21c2b3Svporpo TEST_F(TrackerTest, CatchReturnInstSetters) {
7870d21c2b3Svporpo   parseIR(C, R"IR(
7880d21c2b3Svporpo define void @foo() {
7890d21c2b3Svporpo dispatch:
7900d21c2b3Svporpo   %cs = catchswitch within none [label %catch] unwind to caller
7910d21c2b3Svporpo catch:
7920d21c2b3Svporpo   %catchpad = catchpad within %cs [ptr @foo]
7930d21c2b3Svporpo   catchret from %catchpad to label %continue
7940d21c2b3Svporpo continue:
7950d21c2b3Svporpo   ret void
7960d21c2b3Svporpo catch2:
7970d21c2b3Svporpo   %catchpad2 = catchpad within %cs [ptr @foo]
7980d21c2b3Svporpo   ret void
7990d21c2b3Svporpo }
8000d21c2b3Svporpo )IR");
8010d21c2b3Svporpo   Function &LLVMF = *M->getFunction("foo");
8020d21c2b3Svporpo   BasicBlock *LLVMCatch = getBasicBlockByName(LLVMF, "catch");
8030d21c2b3Svporpo   auto LLVMIt = LLVMCatch->begin();
8040d21c2b3Svporpo   [[maybe_unused]] auto *LLVMCP = cast<llvm::CatchPadInst>(&*LLVMIt++);
8050d21c2b3Svporpo 
8060d21c2b3Svporpo   sandboxir::Context Ctx(C);
8070d21c2b3Svporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
8080d21c2b3Svporpo   auto *Catch = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCatch));
8090d21c2b3Svporpo   auto *Catch2 = cast<sandboxir::BasicBlock>(
8100d21c2b3Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "catch2")));
8110d21c2b3Svporpo   auto It = Catch->begin();
8120d21c2b3Svporpo   [[maybe_unused]] auto *CP = cast<sandboxir::CatchPadInst>(&*It++);
8130d21c2b3Svporpo   auto *CR = cast<sandboxir::CatchReturnInst>(&*It++);
8140d21c2b3Svporpo   auto *CP2 = cast<sandboxir::CatchPadInst>(&*Catch2->begin());
8150d21c2b3Svporpo 
8160d21c2b3Svporpo   // Check setCatchPad().
8170d21c2b3Svporpo   auto *OrigCP = CR->getCatchPad();
8180d21c2b3Svporpo   auto *NewCP = CP2;
8190d21c2b3Svporpo   EXPECT_NE(NewCP, OrigCP);
8200d21c2b3Svporpo   Ctx.save();
8210d21c2b3Svporpo   CR->setCatchPad(NewCP);
8220d21c2b3Svporpo   EXPECT_EQ(CR->getCatchPad(), NewCP);
8230d21c2b3Svporpo   Ctx.revert();
8240d21c2b3Svporpo   EXPECT_EQ(CR->getCatchPad(), OrigCP);
8250d21c2b3Svporpo   // Check setSuccessor().
8260d21c2b3Svporpo   auto *OrigSucc = CR->getSuccessor();
8270d21c2b3Svporpo   auto *NewSucc = Catch;
8280d21c2b3Svporpo   EXPECT_NE(NewSucc, OrigSucc);
8290d21c2b3Svporpo   Ctx.save();
8300d21c2b3Svporpo   CR->setSuccessor(NewSucc);
8310d21c2b3Svporpo   EXPECT_EQ(CR->getSuccessor(), NewSucc);
8320d21c2b3Svporpo   Ctx.revert();
8330d21c2b3Svporpo   EXPECT_EQ(CR->getSuccessor(), OrigSucc);
8340d21c2b3Svporpo }
8350d21c2b3Svporpo 
836d0213216Svporpo TEST_F(TrackerTest, CleanupReturnInstSetters) {
837d0213216Svporpo   parseIR(C, R"IR(
838d0213216Svporpo define void @foo() {
839d0213216Svporpo dispatch:
840d0213216Svporpo   invoke void @foo()
841d0213216Svporpo               to label %throw unwind label %cleanup
842d0213216Svporpo throw:
843d0213216Svporpo   ret void
844d0213216Svporpo cleanup:
845d0213216Svporpo   %cleanuppad = cleanuppad within none []
846d0213216Svporpo   cleanupret from %cleanuppad unwind label %cleanup2
847d0213216Svporpo cleanup2:
848d0213216Svporpo   %cleanuppad2 = cleanuppad within none []
849d0213216Svporpo   ret void
850d0213216Svporpo }
851d0213216Svporpo )IR");
852d0213216Svporpo   Function &LLVMF = *M->getFunction("foo");
853d0213216Svporpo   BasicBlock *LLVMCleanup = getBasicBlockByName(LLVMF, "cleanup");
854d0213216Svporpo 
855d0213216Svporpo   sandboxir::Context Ctx(C);
856d0213216Svporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
857d0213216Svporpo   auto *Throw = cast<sandboxir::BasicBlock>(
858d0213216Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "throw")));
859d0213216Svporpo   auto *Cleanup = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMCleanup));
860d0213216Svporpo   auto *Cleanup2 = cast<sandboxir::BasicBlock>(
861d0213216Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "cleanup2")));
862d0213216Svporpo   auto It = Cleanup->begin();
863d0213216Svporpo   [[maybe_unused]] auto *CP = cast<sandboxir::CleanupPadInst>(&*It++);
864d0213216Svporpo   auto *CRI = cast<sandboxir::CleanupReturnInst>(&*It++);
865d0213216Svporpo   auto *CP2 = cast<sandboxir::CleanupPadInst>(&*Cleanup2->begin());
866d0213216Svporpo 
867d0213216Svporpo   // Check setCleanupPad().
868d0213216Svporpo   auto *OrigCleanupPad = CRI->getCleanupPad();
869d0213216Svporpo   auto *NewCleanupPad = CP2;
870d0213216Svporpo   EXPECT_NE(NewCleanupPad, OrigCleanupPad);
871d0213216Svporpo   Ctx.save();
872d0213216Svporpo   CRI->setCleanupPad(NewCleanupPad);
873d0213216Svporpo   EXPECT_EQ(CRI->getCleanupPad(), NewCleanupPad);
874d0213216Svporpo   Ctx.revert();
875d0213216Svporpo   EXPECT_EQ(CRI->getCleanupPad(), OrigCleanupPad);
876d0213216Svporpo   // Check setUnwindDest().
877d0213216Svporpo   auto *OrigUnwindDest = CRI->getUnwindDest();
878d0213216Svporpo   auto *NewUnwindDest = Throw;
879d0213216Svporpo   EXPECT_NE(NewUnwindDest, OrigUnwindDest);
880d0213216Svporpo   Ctx.save();
881d0213216Svporpo   CRI->setUnwindDest(NewUnwindDest);
882d0213216Svporpo   EXPECT_EQ(CRI->getUnwindDest(), NewUnwindDest);
883d0213216Svporpo   Ctx.revert();
884d0213216Svporpo   EXPECT_EQ(CRI->getUnwindDest(), OrigUnwindDest);
885d0213216Svporpo }
886d0213216Svporpo 
887516c1a0eSvporpo TEST_F(TrackerTest, SwitchInstSetters) {
888516c1a0eSvporpo   parseIR(C, R"IR(
889516c1a0eSvporpo define void @foo(i32 %cond0, i32 %cond1) {
890516c1a0eSvporpo   entry:
891516c1a0eSvporpo     switch i32 %cond0, label %default [ i32 0, label %bb0
892516c1a0eSvporpo                                         i32 1, label %bb1 ]
893516c1a0eSvporpo   bb0:
894516c1a0eSvporpo     ret void
895516c1a0eSvporpo   bb1:
896516c1a0eSvporpo     ret void
897516c1a0eSvporpo   default:
898516c1a0eSvporpo     ret void
899516c1a0eSvporpo }
900516c1a0eSvporpo )IR");
901516c1a0eSvporpo   Function &LLVMF = *M->getFunction("foo");
902516c1a0eSvporpo   auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry");
903516c1a0eSvporpo 
904516c1a0eSvporpo   sandboxir::Context Ctx(C);
905516c1a0eSvporpo   auto &F = *Ctx.createFunction(&LLVMF);
906516c1a0eSvporpo   auto *Cond1 = F.getArg(1);
907516c1a0eSvporpo   auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry));
908516c1a0eSvporpo   auto *BB0 = cast<sandboxir::BasicBlock>(
909516c1a0eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
910516c1a0eSvporpo   auto *BB1 = cast<sandboxir::BasicBlock>(
911516c1a0eSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
912516c1a0eSvporpo   auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin());
913516c1a0eSvporpo 
914516c1a0eSvporpo   // Check setCondition().
915516c1a0eSvporpo   auto *OrigCond = Switch->getCondition();
916516c1a0eSvporpo   auto *NewCond = Cond1;
917516c1a0eSvporpo   EXPECT_NE(NewCond, OrigCond);
918516c1a0eSvporpo   Ctx.save();
919516c1a0eSvporpo   Switch->setCondition(NewCond);
920516c1a0eSvporpo   EXPECT_EQ(Switch->getCondition(), NewCond);
921516c1a0eSvporpo   Ctx.revert();
922516c1a0eSvporpo   EXPECT_EQ(Switch->getCondition(), OrigCond);
923516c1a0eSvporpo   // Check setDefaultDest().
924516c1a0eSvporpo   auto *OrigDefaultDest = Switch->getDefaultDest();
925516c1a0eSvporpo   auto *NewDefaultDest = Entry;
926516c1a0eSvporpo   EXPECT_NE(NewDefaultDest, OrigDefaultDest);
927516c1a0eSvporpo   Ctx.save();
928516c1a0eSvporpo   Switch->setDefaultDest(NewDefaultDest);
929516c1a0eSvporpo   EXPECT_EQ(Switch->getDefaultDest(), NewDefaultDest);
930516c1a0eSvporpo   Ctx.revert();
931516c1a0eSvporpo   EXPECT_EQ(Switch->getDefaultDest(), OrigDefaultDest);
932516c1a0eSvporpo   // Check setSuccessor().
933516c1a0eSvporpo   auto *OrigSucc = Switch->getSuccessor(0);
934516c1a0eSvporpo   auto *NewSucc = Entry;
935516c1a0eSvporpo   EXPECT_NE(NewSucc, OrigSucc);
936516c1a0eSvporpo   Ctx.save();
937516c1a0eSvporpo   Switch->setSuccessor(0, NewSucc);
938516c1a0eSvporpo   EXPECT_EQ(Switch->getSuccessor(0), NewSucc);
939516c1a0eSvporpo   Ctx.revert();
940516c1a0eSvporpo   EXPECT_EQ(Switch->getSuccessor(0), OrigSucc);
941516c1a0eSvporpo   // Check addCase().
942034f2b38Svporpo   auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);
943034f2b38Svporpo   auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1);
944034f2b38Svporpo   auto *FortyTwo =
945034f2b38Svporpo       sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 42);
946516c1a0eSvporpo   Ctx.save();
947516c1a0eSvporpo   Switch->addCase(FortyTwo, Entry);
948516c1a0eSvporpo   EXPECT_EQ(Switch->getNumCases(), 3u);
949516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(Entry), FortyTwo);
950516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseValue(FortyTwo)->getCaseSuccessor(), Entry);
951516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
952516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB1), One);
953516c1a0eSvporpo   Ctx.revert();
954516c1a0eSvporpo   EXPECT_EQ(Switch->getNumCases(), 2u);
955516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
956516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB1), One);
957516c1a0eSvporpo   // Check removeCase().
958516c1a0eSvporpo   Ctx.save();
959516c1a0eSvporpo   Switch->removeCase(Switch->findCaseValue(Zero));
960516c1a0eSvporpo   EXPECT_EQ(Switch->getNumCases(), 1u);
961516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB1), One);
962516c1a0eSvporpo   Ctx.revert();
963516c1a0eSvporpo   EXPECT_EQ(Switch->getNumCases(), 2u);
964516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
965516c1a0eSvporpo   EXPECT_EQ(Switch->findCaseDest(BB1), One);
966516c1a0eSvporpo }
967516c1a0eSvporpo 
9689d85ba57SJorge Gorbe Moya TEST_F(TrackerTest, SwitchInstPreservesSuccesorOrder) {
9699d85ba57SJorge Gorbe Moya   parseIR(C, R"IR(
9709d85ba57SJorge Gorbe Moya define void @foo(i32 %cond0) {
9719d85ba57SJorge Gorbe Moya   entry:
9729d85ba57SJorge Gorbe Moya     switch i32 %cond0, label %default [ i32 0, label %bb0
9739d85ba57SJorge Gorbe Moya                                         i32 1, label %bb1
9749d85ba57SJorge Gorbe Moya                                         i32 2, label %bb2 ]
9759d85ba57SJorge Gorbe Moya   bb0:
9769d85ba57SJorge Gorbe Moya     ret void
9779d85ba57SJorge Gorbe Moya   bb1:
9789d85ba57SJorge Gorbe Moya     ret void
9799d85ba57SJorge Gorbe Moya   bb2:
9809d85ba57SJorge Gorbe Moya     ret void
9819d85ba57SJorge Gorbe Moya   default:
9829d85ba57SJorge Gorbe Moya     ret void
9839d85ba57SJorge Gorbe Moya }
9849d85ba57SJorge Gorbe Moya )IR");
9859d85ba57SJorge Gorbe Moya   Function &LLVMF = *M->getFunction("foo");
9869d85ba57SJorge Gorbe Moya   auto *LLVMEntry = getBasicBlockByName(LLVMF, "entry");
9879d85ba57SJorge Gorbe Moya 
9889d85ba57SJorge Gorbe Moya   sandboxir::Context Ctx(C);
9899d85ba57SJorge Gorbe Moya   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
9909d85ba57SJorge Gorbe Moya   auto *Entry = cast<sandboxir::BasicBlock>(Ctx.getValue(LLVMEntry));
9919d85ba57SJorge Gorbe Moya   auto *BB0 = cast<sandboxir::BasicBlock>(
9929d85ba57SJorge Gorbe Moya       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
9939d85ba57SJorge Gorbe Moya   auto *BB1 = cast<sandboxir::BasicBlock>(
9949d85ba57SJorge Gorbe Moya       Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
9959d85ba57SJorge Gorbe Moya   auto *BB2 = cast<sandboxir::BasicBlock>(
9969d85ba57SJorge Gorbe Moya       Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));
9979d85ba57SJorge Gorbe Moya   auto *Switch = cast<sandboxir::SwitchInst>(&*Entry->begin());
9989d85ba57SJorge Gorbe Moya 
9999d85ba57SJorge Gorbe Moya   auto *DefaultDest = Switch->getDefaultDest();
10009d85ba57SJorge Gorbe Moya   auto *Zero = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 0);
10019d85ba57SJorge Gorbe Moya   auto *One = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 1);
10029d85ba57SJorge Gorbe Moya   auto *Two = sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx), 2);
10039d85ba57SJorge Gorbe Moya 
10049d85ba57SJorge Gorbe Moya   // Check that we can properly revert a removeCase multiple positions apart
10059d85ba57SJorge Gorbe Moya   // from the end of the operand list.
10069d85ba57SJorge Gorbe Moya   Ctx.save();
10079d85ba57SJorge Gorbe Moya   Switch->removeCase(Switch->findCaseValue(Zero));
10089d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 2u);
10099d85ba57SJorge Gorbe Moya   Ctx.revert();
10109d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 3u);
10119d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
10129d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB1), One);
10139d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB2), Two);
10149d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);
10159d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(1), BB0);
10169d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(2), BB1);
10179d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(3), BB2);
10189d85ba57SJorge Gorbe Moya 
10199d85ba57SJorge Gorbe Moya   // Check that we can properly revert a removeCase of the last case.
10209d85ba57SJorge Gorbe Moya   Ctx.save();
10219d85ba57SJorge Gorbe Moya   Switch->removeCase(Switch->findCaseValue(Two));
10229d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 2u);
10239d85ba57SJorge Gorbe Moya   Ctx.revert();
10249d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 3u);
10259d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
10269d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB1), One);
10279d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB2), Two);
10289d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);
10299d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(1), BB0);
10309d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(2), BB1);
10319d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(3), BB2);
10329d85ba57SJorge Gorbe Moya 
10339d85ba57SJorge Gorbe Moya   // Check order is preserved after reverting multiple removeCase invocations.
10349d85ba57SJorge Gorbe Moya   Ctx.save();
10359d85ba57SJorge Gorbe Moya   Switch->removeCase(Switch->findCaseValue(One));
10369d85ba57SJorge Gorbe Moya   Switch->removeCase(Switch->findCaseValue(Zero));
10379d85ba57SJorge Gorbe Moya   Switch->removeCase(Switch->findCaseValue(Two));
10389d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 0u);
10399d85ba57SJorge Gorbe Moya   Ctx.revert();
10409d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getNumCases(), 3u);
10419d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB0), Zero);
10429d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB1), One);
10439d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->findCaseDest(BB2), Two);
10449d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(0), DefaultDest);
10459d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(1), BB0);
10469d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(2), BB1);
10479d85ba57SJorge Gorbe Moya   EXPECT_EQ(Switch->getSuccessor(3), BB2);
10489d85ba57SJorge Gorbe Moya }
10499d85ba57SJorge Gorbe Moya 
1050956591beSJorge Gorbe Moya TEST_F(TrackerTest, SelectInst) {
1051956591beSJorge Gorbe Moya   parseIR(C, R"IR(
1052956591beSJorge Gorbe Moya define void @foo(i1 %c0, i8 %v0, i8 %v1) {
1053956591beSJorge Gorbe Moya   %sel = select i1 %c0, i8 %v0, i8 %v1
1054956591beSJorge Gorbe Moya   ret void
1055956591beSJorge Gorbe Moya }
1056956591beSJorge Gorbe Moya )IR");
1057956591beSJorge Gorbe Moya   llvm::Function *LLVMF = &*M->getFunction("foo");
1058956591beSJorge Gorbe Moya   sandboxir::Context Ctx(C);
1059956591beSJorge Gorbe Moya   sandboxir::Function *F = Ctx.createFunction(LLVMF);
1060956591beSJorge Gorbe Moya   auto *V0 = F->getArg(1);
1061956591beSJorge Gorbe Moya   auto *V1 = F->getArg(2);
1062956591beSJorge Gorbe Moya   auto *BB = &*F->begin();
1063956591beSJorge Gorbe Moya   auto It = BB->begin();
1064956591beSJorge Gorbe Moya   auto *Select = cast<sandboxir::SelectInst>(&*It++);
1065956591beSJorge Gorbe Moya 
1066956591beSJorge Gorbe Moya   // Check tracking for swapValues.
1067956591beSJorge Gorbe Moya   Ctx.save();
1068956591beSJorge Gorbe Moya   Select->swapValues();
1069956591beSJorge Gorbe Moya   EXPECT_EQ(Select->getTrueValue(), V1);
1070956591beSJorge Gorbe Moya   EXPECT_EQ(Select->getFalseValue(), V0);
1071956591beSJorge Gorbe Moya   Ctx.revert();
1072956591beSJorge Gorbe Moya   EXPECT_EQ(Select->getTrueValue(), V0);
1073956591beSJorge Gorbe Moya   EXPECT_EQ(Select->getFalseValue(), V1);
1074956591beSJorge Gorbe Moya }
1075956591beSJorge Gorbe Moya 
1076e89bcfc0SJorge Gorbe Moya TEST_F(TrackerTest, ShuffleVectorInst) {
1077b5ba7265SJorge Gorbe Moya   parseIR(C, R"IR(
1078b5ba7265SJorge Gorbe Moya define void @foo(<2 x i8> %v1, <2 x i8> %v2) {
1079b5ba7265SJorge Gorbe Moya   %shuf = shufflevector <2 x i8> %v1, <2 x i8> %v2, <2 x i32> <i32 1, i32 2>
1080b5ba7265SJorge Gorbe Moya   ret void
1081b5ba7265SJorge Gorbe Moya }
1082b5ba7265SJorge Gorbe Moya )IR");
1083b5ba7265SJorge Gorbe Moya   Function &LLVMF = *M->getFunction("foo");
1084b5ba7265SJorge Gorbe Moya   sandboxir::Context Ctx(C);
1085b5ba7265SJorge Gorbe Moya 
1086b5ba7265SJorge Gorbe Moya   auto *F = Ctx.createFunction(&LLVMF);
1087b5ba7265SJorge Gorbe Moya   auto *BB = &*F->begin();
1088b5ba7265SJorge Gorbe Moya   auto It = BB->begin();
1089b5ba7265SJorge Gorbe Moya   auto *SVI = cast<sandboxir::ShuffleVectorInst>(&*It++);
1090b5ba7265SJorge Gorbe Moya 
1091b5ba7265SJorge Gorbe Moya   // Check setShuffleMask.
1092b5ba7265SJorge Gorbe Moya   SmallVector<int, 2> OrigMask(SVI->getShuffleMask());
1093b5ba7265SJorge Gorbe Moya   Ctx.save();
1094b5ba7265SJorge Gorbe Moya   SVI->setShuffleMask(ArrayRef<int>({0, 0}));
1095e89bcfc0SJorge Gorbe Moya   EXPECT_NE(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));
1096b5ba7265SJorge Gorbe Moya   Ctx.revert();
1097e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));
1098e89bcfc0SJorge Gorbe Moya 
1099e89bcfc0SJorge Gorbe Moya   // Check commute.
1100e89bcfc0SJorge Gorbe Moya   auto *Op0 = SVI->getOperand(0);
1101e89bcfc0SJorge Gorbe Moya   auto *Op1 = SVI->getOperand(1);
1102e89bcfc0SJorge Gorbe Moya   Ctx.save();
1103e89bcfc0SJorge Gorbe Moya   SVI->commute();
1104e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getOperand(0), Op1);
1105e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getOperand(1), Op0);
1106e89bcfc0SJorge Gorbe Moya   EXPECT_NE(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));
1107e89bcfc0SJorge Gorbe Moya   Ctx.revert();
1108e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getOperand(0), Op0);
1109e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getOperand(1), Op1);
1110e89bcfc0SJorge Gorbe Moya   EXPECT_EQ(SVI->getShuffleMask(), ArrayRef<int>(OrigMask));
1111b5ba7265SJorge Gorbe Moya }
1112b5ba7265SJorge Gorbe Moya 
11133b0a1ecbSvporpo TEST_F(TrackerTest, PossiblyDisjointInstSetters) {
11143b0a1ecbSvporpo   parseIR(C, R"IR(
11153b0a1ecbSvporpo define void @foo(i8 %arg0, i8 %arg1) {
11163b0a1ecbSvporpo   %or = or i8 %arg0, %arg1
11173b0a1ecbSvporpo   ret void
11183b0a1ecbSvporpo }
11193b0a1ecbSvporpo )IR");
11203b0a1ecbSvporpo   Function &LLVMF = *M->getFunction("foo");
11213b0a1ecbSvporpo   sandboxir::Context Ctx(C);
11223b0a1ecbSvporpo 
11233b0a1ecbSvporpo   auto &F = *Ctx.createFunction(&LLVMF);
11243b0a1ecbSvporpo   auto *BB = &*F.begin();
11253b0a1ecbSvporpo   auto It = BB->begin();
11263b0a1ecbSvporpo   auto *PDI = cast<sandboxir::PossiblyDisjointInst>(&*It++);
11273b0a1ecbSvporpo 
11283b0a1ecbSvporpo   // Check setIsDisjoint().
11293b0a1ecbSvporpo   auto OrigIsDisjoint = PDI->isDisjoint();
11303b0a1ecbSvporpo   auto NewIsDisjoint = true;
11313b0a1ecbSvporpo   EXPECT_NE(NewIsDisjoint, OrigIsDisjoint);
11323b0a1ecbSvporpo   Ctx.save();
11333b0a1ecbSvporpo   PDI->setIsDisjoint(NewIsDisjoint);
11343b0a1ecbSvporpo   EXPECT_EQ(PDI->isDisjoint(), NewIsDisjoint);
11353b0a1ecbSvporpo   Ctx.revert();
11363b0a1ecbSvporpo   EXPECT_EQ(PDI->isDisjoint(), OrigIsDisjoint);
11373b0a1ecbSvporpo }
11383b0a1ecbSvporpo 
1139af4a82e4Svporpo TEST_F(TrackerTest, PossiblyNonNegInstSetters) {
1140af4a82e4Svporpo   parseIR(C, R"IR(
1141af4a82e4Svporpo define void @foo(i32 %arg) {
1142af4a82e4Svporpo   %zext = zext i32 %arg to i64
1143af4a82e4Svporpo   ret void
1144af4a82e4Svporpo }
1145af4a82e4Svporpo )IR");
1146af4a82e4Svporpo   Function &LLVMF = *M->getFunction("foo");
1147af4a82e4Svporpo   sandboxir::Context Ctx(C);
1148af4a82e4Svporpo 
1149af4a82e4Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
1150af4a82e4Svporpo   auto *BB = &*F.begin();
1151af4a82e4Svporpo   auto It = BB->begin();
1152af4a82e4Svporpo   auto *PNNI = cast<sandboxir::PossiblyNonNegInst>(&*It++);
1153af4a82e4Svporpo 
1154af4a82e4Svporpo   // Check setNonNeg().
1155af4a82e4Svporpo   auto OrigNonNeg = PNNI->hasNonNeg();
1156af4a82e4Svporpo   auto NewNonNeg = true;
1157af4a82e4Svporpo   EXPECT_NE(NewNonNeg, OrigNonNeg);
1158af4a82e4Svporpo   Ctx.save();
1159af4a82e4Svporpo   PNNI->setNonNeg(NewNonNeg);
1160af4a82e4Svporpo   EXPECT_EQ(PNNI->hasNonNeg(), NewNonNeg);
1161af4a82e4Svporpo   Ctx.revert();
1162af4a82e4Svporpo   EXPECT_EQ(PNNI->hasNonNeg(), OrigNonNeg);
1163af4a82e4Svporpo }
1164af4a82e4Svporpo 
1165ab5102d6Svporpo TEST_F(TrackerTest, AtomicRMWSetters) {
1166ab5102d6Svporpo   parseIR(C, R"IR(
1167ab5102d6Svporpo define void @foo(ptr %ptr, i8 %arg) {
1168ab5102d6Svporpo   %atomicrmw = atomicrmw add ptr %ptr, i8 %arg acquire, align 128
1169ab5102d6Svporpo   ret void
1170ab5102d6Svporpo }
1171ab5102d6Svporpo )IR");
1172ab5102d6Svporpo   Function &LLVMF = *M->getFunction("foo");
1173ab5102d6Svporpo   sandboxir::Context Ctx(C);
1174ab5102d6Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
1175ab5102d6Svporpo   auto *BB = &*F.begin();
1176ab5102d6Svporpo   auto It = BB->begin();
1177ab5102d6Svporpo   auto *RMW = cast<sandboxir::AtomicRMWInst>(&*It++);
1178ab5102d6Svporpo 
1179ab5102d6Svporpo   // Check setAlignment().
1180ab5102d6Svporpo   Ctx.save();
1181ab5102d6Svporpo   auto OrigAlign = RMW->getAlign();
1182ab5102d6Svporpo   Align NewAlign(1024);
1183ab5102d6Svporpo   EXPECT_NE(NewAlign, OrigAlign);
1184ab5102d6Svporpo   RMW->setAlignment(NewAlign);
1185ab5102d6Svporpo   EXPECT_EQ(RMW->getAlign(), NewAlign);
1186ab5102d6Svporpo   Ctx.revert();
1187ab5102d6Svporpo   EXPECT_EQ(RMW->getAlign(), OrigAlign);
1188ab5102d6Svporpo 
1189ab5102d6Svporpo   // Check setVolatile().
1190ab5102d6Svporpo   Ctx.save();
1191ab5102d6Svporpo   auto OrigIsVolatile = RMW->isVolatile();
1192ab5102d6Svporpo   bool NewIsVolatile = true;
1193ab5102d6Svporpo   EXPECT_NE(NewIsVolatile, OrigIsVolatile);
1194ab5102d6Svporpo   RMW->setVolatile(NewIsVolatile);
1195ab5102d6Svporpo   EXPECT_EQ(RMW->isVolatile(), NewIsVolatile);
1196ab5102d6Svporpo   Ctx.revert();
1197ab5102d6Svporpo   EXPECT_EQ(RMW->isVolatile(), OrigIsVolatile);
1198ab5102d6Svporpo 
1199ab5102d6Svporpo   // Check setOrdering().
1200ab5102d6Svporpo   Ctx.save();
1201ab5102d6Svporpo   auto OrigOrdering = RMW->getOrdering();
1202ab5102d6Svporpo   auto NewOrdering = AtomicOrdering::SequentiallyConsistent;
1203ab5102d6Svporpo   EXPECT_NE(NewOrdering, OrigOrdering);
1204ab5102d6Svporpo   RMW->setOrdering(NewOrdering);
1205ab5102d6Svporpo   EXPECT_EQ(RMW->getOrdering(), NewOrdering);
1206ab5102d6Svporpo   Ctx.revert();
1207ab5102d6Svporpo   EXPECT_EQ(RMW->getOrdering(), OrigOrdering);
1208ab5102d6Svporpo 
1209ab5102d6Svporpo   // Check setSyncScopeID().
1210ab5102d6Svporpo   Ctx.save();
1211ab5102d6Svporpo   auto OrigSSID = RMW->getSyncScopeID();
1212ab5102d6Svporpo   auto NewSSID = SyncScope::SingleThread;
1213ab5102d6Svporpo   EXPECT_NE(NewSSID, OrigSSID);
1214ab5102d6Svporpo   RMW->setSyncScopeID(NewSSID);
1215ab5102d6Svporpo   EXPECT_EQ(RMW->getSyncScopeID(), NewSSID);
1216ab5102d6Svporpo   Ctx.revert();
1217ab5102d6Svporpo   EXPECT_EQ(RMW->getSyncScopeID(), OrigSSID);
1218ab5102d6Svporpo }
1219ab5102d6Svporpo 
122000a40422Svporpo TEST_F(TrackerTest, AtomicCmpXchgSetters) {
122100a40422Svporpo   parseIR(C, R"IR(
122200a40422Svporpo define void @foo(ptr %ptr, i8 %cmp, i8 %new) {
122300a40422Svporpo   %cmpxchg = cmpxchg ptr %ptr, i8 %cmp, i8 %new monotonic monotonic, align 128
122400a40422Svporpo   ret void
122500a40422Svporpo }
122600a40422Svporpo )IR");
122700a40422Svporpo   Function &LLVMF = *M->getFunction("foo");
122800a40422Svporpo   sandboxir::Context Ctx(C);
122900a40422Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
123000a40422Svporpo   auto *BB = &*F.begin();
123100a40422Svporpo   auto It = BB->begin();
123200a40422Svporpo   auto *CmpXchg = cast<sandboxir::AtomicCmpXchgInst>(&*It++);
123300a40422Svporpo 
123400a40422Svporpo   // Check setAlignment().
123500a40422Svporpo   Ctx.save();
123600a40422Svporpo   auto OrigAlign = CmpXchg->getAlign();
123700a40422Svporpo   Align NewAlign(1024);
123800a40422Svporpo   EXPECT_NE(NewAlign, OrigAlign);
123900a40422Svporpo   CmpXchg->setAlignment(NewAlign);
124000a40422Svporpo   EXPECT_EQ(CmpXchg->getAlign(), NewAlign);
124100a40422Svporpo   Ctx.revert();
124200a40422Svporpo   EXPECT_EQ(CmpXchg->getAlign(), OrigAlign);
124300a40422Svporpo 
124400a40422Svporpo   // Check setVolatile().
124500a40422Svporpo   Ctx.save();
124600a40422Svporpo   auto OrigIsVolatile = CmpXchg->isVolatile();
124700a40422Svporpo   bool NewIsVolatile = true;
124800a40422Svporpo   EXPECT_NE(NewIsVolatile, OrigIsVolatile);
124900a40422Svporpo   CmpXchg->setVolatile(NewIsVolatile);
125000a40422Svporpo   EXPECT_EQ(CmpXchg->isVolatile(), NewIsVolatile);
125100a40422Svporpo   Ctx.revert();
125200a40422Svporpo   EXPECT_EQ(CmpXchg->isVolatile(), OrigIsVolatile);
125300a40422Svporpo 
125400a40422Svporpo   // Check setWeak().
125500a40422Svporpo   Ctx.save();
125600a40422Svporpo   auto OrigIsWeak = CmpXchg->isWeak();
125700a40422Svporpo   bool NewIsWeak = true;
125800a40422Svporpo   EXPECT_NE(NewIsWeak, OrigIsWeak);
125900a40422Svporpo   CmpXchg->setWeak(NewIsWeak);
126000a40422Svporpo   EXPECT_EQ(CmpXchg->isWeak(), NewIsWeak);
126100a40422Svporpo   Ctx.revert();
126200a40422Svporpo   EXPECT_EQ(CmpXchg->isWeak(), OrigIsWeak);
126300a40422Svporpo 
126400a40422Svporpo   // Check setSuccessOrdering().
126500a40422Svporpo   Ctx.save();
126600a40422Svporpo   auto OrigSuccessOrdering = CmpXchg->getSuccessOrdering();
126700a40422Svporpo   auto NewSuccessOrdering = AtomicOrdering::SequentiallyConsistent;
126800a40422Svporpo   EXPECT_NE(NewSuccessOrdering, OrigSuccessOrdering);
126900a40422Svporpo   CmpXchg->setSuccessOrdering(NewSuccessOrdering);
127000a40422Svporpo   EXPECT_EQ(CmpXchg->getSuccessOrdering(), NewSuccessOrdering);
127100a40422Svporpo   Ctx.revert();
127200a40422Svporpo   EXPECT_EQ(CmpXchg->getSuccessOrdering(), OrigSuccessOrdering);
127300a40422Svporpo 
127400a40422Svporpo   // Check setFailureOrdering().
127500a40422Svporpo   Ctx.save();
127600a40422Svporpo   auto OrigFailureOrdering = CmpXchg->getFailureOrdering();
127700a40422Svporpo   auto NewFailureOrdering = AtomicOrdering::SequentiallyConsistent;
127800a40422Svporpo   EXPECT_NE(NewFailureOrdering, OrigFailureOrdering);
127900a40422Svporpo   CmpXchg->setFailureOrdering(NewFailureOrdering);
128000a40422Svporpo   EXPECT_EQ(CmpXchg->getFailureOrdering(), NewFailureOrdering);
128100a40422Svporpo   Ctx.revert();
128200a40422Svporpo   EXPECT_EQ(CmpXchg->getFailureOrdering(), OrigFailureOrdering);
128300a40422Svporpo 
128400a40422Svporpo   // Check setSyncScopeID().
128500a40422Svporpo   Ctx.save();
128600a40422Svporpo   auto OrigSSID = CmpXchg->getSyncScopeID();
128700a40422Svporpo   auto NewSSID = SyncScope::SingleThread;
128800a40422Svporpo   EXPECT_NE(NewSSID, OrigSSID);
128900a40422Svporpo   CmpXchg->setSyncScopeID(NewSSID);
129000a40422Svporpo   EXPECT_EQ(CmpXchg->getSyncScopeID(), NewSSID);
129100a40422Svporpo   Ctx.revert();
129200a40422Svporpo   EXPECT_EQ(CmpXchg->getSyncScopeID(), OrigSSID);
129300a40422Svporpo }
129400a40422Svporpo 
129536f0d648Svporpo TEST_F(TrackerTest, AllocaInstSetters) {
129636f0d648Svporpo   parseIR(C, R"IR(
129736f0d648Svporpo define void @foo(i8 %arg) {
129836f0d648Svporpo   %alloca = alloca i32, align 64
129936f0d648Svporpo   ret void
130036f0d648Svporpo }
130136f0d648Svporpo )IR");
130236f0d648Svporpo   Function &LLVMF = *M->getFunction("foo");
130336f0d648Svporpo   sandboxir::Context Ctx(C);
130436f0d648Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
130536f0d648Svporpo   auto *BB = &*F.begin();
130636f0d648Svporpo   auto It = BB->begin();
130736f0d648Svporpo   auto *Alloca = cast<sandboxir::AllocaInst>(&*It++);
130836f0d648Svporpo 
130936f0d648Svporpo   // Check setAllocatedType().
131036f0d648Svporpo   Ctx.save();
131136f0d648Svporpo   auto *OrigTy = Alloca->getAllocatedType();
1312034f2b38Svporpo   auto *NewTy = sandboxir::Type::getInt64Ty(Ctx);
131336f0d648Svporpo   EXPECT_NE(NewTy, OrigTy);
131436f0d648Svporpo   Alloca->setAllocatedType(NewTy);
131536f0d648Svporpo   EXPECT_EQ(Alloca->getAllocatedType(), NewTy);
131636f0d648Svporpo   Ctx.revert();
131736f0d648Svporpo   EXPECT_EQ(Alloca->getAllocatedType(), OrigTy);
131836f0d648Svporpo 
131936f0d648Svporpo   // Check setAlignment().
132036f0d648Svporpo   Ctx.save();
132136f0d648Svporpo   auto OrigAlign = Alloca->getAlign();
132236f0d648Svporpo   Align NewAlign(128);
132336f0d648Svporpo   EXPECT_NE(NewAlign, OrigAlign);
132436f0d648Svporpo   Alloca->setAlignment(NewAlign);
132536f0d648Svporpo   EXPECT_EQ(Alloca->getAlign(), NewAlign);
132636f0d648Svporpo   Ctx.revert();
132736f0d648Svporpo   EXPECT_EQ(Alloca->getAlign(), OrigAlign);
132836f0d648Svporpo 
132936f0d648Svporpo   // Check setUsedWithInAlloca().
133036f0d648Svporpo   Ctx.save();
133136f0d648Svporpo   auto OrigWIA = Alloca->isUsedWithInAlloca();
133236f0d648Svporpo   bool NewWIA = true;
133336f0d648Svporpo   EXPECT_NE(NewWIA, OrigWIA);
133436f0d648Svporpo   Alloca->setUsedWithInAlloca(NewWIA);
133536f0d648Svporpo   EXPECT_EQ(Alloca->isUsedWithInAlloca(), NewWIA);
133636f0d648Svporpo   Ctx.revert();
133736f0d648Svporpo   EXPECT_EQ(Alloca->isUsedWithInAlloca(), OrigWIA);
133836f0d648Svporpo }
133936f0d648Svporpo 
1340cfb92be0Svporpo TEST_F(TrackerTest, CallBrSetters) {
1341cfb92be0Svporpo   parseIR(C, R"IR(
1342cfb92be0Svporpo define void @foo(i8 %arg) {
1343cfb92be0Svporpo  bb0:
1344cfb92be0Svporpo    callbr void @foo(i8 %arg)
1345cfb92be0Svporpo                to label %bb1 [label %bb2]
1346cfb92be0Svporpo  bb1:
1347cfb92be0Svporpo    ret void
1348cfb92be0Svporpo  bb2:
1349cfb92be0Svporpo    ret void
1350cfb92be0Svporpo  other_bb:
1351cfb92be0Svporpo    ret void
1352cfb92be0Svporpo }
1353cfb92be0Svporpo )IR");
1354cfb92be0Svporpo   Function &LLVMF = *M->getFunction("foo");
1355cfb92be0Svporpo   sandboxir::Context Ctx(C);
1356cfb92be0Svporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
1357cfb92be0Svporpo   auto *BB0 = cast<sandboxir::BasicBlock>(
1358cfb92be0Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
1359cfb92be0Svporpo   auto *OtherBB = cast<sandboxir::BasicBlock>(
1360cfb92be0Svporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "other_bb")));
1361cfb92be0Svporpo   auto It = BB0->begin();
1362cfb92be0Svporpo   auto *CallBr = cast<sandboxir::CallBrInst>(&*It++);
1363cfb92be0Svporpo   // Check setDefaultDest().
1364cfb92be0Svporpo   Ctx.save();
1365cfb92be0Svporpo   auto *OrigDefaultDest = CallBr->getDefaultDest();
1366cfb92be0Svporpo   CallBr->setDefaultDest(OtherBB);
1367cfb92be0Svporpo   EXPECT_EQ(CallBr->getDefaultDest(), OtherBB);
1368cfb92be0Svporpo   Ctx.revert();
1369cfb92be0Svporpo   EXPECT_EQ(CallBr->getDefaultDest(), OrigDefaultDest);
1370cfb92be0Svporpo 
1371cfb92be0Svporpo   // Check setIndirectDest().
1372cfb92be0Svporpo   Ctx.save();
1373cfb92be0Svporpo   auto *OrigIndirectDest = CallBr->getIndirectDest(0);
1374cfb92be0Svporpo   CallBr->setIndirectDest(0, OtherBB);
1375cfb92be0Svporpo   EXPECT_EQ(CallBr->getIndirectDest(0), OtherBB);
1376cfb92be0Svporpo   Ctx.revert();
1377cfb92be0Svporpo   EXPECT_EQ(CallBr->getIndirectDest(0), OrigIndirectDest);
1378cfb92be0Svporpo }
13793403b593SSterling-Augustine 
13807854b16dSvporpo TEST_F(TrackerTest, FuncletPadInstSetters) {
13817854b16dSvporpo   parseIR(C, R"IR(
13827854b16dSvporpo define void @foo() {
13837854b16dSvporpo dispatch:
13847854b16dSvporpo   %cs = catchswitch within none [label %handler0] unwind to caller
13857854b16dSvporpo handler0:
13867854b16dSvporpo   %catchpad = catchpad within %cs [ptr @foo]
13877854b16dSvporpo   ret void
13887854b16dSvporpo handler1:
13897854b16dSvporpo   %cleanuppad = cleanuppad within %cs [ptr @foo]
13907854b16dSvporpo   ret void
13917854b16dSvporpo bb:
13927854b16dSvporpo   ret void
13937854b16dSvporpo }
13947854b16dSvporpo )IR");
13957854b16dSvporpo   Function &LLVMF = *M->getFunction("foo");
13967854b16dSvporpo   sandboxir::Context Ctx(C);
13977854b16dSvporpo   [[maybe_unused]] auto &F = *Ctx.createFunction(&LLVMF);
13987854b16dSvporpo   auto *Dispatch = cast<sandboxir::BasicBlock>(
13997854b16dSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "dispatch")));
14007854b16dSvporpo   auto *Handler0 = cast<sandboxir::BasicBlock>(
14017854b16dSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "handler0")));
14027854b16dSvporpo   auto *Handler1 = cast<sandboxir::BasicBlock>(
14037854b16dSvporpo       Ctx.getValue(getBasicBlockByName(LLVMF, "handler1")));
14047854b16dSvporpo   auto *CP = cast<sandboxir::CatchPadInst>(&*Handler0->begin());
14057854b16dSvporpo   auto *CLP = cast<sandboxir::CleanupPadInst>(&*Handler1->begin());
14067854b16dSvporpo 
14077854b16dSvporpo   for (auto *FPI : {static_cast<sandboxir::FuncletPadInst *>(CP),
14087854b16dSvporpo                     static_cast<sandboxir::FuncletPadInst *>(CLP)}) {
14097854b16dSvporpo     // Check setParentPad().
14107854b16dSvporpo     auto *OrigParentPad = FPI->getParentPad();
14117854b16dSvporpo     auto *NewParentPad = Dispatch;
14127854b16dSvporpo     EXPECT_NE(NewParentPad, OrigParentPad);
14137854b16dSvporpo     Ctx.save();
14147854b16dSvporpo     FPI->setParentPad(NewParentPad);
14157854b16dSvporpo     EXPECT_EQ(FPI->getParentPad(), NewParentPad);
14167854b16dSvporpo     Ctx.revert();
14177854b16dSvporpo     EXPECT_EQ(FPI->getParentPad(), OrigParentPad);
14187854b16dSvporpo 
14197854b16dSvporpo     // Check setArgOperand().
14207854b16dSvporpo     auto *OrigArgOperand = FPI->getArgOperand(0);
14217854b16dSvporpo     auto *NewArgOperand = Dispatch;
14227854b16dSvporpo     EXPECT_NE(NewArgOperand, OrigArgOperand);
14237854b16dSvporpo     Ctx.save();
14247854b16dSvporpo     FPI->setArgOperand(0, NewArgOperand);
14257854b16dSvporpo     EXPECT_EQ(FPI->getArgOperand(0), NewArgOperand);
14267854b16dSvporpo     Ctx.revert();
14277854b16dSvporpo     EXPECT_EQ(FPI->getArgOperand(0), OrigArgOperand);
14287854b16dSvporpo   }
14297854b16dSvporpo }
14307854b16dSvporpo 
14313403b593SSterling-Augustine TEST_F(TrackerTest, PHINodeSetters) {
14323403b593SSterling-Augustine   parseIR(C, R"IR(
14333403b593SSterling-Augustine define void @foo(i8 %arg0, i8 %arg1, i8 %arg2) {
14343403b593SSterling-Augustine bb0:
14353403b593SSterling-Augustine   br label %bb2
14363403b593SSterling-Augustine 
14373403b593SSterling-Augustine bb1:
14383403b593SSterling-Augustine   %phi = phi i8 [ %arg0, %bb0 ], [ %arg1, %bb1 ]
14393403b593SSterling-Augustine   br label %bb1
14403403b593SSterling-Augustine 
14413403b593SSterling-Augustine bb2:
14423403b593SSterling-Augustine   ret void
14433403b593SSterling-Augustine }
14443403b593SSterling-Augustine )IR");
14453403b593SSterling-Augustine   Function &LLVMF = *M->getFunction("foo");
14463403b593SSterling-Augustine   sandboxir::Context Ctx(C);
14473403b593SSterling-Augustine   auto &F = *Ctx.createFunction(&LLVMF);
14483403b593SSterling-Augustine   unsigned ArgIdx = 0;
14493403b593SSterling-Augustine   auto *Arg0 = F.getArg(ArgIdx++);
14503403b593SSterling-Augustine   auto *Arg1 = F.getArg(ArgIdx++);
14513403b593SSterling-Augustine   auto *Arg2 = F.getArg(ArgIdx++);
14523403b593SSterling-Augustine   auto *BB0 = cast<sandboxir::BasicBlock>(
14533403b593SSterling-Augustine       Ctx.getValue(getBasicBlockByName(LLVMF, "bb0")));
14543403b593SSterling-Augustine   auto *BB1 = cast<sandboxir::BasicBlock>(
14553403b593SSterling-Augustine       Ctx.getValue(getBasicBlockByName(LLVMF, "bb1")));
14563403b593SSterling-Augustine   auto *BB2 = cast<sandboxir::BasicBlock>(
14573403b593SSterling-Augustine       Ctx.getValue(getBasicBlockByName(LLVMF, "bb2")));
14583403b593SSterling-Augustine   auto *PHI = cast<sandboxir::PHINode>(&*BB1->begin());
14593403b593SSterling-Augustine 
14603403b593SSterling-Augustine   // Check setIncomingValue().
14613403b593SSterling-Augustine   Ctx.save();
14623403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
14633403b593SSterling-Augustine   PHI->setIncomingValue(0, Arg2);
14643403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg2);
14653403b593SSterling-Augustine   Ctx.revert();
14663403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
14673403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
14683403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
14693403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
14703403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
14713403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
14723403b593SSterling-Augustine 
14733403b593SSterling-Augustine   // Check setIncomingBlock().
14743403b593SSterling-Augustine   Ctx.save();
14753403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
14763403b593SSterling-Augustine   PHI->setIncomingBlock(0, BB2);
14773403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB2);
14783403b593SSterling-Augustine   Ctx.revert();
14793403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
14803403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
14813403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
14823403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
14833403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
14843403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
14853403b593SSterling-Augustine 
14863403b593SSterling-Augustine   // Check addIncoming().
14873403b593SSterling-Augustine   Ctx.save();
14883403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
14893403b593SSterling-Augustine   PHI->addIncoming(Arg1, BB2);
14903403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 3u);
14913403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(2), BB2);
14923403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(2), Arg1);
14933403b593SSterling-Augustine   Ctx.revert();
14943403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
14953403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
14963403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
14973403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
14983403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
14993403b593SSterling-Augustine 
15003403b593SSterling-Augustine   // Check removeIncomingValue(1).
15013403b593SSterling-Augustine   Ctx.save();
15023403b593SSterling-Augustine   PHI->removeIncomingValue(1);
15033403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 1u);
15043403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15053403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15063403b593SSterling-Augustine   Ctx.revert();
15073403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
15083403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15093403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15103403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
15113403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
15123403b593SSterling-Augustine 
15133403b593SSterling-Augustine   // Check removeIncomingValue(0).
15143403b593SSterling-Augustine   Ctx.save();
15153403b593SSterling-Augustine   PHI->removeIncomingValue(0u);
15163403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 1u);
15173403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB1);
15183403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg1);
15193403b593SSterling-Augustine   Ctx.revert();
15203403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
15213403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15223403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15233403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
15243403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
15253403b593SSterling-Augustine 
152666f4e3f8SSterling-Augustine   // Check removeIncomingValueIf(FromBB1).
152766f4e3f8SSterling-Augustine   Ctx.save();
152866f4e3f8SSterling-Augustine   PHI->removeIncomingValueIf(
152966f4e3f8SSterling-Augustine       [&](unsigned Idx) { return PHI->getIncomingBlock(Idx) == BB1; });
153066f4e3f8SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 1u);
153166f4e3f8SSterling-Augustine   Ctx.revert();
153266f4e3f8SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
153366f4e3f8SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
153466f4e3f8SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
15353403b593SSterling-Augustine   // Check removeIncomingValue() remove all.
15363403b593SSterling-Augustine   Ctx.save();
15373403b593SSterling-Augustine   PHI->removeIncomingValue(0u);
15383403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 1u);
15393403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB1);
15403403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg1);
15413403b593SSterling-Augustine   PHI->removeIncomingValue(0u);
15423403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 0u);
15433403b593SSterling-Augustine   Ctx.revert();
15443403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
15453403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15463403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15473403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
15483403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
15493403b593SSterling-Augustine 
15503403b593SSterling-Augustine   // Check removeIncomingValue(BasicBlock *).
15513403b593SSterling-Augustine   Ctx.save();
15523403b593SSterling-Augustine   PHI->removeIncomingValue(BB1);
15533403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 1u);
15543403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15553403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15563403b593SSterling-Augustine   Ctx.revert();
15573403b593SSterling-Augustine   EXPECT_EQ(PHI->getNumIncomingValues(), 2u);
15583403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(0), BB0);
15593403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(0), Arg0);
15603403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingBlock(1), BB1);
15613403b593SSterling-Augustine   EXPECT_EQ(PHI->getIncomingValue(1), Arg1);
15623403b593SSterling-Augustine }
156395b366caSJulius Alexandre 
1564840da2e8SSterling-Augustine void checkCmpInst(sandboxir::Context &Ctx, sandboxir::CmpInst *Cmp) {
1565840da2e8SSterling-Augustine   Ctx.save();
1566840da2e8SSterling-Augustine   auto OrigP = Cmp->getPredicate();
1567840da2e8SSterling-Augustine   auto NewP = Cmp->getSwappedPredicate();
1568840da2e8SSterling-Augustine   Cmp->setPredicate(NewP);
1569840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getPredicate(), NewP);
1570840da2e8SSterling-Augustine   Ctx.revert();
1571840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getPredicate(), OrigP);
1572840da2e8SSterling-Augustine 
1573840da2e8SSterling-Augustine   Ctx.save();
1574840da2e8SSterling-Augustine   auto OrigOp0 = Cmp->getOperand(0);
1575840da2e8SSterling-Augustine   auto OrigOp1 = Cmp->getOperand(1);
1576840da2e8SSterling-Augustine   Cmp->swapOperands();
1577840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getPredicate(), NewP);
1578840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getOperand(0), OrigOp1);
1579840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getOperand(1), OrigOp0);
1580840da2e8SSterling-Augustine   Ctx.revert();
1581840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getPredicate(), OrigP);
1582840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getOperand(0), OrigOp0);
1583840da2e8SSterling-Augustine   EXPECT_EQ(Cmp->getOperand(1), OrigOp1);
1584840da2e8SSterling-Augustine }
1585840da2e8SSterling-Augustine 
1586840da2e8SSterling-Augustine TEST_F(TrackerTest, CmpInst) {
1587840da2e8SSterling-Augustine   SCOPED_TRACE("TrackerTest sandboxir::CmpInst tests");
1588840da2e8SSterling-Augustine   parseIR(C, R"IR(
1589840da2e8SSterling-Augustine define void @foo(i64 %i0, i64 %i1, float %f0, float %f1) {
1590840da2e8SSterling-Augustine   %foeq = fcmp ogt float %f0, %f1
1591840da2e8SSterling-Augustine   %ioeq = icmp uge i64 %i0, %i1
1592840da2e8SSterling-Augustine 
1593840da2e8SSterling-Augustine   ret void
1594840da2e8SSterling-Augustine }
1595840da2e8SSterling-Augustine )IR");
1596840da2e8SSterling-Augustine   Function &LLVMF = *M->getFunction("foo");
1597840da2e8SSterling-Augustine   sandboxir::Context Ctx(C);
1598840da2e8SSterling-Augustine   auto &F = *Ctx.createFunction(&LLVMF);
1599840da2e8SSterling-Augustine   auto *BB = &*F.begin();
1600840da2e8SSterling-Augustine   auto It = BB->begin();
1601840da2e8SSterling-Augustine   auto *FCmp = cast<sandboxir::CmpInst>(&*It++);
1602840da2e8SSterling-Augustine   checkCmpInst(Ctx, FCmp);
1603840da2e8SSterling-Augustine   auto *ICmp = cast<sandboxir::CmpInst>(&*It++);
1604840da2e8SSterling-Augustine   checkCmpInst(Ctx, ICmp);
1605840da2e8SSterling-Augustine }
1606840da2e8SSterling-Augustine 
16076d859c17Svporpo TEST_F(TrackerTest, GlobalValueSetters) {
16086d859c17Svporpo   parseIR(C, R"IR(
16096d859c17Svporpo define void @foo() {
16106d859c17Svporpo   call void @foo()
16116d859c17Svporpo   ret void
16126d859c17Svporpo }
16136d859c17Svporpo )IR");
16146d859c17Svporpo   Function &LLVMF = *M->getFunction("foo");
16156d859c17Svporpo   sandboxir::Context Ctx(C);
16166d859c17Svporpo 
16176d859c17Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
16186d859c17Svporpo   auto *BB = &*F.begin();
16196d859c17Svporpo   auto *Call = cast<sandboxir::CallInst>(&*BB->begin());
16206d859c17Svporpo 
16216d859c17Svporpo   auto *GV = cast<sandboxir::GlobalValue>(Call->getCalledOperand());
16226d859c17Svporpo   // Check setUnnamedAddr().
16236d859c17Svporpo   auto OrigUnnamedAddr = GV->getUnnamedAddr();
16246d859c17Svporpo   auto NewUnnamedAddr = sandboxir::GlobalValue::UnnamedAddr::Global;
16256d859c17Svporpo   EXPECT_NE(NewUnnamedAddr, OrigUnnamedAddr);
16266d859c17Svporpo   Ctx.save();
16276d859c17Svporpo   GV->setUnnamedAddr(NewUnnamedAddr);
16286d859c17Svporpo   EXPECT_EQ(GV->getUnnamedAddr(), NewUnnamedAddr);
16296d859c17Svporpo   Ctx.revert();
16306d859c17Svporpo   EXPECT_EQ(GV->getUnnamedAddr(), OrigUnnamedAddr);
16316d859c17Svporpo 
16326d859c17Svporpo   // Check setVisibility().
16336d859c17Svporpo   auto OrigVisibility = GV->getVisibility();
16346d859c17Svporpo   auto NewVisibility =
16356d859c17Svporpo       sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility;
16366d859c17Svporpo   EXPECT_NE(NewVisibility, OrigVisibility);
16376d859c17Svporpo   Ctx.save();
16386d859c17Svporpo   GV->setVisibility(NewVisibility);
16396d859c17Svporpo   EXPECT_EQ(GV->getVisibility(), NewVisibility);
16406d859c17Svporpo   Ctx.revert();
16416d859c17Svporpo   EXPECT_EQ(GV->getVisibility(), OrigVisibility);
16426d859c17Svporpo }
16436d859c17Svporpo 
1644ae3e8258Svporpo TEST_F(TrackerTest, GlobalIFuncSetters) {
1645ae3e8258Svporpo   parseIR(C, R"IR(
1646ae3e8258Svporpo declare external void @bar()
1647ae3e8258Svporpo @ifunc = ifunc void(), ptr @foo
1648ae3e8258Svporpo define void @foo() {
1649ae3e8258Svporpo   call void @ifunc()
1650ae3e8258Svporpo   call void @bar()
1651ae3e8258Svporpo   ret void
1652ae3e8258Svporpo }
1653ae3e8258Svporpo )IR");
1654ae3e8258Svporpo   Function &LLVMF = *M->getFunction("foo");
1655ae3e8258Svporpo   sandboxir::Context Ctx(C);
1656ae3e8258Svporpo 
1657ae3e8258Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
1658ae3e8258Svporpo   auto *BB = &*F.begin();
1659ae3e8258Svporpo   auto It = BB->begin();
1660ae3e8258Svporpo   auto *Call0 = cast<sandboxir::CallInst>(&*It++);
1661ae3e8258Svporpo   auto *Call1 = cast<sandboxir::CallInst>(&*It++);
1662ae3e8258Svporpo   // Check classof(), creation.
1663ae3e8258Svporpo   auto *IFunc = cast<sandboxir::GlobalIFunc>(Call0->getCalledOperand());
1664ae3e8258Svporpo   auto *Bar = cast<sandboxir::Function>(Call1->getCalledOperand());
1665ae3e8258Svporpo   // Check setResolver().
1666ae3e8258Svporpo   auto *OrigResolver = IFunc->getResolver();
1667ae3e8258Svporpo   auto *NewResolver = Bar;
1668ae3e8258Svporpo   EXPECT_NE(NewResolver, OrigResolver);
1669ae3e8258Svporpo   Ctx.save();
1670ae3e8258Svporpo   IFunc->setResolver(NewResolver);
1671ae3e8258Svporpo   EXPECT_EQ(IFunc->getResolver(), NewResolver);
1672ae3e8258Svporpo   Ctx.revert();
1673ae3e8258Svporpo   EXPECT_EQ(IFunc->getResolver(), OrigResolver);
1674ae3e8258Svporpo }
1675ae3e8258Svporpo 
1676b9bf831eSvporpo TEST_F(TrackerTest, GlobalVariableSetters) {
1677b9bf831eSvporpo   parseIR(C, R"IR(
1678b9bf831eSvporpo @glob0 = global i32 42
1679b9bf831eSvporpo @glob1 = global i32 43
1680b9bf831eSvporpo define void @foo() {
1681b9bf831eSvporpo   %ld0 = load i32, ptr @glob0
1682b9bf831eSvporpo   %ld1 = load i32, ptr @glob1
1683b9bf831eSvporpo   ret void
1684b9bf831eSvporpo }
1685b9bf831eSvporpo )IR");
1686b9bf831eSvporpo   Function &LLVMF = *M->getFunction("foo");
1687b9bf831eSvporpo   sandboxir::Context Ctx(C);
1688b9bf831eSvporpo 
1689b9bf831eSvporpo   auto &F = *Ctx.createFunction(&LLVMF);
1690b9bf831eSvporpo   auto *BB = &*F.begin();
1691b9bf831eSvporpo   auto It = BB->begin();
1692b9bf831eSvporpo   auto *Ld0 = cast<sandboxir::LoadInst>(&*It++);
1693b9bf831eSvporpo   auto *Ld1 = cast<sandboxir::LoadInst>(&*It++);
1694b9bf831eSvporpo   // Check classof(), creation.
1695b9bf831eSvporpo   auto *GV0 = cast<sandboxir::GlobalVariable>(Ld0->getPointerOperand());
1696b9bf831eSvporpo   auto *GV1 = cast<sandboxir::GlobalVariable>(Ld1->getPointerOperand());
1697b9bf831eSvporpo   // Check setInitializer().
1698b9bf831eSvporpo   auto *OrigInitializer = GV0->getInitializer();
1699b9bf831eSvporpo   auto *NewInitializer = GV1->getInitializer();
1700b9bf831eSvporpo   EXPECT_NE(NewInitializer, OrigInitializer);
1701b9bf831eSvporpo   Ctx.save();
1702b9bf831eSvporpo   GV0->setInitializer(NewInitializer);
1703b9bf831eSvporpo   EXPECT_EQ(GV0->getInitializer(), NewInitializer);
1704b9bf831eSvporpo   Ctx.revert();
1705b9bf831eSvporpo   EXPECT_EQ(GV0->getInitializer(), OrigInitializer);
1706b9bf831eSvporpo   // Check setConstant().
1707b9bf831eSvporpo   bool OrigIsConstant = GV0->isConstant();
1708b9bf831eSvporpo   bool NewIsConstant = !OrigIsConstant;
1709b9bf831eSvporpo   Ctx.save();
1710b9bf831eSvporpo   GV0->setConstant(NewIsConstant);
1711b9bf831eSvporpo   EXPECT_EQ(GV0->isConstant(), NewIsConstant);
1712b9bf831eSvporpo   Ctx.revert();
1713b9bf831eSvporpo   EXPECT_EQ(GV0->isConstant(), OrigIsConstant);
1714b9bf831eSvporpo   // Check setExternallyInitialized().
1715b9bf831eSvporpo   bool OrigIsExtInit = GV0->isExternallyInitialized();
1716b9bf831eSvporpo   bool NewIsExtInit = !OrigIsExtInit;
1717b9bf831eSvporpo   Ctx.save();
1718b9bf831eSvporpo   GV0->setExternallyInitialized(NewIsExtInit);
1719b9bf831eSvporpo   EXPECT_EQ(GV0->isExternallyInitialized(), NewIsExtInit);
1720b9bf831eSvporpo   Ctx.revert();
1721b9bf831eSvporpo   EXPECT_EQ(GV0->isExternallyInitialized(), OrigIsExtInit);
1722b9bf831eSvporpo }
1723b9bf831eSvporpo 
17249a312d47Svporpo TEST_F(TrackerTest, GlobalAliasSetters) {
17259a312d47Svporpo   parseIR(C, R"IR(
17269a312d47Svporpo @alias = dso_local alias void(), ptr @foo
17279a312d47Svporpo declare void @bar();
17289a312d47Svporpo define void @foo() {
17299a312d47Svporpo   call void @alias()
17309a312d47Svporpo   call void @bar()
17319a312d47Svporpo   ret void
17329a312d47Svporpo }
17339a312d47Svporpo )IR");
17349a312d47Svporpo   Function &LLVMF = *M->getFunction("foo");
17359a312d47Svporpo   sandboxir::Context Ctx(C);
17369a312d47Svporpo 
17379a312d47Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
17389a312d47Svporpo   auto *BB = &*F.begin();
17399a312d47Svporpo   auto It = BB->begin();
17409a312d47Svporpo   auto *Call0 = cast<sandboxir::CallInst>(&*It++);
17419a312d47Svporpo   auto *Call1 = cast<sandboxir::CallInst>(&*It++);
17429a312d47Svporpo   auto *Callee1 = cast<sandboxir::Constant>(Call1->getCalledOperand());
17439a312d47Svporpo   auto *Alias = cast<sandboxir::GlobalAlias>(Call0->getCalledOperand());
17449a312d47Svporpo   // Check setAliasee().
17459a312d47Svporpo   auto *OrigAliasee = Alias->getAliasee();
17469a312d47Svporpo   auto *NewAliasee = Callee1;
17479a312d47Svporpo   EXPECT_NE(NewAliasee, OrigAliasee);
17489a312d47Svporpo   Ctx.save();
17499a312d47Svporpo   Alias->setAliasee(NewAliasee);
17509a312d47Svporpo   EXPECT_EQ(Alias->getAliasee(), NewAliasee);
17519a312d47Svporpo   Ctx.revert();
17529a312d47Svporpo   EXPECT_EQ(Alias->getAliasee(), OrigAliasee);
17539a312d47Svporpo }
17549a312d47Svporpo 
175595b366caSJulius Alexandre TEST_F(TrackerTest, SetVolatile) {
175695b366caSJulius Alexandre   parseIR(C, R"IR(
175795b366caSJulius Alexandre define void @foo(ptr %arg0, i8 %val) {
175895b366caSJulius Alexandre   %ld = load i8, ptr %arg0, align 64
175995b366caSJulius Alexandre   store i8 %val, ptr %arg0, align 64
176095b366caSJulius Alexandre   ret void
176195b366caSJulius Alexandre }
176295b366caSJulius Alexandre )IR");
176395b366caSJulius Alexandre   Function &LLVMF = *M->getFunction("foo");
176495b366caSJulius Alexandre   sandboxir::Context Ctx(C);
176595b366caSJulius Alexandre 
176695b366caSJulius Alexandre   auto *F = Ctx.createFunction(&LLVMF);
176795b366caSJulius Alexandre   auto *BB = &*F->begin();
176895b366caSJulius Alexandre   auto It = BB->begin();
176995b366caSJulius Alexandre   auto *Load = cast<sandboxir::LoadInst>(&*It++);
177095b366caSJulius Alexandre   auto *Store = cast<sandboxir::StoreInst>(&*It++);
177195b366caSJulius Alexandre 
177295b366caSJulius Alexandre   EXPECT_FALSE(Load->isVolatile());
177395b366caSJulius Alexandre   Ctx.save();
177495b366caSJulius Alexandre   Load->setVolatile(true);
177595b366caSJulius Alexandre   EXPECT_TRUE(Load->isVolatile());
177695b366caSJulius Alexandre   Ctx.revert();
177795b366caSJulius Alexandre   EXPECT_FALSE(Load->isVolatile());
177895b366caSJulius Alexandre 
177995b366caSJulius Alexandre   EXPECT_FALSE(Store->isVolatile());
178095b366caSJulius Alexandre   Ctx.save();
178195b366caSJulius Alexandre   Store->setVolatile(true);
178295b366caSJulius Alexandre   EXPECT_TRUE(Store->isVolatile());
178395b366caSJulius Alexandre   Ctx.revert();
178495b366caSJulius Alexandre   EXPECT_FALSE(Store->isVolatile());
178595b366caSJulius Alexandre }
1786c4ae8b15Svporpo 
1787c4ae8b15Svporpo TEST_F(TrackerTest, Flags) {
1788c4ae8b15Svporpo   parseIR(C, R"IR(
1789c4ae8b15Svporpo define void @foo(i32 %arg, float %farg) {
1790c4ae8b15Svporpo   %add = add i32 %arg, %arg
1791c4ae8b15Svporpo   %fadd = fadd float %farg, %farg
1792c4ae8b15Svporpo   %udiv = udiv i32 %arg, %arg
1793c4ae8b15Svporpo   ret void
1794c4ae8b15Svporpo }
1795c4ae8b15Svporpo )IR");
1796c4ae8b15Svporpo   Function &LLVMF = *M->getFunction("foo");
1797c4ae8b15Svporpo   sandboxir::Context Ctx(C);
1798c4ae8b15Svporpo   auto &F = *Ctx.createFunction(&LLVMF);
1799c4ae8b15Svporpo   auto *BB = &*F.begin();
1800c4ae8b15Svporpo   auto It = BB->begin();
1801c4ae8b15Svporpo   auto *Add = &*It++;
1802c4ae8b15Svporpo   auto *FAdd = &*It++;
1803c4ae8b15Svporpo   auto *UDiv = &*It++;
1804c4ae8b15Svporpo 
1805c4ae8b15Svporpo #define CHECK_FLAG(I, GETTER, SETTER)                                          \
1806c4ae8b15Svporpo   {                                                                            \
1807c4ae8b15Svporpo     Ctx.save();                                                                \
1808c4ae8b15Svporpo     bool OrigFlag = I->GETTER();                                               \
1809c4ae8b15Svporpo     bool NewFlag = !OrigFlag;                                                  \
1810c4ae8b15Svporpo     I->SETTER(NewFlag);                                                        \
1811c4ae8b15Svporpo     EXPECT_EQ(I->GETTER(), NewFlag);                                           \
1812c4ae8b15Svporpo     Ctx.revert();                                                              \
1813c4ae8b15Svporpo     EXPECT_EQ(I->GETTER(), OrigFlag);                                          \
1814c4ae8b15Svporpo   }
1815c4ae8b15Svporpo 
1816c4ae8b15Svporpo   CHECK_FLAG(Add, hasNoUnsignedWrap, setHasNoUnsignedWrap);
1817c4ae8b15Svporpo   CHECK_FLAG(Add, hasNoSignedWrap, setHasNoSignedWrap);
1818c4ae8b15Svporpo   CHECK_FLAG(FAdd, isFast, setFast);
1819c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasAllowReassoc, setHasAllowReassoc);
1820c4ae8b15Svporpo   CHECK_FLAG(UDiv, isExact, setIsExact);
1821c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasNoNaNs, setHasNoNaNs);
1822c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasNoInfs, setHasNoInfs);
1823c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasNoSignedZeros, setHasNoSignedZeros);
1824c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasAllowReciprocal, setHasAllowReciprocal);
1825c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasAllowContract, setHasAllowContract);
1826c4ae8b15Svporpo   CHECK_FLAG(FAdd, hasApproxFunc, setHasApproxFunc);
1827c4ae8b15Svporpo 
1828c4ae8b15Svporpo   // Check setFastMathFlags().
1829c4ae8b15Svporpo   FastMathFlags OrigFMF = FAdd->getFastMathFlags();
1830c4ae8b15Svporpo   FastMathFlags NewFMF;
1831c4ae8b15Svporpo   NewFMF.setAllowReassoc(true);
1832c4ae8b15Svporpo   EXPECT_TRUE(NewFMF != OrigFMF);
1833c4ae8b15Svporpo 
1834c4ae8b15Svporpo   Ctx.save();
1835c4ae8b15Svporpo   FAdd->setFastMathFlags(NewFMF);
1836c4ae8b15Svporpo   EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
1837c4ae8b15Svporpo   Ctx.revert();
1838c4ae8b15Svporpo   EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
1839c4ae8b15Svporpo 
1840c4ae8b15Svporpo   // Check copyFastMathFlags().
1841c4ae8b15Svporpo   Ctx.save();
1842c4ae8b15Svporpo   FAdd->copyFastMathFlags(NewFMF);
1843c4ae8b15Svporpo   EXPECT_FALSE(FAdd->getFastMathFlags() != NewFMF);
1844c4ae8b15Svporpo   Ctx.revert();
1845c4ae8b15Svporpo   EXPECT_FALSE(FAdd->getFastMathFlags() != OrigFMF);
1846c4ae8b15Svporpo }
1847*3b8606beSJorge Gorbe Moya 
1848*3b8606beSJorge Gorbe Moya // IRSnapshotChecker is only defined in debug mode.
1849*3b8606beSJorge Gorbe Moya #ifndef NDEBUG
1850*3b8606beSJorge Gorbe Moya 
1851*3b8606beSJorge Gorbe Moya TEST_F(TrackerTest, IRSnapshotCheckerNoChanges) {
1852*3b8606beSJorge Gorbe Moya   parseIR(C, R"IR(
1853*3b8606beSJorge Gorbe Moya define i32 @foo(i32 %arg) {
1854*3b8606beSJorge Gorbe Moya   %add0 = add i32 %arg, %arg
1855*3b8606beSJorge Gorbe Moya   ret i32 %add0
1856*3b8606beSJorge Gorbe Moya }
1857*3b8606beSJorge Gorbe Moya )IR");
1858*3b8606beSJorge Gorbe Moya   Function &LLVMF = *M->getFunction("foo");
1859*3b8606beSJorge Gorbe Moya   sandboxir::Context Ctx(C);
1860*3b8606beSJorge Gorbe Moya 
1861*3b8606beSJorge Gorbe Moya   [[maybe_unused]] auto *F = Ctx.createFunction(&LLVMF);
1862*3b8606beSJorge Gorbe Moya   sandboxir::IRSnapshotChecker Checker(Ctx);
1863*3b8606beSJorge Gorbe Moya   Checker.save();
1864*3b8606beSJorge Gorbe Moya   Checker.expectNoDiff();
1865*3b8606beSJorge Gorbe Moya }
1866*3b8606beSJorge Gorbe Moya 
1867*3b8606beSJorge Gorbe Moya TEST_F(TrackerTest, IRSnapshotCheckerDiesWithUnexpectedChanges) {
1868*3b8606beSJorge Gorbe Moya   parseIR(C, R"IR(
1869*3b8606beSJorge Gorbe Moya define i32 @foo(i32 %arg) {
1870*3b8606beSJorge Gorbe Moya   %add0 = add i32 %arg, %arg
1871*3b8606beSJorge Gorbe Moya   %add1 = add i32 %add0, %arg
1872*3b8606beSJorge Gorbe Moya   ret i32 %add1
1873*3b8606beSJorge Gorbe Moya }
1874*3b8606beSJorge Gorbe Moya )IR");
1875*3b8606beSJorge Gorbe Moya   Function &LLVMF = *M->getFunction("foo");
1876*3b8606beSJorge Gorbe Moya   sandboxir::Context Ctx(C);
1877*3b8606beSJorge Gorbe Moya 
1878*3b8606beSJorge Gorbe Moya   auto *F = Ctx.createFunction(&LLVMF);
1879*3b8606beSJorge Gorbe Moya   auto *BB = &*F->begin();
1880*3b8606beSJorge Gorbe Moya   auto It = BB->begin();
1881*3b8606beSJorge Gorbe Moya   sandboxir::Instruction *Add0 = &*It++;
1882*3b8606beSJorge Gorbe Moya   sandboxir::Instruction *Add1 = &*It++;
1883*3b8606beSJorge Gorbe Moya   sandboxir::IRSnapshotChecker Checker(Ctx);
1884*3b8606beSJorge Gorbe Moya   Checker.save();
1885*3b8606beSJorge Gorbe Moya   Add1->setOperand(1, Add0);
1886*3b8606beSJorge Gorbe Moya   EXPECT_DEATH(Checker.expectNoDiff(), "Found IR difference");
1887*3b8606beSJorge Gorbe Moya }
1888*3b8606beSJorge Gorbe Moya 
1889*3b8606beSJorge Gorbe Moya TEST_F(TrackerTest, IRSnapshotCheckerSaveMultipleTimes) {
1890*3b8606beSJorge Gorbe Moya   parseIR(C, R"IR(
1891*3b8606beSJorge Gorbe Moya define i32 @foo(i32 %arg) {
1892*3b8606beSJorge Gorbe Moya   %add0 = add i32 %arg, %arg
1893*3b8606beSJorge Gorbe Moya   %add1 = add i32 %add0, %arg
1894*3b8606beSJorge Gorbe Moya   ret i32 %add1
1895*3b8606beSJorge Gorbe Moya }
1896*3b8606beSJorge Gorbe Moya )IR");
1897*3b8606beSJorge Gorbe Moya   Function &LLVMF = *M->getFunction("foo");
1898*3b8606beSJorge Gorbe Moya   sandboxir::Context Ctx(C);
1899*3b8606beSJorge Gorbe Moya 
1900*3b8606beSJorge Gorbe Moya   auto *F = Ctx.createFunction(&LLVMF);
1901*3b8606beSJorge Gorbe Moya   auto *BB = &*F->begin();
1902*3b8606beSJorge Gorbe Moya   auto It = BB->begin();
1903*3b8606beSJorge Gorbe Moya   sandboxir::Instruction *Add0 = &*It++;
1904*3b8606beSJorge Gorbe Moya   sandboxir::Instruction *Add1 = &*It++;
1905*3b8606beSJorge Gorbe Moya   sandboxir::IRSnapshotChecker Checker(Ctx);
1906*3b8606beSJorge Gorbe Moya   Checker.save();
1907*3b8606beSJorge Gorbe Moya   Add1->setOperand(1, Add0);
1908*3b8606beSJorge Gorbe Moya   // Now IR differs from the last snapshot. Let's take a new snapshot.
1909*3b8606beSJorge Gorbe Moya   Checker.save();
1910*3b8606beSJorge Gorbe Moya   // The new snapshot should have replaced the old one, so this should succeed.
1911*3b8606beSJorge Gorbe Moya   Checker.expectNoDiff();
1912*3b8606beSJorge Gorbe Moya }
1913*3b8606beSJorge Gorbe Moya 
1914*3b8606beSJorge Gorbe Moya #endif // NDEBUG
1915