1 //===- MachineDomTreeUpdaterTest.cpp - MachineDomTreeUpdater unit tests ---===//
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/CodeGen/MachineDomTreeUpdater.h"
10 #include "llvm/Analysis/CGSCCPassManager.h"
11 #include "llvm/Analysis/LoopAnalysisManager.h"
12 #include "llvm/CodeGen/MIRParser/MIRParser.h"
13 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/MachinePassManager.h"
16 #include "llvm/CodeGen/MachinePostDominators.h"
17 #include "llvm/CodeGen/SelectionDAG.h"
18 #include "llvm/CodeGen/TargetLowering.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/MC/TargetRegistry.h"
21 #include "llvm/Passes/PassBuilder.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "llvm/Target/TargetMachine.h"
25 #include "gtest/gtest.h"
29 class MachineDomTreeUpdaterTest
: public testing::Test
{
32 std::unique_ptr
<TargetMachine
> TM
;
33 std::unique_ptr
<Module
> M
;
34 std::unique_ptr
<MachineModuleInfo
> MMI
;
35 std::unique_ptr
<MIRParser
> MIR
;
37 LoopAnalysisManager LAM
;
38 MachineFunctionAnalysisManager MFAM
;
39 FunctionAnalysisManager FAM
;
40 CGSCCAnalysisManager CGAM
;
41 ModuleAnalysisManager MAM
;
43 ModulePassManager MPM
;
44 FunctionPassManager FPM
;
45 MachineFunctionPassManager MFPM
;
47 static void SetUpTestCase() {
48 InitializeAllTargets();
49 InitializeAllTargetMCs();
52 void SetUp() override
{
53 Triple
TargetTriple("x86_64-unknown-linux-gnu");
55 const Target
*T
= TargetRegistry::lookupTarget("", TargetTriple
, Error
);
58 TargetOptions Options
;
59 TM
= std::unique_ptr
<TargetMachine
>(
60 T
->createTargetMachine("X86", "", "", Options
, std::nullopt
));
63 MMI
= std::make_unique
<MachineModuleInfo
>(TM
.get());
65 PassBuilder
PB(TM
.get());
66 PB
.registerModuleAnalyses(MAM
);
67 PB
.registerCGSCCAnalyses(CGAM
);
68 PB
.registerFunctionAnalyses(FAM
);
69 PB
.registerLoopAnalyses(LAM
);
70 PB
.registerMachineFunctionAnalyses(MFAM
);
71 PB
.crossRegisterProxies(LAM
, FAM
, CGAM
, MAM
, &MFAM
);
72 MAM
.registerPass([&] { return MachineModuleAnalysis(*MMI
); });
75 bool parseMIR(StringRef MIRCode
) {
76 SMDiagnostic Diagnostic
;
77 std::unique_ptr
<MemoryBuffer
> MBuffer
= MemoryBuffer::getMemBuffer(MIRCode
);
78 MIR
= createMIRParser(std::move(MBuffer
), Context
);
82 M
= MIR
->parseIRModule();
83 M
->setDataLayout(TM
->createDataLayout());
85 if (MIR
->parseMachineFunctions(*M
, MAM
)) {
94 TEST_F(MachineDomTreeUpdaterTest
, EagerUpdateBasicOperations
) {
95 StringRef MIRString
= R
"(
97 define i64 @f0(i64 %i, ptr %p) {
99 store i64 %i, ptr %p, align 4
100 switch i64 %i, label %bb1 [
116 successors: %bb.2, %bb.4
121 MOV64mr %1, 1, $noreg, 0, $noreg, %0 :: (store (s64) into %ir.p)
122 %2:gr64 = SUB64ri32 %0, 1, implicit-def $eflags
123 JCC_1 %bb.2, 4, implicit $eflags
127 successors: %bb.3, %bb.1
129 %3:gr64 = SUB64ri32 %0, 2, implicit-def $eflags
130 JCC_1 %bb.3, 4, implicit $eflags
134 %6:gr64 = MOV32ri64 1
139 %5:gr64 = MOV32ri64 2
144 %4:gr64 = MOV32ri64 3
151 ASSERT_TRUE(parseMIR(MIRString
));
154 FAM
.getResult
<MachineFunctionAnalysis
>(*M
->getFunction("f0")).getMF();
156 MachineDominatorTree
DT(MF
);
157 MachinePostDominatorTree
PDT(MF
);
158 MachineDomTreeUpdater
DTU(DT
, PDT
,
159 MachineDomTreeUpdater::UpdateStrategy::Eager
);
161 ASSERT_TRUE(DTU
.hasDomTree());
162 ASSERT_TRUE(DTU
.hasPostDomTree());
163 ASSERT_TRUE(DTU
.isEager());
164 ASSERT_FALSE(DTU
.isLazy());
165 ASSERT_TRUE(DTU
.getDomTree().verify());
166 ASSERT_TRUE(DTU
.getPostDomTree().verify());
167 ASSERT_FALSE(DTU
.hasPendingUpdates());
170 [[maybe_unused
]] auto BB0
= B
;
173 [[maybe_unused
]] auto BB3
= ++B
;
175 EXPECT_EQ(BB1
->succ_size(), 2u);
176 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB2
));
177 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB4
));
178 BB1
->removeSuccessor(&*BB4
);
180 EXPECT_EQ(BB1
->succ_size(), 1u);
181 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB2
));
184 TEST_F(MachineDomTreeUpdaterTest
, LazyUpdateBasicOperations
) {
185 StringRef MIRString
= R
"(
187 define i64 @f0(i64 %i, ptr %p) {
189 store i64 %i, ptr %p, align 4
190 switch i64 %i, label %bb1 [
206 successors: %bb.2, %bb.4
211 MOV64mr %1, 1, $noreg, 0, $noreg, %0 :: (store (s64) into %ir.p)
212 %2:gr64 = SUB64ri32 %0, 1, implicit-def $eflags
213 JCC_1 %bb.2, 4, implicit $eflags
217 successors: %bb.3, %bb.1
219 %3:gr64 = SUB64ri32 %0, 2, implicit-def $eflags
220 JCC_1 %bb.3, 4, implicit $eflags
224 %6:gr64 = MOV32ri64 1
229 %5:gr64 = MOV32ri64 2
234 %4:gr64 = MOV32ri64 3
241 ASSERT_TRUE(parseMIR(MIRString
));
244 FAM
.getResult
<MachineFunctionAnalysis
>(*M
->getFunction("f0")).getMF();
246 MachineDominatorTree
DT(MF
);
247 MachinePostDominatorTree
PDT(MF
);
248 MachineDomTreeUpdater
DTU(DT
, PDT
,
249 MachineDomTreeUpdater::UpdateStrategy::Lazy
);
251 ASSERT_TRUE(DTU
.hasDomTree());
252 ASSERT_TRUE(DTU
.hasPostDomTree());
253 ASSERT_FALSE(DTU
.isEager());
254 ASSERT_TRUE(DTU
.isLazy());
255 ASSERT_TRUE(DTU
.getDomTree().verify());
256 ASSERT_TRUE(DTU
.getPostDomTree().verify());
257 ASSERT_FALSE(DTU
.hasPendingUpdates());
260 [[maybe_unused
]] auto BB0
= B
;
263 [[maybe_unused
]] auto BB3
= ++B
;
265 EXPECT_EQ(BB1
->succ_size(), 2u);
266 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB2
));
267 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB4
));
268 BB1
->removeSuccessor(&*BB4
);
270 ASSERT_TRUE(DTU
.hasPendingDeletedBB());
271 EXPECT_EQ(BB1
->succ_size(), 1u);
272 ASSERT_TRUE(DT
.dominates(&*BB1
, &*BB2
));
273 ASSERT_NE(DT
.getNode(&*BB4
), nullptr);