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