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