1 //===----------- llvm/unittest/CodeGen/LexicalScopesTest.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/CodeGen/LexicalScopes.h"
10 #include "llvm/CodeGen/MachineBasicBlock.h"
11 #include "llvm/CodeGen/MachineFunction.h"
12 #include "llvm/CodeGen/MachineInstr.h"
13 #include "llvm/CodeGen/MachineMemOperand.h"
14 #include "llvm/CodeGen/MachineModuleInfo.h"
15 #include "llvm/CodeGen/TargetFrameLowering.h"
16 #include "llvm/CodeGen/TargetInstrInfo.h"
17 #include "llvm/CodeGen/TargetLowering.h"
18 #include "llvm/CodeGen/TargetSubtargetInfo.h"
19 #include "llvm/IR/DIBuilder.h"
20 #include "llvm/IR/DebugInfoMetadata.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/ModuleSlotTracker.h"
23 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCSymbol.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/Support/TargetSelect.h"
27 #include "llvm/Target/TargetMachine.h"
28 #include "llvm/Target/TargetOptions.h"
30 #include "gtest/gtest.h"
35 // Include helper functions to ease the manipulation of MachineFunctions
36 #include "MFCommon.inc"
38 class LexicalScopesTest
: public testing::Test
{
43 std::unique_ptr
<MachineFunction
> MF
;
46 DISubprogram
*OurFunc
;
47 DILexicalBlock
*OurBlock
, *AnotherBlock
;
48 DISubprogram
*ToInlineFunc
;
49 DILexicalBlock
*ToInlineBlock
;
50 // DebugLocs that we'll used to create test environments.
51 DebugLoc OutermostLoc
, InBlockLoc
, NotNestedBlockLoc
, InlinedLoc
;
53 // Test environment blocks -- these form a diamond control flow pattern,
54 // MBB1 being the entry block, blocks two and three being the branches, and
55 // block four joining the branches and being an exit block.
56 MachineBasicBlock
*MBB1
, *MBB2
, *MBB3
, *MBB4
;
58 // Some meaningless instructions -- the first is fully meaningless,
59 // while the second is supposed to impersonate DBG_VALUEs through its
62 MCInstrDesc DbgValueInst
;
64 LexicalScopesTest() : Ctx(), Mod("beehives", Ctx
) {
65 memset(&BeanInst
, 0, sizeof(BeanInst
));
69 memset(&DbgValueInst
, 0, sizeof(DbgValueInst
));
70 DbgValueInst
.Opcode
= TargetOpcode::DBG_VALUE
;
71 DbgValueInst
.Size
= 1;
72 DbgValueInst
.Flags
= 1U << MCID::Meta
;
74 // Boilerplate that creates a MachineFunction and associated blocks.
75 MF
= createMachineFunction(Ctx
, Mod
);
76 llvm::Function
&F
= const_cast<llvm::Function
&>(MF
->getFunction());
77 auto BB1
= BasicBlock::Create(Ctx
, "a", &F
);
78 auto BB2
= BasicBlock::Create(Ctx
, "b", &F
);
79 auto BB3
= BasicBlock::Create(Ctx
, "c", &F
);
80 auto BB4
= BasicBlock::Create(Ctx
, "d", &F
);
81 IRBuilder
<> IRB1(BB1
), IRB2(BB2
), IRB3(BB3
), IRB4(BB4
);
86 MBB1
= MF
->CreateMachineBasicBlock(BB1
);
87 MF
->insert(MF
->end(), MBB1
);
88 MBB2
= MF
->CreateMachineBasicBlock(BB2
);
89 MF
->insert(MF
->end(), MBB2
);
90 MBB3
= MF
->CreateMachineBasicBlock(BB3
);
91 MF
->insert(MF
->end(), MBB3
);
92 MBB4
= MF
->CreateMachineBasicBlock(BB4
);
93 MF
->insert(MF
->end(), MBB4
);
94 MBB1
->addSuccessor(MBB2
);
95 MBB1
->addSuccessor(MBB3
);
96 MBB2
->addSuccessor(MBB4
);
97 MBB3
->addSuccessor(MBB4
);
99 // Create metadata: CU, subprogram, some blocks and an inline function
102 OurFile
= DIB
.createFile("xyzzy.c", "/cave");
104 DIB
.createCompileUnit(dwarf::DW_LANG_C99
, OurFile
, "nou", false, "", 0);
105 auto OurSubT
= DIB
.createSubroutineType(DIB
.getOrCreateTypeArray(None
));
107 DIB
.createFunction(OurCU
, "bees", "", OurFile
, 1, OurSubT
, 1,
108 DINode::FlagZero
, DISubprogram::SPFlagDefinition
);
109 F
.setSubprogram(OurFunc
);
110 OurBlock
= DIB
.createLexicalBlock(OurFunc
, OurFile
, 2, 3);
111 AnotherBlock
= DIB
.createLexicalBlock(OurFunc
, OurFile
, 2, 6);
113 DIB
.createFunction(OurFile
, "shoes", "", OurFile
, 10, OurSubT
, 10,
114 DINode::FlagZero
, DISubprogram::SPFlagDefinition
);
116 // Make some nested scopes.
117 OutermostLoc
= DILocation::get(Ctx
, 3, 1, OurFunc
);
118 InBlockLoc
= DILocation::get(Ctx
, 4, 1, OurBlock
);
119 InlinedLoc
= DILocation::get(Ctx
, 10, 1, ToInlineFunc
, InBlockLoc
.get());
121 // Make a scope that isn't nested within the others.
122 NotNestedBlockLoc
= DILocation::get(Ctx
, 4, 1, AnotherBlock
);
128 // Fill blocks with dummy instructions, test some base lexical scope
130 TEST_F(LexicalScopesTest
, FlatLayout
) {
131 BuildMI(*MBB1
, MBB1
->end(), OutermostLoc
, BeanInst
);
132 BuildMI(*MBB2
, MBB2
->end(), OutermostLoc
, BeanInst
);
133 BuildMI(*MBB3
, MBB3
->end(), OutermostLoc
, BeanInst
);
134 BuildMI(*MBB4
, MBB4
->end(), OutermostLoc
, BeanInst
);
137 EXPECT_TRUE(LS
.empty());
139 EXPECT_EQ(LS
.getCurrentFunctionScope(), nullptr);
142 EXPECT_FALSE(LS
.empty());
143 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
144 EXPECT_EQ(FuncScope
->getParent(), nullptr);
145 EXPECT_EQ(FuncScope
->getDesc(), OurFunc
);
146 EXPECT_EQ(FuncScope
->getInlinedAt(), nullptr);
147 EXPECT_EQ(FuncScope
->getScopeNode(), OurFunc
);
148 EXPECT_FALSE(FuncScope
->isAbstractScope());
149 EXPECT_EQ(FuncScope
->getChildren().size(), 0u);
151 // There should be one range, covering the whole function. Test that it
152 // points at the correct instructions.
153 auto &Ranges
= FuncScope
->getRanges();
154 ASSERT_EQ(Ranges
.size(), 1u);
155 EXPECT_EQ(Ranges
.front().first
, &*MF
->begin()->begin());
156 auto BBIt
= MF
->end();
157 BBIt
= std::prev(BBIt
);
158 EXPECT_EQ(Ranges
.front().second
, &*BBIt
->begin());
160 EXPECT_TRUE(FuncScope
->dominates(FuncScope
));
161 SmallPtrSet
<const MachineBasicBlock
*, 4> MBBVec
;
162 LS
.getMachineBasicBlocks(OutermostLoc
.get(), MBBVec
);
164 EXPECT_EQ(MBBVec
.size(), 4u);
165 // All the blocks should be in that set; the outermost loc should dominate
166 // them; and no other scope should.
167 for (auto &MBB
: *MF
) {
168 EXPECT_EQ(MBBVec
.count(&MBB
), 1u);
169 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), &MBB
));
170 EXPECT_FALSE(LS
.dominates(InBlockLoc
.get(), &MBB
));
171 EXPECT_FALSE(LS
.dominates(InlinedLoc
.get(), &MBB
));
175 // Examine relationship between two nested scopes inside the function, the
176 // outer function and the lexical block within it.
177 TEST_F(LexicalScopesTest
, BlockScopes
) {
178 BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
179 BuildMI(*MBB2
, MBB2
->end(), InBlockLoc
, BeanInst
);
180 BuildMI(*MBB3
, MBB3
->end(), InBlockLoc
, BeanInst
);
181 BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
185 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
186 EXPECT_EQ(FuncScope
->getDesc(), OurFunc
);
187 auto &Children
= FuncScope
->getChildren();
188 ASSERT_EQ(Children
.size(), 1u);
189 auto *BlockScope
= Children
[0];
190 EXPECT_EQ(LS
.findLexicalScope(InBlockLoc
.get()), BlockScope
);
191 EXPECT_EQ(BlockScope
->getDesc(), InBlockLoc
->getScope());
192 EXPECT_FALSE(BlockScope
->isAbstractScope());
194 EXPECT_TRUE(FuncScope
->dominates(BlockScope
));
195 EXPECT_FALSE(BlockScope
->dominates(FuncScope
));
196 EXPECT_EQ(FuncScope
->getParent(), nullptr);
197 EXPECT_EQ(BlockScope
->getParent(), FuncScope
);
199 SmallPtrSet
<const MachineBasicBlock
*, 4> MBBVec
;
200 LS
.getMachineBasicBlocks(OutermostLoc
.get(), MBBVec
);
202 EXPECT_EQ(MBBVec
.size(), 4u);
203 for (auto &MBB
: *MF
) {
204 EXPECT_EQ(MBBVec
.count(&MBB
), 1u);
205 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), &MBB
));
206 EXPECT_TRUE(LS
.dominates(InBlockLoc
.get(), &MBB
));
207 EXPECT_FALSE(LS
.dominates(InlinedLoc
.get(), &MBB
));
211 // Test inlined scopes functionality and relationship with the outer scopes.
212 TEST_F(LexicalScopesTest
, InlinedScopes
) {
213 BuildMI(*MBB1
, MBB1
->end(), InlinedLoc
, BeanInst
);
214 BuildMI(*MBB2
, MBB2
->end(), InlinedLoc
, BeanInst
);
215 BuildMI(*MBB3
, MBB3
->end(), InlinedLoc
, BeanInst
);
216 BuildMI(*MBB4
, MBB4
->end(), InlinedLoc
, BeanInst
);
220 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
221 auto &Children
= FuncScope
->getChildren();
222 ASSERT_EQ(Children
.size(), 1u);
223 auto *BlockScope
= Children
[0];
224 auto &BlockChildren
= BlockScope
->getChildren();
225 ASSERT_EQ(BlockChildren
.size(), 1u);
226 auto *InlinedScope
= BlockChildren
[0];
228 EXPECT_FALSE(InlinedScope
->isAbstractScope());
229 EXPECT_EQ(InlinedScope
->getInlinedAt(), InlinedLoc
.getInlinedAt());
230 EXPECT_EQ(InlinedScope
->getDesc(), InlinedLoc
.getScope());
231 EXPECT_EQ(InlinedScope
->getChildren().size(), 0u);
233 EXPECT_EQ(FuncScope
->getParent(), nullptr);
234 EXPECT_EQ(BlockScope
->getParent(), FuncScope
);
235 EXPECT_EQ(InlinedScope
->getParent(), BlockScope
);
237 const auto &AbstractScopes
= LS
.getAbstractScopesList();
238 ASSERT_EQ(AbstractScopes
.size(), 1u);
239 const auto &AbstractScope
= *AbstractScopes
[0];
240 EXPECT_TRUE(AbstractScope
.isAbstractScope());
241 EXPECT_EQ(AbstractScope
.getDesc(), InlinedLoc
.getScope());
242 EXPECT_EQ(AbstractScope
.getInlinedAt(), nullptr);
243 EXPECT_EQ(AbstractScope
.getParent(), nullptr);
246 // Test behaviour in a function that has empty DebugLocs.
247 TEST_F(LexicalScopesTest
, FuncWithEmptyGap
) {
248 BuildMI(*MBB1
, MBB1
->end(), OutermostLoc
, BeanInst
);
249 BuildMI(*MBB2
, MBB2
->end(), DebugLoc(), BeanInst
);
250 BuildMI(*MBB3
, MBB3
->end(), DebugLoc(), BeanInst
);
251 BuildMI(*MBB4
, MBB4
->end(), OutermostLoc
, BeanInst
);
255 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
257 // A gap in a range that contains no other location, is not actually a
258 // gap as far as lexical scopes are concerned.
259 auto &Ranges
= FuncScope
->getRanges();
260 ASSERT_EQ(Ranges
.size(), 1u);
261 EXPECT_EQ(Ranges
[0].first
, &*MF
->begin()->begin());
262 auto BBIt
= MF
->end();
263 BBIt
= std::prev(BBIt
);
264 EXPECT_EQ(Ranges
[0].second
, &*BBIt
->begin());
267 // Now a function with intervening not-in-scope instructions.
268 TEST_F(LexicalScopesTest
, FuncWithRealGap
) {
269 MachineInstr
*FirstI
= BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
270 BuildMI(*MBB2
, MBB2
->end(), OutermostLoc
, BeanInst
);
271 BuildMI(*MBB3
, MBB3
->end(), OutermostLoc
, BeanInst
);
272 MachineInstr
*LastI
= BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
276 LexicalScope
*BlockScope
= LS
.findLexicalScope(InBlockLoc
.get());
277 ASSERT_NE(BlockScope
, nullptr);
279 // Within the block scope, there's a gap between the first and last
280 // block / instruction, where it's only the outermost scope.
281 auto &Ranges
= BlockScope
->getRanges();
282 ASSERT_EQ(Ranges
.size(), 2u);
283 EXPECT_EQ(Ranges
[0].first
, FirstI
);
284 EXPECT_EQ(Ranges
[0].second
, FirstI
);
285 EXPECT_EQ(Ranges
[1].first
, LastI
);
286 EXPECT_EQ(Ranges
[1].second
, LastI
);
288 // The outer function scope should cover the whole function, including
289 // blocks the lexicalblock covers.
290 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
291 auto &FuncRanges
= FuncScope
->getRanges();
292 ASSERT_EQ(FuncRanges
.size(), 1u);
293 EXPECT_NE(FuncRanges
[0].first
, FuncRanges
[0].second
);
294 EXPECT_EQ(FuncRanges
[0].first
, FirstI
);
295 EXPECT_EQ(FuncRanges
[0].second
, LastI
);
298 // Examine the relationship between two scopes that don't nest (are siblings).
299 TEST_F(LexicalScopesTest
, NotNested
) {
300 MachineInstr
*FirstI
= BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
301 MachineInstr
*SecondI
=
302 BuildMI(*MBB2
, MBB2
->end(), NotNestedBlockLoc
, BeanInst
);
303 MachineInstr
*ThirdI
=
304 BuildMI(*MBB3
, MBB3
->end(), NotNestedBlockLoc
, BeanInst
);
305 MachineInstr
*FourthI
= BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
309 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
310 LexicalScope
*BlockScope
= LS
.findLexicalScope(InBlockLoc
.get());
311 LexicalScope
*OtherBlockScope
= LS
.findLexicalScope(NotNestedBlockLoc
.get());
312 ASSERT_NE(FuncScope
, nullptr);
313 ASSERT_NE(BlockScope
, nullptr);
314 ASSERT_NE(OtherBlockScope
, nullptr);
316 // The function should cover everything; the two blocks are distinct and
318 auto &FuncRanges
= FuncScope
->getRanges();
319 ASSERT_EQ(FuncRanges
.size(), 1u);
320 EXPECT_EQ(FuncRanges
[0].first
, FirstI
);
321 EXPECT_EQ(FuncRanges
[0].second
, FourthI
);
323 // Two ranges, start and end instructions.
324 auto &BlockRanges
= BlockScope
->getRanges();
325 ASSERT_EQ(BlockRanges
.size(), 2u);
326 EXPECT_EQ(BlockRanges
[0].first
, FirstI
);
327 EXPECT_EQ(BlockRanges
[0].second
, FirstI
);
328 EXPECT_EQ(BlockRanges
[1].first
, FourthI
);
329 EXPECT_EQ(BlockRanges
[1].second
, FourthI
);
331 // One inner range, covering the two inner blocks.
332 auto &OtherBlockRanges
= OtherBlockScope
->getRanges();
333 ASSERT_EQ(OtherBlockRanges
.size(), 1u);
334 EXPECT_EQ(OtherBlockRanges
[0].first
, SecondI
);
335 EXPECT_EQ(OtherBlockRanges
[0].second
, ThirdI
);
338 // Test the scope-specific and block-specific dominates methods.
339 TEST_F(LexicalScopesTest
, TestDominates
) {
340 BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
341 BuildMI(*MBB2
, MBB2
->end(), NotNestedBlockLoc
, BeanInst
);
342 BuildMI(*MBB3
, MBB3
->end(), NotNestedBlockLoc
, BeanInst
);
343 BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
347 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
348 LexicalScope
*BlockScope
= LS
.findLexicalScope(InBlockLoc
.get());
349 LexicalScope
*OtherBlockScope
= LS
.findLexicalScope(NotNestedBlockLoc
.get());
350 ASSERT_NE(FuncScope
, nullptr);
351 ASSERT_NE(BlockScope
, nullptr);
352 ASSERT_NE(OtherBlockScope
, nullptr);
354 EXPECT_TRUE(FuncScope
->dominates(BlockScope
));
355 EXPECT_TRUE(FuncScope
->dominates(OtherBlockScope
));
356 EXPECT_FALSE(BlockScope
->dominates(FuncScope
));
357 EXPECT_FALSE(BlockScope
->dominates(OtherBlockScope
));
358 EXPECT_FALSE(OtherBlockScope
->dominates(FuncScope
));
359 EXPECT_FALSE(OtherBlockScope
->dominates(BlockScope
));
361 // Outermost scope dominates everything, as all insts are within it.
362 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB1
));
363 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB2
));
364 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB3
));
365 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB4
));
367 // One inner block dominates the outer pair of blocks,
368 EXPECT_TRUE(LS
.dominates(InBlockLoc
.get(), MBB1
));
369 EXPECT_FALSE(LS
.dominates(InBlockLoc
.get(), MBB2
));
370 EXPECT_FALSE(LS
.dominates(InBlockLoc
.get(), MBB3
));
371 EXPECT_TRUE(LS
.dominates(InBlockLoc
.get(), MBB4
));
373 // While the other dominates the inner two blocks.
374 EXPECT_FALSE(LS
.dominates(NotNestedBlockLoc
.get(), MBB1
));
375 EXPECT_TRUE(LS
.dominates(NotNestedBlockLoc
.get(), MBB2
));
376 EXPECT_TRUE(LS
.dominates(NotNestedBlockLoc
.get(), MBB3
));
377 EXPECT_FALSE(LS
.dominates(NotNestedBlockLoc
.get(), MBB4
));
380 // Test getMachineBasicBlocks returns all dominated blocks.
381 TEST_F(LexicalScopesTest
, TestGetBlocks
) {
382 BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
383 BuildMI(*MBB2
, MBB2
->end(), NotNestedBlockLoc
, BeanInst
);
384 BuildMI(*MBB3
, MBB3
->end(), NotNestedBlockLoc
, BeanInst
);
385 BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
389 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
390 LexicalScope
*BlockScope
= LS
.findLexicalScope(InBlockLoc
.get());
391 LexicalScope
*OtherBlockScope
= LS
.findLexicalScope(NotNestedBlockLoc
.get());
392 ASSERT_NE(FuncScope
, nullptr);
393 ASSERT_NE(BlockScope
, nullptr);
394 ASSERT_NE(OtherBlockScope
, nullptr);
396 SmallPtrSet
<const MachineBasicBlock
*, 4> OutermostBlocks
, InBlockBlocks
,
397 NotNestedBlockBlocks
;
398 LS
.getMachineBasicBlocks(OutermostLoc
.get(), OutermostBlocks
);
399 LS
.getMachineBasicBlocks(InBlockLoc
.get(), InBlockBlocks
);
400 LS
.getMachineBasicBlocks(NotNestedBlockLoc
.get(), NotNestedBlockBlocks
);
402 EXPECT_EQ(OutermostBlocks
.count(MBB1
), 1u);
403 EXPECT_EQ(OutermostBlocks
.count(MBB2
), 1u);
404 EXPECT_EQ(OutermostBlocks
.count(MBB3
), 1u);
405 EXPECT_EQ(OutermostBlocks
.count(MBB4
), 1u);
407 EXPECT_EQ(InBlockBlocks
.count(MBB1
), 1u);
408 EXPECT_EQ(InBlockBlocks
.count(MBB2
), 0u);
409 EXPECT_EQ(InBlockBlocks
.count(MBB3
), 0u);
410 EXPECT_EQ(InBlockBlocks
.count(MBB4
), 1u);
412 EXPECT_EQ(NotNestedBlockBlocks
.count(MBB1
), 0u);
413 EXPECT_EQ(NotNestedBlockBlocks
.count(MBB2
), 1u);
414 EXPECT_EQ(NotNestedBlockBlocks
.count(MBB3
), 1u);
415 EXPECT_EQ(NotNestedBlockBlocks
.count(MBB4
), 0u);
418 TEST_F(LexicalScopesTest
, TestMetaInst
) {
419 // Instruction Layout looks like this, where 'F' means funcscope, and
433 // The block / 'B' should only dominate bb1 and bb4. DBG_VALUE is a meta
434 // instruction, and shouldn't contribute to scopes.
435 BuildMI(*MBB1
, MBB1
->end(), OutermostLoc
, BeanInst
);
436 BuildMI(*MBB1
, MBB1
->end(), InBlockLoc
, BeanInst
);
437 BuildMI(*MBB2
, MBB2
->end(), OutermostLoc
, BeanInst
);
438 BuildMI(*MBB2
, MBB2
->end(), InBlockLoc
, DbgValueInst
);
439 BuildMI(*MBB3
, MBB3
->end(), OutermostLoc
, BeanInst
);
440 BuildMI(*MBB3
, MBB3
->end(), InBlockLoc
, DbgValueInst
);
441 BuildMI(*MBB4
, MBB4
->end(), OutermostLoc
, BeanInst
);
442 BuildMI(*MBB4
, MBB4
->end(), InBlockLoc
, BeanInst
);
446 LexicalScope
*FuncScope
= LS
.getCurrentFunctionScope();
447 LexicalScope
*BlockScope
= LS
.findLexicalScope(InBlockLoc
.get());
448 ASSERT_NE(FuncScope
, nullptr);
449 ASSERT_NE(BlockScope
, nullptr);
451 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB1
));
452 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB2
));
453 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB3
));
454 EXPECT_TRUE(LS
.dominates(OutermostLoc
.get(), MBB4
));
455 EXPECT_TRUE(LS
.dominates(InBlockLoc
.get(), MBB1
));
456 EXPECT_FALSE(LS
.dominates(InBlockLoc
.get(), MBB2
));
457 EXPECT_FALSE(LS
.dominates(InBlockLoc
.get(), MBB3
));
458 EXPECT_TRUE(LS
.dominates(InBlockLoc
.get(), MBB4
));
461 } // anonymous namespace