blob: e4567363d39ac7d5c079be85655b5cf37539f587 [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
38/// unittests, we go for "x86_64" which should be available in most builds.
39std::unique_ptr<TargetMachine> createTargetMachine() {
40 Triple TargetTriple("x86_64--");
41 std::string Error;
42 const Target *T = TargetRegistry::lookupTarget("", TargetTriple, Error);
43 if (!T)
44 return nullptr;
45
46 TargetOptions Options;
47 return std::unique_ptr<TargetMachine>(
Rafael Espindola8c34dd82016-05-18 22:04:49 +000048 T->createTargetMachine("x86_64", "", "", Options, None,
Matthias Braun3199c4e2016-05-02 23:05:48 +000049 CodeModel::Default, CodeGenOpt::Aggressive));
50}
51
52std::unique_ptr<Module> parseMIR(LLVMContext &Context,
53 legacy::PassManagerBase &PM, std::unique_ptr<MIRParser> &MIR,
54 const TargetMachine &TM, StringRef MIRCode, const char *FuncName) {
55 SMDiagnostic Diagnostic;
56 std::unique_ptr<MemoryBuffer> MBuffer = MemoryBuffer::getMemBuffer(MIRCode);
57 MIR = createMIRParser(std::move(MBuffer), Context);
58 if (!MIR)
59 return nullptr;
60
61 std::unique_ptr<Module> M = MIR->parseLLVMModule();
62 if (!M)
63 return nullptr;
64
65 M->setDataLayout(TM.createDataLayout());
66
67 Function *F = M->getFunction(FuncName);
68 if (!F)
69 return nullptr;
70
Matthias Braun47cf9182016-05-10 01:32:40 +000071 const LLVMTargetMachine &LLVMTM = static_cast<const LLVMTargetMachine&>(TM);
72 LLVMTM.addMachineModuleInfo(PM);
73 LLVMTM.addMachineFunctionAnalysis(PM, MIR.get());
Matthias Braun3199c4e2016-05-02 23:05:48 +000074
75 return M;
76}
77
78typedef std::function<void(MachineFunction&,LiveIntervals&)> LiveIntervalTest;
79
80struct TestPass : public MachineFunctionPass {
81 static char ID;
82 TestPass() : MachineFunctionPass(ID) {
83 // We should never call this but always use PM.add(new TestPass(...))
84 abort();
85 }
86 TestPass(LiveIntervalTest T) : MachineFunctionPass(ID), T(T) {
87 initializeTestPassPass(*PassRegistry::getPassRegistry());
88 }
89
90 bool runOnMachineFunction(MachineFunction &MF) override {
91 LiveIntervals &LIS = getAnalysis<LiveIntervals>();
92 T(MF, LIS);
93 EXPECT_TRUE(MF.verify(this));
94 return true;
95 }
96
97 void getAnalysisUsage(AnalysisUsage &AU) const override {
98 AU.setPreservesAll();
99 AU.addRequired<LiveIntervals>();
100 AU.addPreserved<LiveIntervals>();
101 MachineFunctionPass::getAnalysisUsage(AU);
102 }
103private:
104 LiveIntervalTest T;
105};
106
107/**
108 * Move instruction number \p From in front of instruction number \p To and
109 * update affected liveness intervals with LiveIntervalAnalysis::handleMove().
110 */
111static void testHandleMove(MachineFunction &MF, LiveIntervals &LIS,
Matthias Braunfc4c8a12016-05-24 21:54:01 +0000112 unsigned From, unsigned To, unsigned BlockNum = 0) {
113 MachineBasicBlock &MBB = *MF.getBlockNumbered(BlockNum);
Matthias Braun3199c4e2016-05-02 23:05:48 +0000114
115 unsigned I = 0;
116 MachineInstr *FromInstr = nullptr;
117 MachineInstr *ToInstr = nullptr;
118 for (MachineInstr &MI : MBB) {
119 if (I == From)
120 FromInstr = &MI;
121 if (I == To)
122 ToInstr = &MI;
123 ++I;
124 }
125 assert(FromInstr != nullptr && ToInstr != nullptr);
126
127 MBB.splice(ToInstr->getIterator(), &MBB, FromInstr->getIterator());
128 LIS.handleMove(*FromInstr, true);
129}
130
131static void liveIntervalTest(StringRef MIRFunc, LiveIntervalTest T) {
132 LLVMContext Context;
133 std::unique_ptr<TargetMachine> TM = createTargetMachine();
134 // This test is designed for the X86 backend; stop if it is not available.
135 if (!TM)
136 return;
137
138 legacy::PassManager PM;
139
140 SmallString<160> S;
141 StringRef MIRString = (Twine(
142"---\n"
143"...\n"
144"name: func\n"
145"registers:\n"
146" - { id: 0, class: gr64 }\n"
147"body: |\n"
148" bb.0:\n"
149 ) + Twine(MIRFunc) + Twine("...\n")).toNullTerminatedStringRef(S);
150 std::unique_ptr<MIRParser> MIR;
151 std::unique_ptr<Module> M = parseMIR(Context, PM, MIR, *TM, MIRString,
152 "func");
153
154 PM.add(new TestPass(T));
155
156 PM.run(*M);
157}
158
159} // End of anonymous namespace.
160
161char TestPass::ID = 0;
162INITIALIZE_PASS(TestPass, "testpass", "testpass", false, false)
163
164TEST(LiveIntervalTest, MoveUpDef) {
165 // Value defined.
166 liveIntervalTest(
167" NOOP\n"
168" NOOP\n"
169" early-clobber %0 = IMPLICIT_DEF\n"
170" RETQ %0\n",
171 [](MachineFunction &MF, LiveIntervals &LIS) {
172 testHandleMove(MF, LIS, 2, 1);
173 });
174}
175
176TEST(LiveIntervalTest, MoveUpRedef) {
177 liveIntervalTest(
178" %0 = IMPLICIT_DEF\n"
179" NOOP\n"
180" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
181" RETQ %0\n",
182 [](MachineFunction &MF, LiveIntervals &LIS) {
183 testHandleMove(MF, LIS, 2, 1);
184 });
185}
186
187TEST(LiveIntervalTest, MoveUpEarlyDef) {
188 liveIntervalTest(
189" NOOP\n"
190" NOOP\n"
191" early-clobber %0 = IMPLICIT_DEF\n"
192" RETQ %0\n",
193 [](MachineFunction &MF, LiveIntervals &LIS) {
194 testHandleMove(MF, LIS, 2, 1);
195 });
196}
197
198TEST(LiveIntervalTest, MoveUpEarlyRedef) {
199 liveIntervalTest(
200" %0 = IMPLICIT_DEF\n"
201" NOOP\n"
202" early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
203" RETQ %0\n",
204 [](MachineFunction &MF, LiveIntervals &LIS) {
205 testHandleMove(MF, LIS, 2, 1);
206 });
207}
208
209TEST(LiveIntervalTest, MoveUpKill) {
210 liveIntervalTest(
211" %0 = IMPLICIT_DEF\n"
212" NOOP\n"
213" NOOP implicit %0\n",
214 [](MachineFunction &MF, LiveIntervals &LIS) {
215 testHandleMove(MF, LIS, 2, 1);
216 });
217}
218
219TEST(LiveIntervalTest, MoveUpKillFollowing) {
220 liveIntervalTest(
221" %0 = IMPLICIT_DEF\n"
222" NOOP\n"
223" NOOP implicit %0\n"
224" RETQ %0\n",
225 [](MachineFunction &MF, LiveIntervals &LIS) {
226 testHandleMove(MF, LIS, 2, 1);
227 });
228}
229
230// TODO: Construct a situation where we have intervals following a hole
231// while still having connected components.
232
233TEST(LiveIntervalTest, MoveDownDef) {
234 // Value defined.
235 liveIntervalTest(
236" NOOP\n"
237" early-clobber %0 = IMPLICIT_DEF\n"
238" NOOP\n"
239" RETQ %0\n",
240 [](MachineFunction &MF, LiveIntervals &LIS) {
241 testHandleMove(MF, LIS, 1, 2);
242 });
243}
244
245TEST(LiveIntervalTest, MoveDownRedef) {
246 liveIntervalTest(
247" %0 = IMPLICIT_DEF\n"
248" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
249" NOOP\n"
250" RETQ %0\n",
251 [](MachineFunction &MF, LiveIntervals &LIS) {
252 testHandleMove(MF, LIS, 1, 2);
253 });
254}
255
256TEST(LiveIntervalTest, MoveDownEarlyDef) {
257 liveIntervalTest(
258" NOOP\n"
259" early-clobber %0 = IMPLICIT_DEF\n"
260" NOOP\n"
261" RETQ %0\n",
262 [](MachineFunction &MF, LiveIntervals &LIS) {
263 testHandleMove(MF, LIS, 1, 2);
264 });
265}
266
267TEST(LiveIntervalTest, MoveDownEarlyRedef) {
268 liveIntervalTest(
269" %0 = IMPLICIT_DEF\n"
270" early-clobber %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
271" NOOP\n"
272" RETQ %0\n",
273 [](MachineFunction &MF, LiveIntervals &LIS) {
274 testHandleMove(MF, LIS, 1, 2);
275 });
276}
277
278TEST(LiveIntervalTest, MoveDownKill) {
279 liveIntervalTest(
280" %0 = IMPLICIT_DEF\n"
281" NOOP implicit %0\n"
282" NOOP\n",
283 [](MachineFunction &MF, LiveIntervals &LIS) {
284 testHandleMove(MF, LIS, 1, 2);
285 });
286}
287
288TEST(LiveIntervalTest, MoveDownKillFollowing) {
289 liveIntervalTest(
290" %0 = IMPLICIT_DEF\n"
291" NOOP\n"
292" NOOP implicit %0\n"
293" RETQ %0\n",
294 [](MachineFunction &MF, LiveIntervals &LIS) {
295 testHandleMove(MF, LIS, 1, 2);
296 });
297}
298
Matthias Braun71474e82016-05-06 21:47:41 +0000299TEST(LiveIntervalTest, MoveUndefUse) {
300 liveIntervalTest(
301" %0 = IMPLICIT_DEF\n"
302" NOOP implicit undef %0\n"
303" NOOP implicit %0\n"
304" NOOP\n",
305 [](MachineFunction &MF, LiveIntervals &LIS) {
306 testHandleMove(MF, LIS, 1, 3);
307 });
308}
309
Matthias Braunfc4c8a12016-05-24 21:54:01 +0000310TEST(LiveIntervalTest, MoveUpValNos) {
311 // handleMoveUp() had a bug where it would reuse the value number of the
312 // destination segment, even though we have no guarntee that this valno wasn't
313 // used in other segments.
314 liveIntervalTest(
315" successors: %bb.1, %bb.2\n"
316" %0 = IMPLICIT_DEF\n"
317" JG_1 %bb.2, implicit %eflags\n"
318" JMP_1 %bb.1\n"
319" bb.2:\n"
320" NOOP implicit %0\n"
321" bb.1:\n"
322" successors: %bb.2\n"
323" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
324" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
325" %0 = IMPLICIT_DEF implicit %0(tied-def 0)\n"
326" JMP_1 %bb.2\n",
327 [](MachineFunction &MF, LiveIntervals &LIS) {
328 testHandleMove(MF, LIS, 2, 0, 2);
329 });
330}
331
Matthias Braun3199c4e2016-05-02 23:05:48 +0000332int main(int argc, char **argv) {
333 ::testing::InitGoogleTest(&argc, argv);
334 initLLVM();
335 return RUN_ALL_TESTS();
NAKAMURA Takumic1857d12016-02-18 07:37:17 +0000336}