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/SandboxIR.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
20 struct TrackerTest
: public testing::Test
{
22 std::unique_ptr
<Module
> M
;
24 void parseIR(LLVMContext
&C
, const char *IR
) {
26 M
= parseAssemblyString(IR
, Err
, C
);
28 Err
.print("TrackerTest", errs());
30 BasicBlock
*getBasicBlockByName(Function
&F
, StringRef Name
) {
31 for (BasicBlock
&BB
: F
)
32 if (BB
.getName() == Name
)
34 llvm_unreachable("Expected to find basic block!");
38 TEST_F(TrackerTest
, SetOperand
) {
40 define void @foo(ptr %ptr) {
41 %gep0 = getelementptr float, ptr %ptr, i32 0
42 %gep1 = getelementptr float, ptr %ptr, i32 1
43 %ld0 = load float, ptr %gep0
44 store float undef, ptr %gep0
48 Function
&LLVMF
= *M
->getFunction("foo");
49 sandboxir::Context
Ctx(C
);
50 auto *F
= Ctx
.createFunction(&LLVMF
);
51 auto *BB
= &*F
->begin();
52 auto &Tracker
= Ctx
.getTracker();
54 auto It
= BB
->begin();
59 St
->setOperand(0, Ld
);
60 St
->setOperand(1, Gep1
);
61 Ld
->setOperand(0, Gep1
);
62 EXPECT_EQ(St
->getOperand(0), Ld
);
63 EXPECT_EQ(St
->getOperand(1), Gep1
);
64 EXPECT_EQ(Ld
->getOperand(0), Gep1
);
66 Ctx
.getTracker().revert();
67 EXPECT_NE(St
->getOperand(0), Ld
);
68 EXPECT_EQ(St
->getOperand(1), Gep0
);
69 EXPECT_EQ(Ld
->getOperand(0), Gep0
);
72 TEST_F(TrackerTest
, RUWIf_RAUW_RUOW
) {
74 define void @foo(ptr %ptr) {
75 %ld0 = load float, ptr %ptr
76 %ld1 = load float, ptr %ptr
77 store float %ld0, ptr %ptr
78 store float %ld0, ptr %ptr
82 llvm::Function
&LLVMF
= *M
->getFunction("foo");
83 sandboxir::Context
Ctx(C
);
84 llvm::BasicBlock
*LLVMBB
= &*LLVMF
.begin();
85 Ctx
.createFunction(&LLVMF
);
86 auto *BB
= cast
<sandboxir::BasicBlock
>(Ctx
.getValue(LLVMBB
));
87 auto It
= BB
->begin();
88 sandboxir::Instruction
*Ld0
= &*It
++;
89 sandboxir::Instruction
*Ld1
= &*It
++;
90 sandboxir::Instruction
*St0
= &*It
++;
91 sandboxir::Instruction
*St1
= &*It
++;
93 // Check RUWIf when the lambda returns false.
94 Ld0
->replaceUsesWithIf(Ld1
, [](const sandboxir::Use
&Use
) { return false; });
95 EXPECT_EQ(St0
->getOperand(0), Ld0
);
96 EXPECT_EQ(St1
->getOperand(0), Ld0
);
98 // Check RUWIf when the lambda returns true.
99 Ld0
->replaceUsesWithIf(Ld1
, [](const sandboxir::Use
&Use
) { return true; });
100 EXPECT_EQ(St0
->getOperand(0), Ld1
);
101 EXPECT_EQ(St1
->getOperand(0), Ld1
);
103 EXPECT_EQ(St0
->getOperand(0), Ld0
);
104 EXPECT_EQ(St1
->getOperand(0), Ld0
);
106 // Check RUWIf user == St0.
108 Ld0
->replaceUsesWithIf(
109 Ld1
, [St0
](const sandboxir::Use
&Use
) { return Use
.getUser() == St0
; });
110 EXPECT_EQ(St0
->getOperand(0), Ld1
);
111 EXPECT_EQ(St1
->getOperand(0), Ld0
);
113 EXPECT_EQ(St0
->getOperand(0), Ld0
);
114 EXPECT_EQ(St1
->getOperand(0), Ld0
);
116 // Check RUWIf user == St1.
118 Ld0
->replaceUsesWithIf(
119 Ld1
, [St1
](const sandboxir::Use
&Use
) { return Use
.getUser() == St1
; });
120 EXPECT_EQ(St0
->getOperand(0), Ld0
);
121 EXPECT_EQ(St1
->getOperand(0), Ld1
);
123 EXPECT_EQ(St0
->getOperand(0), Ld0
);
124 EXPECT_EQ(St1
->getOperand(0), Ld0
);
128 Ld1
->replaceAllUsesWith(Ld0
);
129 EXPECT_EQ(St0
->getOperand(0), Ld0
);
130 EXPECT_EQ(St1
->getOperand(0), Ld0
);
132 EXPECT_EQ(St0
->getOperand(0), Ld0
);
133 EXPECT_EQ(St1
->getOperand(0), Ld0
);
137 St0
->replaceUsesOfWith(Ld0
, Ld1
);
138 EXPECT_EQ(St0
->getOperand(0), Ld1
);
140 EXPECT_EQ(St0
->getOperand(0), Ld0
);
144 St0
->replaceUsesOfWith(Ld0
, Ld1
);
145 EXPECT_EQ(St0
->getOperand(0), Ld1
);
147 EXPECT_EQ(St0
->getOperand(0), Ld1
);
150 // TODO: Test multi-instruction patterns.
151 TEST_F(TrackerTest
, EraseFromParent
) {
153 define void @foo(i32 %v1) {
154 %add0 = add i32 %v1, %v1
155 %add1 = add i32 %add0, %v1
159 Function
&LLVMF
= *M
->getFunction("foo");
160 sandboxir::Context
Ctx(C
);
162 auto *F
= Ctx
.createFunction(&LLVMF
);
163 auto *BB
= &*F
->begin();
164 auto It
= BB
->begin();
165 sandboxir::Instruction
*Add0
= &*It
++;
166 sandboxir::Instruction
*Add1
= &*It
++;
167 sandboxir::Instruction
*Ret
= &*It
++;
171 Add1
->eraseFromParent();
173 EXPECT_EQ(&*It
++, Add0
);
174 EXPECT_EQ(&*It
++, Ret
);
175 EXPECT_EQ(It
, BB
->end());
176 EXPECT_EQ(Add0
->getNumUses(), 0u);
181 EXPECT_EQ(&*It
++, Add0
);
182 EXPECT_EQ(&*It
++, Add1
);
183 EXPECT_EQ(&*It
++, Ret
);
184 EXPECT_EQ(It
, BB
->end());
185 EXPECT_EQ(Add1
->getOperand(0), Add0
);
187 // Same for the last instruction in the block.
189 Ret
->eraseFromParent();
191 EXPECT_EQ(&*It
++, Add0
);
192 EXPECT_EQ(&*It
++, Add1
);
193 EXPECT_EQ(It
, BB
->end());
196 EXPECT_EQ(&*It
++, Add0
);
197 EXPECT_EQ(&*It
++, Add1
);
198 EXPECT_EQ(&*It
++, Ret
);
199 EXPECT_EQ(It
, BB
->end());
202 // TODO: Test multi-instruction patterns.
203 TEST_F(TrackerTest
, RemoveFromParent
) {
205 define i32 @foo(i32 %arg) {
206 %add0 = add i32 %arg, %arg
207 %add1 = add i32 %add0, %arg
211 Function
&LLVMF
= *M
->getFunction("foo");
212 sandboxir::Context
Ctx(C
);
214 auto *F
= Ctx
.createFunction(&LLVMF
);
215 auto *Arg
= F
->getArg(0);
216 auto *BB
= &*F
->begin();
217 auto It
= BB
->begin();
218 sandboxir::Instruction
*Add0
= &*It
++;
219 sandboxir::Instruction
*Add1
= &*It
++;
220 sandboxir::Instruction
*Ret
= &*It
++;
223 // Check removeFromParent().
224 Add1
->removeFromParent();
226 EXPECT_EQ(&*It
++, Add0
);
227 EXPECT_EQ(&*It
++, Ret
);
228 EXPECT_EQ(It
, BB
->end());
229 // Removed instruction still be connected to operands and users.
230 EXPECT_EQ(Add1
->getOperand(0), Add0
);
231 EXPECT_EQ(Add1
->getOperand(1), Arg
);
232 EXPECT_EQ(Add0
->getNumUses(), 1u);
237 EXPECT_EQ(&*It
++, Add0
);
238 EXPECT_EQ(&*It
++, Add1
);
239 EXPECT_EQ(&*It
++, Ret
);
240 EXPECT_EQ(It
, BB
->end());
241 EXPECT_EQ(Add1
->getOperand(0), Add0
);
243 // Same for the last instruction in the block.
245 Ret
->removeFromParent();
247 EXPECT_EQ(&*It
++, Add0
);
248 EXPECT_EQ(&*It
++, Add1
);
249 EXPECT_EQ(It
, BB
->end());
250 EXPECT_EQ(Ret
->getOperand(0), Add1
);
253 EXPECT_EQ(&*It
++, Add0
);
254 EXPECT_EQ(&*It
++, Add1
);
255 EXPECT_EQ(&*It
++, Ret
);
256 EXPECT_EQ(It
, BB
->end());
259 // TODO: Test multi-instruction patterns.
260 TEST_F(TrackerTest
, MoveInstr
) {
262 define i32 @foo(i32 %arg) {
263 %add0 = add i32 %arg, %arg
264 %add1 = add i32 %add0, %arg
268 Function
&LLVMF
= *M
->getFunction("foo");
269 sandboxir::Context
Ctx(C
);
271 auto *F
= Ctx
.createFunction(&LLVMF
);
272 auto *BB
= &*F
->begin();
273 auto It
= BB
->begin();
274 sandboxir::Instruction
*Add0
= &*It
++;
275 sandboxir::Instruction
*Add1
= &*It
++;
276 sandboxir::Instruction
*Ret
= &*It
++;
278 // Check moveBefore(Instruction *) with tracking enabled.
280 Add1
->moveBefore(Add0
);
282 EXPECT_EQ(&*It
++, Add1
);
283 EXPECT_EQ(&*It
++, Add0
);
284 EXPECT_EQ(&*It
++, Ret
);
285 EXPECT_EQ(It
, BB
->end());
289 EXPECT_EQ(&*It
++, Add0
);
290 EXPECT_EQ(&*It
++, Add1
);
291 EXPECT_EQ(&*It
++, Ret
);
292 EXPECT_EQ(It
, BB
->end());
294 // Same for the last instruction in the block.
296 Ret
->moveBefore(Add0
);
298 EXPECT_EQ(&*It
++, Ret
);
299 EXPECT_EQ(&*It
++, Add0
);
300 EXPECT_EQ(&*It
++, Add1
);
301 EXPECT_EQ(It
, BB
->end());
304 EXPECT_EQ(&*It
++, Add0
);
305 EXPECT_EQ(&*It
++, Add1
);
306 EXPECT_EQ(&*It
++, Ret
);
307 EXPECT_EQ(It
, BB
->end());
309 // Check moveBefore(BasicBlock &, BasicBlock::iterator) with tracking enabled.
311 Add1
->moveBefore(*BB
, Add0
->getIterator());
313 EXPECT_EQ(&*It
++, Add1
);
314 EXPECT_EQ(&*It
++, Add0
);
315 EXPECT_EQ(&*It
++, Ret
);
316 EXPECT_EQ(It
, BB
->end());
320 EXPECT_EQ(&*It
++, Add0
);
321 EXPECT_EQ(&*It
++, Add1
);
322 EXPECT_EQ(&*It
++, Ret
);
323 EXPECT_EQ(It
, BB
->end());
325 // Same for the last instruction in the block.
327 Ret
->moveBefore(*BB
, Add0
->getIterator());
329 EXPECT_EQ(&*It
++, Ret
);
330 EXPECT_EQ(&*It
++, Add0
);
331 EXPECT_EQ(&*It
++, Add1
);
332 EXPECT_EQ(It
, BB
->end());
336 EXPECT_EQ(&*It
++, Add0
);
337 EXPECT_EQ(&*It
++, Add1
);
338 EXPECT_EQ(&*It
++, Ret
);
339 EXPECT_EQ(It
, BB
->end());
341 // Check moveAfter(Instruction *) with tracking enabled.
343 Add0
->moveAfter(Add1
);
345 EXPECT_EQ(&*It
++, Add1
);
346 EXPECT_EQ(&*It
++, Add0
);
347 EXPECT_EQ(&*It
++, Ret
);
348 EXPECT_EQ(It
, BB
->end());
352 EXPECT_EQ(&*It
++, Add0
);
353 EXPECT_EQ(&*It
++, Add1
);
354 EXPECT_EQ(&*It
++, Ret
);
355 EXPECT_EQ(It
, BB
->end());
357 // Same for the last instruction in the block.
359 Ret
->moveAfter(Add0
);
361 EXPECT_EQ(&*It
++, Add0
);
362 EXPECT_EQ(&*It
++, Ret
);
363 EXPECT_EQ(&*It
++, Add1
);
364 EXPECT_EQ(It
, BB
->end());
368 EXPECT_EQ(&*It
++, Add0
);
369 EXPECT_EQ(&*It
++, Add1
);
370 EXPECT_EQ(&*It
++, Ret
);
371 EXPECT_EQ(It
, BB
->end());