blob: 026fb42d345f75300190f9d4baf2ab8d2280e203 [file] [log] [blame]
NAKAMURA Takumic1857d12016-02-18 07:37:17 +00001#include "gtest/gtest.h"
Matthias Braun3199c4e2016-05-02 23:05:48 +00002#include "llvm/ADT/STLExtras.h"
3#include "llvm/CodeGen/LiveIntervalAnalysis.h"
4#include "llvm/CodeGen/MIRParser/MIRParser.h"
5#include "llvm/CodeGen/MachineFunction.h"
Matthias Braun7938eee2016-05-10 03:03:55 +00006#include "llvm/CodeGen/MachineModuleInfo.h"
Matthias Braun3199c4e2016-05-02 23:05:48 +00007#include "llvm/CodeGen/MachineRegisterInfo.h"
8#include "llvm/CodeGen/Passes.h"
9#include "llvm/Support/MemoryBuffer.h"
10#include "llvm/Support/SourceMgr.h"
11#include "llvm/Support/TargetRegistry.h"
12#include "llvm/Support/TargetSelect.h"
13#include "llvm/Target/TargetMachine.h"
14#include "llvm/Target/TargetOptions.h"
15#include "llvm/Target/TargetRegisterInfo.h"
16#include "llvm/IR/LegacyPassManager.h"
NAKAMURA Takumic1857d12016-02-18 07:37:17 +000017
Matthias Braun3199c4e2016-05-02 23:05:48 +000018using namespace llvm;
19
20namespace llvm {
21 void initializeTestPassPass(PassRegistry &);
22}
23
24namespace {
25
26void initLLVM() {
27 InitializeAllTargets();
28 InitializeAllTargetMCs();
29 InitializeAllAsmPrinters();
30 InitializeAllAsmParsers();
31
32 PassRegistry *Registry = PassRegistry::getPassRegistry();
33 initializeCore(*Registry);
34 initializeCodeGen(*Registry);
35}
36
37/// Create a TargetMachine. As we lack a dedicated always available target for
Matthias Braun3865b1d2016-07-26 03:57:45 +000038/// unittests, we go for "AMDGPU" to be able to test normal and subregister
39/// liveranges.
Matthias Braun3199c4e2016-05-02 23:05:48 +000040std::unique_ptr<TargetMachine> createTargetMachine() {
Matthias Braun3865b1d2016-07-26 03:57:45 +000041 Triple TargetTriple("amdgcn--");
Matthias Braun3199c4e2016-05-02 23:05:48 +000042 std::string Error;
43 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
44 if (!T)
45 return nullptr;
46
47 TargetOptions Options;
48 return std::unique_ptr<TargetMachine>(
Matthias Braun3865b1d2016-07-26 03:57:45 +000049 T->createTargetMachine("AMDGPU", "", "", Options, None,
Matthias Braun3199c4e2016-05-02 23:05:48 +000050 CodeModel::Default, CodeGenOpt::Aggressive));
51}
52
53std::unique_ptr<Module> parseMIR(LLVMContext &Context,
54 legacy::PassManagerBase &PM, std::unique_ptr<MIRParser> &MIR,
55 const TargetMachine &TM, StringRef MIRCode, const char *FuncName) {
56 SMDiagnostic Diagnostic;
57 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
58 MIR = createMIRParser(std::move(MBuffer), Context);
59 if (!MIR)
60 return nullptr;
61
62 std::unique_ptr<Module> M = MIR->parseLLVMModule();
63 if (!M)
64 return nullptr;
65
66 M->setDataLayout(TM.createDataLayout());
67
68 Function *F = M->getFunction(FuncName);
69 if (!F)
70 return nullptr;
71
Matthias Braun733fe362016-08-24 01:52:46 +000072 MachineModuleInfo *MMI = new MachineModuleInfo(&TM);
73 MMI->setMachineFunctionInitializer(MIR.get());
74 PM.add(MMI);
Matthias Braun3199c4e2016-05-02 23:05:48 +000075
76 return M;
77}
78
79typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;
80
81struct TestPass : public MachineFunctionPass {
82 static char ID;
83 TestPass() : MachineFunctionPass(ID) {
84 // We should never call this but always use PM.add(new TestPass(...))
85 abort();
86 }
87 TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) {
88 initializeTestPassPass(*PassRegistry::getPassRegistry());
89 }
90
91 bool runOnMachineFunction(MachineFunction &MF) override {
92 LiveIntervals &LIS = getAnalysis<LiveIntervals>();
93 T(MF, LIS);
94 EXPECT_TRUE(MF.verify(this));
95 return true;
96 }
97
98 void getAnalysisUsage(AnalysisUsage &AU) const override {
99 AU.setPreservesAll();
100 AU.addRequired<LiveIntervals>();
101 AU.addPreserved<LiveIntervals>();
102 MachineFunctionPass::getAnalysisUsage(AU);
103 }
104private:
105 LiveIntervalTest T;
106};
107
Matthias Braun3865b1d2016-07-26 03:57:45 +0000108static MachineInstr &getMI(MachineFunction &MF, unsigned At,
109 unsigned BlockNum) {
110 MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
111
112 unsigned I = 0;
113 for (MachineInstr &MI : MBB) {
114 if (I == At)
115 return MI;
116 ++I;
117 }
118 llvm_unreachable("Instruction not found");
119}
120
Matthias Braun3199c4e2016-05-02 23:05:48 +0000121/**
122 * Move instruction number \p From in front of instruction number \p To and
123 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
124 */
125static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
Matthias Braunfc4c8a12016-05-24 21:54:01 +0000126 unsigned From, unsigned To, unsigned BlockNum = 0) {
Matthias Braun3865b1d2016-07-26 03:57:45 +0000127 MachineInstr &FromInstr = getMI(MF, From, BlockNum);
128 MachineInstr &ToInstr = getMI(MF, To, BlockNum);
Matthias Braun3199c4e2016-05-02 23:05:48 +0000129
Matthias Braun3865b1d2016-07-26 03:57:45 +0000130 MachineBasicBlock &MBB = *FromInstr.getParent();
131 MBB.splice(ToInstr.getIterator(), &MBB, FromInstr.getIterator());
132 LIS.handleMove(FromInstr, true);
Matthias Braun3199c4e2016-05-02 23:05:48 +0000133}
134
135static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
136 LLVMContext Context;
137 std::unique_ptr<TargetMachine> TM = createTargetMachine();
138 // This test is designed for the X86 backend; stop if it is not available.
139 if (!TM)
140 return;
141
142 legacy::PassManager PM;
143
144 SmallString<160> S;
Matthias Braun1cba1402017-02-23 01:09:01 +0000145 StringRef MIRString = (Twine(R"MIR(
146---
147...
148name: func
149registers:
150 - { id: 0, class: sreg_64 }
151body: |
152 bb.0:
153)MIR") + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
Matthias Braun3199c4e2016-05-02 23:05:48 +0000154 std::unique_ptr<MIRParser> MIR;
155 std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString,
156 "func");
157
158 PM.add(new TestPass(T));
159
160 PM.run(*M);
161}
162
163} // End of anonymous namespace.
164
165char TestPass::ID = 0;
166INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)
167
168TEST(LiveIntervalTest, MoveUpDef) {
169 // Value defined.
Matthias Braun1cba1402017-02-23 01:09:01 +0000170 liveIntervalTest(R"MIR(
171 S_NOP 0
172 S_NOP 0
173 early-clobber %0 = IMPLICIT_DEF
174 S_NOP 0, implicit %0
175)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000176 testHandleMove(MF, LIS, 2, 1);
177 });
178}
179
180TEST(LiveIntervalTest, MoveUpRedef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000181 liveIntervalTest(R"MIR(
182 %0 = IMPLICIT_DEF
183 S_NOP 0
184 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
185 S_NOP 0, implicit %0
186)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000187 testHandleMove(MF, LIS, 2, 1);
188 });
189}
190
191TEST(LiveIntervalTest, MoveUpEarlyDef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000192 liveIntervalTest(R"MIR(
193 S_NOP 0
194 S_NOP 0
195 early-clobber %0 = IMPLICIT_DEF
196 S_NOP 0, implicit %0
197)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000198 testHandleMove(MF, LIS, 2, 1);
199 });
200}
201
202TEST(LiveIntervalTest, MoveUpEarlyRedef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000203 liveIntervalTest(R"MIR(
204 %0 = IMPLICIT_DEF
205 S_NOP 0
206 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
207 S_NOP 0, implicit %0
208)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000209 testHandleMove(MF, LIS, 2, 1);
210 });
211}
212
213TEST(LiveIntervalTest, MoveUpKill) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000214 liveIntervalTest(R"MIR(
215 %0 = IMPLICIT_DEF
216 S_NOP 0
217 S_NOP 0, implicit %0
218)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000219 testHandleMove(MF, LIS, 2, 1);
220 });
221}
222
223TEST(LiveIntervalTest, MoveUpKillFollowing) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000224 liveIntervalTest(R"MIR(
225 %0 = IMPLICIT_DEF
226 S_NOP 0
227 S_NOP 0, implicit %0
228 S_NOP 0, implicit %0
229)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000230 testHandleMove(MF, LIS, 2, 1);
231 });
232}
233
234// TODO: Construct a situation where we have intervals following a hole
235// while still having connected components.
236
237TEST(LiveIntervalTest, MoveDownDef) {
238 // Value defined.
Matthias Braun1cba1402017-02-23 01:09:01 +0000239 liveIntervalTest(R"MIR(
240 S_NOP 0
241 early-clobber %0 = IMPLICIT_DEF
242 S_NOP 0
243 S_NOP 0, implicit %0
244)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000245 testHandleMove(MF, LIS, 1, 2);
246 });
247}
248
249TEST(LiveIntervalTest, MoveDownRedef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000250 liveIntervalTest(R"MIR(
251 %0 = IMPLICIT_DEF
252 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
253 S_NOP 0
254 S_NOP 0, implicit %0
255)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000256 testHandleMove(MF, LIS, 1, 2);
257 });
258}
259
260TEST(LiveIntervalTest, MoveDownEarlyDef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000261 liveIntervalTest(R"MIR(
262 S_NOP 0
263 early-clobber %0 = IMPLICIT_DEF
264 S_NOP 0
265 S_NOP 0, implicit %0
266)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000267 testHandleMove(MF, LIS, 1, 2);
268 });
269}
270
271TEST(LiveIntervalTest, MoveDownEarlyRedef) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000272 liveIntervalTest(R"MIR(
273 %0 = IMPLICIT_DEF
274 early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)
275 S_NOP 0
276 S_NOP 0, implicit %0
277)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000278 testHandleMove(MF, LIS, 1, 2);
279 });
280}
281
282TEST(LiveIntervalTest, MoveDownKill) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000283 liveIntervalTest(R"MIR(
284 %0 = IMPLICIT_DEF
285 S_NOP 0, implicit %0
286 S_NOP 0
287)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000288 testHandleMove(MF, LIS, 1, 2);
289 });
290}
291
292TEST(LiveIntervalTest, MoveDownKillFollowing) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000293 liveIntervalTest(R"MIR(
294 %0 = IMPLICIT_DEF
295 S_NOP 0
296 S_NOP 0, implicit %0
297 S_NOP 0, implicit %0
298)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3199c4e2016-05-02 23:05:48 +0000299 testHandleMove(MF, LIS, 1, 2);
300 });
301}
302
Matthias Braun71474e82016-05-06 21:47:41 +0000303TEST(LiveIntervalTest, MoveUndefUse) {
Matthias Braun1cba1402017-02-23 01:09:01 +0000304 liveIntervalTest(R"MIR(
305 %0 = IMPLICIT_DEF
306 S_NOP 0, implicit undef %0
307 S_NOP 0, implicit %0
308 S_NOP 0
309)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun71474e82016-05-06 21:47:41 +0000310 testHandleMove(MF, LIS, 1, 3);
311 });
312}
313
Matthias Braunfc4c8a12016-05-24 21:54:01 +0000314TEST(LiveIntervalTest, MoveUpValNos) {
315 // handleMoveUp() had a bug where it would reuse the value number of the
316 // destination segment, even though we have no guarntee that this valno wasn't
317 // used in other segments.
Matthias Braun1cba1402017-02-23 01:09:01 +0000318 liveIntervalTest(R"MIR(
319 successors: %bb.1, %bb.2
320 %0 = IMPLICIT_DEF
321 S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc
322 S_BRANCH %bb.1
323 bb.2:
324 S_NOP 0, implicit %0
325 bb.1:
326 successors: %bb.2
327 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
328 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
329 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
330 S_BRANCH %bb.2
331)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braunfc4c8a12016-05-24 21:54:01 +0000332 testHandleMove(MF, LIS, 2, 0, 2);
333 });
334}
335
Matthias Braun959a8c92016-06-11 00:31:28 +0000336TEST(LiveIntervalTest, MoveOverUndefUse0) {
337 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
Matthias Braun1cba1402017-02-23 01:09:01 +0000338 liveIntervalTest(R"MIR(
339 %0 = IMPLICIT_DEF
340 S_NOP 0
341 S_NOP 0, implicit undef %0
342 %0 = IMPLICIT_DEF implicit %0(tied-def 0)
343)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun959a8c92016-06-11 00:31:28 +0000344 testHandleMove(MF, LIS, 3, 1);
345 });
346}
347
348TEST(LiveIntervalTest, MoveOverUndefUse1) {
349 // findLastUseBefore() used by handleMoveUp() must ignore undef operands.
Matthias Braun1cba1402017-02-23 01:09:01 +0000350 liveIntervalTest(R"MIR(
351 %sgpr0 = IMPLICIT_DEF
352 S_NOP 0
353 S_NOP 0, implicit undef %sgpr0
354 %sgpr0 = IMPLICIT_DEF implicit %sgpr0(tied-def 0)
355)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun959a8c92016-06-11 00:31:28 +0000356 testHandleMove(MF, LIS, 3, 1);
357 });
358}
359
Matthias Braun3865b1d2016-07-26 03:57:45 +0000360TEST(LiveIntervalTest, SubRegMoveDown) {
361 // Subregister ranges can have holes inside a basic block. Check for a
362 // movement of the form 32->150 in a liverange [16, 32) [100,200).
Matthias Braun1cba1402017-02-23 01:09:01 +0000363 liveIntervalTest(R"MIR(
364 successors: %bb.1, %bb.2
365 %0 = IMPLICIT_DEF
366 S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc
367 S_BRANCH %bb.1
368 bb.2:
369 successors: %bb.1
370 S_NOP 0, implicit %0.sub0
371 S_NOP 0, implicit %0.sub1
372 S_NOP 0
373 undef %0.sub0 = IMPLICIT_DEF
374 %0.sub1 = IMPLICIT_DEF
375 bb.1:
376 S_NOP 0, implicit %0
377)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
Matthias Braun3865b1d2016-07-26 03:57:45 +0000378 // Scheduler behaviour: Clear def,read-undef flag and move.
379 MachineInstr &MI = getMI(MF, 3, /*BlockNum=*/1);
380 MI.getOperand(0).setIsUndef(false);
381 testHandleMove(MF, LIS, 1, 4, /*BlockNum=*/1);
382 });
383}
384
Stanislav Mekhanoshinb546174b2017-03-11 00:14:52 +0000385TEST(LiveIntervalTest, SubRegMoveUp) {
386 // handleMoveUp had a bug not updating valno of segment incoming to bb.2
387 // after swapping subreg definitions.
388 liveIntervalTest(R"MIR(
389 successors: %bb.1, %bb.2
390 undef %0.sub0 = IMPLICIT_DEF
391 %0.sub1 = IMPLICIT_DEF
392 S_CBRANCH_VCCNZ %bb.2, implicit undef %vcc
393 S_BRANCH %bb.1
394 bb.1:
395 S_NOP 0, implicit %0.sub1
396 bb.2:
397 S_NOP 0, implicit %0.sub1
398)MIR", [](MachineFunction &MF, LiveIntervals &LIS) {
399 testHandleMove(MF, LIS, 1, 0);
400 });
401}
402
Matthias Braun3199c4e2016-05-02 23:05:48 +0000403int main(int argc, char **argv) {
404 ::testing::InitGoogleTest(&argc, argv);
405 initLLVM();
406 return RUN_ALL_TESTS();
NAKAMURA Takumic1857d12016-02-18 07:37:17 +0000407}