1//===----------- llvm/unittest/CodeGen/LexicalScopesTest.cpp --------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
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"
29
30#include "gtest/gtest.h"
31
32using namespace llvm;
33
34namespace {
35// Include helper functions to ease the manipulation of MachineFunctions
36#include "MFCommon.inc"
37
38class LexicalScopesTest : public testing::Test {
39public:
40 // Boilerplate,
41 LLVMContext Ctx;
42 Module Mod;
43 std::unique_ptr<MachineFunction> MF;
44 DICompileUnit *OurCU;
45 DIFile *OurFile;
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;
52
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;
57
58 // Some meaningless instructions -- the first is fully meaningless,
59 // while the second is supposed to impersonate DBG_VALUEs through its
60 // opcode.
61 MCInstrDesc BeanInst{};
62 MCInstrDesc DbgValueInst{};
63
64 LexicalScopesTest() : Ctx(), Mod("beehives", Ctx) {
65 memset(s: &BeanInst, c: 0, n: sizeof(BeanInst));
66 BeanInst.Opcode = 1;
67 BeanInst.Size = 1;
68
69 memset(s: &DbgValueInst, c: 0, n: sizeof(DbgValueInst));
70 DbgValueInst.Opcode = TargetOpcode::DBG_VALUE;
71 DbgValueInst.Size = 1;
72 DbgValueInst.Flags = 1U << MCID::Meta;
73
74 // Boilerplate that creates a MachineFunction and associated blocks.
75 MF = createMachineFunction(Ctx, M&: Mod);
76 llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
77 auto BB1 = BasicBlock::Create(Context&: Ctx, Name: "a", Parent: &F);
78 auto BB2 = BasicBlock::Create(Context&: Ctx, Name: "b", Parent: &F);
79 auto BB3 = BasicBlock::Create(Context&: Ctx, Name: "c", Parent: &F);
80 auto BB4 = BasicBlock::Create(Context&: Ctx, Name: "d", Parent: &F);
81 IRBuilder<> IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4);
82 IRB1.CreateBr(Dest: BB2);
83 IRB2.CreateBr(Dest: BB3);
84 IRB3.CreateBr(Dest: BB4);
85 IRB4.CreateRetVoid();
86 MBB1 = MF->CreateMachineBasicBlock(BB: BB1);
87 MF->insert(MBBI: MF->end(), MBB: MBB1);
88 MBB2 = MF->CreateMachineBasicBlock(BB: BB2);
89 MF->insert(MBBI: MF->end(), MBB: MBB2);
90 MBB3 = MF->CreateMachineBasicBlock(BB: BB3);
91 MF->insert(MBBI: MF->end(), MBB: MBB3);
92 MBB4 = MF->CreateMachineBasicBlock(BB: BB4);
93 MF->insert(MBBI: MF->end(), MBB: MBB4);
94 MBB1->addSuccessor(Succ: MBB2);
95 MBB1->addSuccessor(Succ: MBB3);
96 MBB2->addSuccessor(Succ: MBB4);
97 MBB3->addSuccessor(Succ: MBB4);
98
99 // Create metadata: CU, subprogram, some blocks and an inline function
100 // scope.
101 DIBuilder DIB(Mod);
102 OurFile = DIB.createFile(Filename: "xyzzy.c", Directory: "/cave");
103 OurCU =
104 DIB.createCompileUnit(Lang: dwarf::DW_LANG_C99, File: OurFile, Producer: "nou", isOptimized: false, Flags: "", RV: 0);
105 auto OurSubT =
106 DIB.createSubroutineType(ParameterTypes: DIB.getOrCreateTypeArray(Elements: std::nullopt));
107 OurFunc =
108 DIB.createFunction(Scope: OurCU, Name: "bees", LinkageName: "", File: OurFile, LineNo: 1, Ty: OurSubT, ScopeLine: 1,
109 Flags: DINode::FlagZero, SPFlags: DISubprogram::SPFlagDefinition);
110 F.setSubprogram(OurFunc);
111 OurBlock = DIB.createLexicalBlock(Scope: OurFunc, File: OurFile, Line: 2, Col: 3);
112 AnotherBlock = DIB.createLexicalBlock(Scope: OurFunc, File: OurFile, Line: 2, Col: 6);
113 ToInlineFunc =
114 DIB.createFunction(Scope: OurFile, Name: "shoes", LinkageName: "", File: OurFile, LineNo: 10, Ty: OurSubT, ScopeLine: 10,
115 Flags: DINode::FlagZero, SPFlags: DISubprogram::SPFlagDefinition);
116
117 // Make some nested scopes.
118 OutermostLoc = DILocation::get(Context&: Ctx, Line: 3, Column: 1, Scope: OurFunc);
119 InBlockLoc = DILocation::get(Context&: Ctx, Line: 4, Column: 1, Scope: OurBlock);
120 InlinedLoc = DILocation::get(Context&: Ctx, Line: 10, Column: 1, Scope: ToInlineFunc, InlinedAt: InBlockLoc.get());
121
122 // Make a scope that isn't nested within the others.
123 NotNestedBlockLoc = DILocation::get(Context&: Ctx, Line: 4, Column: 1, Scope: AnotherBlock);
124
125 DIB.finalize();
126 }
127};
128
129// Fill blocks with dummy instructions, test some base lexical scope
130// functionaliy.
131TEST_F(LexicalScopesTest, FlatLayout) {
132 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: OutermostLoc, MCID: BeanInst);
133 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: OutermostLoc, MCID: BeanInst);
134 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: OutermostLoc, MCID: BeanInst);
135 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: OutermostLoc, MCID: BeanInst);
136
137 LexicalScopes LS;
138 EXPECT_TRUE(LS.empty());
139 LS.reset();
140 EXPECT_EQ(LS.getCurrentFunctionScope(), nullptr);
141
142 LS.initialize(*MF);
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);
151
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(x: BBIt);
159 EXPECT_EQ(Ranges.front().second, &*BBIt->begin());
160
161 EXPECT_TRUE(FuncScope->dominates(FuncScope));
162 SmallPtrSet<const MachineBasicBlock *, 4> MBBVec;
163 LS.getMachineBasicBlocks(DL: OutermostLoc.get(), MBBs&: MBBVec);
164
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));
173 }
174}
175
176// Examine relationship between two nested scopes inside the function, the
177// outer function and the lexical block within it.
178TEST_F(LexicalScopesTest, BlockScopes) {
179 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
180 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: InBlockLoc, MCID: BeanInst);
181 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: InBlockLoc, MCID: BeanInst);
182 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
183
184 LexicalScopes LS;
185 LS.initialize(*MF);
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());
194
195 EXPECT_TRUE(FuncScope->dominates(BlockScope));
196 EXPECT_FALSE(BlockScope->dominates(FuncScope));
197 EXPECT_EQ(FuncScope->getParent(), nullptr);
198 EXPECT_EQ(BlockScope->getParent(), FuncScope);
199
200 SmallPtrSet<const MachineBasicBlock *, 4> MBBVec;
201 LS.getMachineBasicBlocks(DL: OutermostLoc.get(), MBBs&: MBBVec);
202
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));
209 }
210}
211
212// Test inlined scopes functionality and relationship with the outer scopes.
213TEST_F(LexicalScopesTest, InlinedScopes) {
214 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InlinedLoc, MCID: BeanInst);
215 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: InlinedLoc, MCID: BeanInst);
216 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: InlinedLoc, MCID: BeanInst);
217 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InlinedLoc, MCID: BeanInst);
218
219 LexicalScopes LS;
220 LS.initialize(*MF);
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];
228
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);
233
234 EXPECT_EQ(FuncScope->getParent(), nullptr);
235 EXPECT_EQ(BlockScope->getParent(), FuncScope);
236 EXPECT_EQ(InlinedScope->getParent(), BlockScope);
237
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);
245}
246
247// Test behaviour in a function that has empty DebugLocs.
248TEST_F(LexicalScopesTest, FuncWithEmptyGap) {
249 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: OutermostLoc, MCID: BeanInst);
250 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: DebugLoc(), MCID: BeanInst);
251 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: DebugLoc(), MCID: BeanInst);
252 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: OutermostLoc, MCID: BeanInst);
253
254 LexicalScopes LS;
255 LS.initialize(*MF);
256 LexicalScope *FuncScope = LS.getCurrentFunctionScope();
257
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(x: BBIt);
265 EXPECT_EQ(Ranges[0].second, &*BBIt->begin());
266}
267
268// Now a function with intervening not-in-scope instructions.
269TEST_F(LexicalScopesTest, FuncWithRealGap) {
270 MachineInstr *FirstI = BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
271 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: OutermostLoc, MCID: BeanInst);
272 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: OutermostLoc, MCID: BeanInst);
273 MachineInstr *LastI = BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
274
275 LexicalScopes LS;
276 LS.initialize(*MF);
277 LexicalScope *BlockScope = LS.findLexicalScope(DL: InBlockLoc.get());
278 ASSERT_NE(BlockScope, nullptr);
279
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);
288
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);
297}
298
299// Examine the relationship between two scopes that don't nest (are siblings).
300TEST_F(LexicalScopesTest, NotNested) {
301 MachineInstr *FirstI = BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
302 MachineInstr *SecondI =
303 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
304 MachineInstr *ThirdI =
305 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
306 MachineInstr *FourthI = BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
307
308 LexicalScopes LS;
309 LS.initialize(*MF);
310 LexicalScope *FuncScope = LS.getCurrentFunctionScope();
311 LexicalScope *BlockScope = LS.findLexicalScope(DL: InBlockLoc.get());
312 LexicalScope *OtherBlockScope = LS.findLexicalScope(DL: NotNestedBlockLoc.get());
313 ASSERT_NE(FuncScope, nullptr);
314 ASSERT_NE(BlockScope, nullptr);
315 ASSERT_NE(OtherBlockScope, nullptr);
316
317 // The function should cover everything; the two blocks are distinct and
318 // should not.
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);
323
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);
331
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);
337}
338
339// Test the scope-specific and block-specific dominates methods.
340TEST_F(LexicalScopesTest, TestDominates) {
341 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
342 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
343 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
344 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
345
346 LexicalScopes LS;
347 LS.initialize(*MF);
348 LexicalScope *FuncScope = LS.getCurrentFunctionScope();
349 LexicalScope *BlockScope = LS.findLexicalScope(DL: InBlockLoc.get());
350 LexicalScope *OtherBlockScope = LS.findLexicalScope(DL: NotNestedBlockLoc.get());
351 ASSERT_NE(FuncScope, nullptr);
352 ASSERT_NE(BlockScope, nullptr);
353 ASSERT_NE(OtherBlockScope, nullptr);
354
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));
361
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));
367
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));
373
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));
379}
380
381// Test getMachineBasicBlocks returns all dominated blocks.
382TEST_F(LexicalScopesTest, TestGetBlocks) {
383 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
384 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
385 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: NotNestedBlockLoc, MCID: BeanInst);
386 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
387
388 LexicalScopes LS;
389 LS.initialize(*MF);
390 LexicalScope *FuncScope = LS.getCurrentFunctionScope();
391 LexicalScope *BlockScope = LS.findLexicalScope(DL: InBlockLoc.get());
392 LexicalScope *OtherBlockScope = LS.findLexicalScope(DL: NotNestedBlockLoc.get());
393 ASSERT_NE(FuncScope, nullptr);
394 ASSERT_NE(BlockScope, nullptr);
395 ASSERT_NE(OtherBlockScope, nullptr);
396
397 SmallPtrSet<const MachineBasicBlock *, 4> OutermostBlocks, InBlockBlocks,
398 NotNestedBlockBlocks;
399 LS.getMachineBasicBlocks(DL: OutermostLoc.get(), MBBs&: OutermostBlocks);
400 LS.getMachineBasicBlocks(DL: InBlockLoc.get(), MBBs&: InBlockBlocks);
401 LS.getMachineBasicBlocks(DL: NotNestedBlockLoc.get(), MBBs&: NotNestedBlockBlocks);
402
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);
407
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);
412
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);
417}
418
419TEST_F(LexicalScopesTest, TestMetaInst) {
420 // Instruction Layout looks like this, where 'F' means funcscope, and
421 // 'B' blockscope:
422 // bb1:
423 // F: bean
424 // B: bean
425 // bb2:
426 // F: bean
427 // B: DBG_VALUE
428 // bb3:
429 // F: bean
430 // B: DBG_VALUE
431 // bb4:
432 // F: bean
433 // B: bean
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(BB&: *MBB1, I: MBB1->end(), MIMD: OutermostLoc, MCID: BeanInst);
437 BuildMI(BB&: *MBB1, I: MBB1->end(), MIMD: InBlockLoc, MCID: BeanInst);
438 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: OutermostLoc, MCID: BeanInst);
439 BuildMI(BB&: *MBB2, I: MBB2->end(), MIMD: InBlockLoc, MCID: DbgValueInst);
440 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: OutermostLoc, MCID: BeanInst);
441 BuildMI(BB&: *MBB3, I: MBB3->end(), MIMD: InBlockLoc, MCID: DbgValueInst);
442 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: OutermostLoc, MCID: BeanInst);
443 BuildMI(BB&: *MBB4, I: MBB4->end(), MIMD: InBlockLoc, MCID: BeanInst);
444
445 LexicalScopes LS;
446 LS.initialize(*MF);
447 LexicalScope *FuncScope = LS.getCurrentFunctionScope();
448 LexicalScope *BlockScope = LS.findLexicalScope(DL: InBlockLoc.get());
449 ASSERT_NE(FuncScope, nullptr);
450 ASSERT_NE(BlockScope, nullptr);
451
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));
460}
461
462} // anonymous namespace
463

source code of llvm/unittests/CodeGen/LexicalScopesTest.cpp