Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / unittests / SandboxIR / TrackerTest.cpp
blob354cd187adb1079a728b29721517e95ad338a0ca
1 //===- TrackerTest.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
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"
18 using namespace llvm;
20 struct TrackerTest : public testing::Test {
21 LLVMContext C;
22 std::unique_ptr<Module> M;
24 void parseIR(LLVMContext &C, const char *IR) {
25 SMDiagnostic Err;
26 M = parseAssemblyString(IR, Err, C);
27 if (!M)
28 Err.print("TrackerTest", errs());
30 BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
31 for (BasicBlock &BB : F)
32 if (BB.getName() == Name)
33 return &BB;
34 llvm_unreachable("Expected to find basic block!");
38 TEST_F(TrackerTest, SetOperand) {
39 parseIR(C, R"IR(
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
45 ret void
47 )IR");
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();
53 Tracker.save();
54 auto It = BB->begin();
55 auto *Gep0 = &*It++;
56 auto *Gep1 = &*It++;
57 auto *Ld = &*It++;
58 auto *St = &*It++;
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) {
73 parseIR(C, R"IR(
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
79 ret void
81 )IR");
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++;
92 Ctx.save();
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);
102 Ctx.revert();
103 EXPECT_EQ(St0->getOperand(0), Ld0);
104 EXPECT_EQ(St1->getOperand(0), Ld0);
106 // Check RUWIf user == St0.
107 Ctx.save();
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);
112 Ctx.revert();
113 EXPECT_EQ(St0->getOperand(0), Ld0);
114 EXPECT_EQ(St1->getOperand(0), Ld0);
116 // Check RUWIf user == St1.
117 Ctx.save();
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);
122 Ctx.revert();
123 EXPECT_EQ(St0->getOperand(0), Ld0);
124 EXPECT_EQ(St1->getOperand(0), Ld0);
126 // Check RAUW.
127 Ctx.save();
128 Ld1->replaceAllUsesWith(Ld0);
129 EXPECT_EQ(St0->getOperand(0), Ld0);
130 EXPECT_EQ(St1->getOperand(0), Ld0);
131 Ctx.revert();
132 EXPECT_EQ(St0->getOperand(0), Ld0);
133 EXPECT_EQ(St1->getOperand(0), Ld0);
135 // Check RUOW.
136 Ctx.save();
137 St0->replaceUsesOfWith(Ld0, Ld1);
138 EXPECT_EQ(St0->getOperand(0), Ld1);
139 Ctx.revert();
140 EXPECT_EQ(St0->getOperand(0), Ld0);
142 // Check accept().
143 Ctx.save();
144 St0->replaceUsesOfWith(Ld0, Ld1);
145 EXPECT_EQ(St0->getOperand(0), Ld1);
146 Ctx.accept();
147 EXPECT_EQ(St0->getOperand(0), Ld1);
150 // TODO: Test multi-instruction patterns.
151 TEST_F(TrackerTest, EraseFromParent) {
152 parseIR(C, R"IR(
153 define void @foo(i32 %v1) {
154 %add0 = add i32 %v1, %v1
155 %add1 = add i32 %add0, %v1
156 ret void
158 )IR");
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++;
169 Ctx.save();
170 // Check erase.
171 Add1->eraseFromParent();
172 It = BB->begin();
173 EXPECT_EQ(&*It++, Add0);
174 EXPECT_EQ(&*It++, Ret);
175 EXPECT_EQ(It, BB->end());
176 EXPECT_EQ(Add0->getNumUses(), 0u);
178 // Check revert().
179 Ctx.revert();
180 It = BB->begin();
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.
188 Ctx.save();
189 Ret->eraseFromParent();
190 It = BB->begin();
191 EXPECT_EQ(&*It++, Add0);
192 EXPECT_EQ(&*It++, Add1);
193 EXPECT_EQ(It, BB->end());
194 Ctx.revert();
195 It = BB->begin();
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) {
204 parseIR(C, R"IR(
205 define i32 @foo(i32 %arg) {
206 %add0 = add i32 %arg, %arg
207 %add1 = add i32 %add0, %arg
208 ret i32 %add1
210 )IR");
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++;
222 Ctx.save();
223 // Check removeFromParent().
224 Add1->removeFromParent();
225 It = BB->begin();
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);
234 // Check revert().
235 Ctx.revert();
236 It = BB->begin();
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.
244 Ctx.save();
245 Ret->removeFromParent();
246 It = BB->begin();
247 EXPECT_EQ(&*It++, Add0);
248 EXPECT_EQ(&*It++, Add1);
249 EXPECT_EQ(It, BB->end());
250 EXPECT_EQ(Ret->getOperand(0), Add1);
251 Ctx.revert();
252 It = BB->begin();
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) {
261 parseIR(C, R"IR(
262 define i32 @foo(i32 %arg) {
263 %add0 = add i32 %arg, %arg
264 %add1 = add i32 %add0, %arg
265 ret i32 %add1
267 )IR");
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.
279 Ctx.save();
280 Add1->moveBefore(Add0);
281 It = BB->begin();
282 EXPECT_EQ(&*It++, Add1);
283 EXPECT_EQ(&*It++, Add0);
284 EXPECT_EQ(&*It++, Ret);
285 EXPECT_EQ(It, BB->end());
286 // Check revert().
287 Ctx.revert();
288 It = BB->begin();
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.
295 Ctx.save();
296 Ret->moveBefore(Add0);
297 It = BB->begin();
298 EXPECT_EQ(&*It++, Ret);
299 EXPECT_EQ(&*It++, Add0);
300 EXPECT_EQ(&*It++, Add1);
301 EXPECT_EQ(It, BB->end());
302 Ctx.revert();
303 It = BB->begin();
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.
310 Ctx.save();
311 Add1->moveBefore(*BB, Add0->getIterator());
312 It = BB->begin();
313 EXPECT_EQ(&*It++, Add1);
314 EXPECT_EQ(&*It++, Add0);
315 EXPECT_EQ(&*It++, Ret);
316 EXPECT_EQ(It, BB->end());
317 // Check revert().
318 Ctx.revert();
319 It = BB->begin();
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.
326 Ctx.save();
327 Ret->moveBefore(*BB, Add0->getIterator());
328 It = BB->begin();
329 EXPECT_EQ(&*It++, Ret);
330 EXPECT_EQ(&*It++, Add0);
331 EXPECT_EQ(&*It++, Add1);
332 EXPECT_EQ(It, BB->end());
333 // Check revert().
334 Ctx.revert();
335 It = BB->begin();
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.
342 Ctx.save();
343 Add0->moveAfter(Add1);
344 It = BB->begin();
345 EXPECT_EQ(&*It++, Add1);
346 EXPECT_EQ(&*It++, Add0);
347 EXPECT_EQ(&*It++, Ret);
348 EXPECT_EQ(It, BB->end());
349 // Check revert().
350 Ctx.revert();
351 It = BB->begin();
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.
358 Ctx.save();
359 Ret->moveAfter(Add0);
360 It = BB->begin();
361 EXPECT_EQ(&*It++, Add0);
362 EXPECT_EQ(&*It++, Ret);
363 EXPECT_EQ(&*It++, Add1);
364 EXPECT_EQ(It, BB->end());
365 // Check revert().
366 Ctx.revert();
367 It = BB->begin();
368 EXPECT_EQ(&*It++, Add0);
369 EXPECT_EQ(&*It++, Add1);
370 EXPECT_EQ(&*It++, Ret);
371 EXPECT_EQ(It, BB->end());