1 //===- TrackerTest.cpp ----------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/AsmParser/Parser.h"
10 #include "llvm/IR/BasicBlock.h"
11 #include "llvm/IR/Function.h"
12 #include "llvm/IR/Instruction.h"
13 #include "llvm/IR/Module.h"
14 #include "llvm/SandboxIR/Function.h"
15 #include "llvm/SandboxIR/Instruction.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gmock/gmock-matchers.h"
18 #include "gtest/gtest.h"
22 struct TrackerTest
: public testing::Test
{
24 std::unique_ptr
<Module
> M
;
26 void parseIR(LLVMContext
&C
, const char *IR
) {
28 M
= parseAssemblyString(IR
, Err
, C
);
30 Err
.print("TrackerTest", errs());
32 BasicBlock
*getBasicBlockByName(Function
&F
, StringRef Name
) {
33 for (BasicBlock
&BB
: F
)
34 if (BB
.getName() == Name
)
36 llvm_unreachable("Expected to find basic block!");
40 TEST_F(TrackerTest
, SetOperand
) {
42 define void @foo(ptr %ptr) {
43 %gep0 = getelementptr float, ptr %ptr, i32 0
44 %gep1 = getelementptr float, ptr %ptr, i32 1
45 %ld0 = load float, ptr %gep0
46 store float undef, ptr %gep0
50 Function
&LLVMF
= *M
->getFunction("foo");
51 sandboxir::Context
Ctx(C
);
52 auto *F
= Ctx
.createFunction(&LLVMF
);
53 auto *BB
= &*F
->begin();
54 auto &Tracker
= Ctx
.getTracker();
56 auto It
= BB
->begin();
61 St
->setOperand(0, Ld
);
62 St
->setOperand(1, Gep1
);
63 Ld
->setOperand(0, Gep1
);
64 EXPECT_EQ(St
->getOperand(0), Ld
);
65 EXPECT_EQ(St
->getOperand(1), Gep1
);
66 EXPECT_EQ(Ld
->getOperand(0), Gep1
);
68 Ctx
.getTracker().revert();
69 EXPECT_NE(St
->getOperand(0), Ld
);
70 EXPECT_EQ(St
->getOperand(1), Gep0
);
71 EXPECT_EQ(Ld
->getOperand(0), Gep0
);
74 TEST_F(TrackerTest
, SetUse
) {
76 define void @foo(ptr %ptr, i8 %arg) {
77 %ld = load i8, ptr %ptr
78 %add = add i8 %ld, %arg
82 Function
&LLVMF
= *M
->getFunction("foo");
83 sandboxir::Context
Ctx(C
);
84 auto *F
= Ctx
.createFunction(&LLVMF
);
86 auto *Arg0
= F
->getArg(ArgIdx
++);
87 auto *BB
= &*F
->begin();
88 auto &Tracker
= Ctx
.getTracker();
90 auto It
= BB
->begin();
95 sandboxir::Use Use
= Add
->getOperandUse(0);
97 EXPECT_EQ(Add
->getOperand(0), Arg0
);
99 EXPECT_EQ(Add
->getOperand(0), Ld
);
102 TEST_F(TrackerTest
, SwapOperands
) {
104 define void @foo(i1 %cond) {
106 br i1 %cond, label %bb1, label %bb2
113 Function
&LLVMF
= *M
->getFunction("foo");
114 sandboxir::Context
Ctx(C
);
115 Ctx
.createFunction(&LLVMF
);
116 auto *BB0
= cast
<sandboxir::BasicBlock
>(
117 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
118 auto *BB1
= cast
<sandboxir::BasicBlock
>(
119 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb1")));
120 auto *BB2
= cast
<sandboxir::BasicBlock
>(
121 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb2")));
122 auto &Tracker
= Ctx
.getTracker();
124 auto It
= BB0
->begin();
125 auto *Br
= cast
<sandboxir::BranchInst
>(&*It
++);
127 unsigned SuccIdx
= 0;
128 SmallVector
<sandboxir::BasicBlock
*> ExpectedSuccs({BB2
, BB1
});
129 for (auto *Succ
: Br
->successors())
130 EXPECT_EQ(Succ
, ExpectedSuccs
[SuccIdx
++]);
132 // This calls User::swapOperandsInternal() internally.
133 Br
->swapSuccessors();
136 for (auto *Succ
: reverse(Br
->successors()))
137 EXPECT_EQ(Succ
, ExpectedSuccs
[SuccIdx
++]);
139 Ctx
.getTracker().revert();
141 for (auto *Succ
: Br
->successors())
142 EXPECT_EQ(Succ
, ExpectedSuccs
[SuccIdx
++]);
145 TEST_F(TrackerTest
, RUWIf_RAUW_RUOW
) {
147 define void @foo(ptr %ptr) {
148 %ld0 = load float, ptr %ptr
149 %ld1 = load float, ptr %ptr
150 store float %ld0, ptr %ptr
151 store float %ld0, ptr %ptr
155 llvm::Function
&LLVMF
= *M
->getFunction("foo");
156 sandboxir::Context
Ctx(C
);
157 llvm::BasicBlock
*LLVMBB
= &*LLVMF
.begin();
158 Ctx
.createFunction(&LLVMF
);
159 auto *BB
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMBB
));
160 auto It
= BB
->begin();
161 sandboxir::Instruction
*Ld0
= &*It
++;
162 sandboxir::Instruction
*Ld1
= &*It
++;
163 sandboxir::Instruction
*St0
= &*It
++;
164 sandboxir::Instruction
*St1
= &*It
++;
166 // Check RUWIf when the lambda returns false.
167 Ld0
->replaceUsesWithIf(Ld1
, [](const sandboxir::Use
&Use
) { return false; });
168 EXPECT_EQ(St0
->getOperand(0), Ld0
);
169 EXPECT_EQ(St1
->getOperand(0), Ld0
);
171 // Check RUWIf when the lambda returns true.
172 Ld0
->replaceUsesWithIf(Ld1
, [](const sandboxir::Use
&Use
) { return true; });
173 EXPECT_EQ(St0
->getOperand(0), Ld1
);
174 EXPECT_EQ(St1
->getOperand(0), Ld1
);
176 EXPECT_EQ(St0
->getOperand(0), Ld0
);
177 EXPECT_EQ(St1
->getOperand(0), Ld0
);
179 // Check RUWIf user == St0.
181 Ld0
->replaceUsesWithIf(
182 Ld1
, [St0
](const sandboxir::Use
&Use
) { return Use
.getUser() == St0
; });
183 EXPECT_EQ(St0
->getOperand(0), Ld1
);
184 EXPECT_EQ(St1
->getOperand(0), Ld0
);
186 EXPECT_EQ(St0
->getOperand(0), Ld0
);
187 EXPECT_EQ(St1
->getOperand(0), Ld0
);
189 // Check RUWIf user == St1.
191 Ld0
->replaceUsesWithIf(
192 Ld1
, [St1
](const sandboxir::Use
&Use
) { return Use
.getUser() == St1
; });
193 EXPECT_EQ(St0
->getOperand(0), Ld0
);
194 EXPECT_EQ(St1
->getOperand(0), Ld1
);
196 EXPECT_EQ(St0
->getOperand(0), Ld0
);
197 EXPECT_EQ(St1
->getOperand(0), Ld0
);
201 Ld1
->replaceAllUsesWith(Ld0
);
202 EXPECT_EQ(St0
->getOperand(0), Ld0
);
203 EXPECT_EQ(St1
->getOperand(0), Ld0
);
205 EXPECT_EQ(St0
->getOperand(0), Ld0
);
206 EXPECT_EQ(St1
->getOperand(0), Ld0
);
210 St0
->replaceUsesOfWith(Ld0
, Ld1
);
211 EXPECT_EQ(St0
->getOperand(0), Ld1
);
213 EXPECT_EQ(St0
->getOperand(0), Ld0
);
217 St0
->replaceUsesOfWith(Ld0
, Ld1
);
218 EXPECT_EQ(St0
->getOperand(0), Ld1
);
220 EXPECT_EQ(St0
->getOperand(0), Ld1
);
223 // TODO: Test multi-instruction patterns.
224 TEST_F(TrackerTest
, EraseFromParent
) {
226 define void @foo(i32 %v1) {
227 %add0 = add i32 %v1, %v1
228 %add1 = add i32 %add0, %v1
232 Function
&LLVMF
= *M
->getFunction("foo");
233 sandboxir::Context
Ctx(C
);
235 auto *F
= Ctx
.createFunction(&LLVMF
);
236 auto *BB
= &*F
->begin();
237 auto It
= BB
->begin();
238 sandboxir::Instruction
*Add0
= &*It
++;
239 sandboxir::Instruction
*Add1
= &*It
++;
240 sandboxir::Instruction
*Ret
= &*It
++;
244 Add1
->eraseFromParent();
246 EXPECT_EQ(&*It
++, Add0
);
247 EXPECT_EQ(&*It
++, Ret
);
248 EXPECT_EQ(It
, BB
->end());
249 EXPECT_EQ(Add0
->getNumUses(), 0u);
254 EXPECT_EQ(&*It
++, Add0
);
255 EXPECT_EQ(&*It
++, Add1
);
256 EXPECT_EQ(&*It
++, Ret
);
257 EXPECT_EQ(It
, BB
->end());
258 EXPECT_EQ(Add1
->getOperand(0), Add0
);
260 // Same for the last instruction in the block.
262 Ret
->eraseFromParent();
264 EXPECT_EQ(&*It
++, Add0
);
265 EXPECT_EQ(&*It
++, Add1
);
266 EXPECT_EQ(It
, BB
->end());
269 EXPECT_EQ(&*It
++, Add0
);
270 EXPECT_EQ(&*It
++, Add1
);
271 EXPECT_EQ(&*It
++, Ret
);
272 EXPECT_EQ(It
, BB
->end());
275 // TODO: Test multi-instruction patterns.
276 TEST_F(TrackerTest
, RemoveFromParent
) {
278 define i32 @foo(i32 %arg) {
279 %add0 = add i32 %arg, %arg
280 %add1 = add i32 %add0, %arg
284 Function
&LLVMF
= *M
->getFunction("foo");
285 sandboxir::Context
Ctx(C
);
287 auto *F
= Ctx
.createFunction(&LLVMF
);
288 auto *Arg
= F
->getArg(0);
289 auto *BB
= &*F
->begin();
290 auto It
= BB
->begin();
291 sandboxir::Instruction
*Add0
= &*It
++;
292 sandboxir::Instruction
*Add1
= &*It
++;
293 sandboxir::Instruction
*Ret
= &*It
++;
296 // Check removeFromParent().
297 Add1
->removeFromParent();
299 EXPECT_EQ(&*It
++, Add0
);
300 EXPECT_EQ(&*It
++, Ret
);
301 EXPECT_EQ(It
, BB
->end());
302 // Removed instruction still be connected to operands and users.
303 EXPECT_EQ(Add1
->getOperand(0), Add0
);
304 EXPECT_EQ(Add1
->getOperand(1), Arg
);
305 EXPECT_EQ(Add0
->getNumUses(), 1u);
310 EXPECT_EQ(&*It
++, Add0
);
311 EXPECT_EQ(&*It
++, Add1
);
312 EXPECT_EQ(&*It
++, Ret
);
313 EXPECT_EQ(It
, BB
->end());
314 EXPECT_EQ(Add1
->getOperand(0), Add0
);
316 // Same for the last instruction in the block.
318 Ret
->removeFromParent();
320 EXPECT_EQ(&*It
++, Add0
);
321 EXPECT_EQ(&*It
++, Add1
);
322 EXPECT_EQ(It
, BB
->end());
323 EXPECT_EQ(Ret
->getOperand(0), Add1
);
326 EXPECT_EQ(&*It
++, Add0
);
327 EXPECT_EQ(&*It
++, Add1
);
328 EXPECT_EQ(&*It
++, Ret
);
329 EXPECT_EQ(It
, BB
->end());
332 // TODO: Test multi-instruction patterns.
333 TEST_F(TrackerTest
, MoveInstr
) {
335 define i32 @foo(i32 %arg) {
336 %add0 = add i32 %arg, %arg
337 %add1 = add i32 %add0, %arg
341 Function
&LLVMF
= *M
->getFunction("foo");
342 sandboxir::Context
Ctx(C
);
344 auto *F
= Ctx
.createFunction(&LLVMF
);
345 auto *BB
= &*F
->begin();
346 auto It
= BB
->begin();
347 sandboxir::Instruction
*Add0
= &*It
++;
348 sandboxir::Instruction
*Add1
= &*It
++;
349 sandboxir::Instruction
*Ret
= &*It
++;
351 // Check moveBefore(Instruction *) with tracking enabled.
353 Add1
->moveBefore(Add0
);
355 EXPECT_EQ(&*It
++, Add1
);
356 EXPECT_EQ(&*It
++, Add0
);
357 EXPECT_EQ(&*It
++, Ret
);
358 EXPECT_EQ(It
, BB
->end());
362 EXPECT_EQ(&*It
++, Add0
);
363 EXPECT_EQ(&*It
++, Add1
);
364 EXPECT_EQ(&*It
++, Ret
);
365 EXPECT_EQ(It
, BB
->end());
367 // Same for the last instruction in the block.
369 Ret
->moveBefore(Add0
);
371 EXPECT_EQ(&*It
++, Ret
);
372 EXPECT_EQ(&*It
++, Add0
);
373 EXPECT_EQ(&*It
++, Add1
);
374 EXPECT_EQ(It
, BB
->end());
377 EXPECT_EQ(&*It
++, Add0
);
378 EXPECT_EQ(&*It
++, Add1
);
379 EXPECT_EQ(&*It
++, Ret
);
380 EXPECT_EQ(It
, BB
->end());
382 // Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.
384 Add1
->moveBefore(*BB
, Add0
->getIterator());
386 EXPECT_EQ(&*It
++, Add1
);
387 EXPECT_EQ(&*It
++, Add0
);
388 EXPECT_EQ(&*It
++, Ret
);
389 EXPECT_EQ(It
, BB
->end());
393 EXPECT_EQ(&*It
++, Add0
);
394 EXPECT_EQ(&*It
++, Add1
);
395 EXPECT_EQ(&*It
++, Ret
);
396 EXPECT_EQ(It
, BB
->end());
398 // Same for the last instruction in the block.
400 Ret
->moveBefore(*BB
, Add0
->getIterator());
402 EXPECT_EQ(&*It
++, Ret
);
403 EXPECT_EQ(&*It
++, Add0
);
404 EXPECT_EQ(&*It
++, Add1
);
405 EXPECT_EQ(It
, BB
->end());
409 EXPECT_EQ(&*It
++, Add0
);
410 EXPECT_EQ(&*It
++, Add1
);
411 EXPECT_EQ(&*It
++, Ret
);
412 EXPECT_EQ(It
, BB
->end());
414 // Check moveAfter(Instruction *) with tracking enabled.
416 Add0
->moveAfter(Add1
);
418 EXPECT_EQ(&*It
++, Add1
);
419 EXPECT_EQ(&*It
++, Add0
);
420 EXPECT_EQ(&*It
++, Ret
);
421 EXPECT_EQ(It
, BB
->end());
425 EXPECT_EQ(&*It
++, Add0
);
426 EXPECT_EQ(&*It
++, Add1
);
427 EXPECT_EQ(&*It
++, Ret
);
428 EXPECT_EQ(It
, BB
->end());
430 // Same for the last instruction in the block.
432 Ret
->moveAfter(Add0
);
434 EXPECT_EQ(&*It
++, Add0
);
435 EXPECT_EQ(&*It
++, Ret
);
436 EXPECT_EQ(&*It
++, Add1
);
437 EXPECT_EQ(It
, BB
->end());
441 EXPECT_EQ(&*It
++, Add0
);
442 EXPECT_EQ(&*It
++, Add1
);
443 EXPECT_EQ(&*It
++, Ret
);
444 EXPECT_EQ(It
, BB
->end());
447 // TODO: Test multi-instruction patterns.
448 TEST_F(TrackerTest
, InsertIntoBB
) {
450 define void @foo(i32 %arg) {
451 %add0 = add i32 %arg, %arg
455 Function
&LLVMF
= *M
->getFunction("foo");
456 sandboxir::Context
Ctx(C
);
458 auto *F
= Ctx
.createFunction(&LLVMF
);
459 auto *BB
= &*F
->begin();
460 auto It
= BB
->begin();
461 sandboxir::Instruction
*Add0
= &*It
++;
462 sandboxir::Instruction
*Ret
= &*It
++;
463 // Detach `Add0` before we save.
464 Add0
->removeFromParent();
466 // Check insertBefore(Instruction *) with tracking enabled.
468 Add0
->insertBefore(Ret
);
470 EXPECT_EQ(&*It
++, Add0
);
471 EXPECT_EQ(&*It
++, Ret
);
472 EXPECT_EQ(It
, BB
->end());
476 EXPECT_EQ(&*It
++, Ret
);
477 EXPECT_EQ(It
, BB
->end());
479 // Check insertAfter(Instruction *) with tracking enabled.
481 Add0
->insertAfter(Ret
);
483 EXPECT_EQ(&*It
++, Ret
);
484 EXPECT_EQ(&*It
++, Add0
);
485 EXPECT_EQ(It
, BB
->end());
489 EXPECT_EQ(&*It
++, Ret
);
490 EXPECT_EQ(It
, BB
->end());
492 // Check insertInto(BasicBlock *, BasicBlock::iterator) with tracking enabled.
494 Add0
->insertInto(BB
, Ret
->getIterator());
496 EXPECT_EQ(&*It
++, Add0
);
497 EXPECT_EQ(&*It
++, Ret
);
498 EXPECT_EQ(It
, BB
->end());
502 EXPECT_EQ(&*It
++, Ret
);
503 EXPECT_EQ(It
, BB
->end());
505 // To make sure we don't leak memory insert `Add0` back into the BB before the
507 Add0
->insertBefore(Ret
);
510 // TODO: Test multi-instruction patterns.
511 TEST_F(TrackerTest
, CreateAndInsertInst
) {
513 define void @foo(ptr %ptr) {
514 %ld = load i8, ptr %ptr, align 64
518 Function
&LLVMF
= *M
->getFunction("foo");
519 sandboxir::Context
Ctx(C
);
521 auto *F
= Ctx
.createFunction(&LLVMF
);
522 auto *Ptr
= F
->getArg(0);
523 auto *BB
= &*F
->begin();
524 auto It
= BB
->begin();
525 auto *Ld
= cast
<sandboxir::LoadInst
>(&*It
++);
529 // Check create(InsertBefore) with tracking enabled.
530 sandboxir::LoadInst
*NewLd
= sandboxir::LoadInst::create(
531 Ld
->getType(), Ptr
, Align(8),
532 /*InsertBefore=*/Ld
->getIterator(), Ctx
, "NewLd");
534 EXPECT_EQ(&*It
++, NewLd
);
535 EXPECT_EQ(&*It
++, Ld
);
536 EXPECT_EQ(&*It
++, Ret
);
537 EXPECT_EQ(It
, BB
->end());
541 EXPECT_EQ(&*It
++, Ld
);
542 EXPECT_EQ(&*It
++, Ret
);
543 EXPECT_EQ(It
, BB
->end());
546 TEST_F(TrackerTest
, FenceInstSetters
) {
549 fence syncscope("singlethread
") seq_cst
553 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
554 sandboxir::Context
Ctx(C
);
555 sandboxir::Function
*F
= Ctx
.createFunction(LLVMF
);
556 auto *BB
= &*F
->begin();
557 auto It
= BB
->begin();
558 auto *Fence
= cast
<sandboxir::FenceInst
>(&*It
++);
560 // Check setOrdering().
561 auto OrigOrdering
= Fence
->getOrdering();
562 auto NewOrdering
= AtomicOrdering::Release
;
563 EXPECT_NE(NewOrdering
, OrigOrdering
);
565 Fence
->setOrdering(NewOrdering
);
566 EXPECT_EQ(Fence
->getOrdering(), NewOrdering
);
568 EXPECT_EQ(Fence
->getOrdering(), OrigOrdering
);
569 // Check setSyncScopeID().
570 auto OrigSSID
= Fence
->getSyncScopeID();
571 auto NewSSID
= SyncScope::System
;
572 EXPECT_NE(NewSSID
, OrigSSID
);
574 Fence
->setSyncScopeID(NewSSID
);
575 EXPECT_EQ(Fence
->getSyncScopeID(), NewSSID
);
577 EXPECT_EQ(Fence
->getSyncScopeID(), OrigSSID
);
580 TEST_F(TrackerTest
, CallBaseSetters
) {
582 declare void @bar1(i8)
583 declare void @bar2(i8)
585 define void @foo(i8 %arg0, i8 %arg1) {
586 call void @bar1(i8 %arg0)
590 Function
&LLVMF
= *M
->getFunction("foo");
591 sandboxir::Context
Ctx(C
);
593 auto *F
= Ctx
.createFunction(&LLVMF
);
595 auto *Arg0
= F
->getArg(ArgIdx
++);
596 auto *Arg1
= F
->getArg(ArgIdx
++);
597 auto *BB
= &*F
->begin();
598 auto It
= BB
->begin();
599 auto *Call
= cast
<sandboxir::CallBase
>(&*It
++);
600 [[maybe_unused
]] auto *Ret
= cast
<sandboxir::ReturnInst
>(&*It
++);
602 // Check setArgOperand().
604 Call
->setArgOperand(0, Arg1
);
605 EXPECT_EQ(Call
->getArgOperand(0), Arg1
);
607 EXPECT_EQ(Call
->getArgOperand(0), Arg0
);
609 auto *Bar1F
= Call
->getCalledFunction();
610 auto *Bar2F
= Ctx
.createFunction(M
->getFunction("bar2"));
612 // Check setCalledOperand().
614 Call
->setCalledOperand(Bar2F
);
615 EXPECT_EQ(Call
->getCalledOperand(), Bar2F
);
617 EXPECT_EQ(Call
->getCalledOperand(), Bar1F
);
619 // Check setCalledFunction().
621 Call
->setCalledFunction(Bar2F
);
622 EXPECT_EQ(Call
->getCalledFunction(), Bar2F
);
624 EXPECT_EQ(Call
->getCalledFunction(), Bar1F
);
627 TEST_F(TrackerTest
, InvokeSetters
) {
629 define void @foo(i8 %arg) {
631 invoke i8 @foo(i8 %arg) to label %normal_bb
632 unwind label %exception_bb
641 Function
&LLVMF
= *M
->getFunction("foo");
642 sandboxir::Context
Ctx(C
);
643 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
644 auto *BB0
= cast
<sandboxir::BasicBlock
>(
645 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
646 auto *NormalBB
= cast
<sandboxir::BasicBlock
>(
647 Ctx
.getValue(getBasicBlockByName(LLVMF
, "normal_bb")));
648 auto *ExceptionBB
= cast
<sandboxir::BasicBlock
>(
649 Ctx
.getValue(getBasicBlockByName(LLVMF
, "exception_bb")));
650 auto *OtherBB
= cast
<sandboxir::BasicBlock
>(
651 Ctx
.getValue(getBasicBlockByName(LLVMF
, "other_bb")));
652 auto It
= BB0
->begin();
653 auto *Invoke
= cast
<sandboxir::InvokeInst
>(&*It
++);
655 // Check setNormalDest().
657 Invoke
->setNormalDest(OtherBB
);
658 EXPECT_EQ(Invoke
->getNormalDest(), OtherBB
);
660 EXPECT_EQ(Invoke
->getNormalDest(), NormalBB
);
662 // Check setUnwindDest().
664 Invoke
->setUnwindDest(OtherBB
);
665 EXPECT_EQ(Invoke
->getUnwindDest(), OtherBB
);
667 EXPECT_EQ(Invoke
->getUnwindDest(), ExceptionBB
);
669 // Check setSuccessor().
671 Invoke
->setSuccessor(0, OtherBB
);
672 EXPECT_EQ(Invoke
->getSuccessor(0), OtherBB
);
674 EXPECT_EQ(Invoke
->getSuccessor(0), NormalBB
);
677 Invoke
->setSuccessor(1, OtherBB
);
678 EXPECT_EQ(Invoke
->getSuccessor(1), OtherBB
);
680 EXPECT_EQ(Invoke
->getSuccessor(1), ExceptionBB
);
683 TEST_F(TrackerTest
, CatchSwitchInst
) {
685 define void @foo(i32 %cond0, i32 %cond1) {
687 %cs0 = catchswitch within none [label %handler0, label %handler1] unwind to caller
689 %cs1 = catchswitch within %cs0 [label %handler0, label %handler1] unwind label %cleanup
698 Function
&LLVMF
= *M
->getFunction("foo");
700 sandboxir::Context
Ctx(C
);
701 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
702 auto *BB0
= cast
<sandboxir::BasicBlock
>(
703 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
704 auto *BB1
= cast
<sandboxir::BasicBlock
>(
705 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb1")));
706 auto *Handler0
= cast
<sandboxir::BasicBlock
>(
707 Ctx
.getValue(getBasicBlockByName(LLVMF
, "handler0")));
708 auto *Handler1
= cast
<sandboxir::BasicBlock
>(
709 Ctx
.getValue(getBasicBlockByName(LLVMF
, "handler1")));
710 auto *CS0
= cast
<sandboxir::CatchSwitchInst
>(&*BB0
->begin());
711 auto *CS1
= cast
<sandboxir::CatchSwitchInst
>(&*BB1
->begin());
713 // Check setParentPad().
714 auto *OrigPad
= CS0
->getParentPad();
716 EXPECT_NE(NewPad
, OrigPad
);
718 CS0
->setParentPad(NewPad
);
719 EXPECT_EQ(CS0
->getParentPad(), NewPad
);
721 EXPECT_EQ(CS0
->getParentPad(), OrigPad
);
722 // Check setUnwindDest().
723 auto *OrigUnwindDest
= CS1
->getUnwindDest();
724 auto *NewUnwindDest
= BB0
;
725 EXPECT_NE(NewUnwindDest
, OrigUnwindDest
);
727 CS1
->setUnwindDest(NewUnwindDest
);
728 EXPECT_EQ(CS1
->getUnwindDest(), NewUnwindDest
);
730 EXPECT_EQ(CS1
->getUnwindDest(), OrigUnwindDest
);
731 // Check setSuccessor().
732 auto *OrigSuccessor
= CS0
->getSuccessor(0);
733 auto *NewSuccessor
= BB0
;
734 EXPECT_NE(NewSuccessor
, OrigSuccessor
);
736 CS0
->setSuccessor(0, NewSuccessor
);
737 EXPECT_EQ(CS0
->getSuccessor(0), NewSuccessor
);
739 EXPECT_EQ(CS0
->getSuccessor(0), OrigSuccessor
);
740 // Check addHandler().
742 CS0
->addHandler(BB0
);
743 EXPECT_EQ(CS0
->getNumHandlers(), 3u);
745 EXPECT_EQ(CS0
->getNumHandlers(), 2u);
746 auto HIt
= CS0
->handler_begin();
747 EXPECT_EQ(*HIt
++, Handler0
);
748 EXPECT_EQ(*HIt
++, Handler1
);
751 TEST_F(TrackerTest
, LandingPadInstSetters
) {
756 to label %bb unwind label %unwind
758 %lpad = landingpad { ptr, i32 }
765 Function
&LLVMF
= *M
->getFunction("foo");
766 auto *LLVMUnwind
= getBasicBlockByName(LLVMF
, "unwind");
768 sandboxir::Context
Ctx(C
);
769 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
770 auto *Unwind
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMUnwind
));
771 auto It
= Unwind
->begin();
772 auto *LPad
= cast
<sandboxir::LandingPadInst
>(&*It
++);
773 [[maybe_unused
]] auto *Ret
= cast
<sandboxir::ReturnInst
>(&*It
++);
775 // Check setCleanup().
776 auto OrigIsCleanup
= LPad
->isCleanup();
777 auto NewIsCleanup
= true;
778 EXPECT_NE(NewIsCleanup
, OrigIsCleanup
);
780 LPad
->setCleanup(NewIsCleanup
);
781 EXPECT_EQ(LPad
->isCleanup(), NewIsCleanup
);
783 EXPECT_EQ(LPad
->isCleanup(), OrigIsCleanup
);
786 TEST_F(TrackerTest
, CatchReturnInstSetters
) {
790 %cs = catchswitch within none [label %catch] unwind to caller
792 %catchpad = catchpad within %cs [ptr @foo]
793 catchret from %catchpad to label %continue
797 %catchpad2 = catchpad within %cs [ptr @foo]
801 Function
&LLVMF
= *M
->getFunction("foo");
802 BasicBlock
*LLVMCatch
= getBasicBlockByName(LLVMF
, "catch");
803 auto LLVMIt
= LLVMCatch
->begin();
804 [[maybe_unused
]] auto *LLVMCP
= cast
<llvm::CatchPadInst
>(&*LLVMIt
++);
806 sandboxir::Context
Ctx(C
);
807 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
808 auto *Catch
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMCatch
));
809 auto *Catch2
= cast
<sandboxir::BasicBlock
>(
810 Ctx
.getValue(getBasicBlockByName(LLVMF
, "catch2")));
811 auto It
= Catch
->begin();
812 [[maybe_unused
]] auto *CP
= cast
<sandboxir::CatchPadInst
>(&*It
++);
813 auto *CR
= cast
<sandboxir::CatchReturnInst
>(&*It
++);
814 auto *CP2
= cast
<sandboxir::CatchPadInst
>(&*Catch2
->begin());
816 // Check setCatchPad().
817 auto *OrigCP
= CR
->getCatchPad();
819 EXPECT_NE(NewCP
, OrigCP
);
821 CR
->setCatchPad(NewCP
);
822 EXPECT_EQ(CR
->getCatchPad(), NewCP
);
824 EXPECT_EQ(CR
->getCatchPad(), OrigCP
);
825 // Check setSuccessor().
826 auto *OrigSucc
= CR
->getSuccessor();
827 auto *NewSucc
= Catch
;
828 EXPECT_NE(NewSucc
, OrigSucc
);
830 CR
->setSuccessor(NewSucc
);
831 EXPECT_EQ(CR
->getSuccessor(), NewSucc
);
833 EXPECT_EQ(CR
->getSuccessor(), OrigSucc
);
836 TEST_F(TrackerTest
, CleanupReturnInstSetters
) {
841 to label %throw unwind label %cleanup
845 %cleanuppad = cleanuppad within none []
846 cleanupret from %cleanuppad unwind label %cleanup2
848 %cleanuppad2 = cleanuppad within none []
852 Function
&LLVMF
= *M
->getFunction("foo");
853 BasicBlock
*LLVMCleanup
= getBasicBlockByName(LLVMF
, "cleanup");
855 sandboxir::Context
Ctx(C
);
856 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
857 auto *Throw
= cast
<sandboxir::BasicBlock
>(
858 Ctx
.getValue(getBasicBlockByName(LLVMF
, "throw")));
859 auto *Cleanup
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMCleanup
));
860 auto *Cleanup2
= cast
<sandboxir::BasicBlock
>(
861 Ctx
.getValue(getBasicBlockByName(LLVMF
, "cleanup2")));
862 auto It
= Cleanup
->begin();
863 [[maybe_unused
]] auto *CP
= cast
<sandboxir::CleanupPadInst
>(&*It
++);
864 auto *CRI
= cast
<sandboxir::CleanupReturnInst
>(&*It
++);
865 auto *CP2
= cast
<sandboxir::CleanupPadInst
>(&*Cleanup2
->begin());
867 // Check setCleanupPad().
868 auto *OrigCleanupPad
= CRI
->getCleanupPad();
869 auto *NewCleanupPad
= CP2
;
870 EXPECT_NE(NewCleanupPad
, OrigCleanupPad
);
872 CRI
->setCleanupPad(NewCleanupPad
);
873 EXPECT_EQ(CRI
->getCleanupPad(), NewCleanupPad
);
875 EXPECT_EQ(CRI
->getCleanupPad(), OrigCleanupPad
);
876 // Check setUnwindDest().
877 auto *OrigUnwindDest
= CRI
->getUnwindDest();
878 auto *NewUnwindDest
= Throw
;
879 EXPECT_NE(NewUnwindDest
, OrigUnwindDest
);
881 CRI
->setUnwindDest(NewUnwindDest
);
882 EXPECT_EQ(CRI
->getUnwindDest(), NewUnwindDest
);
884 EXPECT_EQ(CRI
->getUnwindDest(), OrigUnwindDest
);
887 TEST_F(TrackerTest
, SwitchInstSetters
) {
889 define void @foo(i32 %cond0, i32 %cond1) {
891 switch i32 %cond0, label %default [ i32 0, label %bb0
901 Function
&LLVMF
= *M
->getFunction("foo");
902 auto *LLVMEntry
= getBasicBlockByName(LLVMF
, "entry");
904 sandboxir::Context
Ctx(C
);
905 auto &F
= *Ctx
.createFunction(&LLVMF
);
906 auto *Cond1
= F
.getArg(1);
907 auto *Entry
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMEntry
));
908 auto *BB0
= cast
<sandboxir::BasicBlock
>(
909 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
910 auto *BB1
= cast
<sandboxir::BasicBlock
>(
911 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb1")));
912 auto *Switch
= cast
<sandboxir::SwitchInst
>(&*Entry
->begin());
914 // Check setCondition().
915 auto *OrigCond
= Switch
->getCondition();
916 auto *NewCond
= Cond1
;
917 EXPECT_NE(NewCond
, OrigCond
);
919 Switch
->setCondition(NewCond
);
920 EXPECT_EQ(Switch
->getCondition(), NewCond
);
922 EXPECT_EQ(Switch
->getCondition(), OrigCond
);
923 // Check setDefaultDest().
924 auto *OrigDefaultDest
= Switch
->getDefaultDest();
925 auto *NewDefaultDest
= Entry
;
926 EXPECT_NE(NewDefaultDest
, OrigDefaultDest
);
928 Switch
->setDefaultDest(NewDefaultDest
);
929 EXPECT_EQ(Switch
->getDefaultDest(), NewDefaultDest
);
931 EXPECT_EQ(Switch
->getDefaultDest(), OrigDefaultDest
);
932 // Check setSuccessor().
933 auto *OrigSucc
= Switch
->getSuccessor(0);
934 auto *NewSucc
= Entry
;
935 EXPECT_NE(NewSucc
, OrigSucc
);
937 Switch
->setSuccessor(0, NewSucc
);
938 EXPECT_EQ(Switch
->getSuccessor(0), NewSucc
);
940 EXPECT_EQ(Switch
->getSuccessor(0), OrigSucc
);
942 auto *Zero
= sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 0);
943 auto *One
= sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 1);
945 sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 42);
947 Switch
->addCase(FortyTwo
, Entry
);
948 EXPECT_EQ(Switch
->getNumCases(), 3u);
949 EXPECT_EQ(Switch
->findCaseDest(Entry
), FortyTwo
);
950 EXPECT_EQ(Switch
->findCaseValue(FortyTwo
)->getCaseSuccessor(), Entry
);
951 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
952 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
954 EXPECT_EQ(Switch
->getNumCases(), 2u);
955 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
956 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
957 // Check removeCase().
959 Switch
->removeCase(Switch
->findCaseValue(Zero
));
960 EXPECT_EQ(Switch
->getNumCases(), 1u);
961 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
963 EXPECT_EQ(Switch
->getNumCases(), 2u);
964 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
965 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
968 TEST_F(TrackerTest
, SwitchInstPreservesSuccesorOrder
) {
970 define void @foo(i32 %cond0) {
972 switch i32 %cond0, label %default [ i32 0, label %bb0
985 Function
&LLVMF
= *M
->getFunction("foo");
986 auto *LLVMEntry
= getBasicBlockByName(LLVMF
, "entry");
988 sandboxir::Context
Ctx(C
);
989 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
990 auto *Entry
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMEntry
));
991 auto *BB0
= cast
<sandboxir::BasicBlock
>(
992 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
993 auto *BB1
= cast
<sandboxir::BasicBlock
>(
994 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb1")));
995 auto *BB2
= cast
<sandboxir::BasicBlock
>(
996 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb2")));
997 auto *Switch
= cast
<sandboxir::SwitchInst
>(&*Entry
->begin());
999 auto *DefaultDest
= Switch
->getDefaultDest();
1000 auto *Zero
= sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 0);
1001 auto *One
= sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 1);
1002 auto *Two
= sandboxir::ConstantInt::get(sandboxir::Type::getInt32Ty(Ctx
), 2);
1004 // Check that we can properly revert a removeCase multiple positions apart
1005 // from the end of the operand list.
1007 Switch
->removeCase(Switch
->findCaseValue(Zero
));
1008 EXPECT_EQ(Switch
->getNumCases(), 2u);
1010 EXPECT_EQ(Switch
->getNumCases(), 3u);
1011 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
1012 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
1013 EXPECT_EQ(Switch
->findCaseDest(BB2
), Two
);
1014 EXPECT_EQ(Switch
->getSuccessor(0), DefaultDest
);
1015 EXPECT_EQ(Switch
->getSuccessor(1), BB0
);
1016 EXPECT_EQ(Switch
->getSuccessor(2), BB1
);
1017 EXPECT_EQ(Switch
->getSuccessor(3), BB2
);
1019 // Check that we can properly revert a removeCase of the last case.
1021 Switch
->removeCase(Switch
->findCaseValue(Two
));
1022 EXPECT_EQ(Switch
->getNumCases(), 2u);
1024 EXPECT_EQ(Switch
->getNumCases(), 3u);
1025 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
1026 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
1027 EXPECT_EQ(Switch
->findCaseDest(BB2
), Two
);
1028 EXPECT_EQ(Switch
->getSuccessor(0), DefaultDest
);
1029 EXPECT_EQ(Switch
->getSuccessor(1), BB0
);
1030 EXPECT_EQ(Switch
->getSuccessor(2), BB1
);
1031 EXPECT_EQ(Switch
->getSuccessor(3), BB2
);
1033 // Check order is preserved after reverting multiple removeCase invocations.
1035 Switch
->removeCase(Switch
->findCaseValue(One
));
1036 Switch
->removeCase(Switch
->findCaseValue(Zero
));
1037 Switch
->removeCase(Switch
->findCaseValue(Two
));
1038 EXPECT_EQ(Switch
->getNumCases(), 0u);
1040 EXPECT_EQ(Switch
->getNumCases(), 3u);
1041 EXPECT_EQ(Switch
->findCaseDest(BB0
), Zero
);
1042 EXPECT_EQ(Switch
->findCaseDest(BB1
), One
);
1043 EXPECT_EQ(Switch
->findCaseDest(BB2
), Two
);
1044 EXPECT_EQ(Switch
->getSuccessor(0), DefaultDest
);
1045 EXPECT_EQ(Switch
->getSuccessor(1), BB0
);
1046 EXPECT_EQ(Switch
->getSuccessor(2), BB1
);
1047 EXPECT_EQ(Switch
->getSuccessor(3), BB2
);
1050 TEST_F(TrackerTest
, SelectInst
) {
1052 define void @foo(i1 %c0, i8 %v0, i8 %v1) {
1053 %sel = select i1 %c0, i8 %v0, i8 %v1
1057 llvm::Function
*LLVMF
= &*M
->getFunction("foo");
1058 sandboxir::Context
Ctx(C
);
1059 sandboxir::Function
*F
= Ctx
.createFunction(LLVMF
);
1060 auto *V0
= F
->getArg(1);
1061 auto *V1
= F
->getArg(2);
1062 auto *BB
= &*F
->begin();
1063 auto It
= BB
->begin();
1064 auto *Select
= cast
<sandboxir::SelectInst
>(&*It
++);
1066 // Check tracking for swapValues.
1068 Select
->swapValues();
1069 EXPECT_EQ(Select
->getTrueValue(), V1
);
1070 EXPECT_EQ(Select
->getFalseValue(), V0
);
1072 EXPECT_EQ(Select
->getTrueValue(), V0
);
1073 EXPECT_EQ(Select
->getFalseValue(), V1
);
1076 TEST_F(TrackerTest
, ShuffleVectorInst
) {
1078 define void @foo(<2 x i8> %v1, <2 x i8> %v2) {
1079 %shuf = shufflevector <2 x i8> %v1, <2 x i8> %v2, <2 x i32> <i32 1, i32 2>
1083 Function
&LLVMF
= *M
->getFunction("foo");
1084 sandboxir::Context
Ctx(C
);
1086 auto *F
= Ctx
.createFunction(&LLVMF
);
1087 auto *BB
= &*F
->begin();
1088 auto It
= BB
->begin();
1089 auto *SVI
= cast
<sandboxir::ShuffleVectorInst
>(&*It
++);
1091 // Check setShuffleMask.
1092 SmallVector
<int, 2> OrigMask(SVI
->getShuffleMask());
1094 SVI
->setShuffleMask(ArrayRef
<int>({0, 0}));
1095 EXPECT_NE(SVI
->getShuffleMask(), ArrayRef
<int>(OrigMask
));
1097 EXPECT_EQ(SVI
->getShuffleMask(), ArrayRef
<int>(OrigMask
));
1100 auto *Op0
= SVI
->getOperand(0);
1101 auto *Op1
= SVI
->getOperand(1);
1104 EXPECT_EQ(SVI
->getOperand(0), Op1
);
1105 EXPECT_EQ(SVI
->getOperand(1), Op0
);
1106 EXPECT_NE(SVI
->getShuffleMask(), ArrayRef
<int>(OrigMask
));
1108 EXPECT_EQ(SVI
->getOperand(0), Op0
);
1109 EXPECT_EQ(SVI
->getOperand(1), Op1
);
1110 EXPECT_EQ(SVI
->getShuffleMask(), ArrayRef
<int>(OrigMask
));
1113 TEST_F(TrackerTest
, PossiblyDisjointInstSetters
) {
1115 define void @foo(i8 %arg0, i8 %arg1) {
1116 %or = or i8 %arg0, %arg1
1120 Function
&LLVMF
= *M
->getFunction("foo");
1121 sandboxir::Context
Ctx(C
);
1123 auto &F
= *Ctx
.createFunction(&LLVMF
);
1124 auto *BB
= &*F
.begin();
1125 auto It
= BB
->begin();
1126 auto *PDI
= cast
<sandboxir::PossiblyDisjointInst
>(&*It
++);
1128 // Check setIsDisjoint().
1129 auto OrigIsDisjoint
= PDI
->isDisjoint();
1130 auto NewIsDisjoint
= true;
1131 EXPECT_NE(NewIsDisjoint
, OrigIsDisjoint
);
1133 PDI
->setIsDisjoint(NewIsDisjoint
);
1134 EXPECT_EQ(PDI
->isDisjoint(), NewIsDisjoint
);
1136 EXPECT_EQ(PDI
->isDisjoint(), OrigIsDisjoint
);
1139 TEST_F(TrackerTest
, PossiblyNonNegInstSetters
) {
1141 define void @foo(i32 %arg) {
1142 %zext = zext i32 %arg to i64
1146 Function
&LLVMF
= *M
->getFunction("foo");
1147 sandboxir::Context
Ctx(C
);
1149 auto &F
= *Ctx
.createFunction(&LLVMF
);
1150 auto *BB
= &*F
.begin();
1151 auto It
= BB
->begin();
1152 auto *PNNI
= cast
<sandboxir::PossiblyNonNegInst
>(&*It
++);
1154 // Check setNonNeg().
1155 auto OrigNonNeg
= PNNI
->hasNonNeg();
1156 auto NewNonNeg
= true;
1157 EXPECT_NE(NewNonNeg
, OrigNonNeg
);
1159 PNNI
->setNonNeg(NewNonNeg
);
1160 EXPECT_EQ(PNNI
->hasNonNeg(), NewNonNeg
);
1162 EXPECT_EQ(PNNI
->hasNonNeg(), OrigNonNeg
);
1165 TEST_F(TrackerTest
, AtomicRMWSetters
) {
1167 define void @foo(ptr %ptr, i8 %arg) {
1168 %atomicrmw = atomicrmw add ptr %ptr, i8 %arg acquire, align 128
1172 Function
&LLVMF
= *M
->getFunction("foo");
1173 sandboxir::Context
Ctx(C
);
1174 auto &F
= *Ctx
.createFunction(&LLVMF
);
1175 auto *BB
= &*F
.begin();
1176 auto It
= BB
->begin();
1177 auto *RMW
= cast
<sandboxir::AtomicRMWInst
>(&*It
++);
1179 // Check setAlignment().
1181 auto OrigAlign
= RMW
->getAlign();
1182 Align
NewAlign(1024);
1183 EXPECT_NE(NewAlign
, OrigAlign
);
1184 RMW
->setAlignment(NewAlign
);
1185 EXPECT_EQ(RMW
->getAlign(), NewAlign
);
1187 EXPECT_EQ(RMW
->getAlign(), OrigAlign
);
1189 // Check setVolatile().
1191 auto OrigIsVolatile
= RMW
->isVolatile();
1192 bool NewIsVolatile
= true;
1193 EXPECT_NE(NewIsVolatile
, OrigIsVolatile
);
1194 RMW
->setVolatile(NewIsVolatile
);
1195 EXPECT_EQ(RMW
->isVolatile(), NewIsVolatile
);
1197 EXPECT_EQ(RMW
->isVolatile(), OrigIsVolatile
);
1199 // Check setOrdering().
1201 auto OrigOrdering
= RMW
->getOrdering();
1202 auto NewOrdering
= AtomicOrdering::SequentiallyConsistent
;
1203 EXPECT_NE(NewOrdering
, OrigOrdering
);
1204 RMW
->setOrdering(NewOrdering
);
1205 EXPECT_EQ(RMW
->getOrdering(), NewOrdering
);
1207 EXPECT_EQ(RMW
->getOrdering(), OrigOrdering
);
1209 // Check setSyncScopeID().
1211 auto OrigSSID
= RMW
->getSyncScopeID();
1212 auto NewSSID
= SyncScope::SingleThread
;
1213 EXPECT_NE(NewSSID
, OrigSSID
);
1214 RMW
->setSyncScopeID(NewSSID
);
1215 EXPECT_EQ(RMW
->getSyncScopeID(), NewSSID
);
1217 EXPECT_EQ(RMW
->getSyncScopeID(), OrigSSID
);
1220 TEST_F(TrackerTest
, AtomicCmpXchgSetters
) {
1222 define void @foo(ptr %ptr, i8 %cmp, i8 %new) {
1223 %cmpxchg = cmpxchg ptr %ptr, i8 %cmp, i8 %new monotonic monotonic, align 128
1227 Function
&LLVMF
= *M
->getFunction("foo");
1228 sandboxir::Context
Ctx(C
);
1229 auto &F
= *Ctx
.createFunction(&LLVMF
);
1230 auto *BB
= &*F
.begin();
1231 auto It
= BB
->begin();
1232 auto *CmpXchg
= cast
<sandboxir::AtomicCmpXchgInst
>(&*It
++);
1234 // Check setAlignment().
1236 auto OrigAlign
= CmpXchg
->getAlign();
1237 Align
NewAlign(1024);
1238 EXPECT_NE(NewAlign
, OrigAlign
);
1239 CmpXchg
->setAlignment(NewAlign
);
1240 EXPECT_EQ(CmpXchg
->getAlign(), NewAlign
);
1242 EXPECT_EQ(CmpXchg
->getAlign(), OrigAlign
);
1244 // Check setVolatile().
1246 auto OrigIsVolatile
= CmpXchg
->isVolatile();
1247 bool NewIsVolatile
= true;
1248 EXPECT_NE(NewIsVolatile
, OrigIsVolatile
);
1249 CmpXchg
->setVolatile(NewIsVolatile
);
1250 EXPECT_EQ(CmpXchg
->isVolatile(), NewIsVolatile
);
1252 EXPECT_EQ(CmpXchg
->isVolatile(), OrigIsVolatile
);
1256 auto OrigIsWeak
= CmpXchg
->isWeak();
1257 bool NewIsWeak
= true;
1258 EXPECT_NE(NewIsWeak
, OrigIsWeak
);
1259 CmpXchg
->setWeak(NewIsWeak
);
1260 EXPECT_EQ(CmpXchg
->isWeak(), NewIsWeak
);
1262 EXPECT_EQ(CmpXchg
->isWeak(), OrigIsWeak
);
1264 // Check setSuccessOrdering().
1266 auto OrigSuccessOrdering
= CmpXchg
->getSuccessOrdering();
1267 auto NewSuccessOrdering
= AtomicOrdering::SequentiallyConsistent
;
1268 EXPECT_NE(NewSuccessOrdering
, OrigSuccessOrdering
);
1269 CmpXchg
->setSuccessOrdering(NewSuccessOrdering
);
1270 EXPECT_EQ(CmpXchg
->getSuccessOrdering(), NewSuccessOrdering
);
1272 EXPECT_EQ(CmpXchg
->getSuccessOrdering(), OrigSuccessOrdering
);
1274 // Check setFailureOrdering().
1276 auto OrigFailureOrdering
= CmpXchg
->getFailureOrdering();
1277 auto NewFailureOrdering
= AtomicOrdering::SequentiallyConsistent
;
1278 EXPECT_NE(NewFailureOrdering
, OrigFailureOrdering
);
1279 CmpXchg
->setFailureOrdering(NewFailureOrdering
);
1280 EXPECT_EQ(CmpXchg
->getFailureOrdering(), NewFailureOrdering
);
1282 EXPECT_EQ(CmpXchg
->getFailureOrdering(), OrigFailureOrdering
);
1284 // Check setSyncScopeID().
1286 auto OrigSSID
= CmpXchg
->getSyncScopeID();
1287 auto NewSSID
= SyncScope::SingleThread
;
1288 EXPECT_NE(NewSSID
, OrigSSID
);
1289 CmpXchg
->setSyncScopeID(NewSSID
);
1290 EXPECT_EQ(CmpXchg
->getSyncScopeID(), NewSSID
);
1292 EXPECT_EQ(CmpXchg
->getSyncScopeID(), OrigSSID
);
1295 TEST_F(TrackerTest
, AllocaInstSetters
) {
1297 define void @foo(i8 %arg) {
1298 %alloca = alloca i32, align 64
1302 Function
&LLVMF
= *M
->getFunction("foo");
1303 sandboxir::Context
Ctx(C
);
1304 auto &F
= *Ctx
.createFunction(&LLVMF
);
1305 auto *BB
= &*F
.begin();
1306 auto It
= BB
->begin();
1307 auto *Alloca
= cast
<sandboxir::AllocaInst
>(&*It
++);
1309 // Check setAllocatedType().
1311 auto *OrigTy
= Alloca
->getAllocatedType();
1312 auto *NewTy
= sandboxir::Type::getInt64Ty(Ctx
);
1313 EXPECT_NE(NewTy
, OrigTy
);
1314 Alloca
->setAllocatedType(NewTy
);
1315 EXPECT_EQ(Alloca
->getAllocatedType(), NewTy
);
1317 EXPECT_EQ(Alloca
->getAllocatedType(), OrigTy
);
1319 // Check setAlignment().
1321 auto OrigAlign
= Alloca
->getAlign();
1322 Align
NewAlign(128);
1323 EXPECT_NE(NewAlign
, OrigAlign
);
1324 Alloca
->setAlignment(NewAlign
);
1325 EXPECT_EQ(Alloca
->getAlign(), NewAlign
);
1327 EXPECT_EQ(Alloca
->getAlign(), OrigAlign
);
1329 // Check setUsedWithInAlloca().
1331 auto OrigWIA
= Alloca
->isUsedWithInAlloca();
1333 EXPECT_NE(NewWIA
, OrigWIA
);
1334 Alloca
->setUsedWithInAlloca(NewWIA
);
1335 EXPECT_EQ(Alloca
->isUsedWithInAlloca(), NewWIA
);
1337 EXPECT_EQ(Alloca
->isUsedWithInAlloca(), OrigWIA
);
1340 TEST_F(TrackerTest
, CallBrSetters
) {
1342 define void @foo(i8 %arg) {
1344 callbr void @foo(i8 %arg)
1345 to label %bb1 [label %bb2]
1354 Function
&LLVMF
= *M
->getFunction("foo");
1355 sandboxir::Context
Ctx(C
);
1356 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
1357 auto *BB0
= cast
<sandboxir::BasicBlock
>(
1358 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
1359 auto *OtherBB
= cast
<sandboxir::BasicBlock
>(
1360 Ctx
.getValue(getBasicBlockByName(LLVMF
, "other_bb")));
1361 auto It
= BB0
->begin();
1362 auto *CallBr
= cast
<sandboxir::CallBrInst
>(&*It
++);
1363 // Check setDefaultDest().
1365 auto *OrigDefaultDest
= CallBr
->getDefaultDest();
1366 CallBr
->setDefaultDest(OtherBB
);
1367 EXPECT_EQ(CallBr
->getDefaultDest(), OtherBB
);
1369 EXPECT_EQ(CallBr
->getDefaultDest(), OrigDefaultDest
);
1371 // Check setIndirectDest().
1373 auto *OrigIndirectDest
= CallBr
->getIndirectDest(0);
1374 CallBr
->setIndirectDest(0, OtherBB
);
1375 EXPECT_EQ(CallBr
->getIndirectDest(0), OtherBB
);
1377 EXPECT_EQ(CallBr
->getIndirectDest(0), OrigIndirectDest
);
1380 TEST_F(TrackerTest
, FuncletPadInstSetters
) {
1382 define void @foo() {
1384 %cs = catchswitch within none [label %handler0] unwind to caller
1386 %catchpad = catchpad within %cs [ptr @foo]
1389 %cleanuppad = cleanuppad within %cs [ptr @foo]
1395 Function
&LLVMF
= *M
->getFunction("foo");
1396 sandboxir::Context
Ctx(C
);
1397 [[maybe_unused
]] auto &F
= *Ctx
.createFunction(&LLVMF
);
1398 auto *Dispatch
= cast
<sandboxir::BasicBlock
>(
1399 Ctx
.getValue(getBasicBlockByName(LLVMF
, "dispatch")));
1400 auto *Handler0
= cast
<sandboxir::BasicBlock
>(
1401 Ctx
.getValue(getBasicBlockByName(LLVMF
, "handler0")));
1402 auto *Handler1
= cast
<sandboxir::BasicBlock
>(
1403 Ctx
.getValue(getBasicBlockByName(LLVMF
, "handler1")));
1404 auto *CP
= cast
<sandboxir::CatchPadInst
>(&*Handler0
->begin());
1405 auto *CLP
= cast
<sandboxir::CleanupPadInst
>(&*Handler1
->begin());
1407 for (auto *FPI
: {static_cast<sandboxir::FuncletPadInst
*>(CP
),
1408 static_cast<sandboxir::FuncletPadInst
*>(CLP
)}) {
1409 // Check setParentPad().
1410 auto *OrigParentPad
= FPI
->getParentPad();
1411 auto *NewParentPad
= Dispatch
;
1412 EXPECT_NE(NewParentPad
, OrigParentPad
);
1414 FPI
->setParentPad(NewParentPad
);
1415 EXPECT_EQ(FPI
->getParentPad(), NewParentPad
);
1417 EXPECT_EQ(FPI
->getParentPad(), OrigParentPad
);
1419 // Check setArgOperand().
1420 auto *OrigArgOperand
= FPI
->getArgOperand(0);
1421 auto *NewArgOperand
= Dispatch
;
1422 EXPECT_NE(NewArgOperand
, OrigArgOperand
);
1424 FPI
->setArgOperand(0, NewArgOperand
);
1425 EXPECT_EQ(FPI
->getArgOperand(0), NewArgOperand
);
1427 EXPECT_EQ(FPI
->getArgOperand(0), OrigArgOperand
);
1431 TEST_F(TrackerTest
, PHINodeSetters
) {
1433 define void @foo(i8 %arg0, i8 %arg1, i8 %arg2) {
1438 %phi = phi i8 [ %arg0, %bb0 ], [ %arg1, %bb1 ]
1445 Function
&LLVMF
= *M
->getFunction("foo");
1446 sandboxir::Context
Ctx(C
);
1447 auto &F
= *Ctx
.createFunction(&LLVMF
);
1448 unsigned ArgIdx
= 0;
1449 auto *Arg0
= F
.getArg(ArgIdx
++);
1450 auto *Arg1
= F
.getArg(ArgIdx
++);
1451 auto *Arg2
= F
.getArg(ArgIdx
++);
1452 auto *BB0
= cast
<sandboxir::BasicBlock
>(
1453 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb0")));
1454 auto *BB1
= cast
<sandboxir::BasicBlock
>(
1455 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb1")));
1456 auto *BB2
= cast
<sandboxir::BasicBlock
>(
1457 Ctx
.getValue(getBasicBlockByName(LLVMF
, "bb2")));
1458 auto *PHI
= cast
<sandboxir::PHINode
>(&*BB1
->begin());
1460 // Check setIncomingValue().
1462 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1463 PHI
->setIncomingValue(0, Arg2
);
1464 EXPECT_EQ(PHI
->getIncomingValue(0), Arg2
);
1466 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1467 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1468 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1469 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1470 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1471 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1473 // Check setIncomingBlock().
1475 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1476 PHI
->setIncomingBlock(0, BB2
);
1477 EXPECT_EQ(PHI
->getIncomingBlock(0), BB2
);
1479 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1480 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1481 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1482 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1483 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1484 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1486 // Check addIncoming().
1488 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1489 PHI
->addIncoming(Arg1
, BB2
);
1490 EXPECT_EQ(PHI
->getNumIncomingValues(), 3u);
1491 EXPECT_EQ(PHI
->getIncomingBlock(2), BB2
);
1492 EXPECT_EQ(PHI
->getIncomingValue(2), Arg1
);
1494 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1495 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1496 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1497 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1498 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1500 // Check removeIncomingValue(1).
1502 PHI
->removeIncomingValue(1);
1503 EXPECT_EQ(PHI
->getNumIncomingValues(), 1u);
1504 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1505 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1507 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1508 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1509 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1510 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1511 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1513 // Check removeIncomingValue(0).
1515 PHI
->removeIncomingValue(0u);
1516 EXPECT_EQ(PHI
->getNumIncomingValues(), 1u);
1517 EXPECT_EQ(PHI
->getIncomingBlock(0), BB1
);
1518 EXPECT_EQ(PHI
->getIncomingValue(0), Arg1
);
1520 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1521 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1522 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1523 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1524 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1526 // Check removeIncomingValueIf(FromBB1).
1528 PHI
->removeIncomingValueIf(
1529 [&](unsigned Idx
) { return PHI
->getIncomingBlock(Idx
) == BB1
; });
1530 EXPECT_EQ(PHI
->getNumIncomingValues(), 1u);
1532 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1533 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1534 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1535 // Check removeIncomingValue() remove all.
1537 PHI
->removeIncomingValue(0u);
1538 EXPECT_EQ(PHI
->getNumIncomingValues(), 1u);
1539 EXPECT_EQ(PHI
->getIncomingBlock(0), BB1
);
1540 EXPECT_EQ(PHI
->getIncomingValue(0), Arg1
);
1541 PHI
->removeIncomingValue(0u);
1542 EXPECT_EQ(PHI
->getNumIncomingValues(), 0u);
1544 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1545 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1546 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1547 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1548 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1550 // Check removeIncomingValue(BasicBlock *).
1552 PHI
->removeIncomingValue(BB1
);
1553 EXPECT_EQ(PHI
->getNumIncomingValues(), 1u);
1554 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1555 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1557 EXPECT_EQ(PHI
->getNumIncomingValues(), 2u);
1558 EXPECT_EQ(PHI
->getIncomingBlock(0), BB0
);
1559 EXPECT_EQ(PHI
->getIncomingValue(0), Arg0
);
1560 EXPECT_EQ(PHI
->getIncomingBlock(1), BB1
);
1561 EXPECT_EQ(PHI
->getIncomingValue(1), Arg1
);
1564 void checkCmpInst(sandboxir::Context
&Ctx
, sandboxir::CmpInst
*Cmp
) {
1566 auto OrigP
= Cmp
->getPredicate();
1567 auto NewP
= Cmp
->getSwappedPredicate();
1568 Cmp
->setPredicate(NewP
);
1569 EXPECT_EQ(Cmp
->getPredicate(), NewP
);
1571 EXPECT_EQ(Cmp
->getPredicate(), OrigP
);
1574 auto OrigOp0
= Cmp
->getOperand(0);
1575 auto OrigOp1
= Cmp
->getOperand(1);
1576 Cmp
->swapOperands();
1577 EXPECT_EQ(Cmp
->getPredicate(), NewP
);
1578 EXPECT_EQ(Cmp
->getOperand(0), OrigOp1
);
1579 EXPECT_EQ(Cmp
->getOperand(1), OrigOp0
);
1581 EXPECT_EQ(Cmp
->getPredicate(), OrigP
);
1582 EXPECT_EQ(Cmp
->getOperand(0), OrigOp0
);
1583 EXPECT_EQ(Cmp
->getOperand(1), OrigOp1
);
1586 TEST_F(TrackerTest
, CmpInst
) {
1587 SCOPED_TRACE("TrackerTest sandboxir::CmpInst tests");
1589 define void @foo(i64 %i0, i64 %i1, float %f0, float %f1) {
1590 %foeq = fcmp ogt float %f0, %f1
1591 %ioeq = icmp uge i64 %i0, %i1
1596 Function
&LLVMF
= *M
->getFunction("foo");
1597 sandboxir::Context
Ctx(C
);
1598 auto &F
= *Ctx
.createFunction(&LLVMF
);
1599 auto *BB
= &*F
.begin();
1600 auto It
= BB
->begin();
1601 auto *FCmp
= cast
<sandboxir::CmpInst
>(&*It
++);
1602 checkCmpInst(Ctx
, FCmp
);
1603 auto *ICmp
= cast
<sandboxir::CmpInst
>(&*It
++);
1604 checkCmpInst(Ctx
, ICmp
);
1607 TEST_F(TrackerTest
, GlobalValueSetters
) {
1609 define void @foo() {
1614 Function
&LLVMF
= *M
->getFunction("foo");
1615 sandboxir::Context
Ctx(C
);
1617 auto &F
= *Ctx
.createFunction(&LLVMF
);
1618 auto *BB
= &*F
.begin();
1619 auto *Call
= cast
<sandboxir::CallInst
>(&*BB
->begin());
1621 auto *GV
= cast
<sandboxir::GlobalValue
>(Call
->getCalledOperand());
1622 // Check setUnnamedAddr().
1623 auto OrigUnnamedAddr
= GV
->getUnnamedAddr();
1624 auto NewUnnamedAddr
= sandboxir::GlobalValue::UnnamedAddr::Global
;
1625 EXPECT_NE(NewUnnamedAddr
, OrigUnnamedAddr
);
1627 GV
->setUnnamedAddr(NewUnnamedAddr
);
1628 EXPECT_EQ(GV
->getUnnamedAddr(), NewUnnamedAddr
);
1630 EXPECT_EQ(GV
->getUnnamedAddr(), OrigUnnamedAddr
);
1632 // Check setVisibility().
1633 auto OrigVisibility
= GV
->getVisibility();
1634 auto NewVisibility
=
1635 sandboxir::GlobalValue::VisibilityTypes::ProtectedVisibility
;
1636 EXPECT_NE(NewVisibility
, OrigVisibility
);
1638 GV
->setVisibility(NewVisibility
);
1639 EXPECT_EQ(GV
->getVisibility(), NewVisibility
);
1641 EXPECT_EQ(GV
->getVisibility(), OrigVisibility
);
1644 TEST_F(TrackerTest
, GlobalIFuncSetters
) {
1646 declare external void @bar()
1647 @ifunc = ifunc void(), ptr @foo
1648 define void @foo() {
1654 Function
&LLVMF
= *M
->getFunction("foo");
1655 sandboxir::Context
Ctx(C
);
1657 auto &F
= *Ctx
.createFunction(&LLVMF
);
1658 auto *BB
= &*F
.begin();
1659 auto It
= BB
->begin();
1660 auto *Call0
= cast
<sandboxir::CallInst
>(&*It
++);
1661 auto *Call1
= cast
<sandboxir::CallInst
>(&*It
++);
1662 // Check classof(), creation.
1663 auto *IFunc
= cast
<sandboxir::GlobalIFunc
>(Call0
->getCalledOperand());
1664 auto *Bar
= cast
<sandboxir::Function
>(Call1
->getCalledOperand());
1665 // Check setResolver().
1666 auto *OrigResolver
= IFunc
->getResolver();
1667 auto *NewResolver
= Bar
;
1668 EXPECT_NE(NewResolver
, OrigResolver
);
1670 IFunc
->setResolver(NewResolver
);
1671 EXPECT_EQ(IFunc
->getResolver(), NewResolver
);
1673 EXPECT_EQ(IFunc
->getResolver(), OrigResolver
);
1676 TEST_F(TrackerTest
, GlobalVariableSetters
) {
1678 @glob0 = global i32 42
1679 @glob1 = global i32 43
1680 define void @foo() {
1681 %ld0 = load i32, ptr @glob0
1682 %ld1 = load i32, ptr @glob1
1686 Function
&LLVMF
= *M
->getFunction("foo");
1687 sandboxir::Context
Ctx(C
);
1689 auto &F
= *Ctx
.createFunction(&LLVMF
);
1690 auto *BB
= &*F
.begin();
1691 auto It
= BB
->begin();
1692 auto *Ld0
= cast
<sandboxir::LoadInst
>(&*It
++);
1693 auto *Ld1
= cast
<sandboxir::LoadInst
>(&*It
++);
1694 // Check classof(), creation.
1695 auto *GV0
= cast
<sandboxir::GlobalVariable
>(Ld0
->getPointerOperand());
1696 auto *GV1
= cast
<sandboxir::GlobalVariable
>(Ld1
->getPointerOperand());
1697 // Check setInitializer().
1698 auto *OrigInitializer
= GV0
->getInitializer();
1699 auto *NewInitializer
= GV1
->getInitializer();
1700 EXPECT_NE(NewInitializer
, OrigInitializer
);
1702 GV0
->setInitializer(NewInitializer
);
1703 EXPECT_EQ(GV0
->getInitializer(), NewInitializer
);
1705 EXPECT_EQ(GV0
->getInitializer(), OrigInitializer
);
1706 // Check setConstant().
1707 bool OrigIsConstant
= GV0
->isConstant();
1708 bool NewIsConstant
= !OrigIsConstant
;
1710 GV0
->setConstant(NewIsConstant
);
1711 EXPECT_EQ(GV0
->isConstant(), NewIsConstant
);
1713 EXPECT_EQ(GV0
->isConstant(), OrigIsConstant
);
1714 // Check setExternallyInitialized().
1715 bool OrigIsExtInit
= GV0
->isExternallyInitialized();
1716 bool NewIsExtInit
= !OrigIsExtInit
;
1718 GV0
->setExternallyInitialized(NewIsExtInit
);
1719 EXPECT_EQ(GV0
->isExternallyInitialized(), NewIsExtInit
);
1721 EXPECT_EQ(GV0
->isExternallyInitialized(), OrigIsExtInit
);
1724 TEST_F(TrackerTest
, GlobalAliasSetters
) {
1726 @alias = dso_local alias void(), ptr @foo
1727 declare void @bar();
1728 define void @foo() {
1734 Function
&LLVMF
= *M
->getFunction("foo");
1735 sandboxir::Context
Ctx(C
);
1737 auto &F
= *Ctx
.createFunction(&LLVMF
);
1738 auto *BB
= &*F
.begin();
1739 auto It
= BB
->begin();
1740 auto *Call0
= cast
<sandboxir::CallInst
>(&*It
++);
1741 auto *Call1
= cast
<sandboxir::CallInst
>(&*It
++);
1742 auto *Callee1
= cast
<sandboxir::Constant
>(Call1
->getCalledOperand());
1743 auto *Alias
= cast
<sandboxir::GlobalAlias
>(Call0
->getCalledOperand());
1744 // Check setAliasee().
1745 auto *OrigAliasee
= Alias
->getAliasee();
1746 auto *NewAliasee
= Callee1
;
1747 EXPECT_NE(NewAliasee
, OrigAliasee
);
1749 Alias
->setAliasee(NewAliasee
);
1750 EXPECT_EQ(Alias
->getAliasee(), NewAliasee
);
1752 EXPECT_EQ(Alias
->getAliasee(), OrigAliasee
);
1755 TEST_F(TrackerTest
, SetVolatile
) {
1757 define void @foo(ptr %arg0, i8 %val) {
1758 %ld = load i8, ptr %arg0, align 64
1759 store i8 %val, ptr %arg0, align 64
1763 Function
&LLVMF
= *M
->getFunction("foo");
1764 sandboxir::Context
Ctx(C
);
1766 auto *F
= Ctx
.createFunction(&LLVMF
);
1767 auto *BB
= &*F
->begin();
1768 auto It
= BB
->begin();
1769 auto *Load
= cast
<sandboxir::LoadInst
>(&*It
++);
1770 auto *Store
= cast
<sandboxir::StoreInst
>(&*It
++);
1772 EXPECT_FALSE(Load
->isVolatile());
1774 Load
->setVolatile(true);
1775 EXPECT_TRUE(Load
->isVolatile());
1777 EXPECT_FALSE(Load
->isVolatile());
1779 EXPECT_FALSE(Store
->isVolatile());
1781 Store
->setVolatile(true);
1782 EXPECT_TRUE(Store
->isVolatile());
1784 EXPECT_FALSE(Store
->isVolatile());
1787 TEST_F(TrackerTest
, Flags
) {
1789 define void @foo(i32 %arg, float %farg) {
1790 %add = add i32 %arg, %arg
1791 %fadd = fadd float %farg, %farg
1792 %udiv = udiv i32 %arg, %arg
1796 Function
&LLVMF
= *M
->getFunction("foo");
1797 sandboxir::Context
Ctx(C
);
1798 auto &F
= *Ctx
.createFunction(&LLVMF
);
1799 auto *BB
= &*F
.begin();
1800 auto It
= BB
->begin();
1802 auto *FAdd
= &*It
++;
1803 auto *UDiv
= &*It
++;
1805 #define CHECK_FLAG(I, GETTER, SETTER) \
1808 bool OrigFlag = I->GETTER(); \
1809 bool NewFlag = !OrigFlag; \
1810 I->SETTER(NewFlag); \
1811 EXPECT_EQ(I->GETTER(), NewFlag); \
1813 EXPECT_EQ(I->GETTER(), OrigFlag); \
1816 CHECK_FLAG(Add
, hasNoUnsignedWrap
, setHasNoUnsignedWrap
);
1817 CHECK_FLAG(Add
, hasNoSignedWrap
, setHasNoSignedWrap
);
1818 CHECK_FLAG(FAdd
, isFast
, setFast
);
1819 CHECK_FLAG(FAdd
, hasAllowReassoc
, setHasAllowReassoc
);
1820 CHECK_FLAG(UDiv
, isExact
, setIsExact
);
1821 CHECK_FLAG(FAdd
, hasNoNaNs
, setHasNoNaNs
);
1822 CHECK_FLAG(FAdd
, hasNoInfs
, setHasNoInfs
);
1823 CHECK_FLAG(FAdd
, hasNoSignedZeros
, setHasNoSignedZeros
);
1824 CHECK_FLAG(FAdd
, hasAllowReciprocal
, setHasAllowReciprocal
);
1825 CHECK_FLAG(FAdd
, hasAllowContract
, setHasAllowContract
);
1826 CHECK_FLAG(FAdd
, hasApproxFunc
, setHasApproxFunc
);
1828 // Check setFastMathFlags().
1829 FastMathFlags OrigFMF
= FAdd
->getFastMathFlags();
1830 FastMathFlags NewFMF
;
1831 NewFMF
.setAllowReassoc(true);
1832 EXPECT_TRUE(NewFMF
!= OrigFMF
);
1835 FAdd
->setFastMathFlags(NewFMF
);
1836 EXPECT_FALSE(FAdd
->getFastMathFlags() != NewFMF
);
1838 EXPECT_FALSE(FAdd
->getFastMathFlags() != OrigFMF
);
1840 // Check copyFastMathFlags().
1842 FAdd
->copyFastMathFlags(NewFMF
);
1843 EXPECT_FALSE(FAdd
->getFastMathFlags() != NewFMF
);
1845 EXPECT_FALSE(FAdd
->getFastMathFlags() != OrigFMF
);
1848 // IRSnapshotChecker is only defined in debug mode.
1851 TEST_F(TrackerTest
, IRSnapshotCheckerNoChanges
) {
1853 define i32 @foo(i32 %arg) {
1854 %add0 = add i32 %arg, %arg
1858 Function
&LLVMF
= *M
->getFunction("foo");
1859 sandboxir::Context
Ctx(C
);
1861 [[maybe_unused
]] auto *F
= Ctx
.createFunction(&LLVMF
);
1862 sandboxir::IRSnapshotChecker
Checker(Ctx
);
1864 Checker
.expectNoDiff();
1867 TEST_F(TrackerTest
, IRSnapshotCheckerDiesWithUnexpectedChanges
) {
1869 define i32 @foo(i32 %arg) {
1870 %add0 = add i32 %arg, %arg
1871 %add1 = add i32 %add0, %arg
1875 Function
&LLVMF
= *M
->getFunction("foo");
1876 sandboxir::Context
Ctx(C
);
1878 auto *F
= Ctx
.createFunction(&LLVMF
);
1879 auto *BB
= &*F
->begin();
1880 auto It
= BB
->begin();
1881 sandboxir::Instruction
*Add0
= &*It
++;
1882 sandboxir::Instruction
*Add1
= &*It
++;
1883 sandboxir::IRSnapshotChecker
Checker(Ctx
);
1885 Add1
->setOperand(1, Add0
);
1886 EXPECT_DEATH(Checker
.expectNoDiff(), "Found IR difference");
1889 TEST_F(TrackerTest
, IRSnapshotCheckerSaveMultipleTimes
) {
1891 define i32 @foo(i32 %arg) {
1892 %add0 = add i32 %arg, %arg
1893 %add1 = add i32 %add0, %arg
1897 Function
&LLVMF
= *M
->getFunction("foo");
1898 sandboxir::Context
Ctx(C
);
1900 auto *F
= Ctx
.createFunction(&LLVMF
);
1901 auto *BB
= &*F
->begin();
1902 auto It
= BB
->begin();
1903 sandboxir::Instruction
*Add0
= &*It
++;
1904 sandboxir::Instruction
*Add1
= &*It
++;
1905 sandboxir::IRSnapshotChecker
Checker(Ctx
);
1907 Add1
->setOperand(1, Add0
);
1908 // Now IR differs from the last snapshot. Let's take a new snapshot.
1910 // The new snapshot should have replaced the old one, so this should succeed.
1911 Checker
.expectNoDiff();