xref: /llvm-project/llvm/unittests/CodeGen/LexicalScopesTest.cpp (revision bb3f5e1fed7c6ba733b7f273e93f5d3930976185)
16af859dcSJeremy Morse //===----------- llvm/unittest/CodeGen/LexicalScopesTest.cpp --------------===//
26af859dcSJeremy Morse //
36af859dcSJeremy Morse // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46af859dcSJeremy Morse // See https://llvm.org/LICENSE.txt for license information.
56af859dcSJeremy Morse // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66af859dcSJeremy Morse //
76af859dcSJeremy Morse //===----------------------------------------------------------------------===//
86af859dcSJeremy Morse 
96af859dcSJeremy Morse #include "llvm/CodeGen/LexicalScopes.h"
10*bb3f5e1fSMatin Raayai #include "llvm/CodeGen/CodeGenTargetMachineImpl.h"
116af859dcSJeremy Morse #include "llvm/CodeGen/MachineBasicBlock.h"
126af859dcSJeremy Morse #include "llvm/CodeGen/MachineFunction.h"
136af859dcSJeremy Morse #include "llvm/CodeGen/MachineInstr.h"
146af859dcSJeremy Morse #include "llvm/CodeGen/MachineMemOperand.h"
156af859dcSJeremy Morse #include "llvm/CodeGen/MachineModuleInfo.h"
166af859dcSJeremy Morse #include "llvm/CodeGen/TargetFrameLowering.h"
176af859dcSJeremy Morse #include "llvm/CodeGen/TargetInstrInfo.h"
186af859dcSJeremy Morse #include "llvm/CodeGen/TargetLowering.h"
196af859dcSJeremy Morse #include "llvm/CodeGen/TargetSubtargetInfo.h"
206af859dcSJeremy Morse #include "llvm/IR/DIBuilder.h"
216af859dcSJeremy Morse #include "llvm/IR/DebugInfoMetadata.h"
2285dfb377SNikita Popov #include "llvm/IR/IRBuilder.h"
2374deadf1SNikita Popov #include "llvm/IR/Module.h"
246af859dcSJeremy Morse #include "llvm/IR/ModuleSlotTracker.h"
256af859dcSJeremy Morse #include "llvm/MC/MCAsmInfo.h"
266af859dcSJeremy Morse #include "llvm/MC/MCSymbol.h"
2789b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
286af859dcSJeremy Morse #include "llvm/Support/TargetSelect.h"
296af859dcSJeremy Morse #include "llvm/Target/TargetOptions.h"
306af859dcSJeremy Morse 
316af859dcSJeremy Morse #include "gtest/gtest.h"
326af859dcSJeremy Morse 
336af859dcSJeremy Morse using namespace llvm;
346af859dcSJeremy Morse 
356af859dcSJeremy Morse namespace {
366af859dcSJeremy Morse // Include helper functions to ease the manipulation of MachineFunctions
376af859dcSJeremy Morse #include "MFCommon.inc"
386af859dcSJeremy Morse 
396af859dcSJeremy Morse class LexicalScopesTest : public testing::Test {
406af859dcSJeremy Morse public:
416af859dcSJeremy Morse   // Boilerplate,
426af859dcSJeremy Morse   LLVMContext Ctx;
436af859dcSJeremy Morse   Module Mod;
446af859dcSJeremy Morse   std::unique_ptr<MachineFunction> MF;
456af859dcSJeremy Morse   DICompileUnit *OurCU;
466af859dcSJeremy Morse   DIFile *OurFile;
476af859dcSJeremy Morse   DISubprogram *OurFunc;
486af859dcSJeremy Morse   DILexicalBlock *OurBlock, *AnotherBlock;
496af859dcSJeremy Morse   DISubprogram *ToInlineFunc;
506af859dcSJeremy Morse   DILexicalBlock *ToInlineBlock;
516af859dcSJeremy Morse   // DebugLocs that we'll used to create test environments.
526af859dcSJeremy Morse   DebugLoc OutermostLoc, InBlockLoc, NotNestedBlockLoc, InlinedLoc;
536af859dcSJeremy Morse 
546af859dcSJeremy Morse   // Test environment blocks -- these form a diamond control flow pattern,
556af859dcSJeremy Morse   // MBB1 being the entry block, blocks two and three being the branches, and
566af859dcSJeremy Morse   // block four joining the branches and being an exit block.
576af859dcSJeremy Morse   MachineBasicBlock *MBB1, *MBB2, *MBB3, *MBB4;
586af859dcSJeremy Morse 
596af859dcSJeremy Morse   // Some meaningless instructions -- the first is fully meaningless,
606af859dcSJeremy Morse   // while the second is supposed to impersonate DBG_VALUEs through its
616af859dcSJeremy Morse   // opcode.
62245e3dd9SJay Foad   MCInstrDesc BeanInst{};
63245e3dd9SJay Foad   MCInstrDesc DbgValueInst{};
646af859dcSJeremy Morse 
656af859dcSJeremy Morse   LexicalScopesTest() : Ctx(), Mod("beehives", Ctx) {
666af859dcSJeremy Morse     memset(&BeanInst, 0, sizeof(BeanInst));
676af859dcSJeremy Morse     BeanInst.Opcode = 1;
686af859dcSJeremy Morse     BeanInst.Size = 1;
696af859dcSJeremy Morse 
706af859dcSJeremy Morse     memset(&DbgValueInst, 0, sizeof(DbgValueInst));
716af859dcSJeremy Morse     DbgValueInst.Opcode = TargetOpcode::DBG_VALUE;
726af859dcSJeremy Morse     DbgValueInst.Size = 1;
739e832a67SShengchen Kan     DbgValueInst.Flags = 1U << MCID::Meta;
746af859dcSJeremy Morse 
756af859dcSJeremy Morse     // Boilerplate that creates a MachineFunction and associated blocks.
766af859dcSJeremy Morse     MF = createMachineFunction(Ctx, Mod);
776af859dcSJeremy Morse     llvm::Function &F = const_cast<llvm::Function &>(MF->getFunction());
786af859dcSJeremy Morse     auto BB1 = BasicBlock::Create(Ctx, "a", &F);
796af859dcSJeremy Morse     auto BB2 = BasicBlock::Create(Ctx, "b", &F);
806af859dcSJeremy Morse     auto BB3 = BasicBlock::Create(Ctx, "c", &F);
816af859dcSJeremy Morse     auto BB4 = BasicBlock::Create(Ctx, "d", &F);
826af859dcSJeremy Morse     IRBuilder<> IRB1(BB1), IRB2(BB2), IRB3(BB3), IRB4(BB4);
836af859dcSJeremy Morse     IRB1.CreateBr(BB2);
846af859dcSJeremy Morse     IRB2.CreateBr(BB3);
856af859dcSJeremy Morse     IRB3.CreateBr(BB4);
866af859dcSJeremy Morse     IRB4.CreateRetVoid();
876af859dcSJeremy Morse     MBB1 = MF->CreateMachineBasicBlock(BB1);
886af859dcSJeremy Morse     MF->insert(MF->end(), MBB1);
896af859dcSJeremy Morse     MBB2 = MF->CreateMachineBasicBlock(BB2);
906af859dcSJeremy Morse     MF->insert(MF->end(), MBB2);
916af859dcSJeremy Morse     MBB3 = MF->CreateMachineBasicBlock(BB3);
926af859dcSJeremy Morse     MF->insert(MF->end(), MBB3);
936af859dcSJeremy Morse     MBB4 = MF->CreateMachineBasicBlock(BB4);
946af859dcSJeremy Morse     MF->insert(MF->end(), MBB4);
956af859dcSJeremy Morse     MBB1->addSuccessor(MBB2);
966af859dcSJeremy Morse     MBB1->addSuccessor(MBB3);
976af859dcSJeremy Morse     MBB2->addSuccessor(MBB4);
986af859dcSJeremy Morse     MBB3->addSuccessor(MBB4);
996af859dcSJeremy Morse 
1006af859dcSJeremy Morse     // Create metadata: CU, subprogram, some blocks and an inline function
1016af859dcSJeremy Morse     // scope.
1026af859dcSJeremy Morse     DIBuilder DIB(Mod);
1036af859dcSJeremy Morse     OurFile = DIB.createFile("xyzzy.c", "/cave");
1046af859dcSJeremy Morse     OurCU =
1056af859dcSJeremy Morse         DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "nou", false, "", 0);
106eb6e7e8fSJay Foad     auto OurSubT = DIB.createSubroutineType(DIB.getOrCreateTypeArray({}));
1076af859dcSJeremy Morse     OurFunc =
1086af859dcSJeremy Morse         DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1,
1096af859dcSJeremy Morse                            DINode::FlagZero, DISubprogram::SPFlagDefinition);
1106af859dcSJeremy Morse     F.setSubprogram(OurFunc);
1116af859dcSJeremy Morse     OurBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 3);
1126af859dcSJeremy Morse     AnotherBlock = DIB.createLexicalBlock(OurFunc, OurFile, 2, 6);
1136af859dcSJeremy Morse     ToInlineFunc =
1146af859dcSJeremy Morse         DIB.createFunction(OurFile, "shoes", "", OurFile, 10, OurSubT, 10,
1156af859dcSJeremy Morse                            DINode::FlagZero, DISubprogram::SPFlagDefinition);
1166af859dcSJeremy Morse 
1176af859dcSJeremy Morse     // Make some nested scopes.
1188c4e5576SFangrui Song     OutermostLoc = DILocation::get(Ctx, 3, 1, OurFunc);
1198c4e5576SFangrui Song     InBlockLoc = DILocation::get(Ctx, 4, 1, OurBlock);
1208c4e5576SFangrui Song     InlinedLoc = DILocation::get(Ctx, 10, 1, ToInlineFunc, InBlockLoc.get());
1216af859dcSJeremy Morse 
1226af859dcSJeremy Morse     // Make a scope that isn't nested within the others.
1238c4e5576SFangrui Song     NotNestedBlockLoc = DILocation::get(Ctx, 4, 1, AnotherBlock);
1246af859dcSJeremy Morse 
1256af859dcSJeremy Morse     DIB.finalize();
1266af859dcSJeremy Morse   }
1276af859dcSJeremy Morse };
1286af859dcSJeremy Morse 
1296af859dcSJeremy Morse // Fill blocks with dummy instructions, test some base lexical scope
1306af859dcSJeremy Morse // functionaliy.
1316af859dcSJeremy Morse TEST_F(LexicalScopesTest, FlatLayout) {
1326af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), OutermostLoc, BeanInst);
1336af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), OutermostLoc, BeanInst);
1346af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), OutermostLoc, BeanInst);
1356af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), OutermostLoc, BeanInst);
1366af859dcSJeremy Morse 
1376af859dcSJeremy Morse   LexicalScopes LS;
1386af859dcSJeremy Morse   EXPECT_TRUE(LS.empty());
1396af859dcSJeremy Morse   LS.reset();
1406af859dcSJeremy Morse   EXPECT_EQ(LS.getCurrentFunctionScope(), nullptr);
1416af859dcSJeremy Morse 
1426af859dcSJeremy Morse   LS.initialize(*MF);
1436af859dcSJeremy Morse   EXPECT_FALSE(LS.empty());
1446af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
1456af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getParent(), nullptr);
1466af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getDesc(), OurFunc);
1476af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getInlinedAt(), nullptr);
1486af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getScopeNode(), OurFunc);
1496af859dcSJeremy Morse   EXPECT_FALSE(FuncScope->isAbstractScope());
1506af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getChildren().size(), 0u);
1516af859dcSJeremy Morse 
1526af859dcSJeremy Morse   // There should be one range, covering the whole function. Test that it
1536af859dcSJeremy Morse   // points at the correct instructions.
1546af859dcSJeremy Morse   auto &Ranges = FuncScope->getRanges();
1556af859dcSJeremy Morse   ASSERT_EQ(Ranges.size(), 1u);
1566af859dcSJeremy Morse   EXPECT_EQ(Ranges.front().first, &*MF->begin()->begin());
1576af859dcSJeremy Morse   auto BBIt = MF->end();
1586af859dcSJeremy Morse   BBIt = std::prev(BBIt);
1596af859dcSJeremy Morse   EXPECT_EQ(Ranges.front().second, &*BBIt->begin());
1606af859dcSJeremy Morse 
1616af859dcSJeremy Morse   EXPECT_TRUE(FuncScope->dominates(FuncScope));
1626af859dcSJeremy Morse   SmallPtrSet<const MachineBasicBlock *, 4> MBBVec;
1636af859dcSJeremy Morse   LS.getMachineBasicBlocks(OutermostLoc.get(), MBBVec);
1646af859dcSJeremy Morse 
1656af859dcSJeremy Morse   EXPECT_EQ(MBBVec.size(), 4u);
1666af859dcSJeremy Morse   // All the blocks should be in that set; the outermost loc should dominate
1676af859dcSJeremy Morse   // them; and no other scope should.
1686af859dcSJeremy Morse   for (auto &MBB : *MF) {
1696af859dcSJeremy Morse     EXPECT_EQ(MBBVec.count(&MBB), 1u);
1706af859dcSJeremy Morse     EXPECT_TRUE(LS.dominates(OutermostLoc.get(), &MBB));
1716af859dcSJeremy Morse     EXPECT_FALSE(LS.dominates(InBlockLoc.get(), &MBB));
1726af859dcSJeremy Morse     EXPECT_FALSE(LS.dominates(InlinedLoc.get(), &MBB));
1736af859dcSJeremy Morse   }
1746af859dcSJeremy Morse }
1756af859dcSJeremy Morse 
1766af859dcSJeremy Morse // Examine relationship between two nested scopes inside the function, the
1776af859dcSJeremy Morse // outer function and the lexical block within it.
1786af859dcSJeremy Morse TEST_F(LexicalScopesTest, BlockScopes) {
1796af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
1806af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), InBlockLoc, BeanInst);
1816af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), InBlockLoc, BeanInst);
1826af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
1836af859dcSJeremy Morse 
1846af859dcSJeremy Morse   LexicalScopes LS;
1856af859dcSJeremy Morse   LS.initialize(*MF);
1866af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
1876af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getDesc(), OurFunc);
1886af859dcSJeremy Morse   auto &Children = FuncScope->getChildren();
1896af859dcSJeremy Morse   ASSERT_EQ(Children.size(), 1u);
1906af859dcSJeremy Morse   auto *BlockScope = Children[0];
1916af859dcSJeremy Morse   EXPECT_EQ(LS.findLexicalScope(InBlockLoc.get()), BlockScope);
1926af859dcSJeremy Morse   EXPECT_EQ(BlockScope->getDesc(), InBlockLoc->getScope());
1936af859dcSJeremy Morse   EXPECT_FALSE(BlockScope->isAbstractScope());
1946af859dcSJeremy Morse 
1956af859dcSJeremy Morse   EXPECT_TRUE(FuncScope->dominates(BlockScope));
1966af859dcSJeremy Morse   EXPECT_FALSE(BlockScope->dominates(FuncScope));
1976af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getParent(), nullptr);
1986af859dcSJeremy Morse   EXPECT_EQ(BlockScope->getParent(), FuncScope);
1996af859dcSJeremy Morse 
2006af859dcSJeremy Morse   SmallPtrSet<const MachineBasicBlock *, 4> MBBVec;
2016af859dcSJeremy Morse   LS.getMachineBasicBlocks(OutermostLoc.get(), MBBVec);
2026af859dcSJeremy Morse 
2036af859dcSJeremy Morse   EXPECT_EQ(MBBVec.size(), 4u);
2046af859dcSJeremy Morse   for (auto &MBB : *MF) {
2056af859dcSJeremy Morse     EXPECT_EQ(MBBVec.count(&MBB), 1u);
2066af859dcSJeremy Morse     EXPECT_TRUE(LS.dominates(OutermostLoc.get(), &MBB));
2076af859dcSJeremy Morse     EXPECT_TRUE(LS.dominates(InBlockLoc.get(), &MBB));
2086af859dcSJeremy Morse     EXPECT_FALSE(LS.dominates(InlinedLoc.get(), &MBB));
2096af859dcSJeremy Morse   }
2106af859dcSJeremy Morse }
2116af859dcSJeremy Morse 
2126af859dcSJeremy Morse // Test inlined scopes functionality and relationship with the outer scopes.
2136af859dcSJeremy Morse TEST_F(LexicalScopesTest, InlinedScopes) {
2146af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), InlinedLoc, BeanInst);
2156af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), InlinedLoc, BeanInst);
2166af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), InlinedLoc, BeanInst);
2176af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), InlinedLoc, BeanInst);
2186af859dcSJeremy Morse 
2196af859dcSJeremy Morse   LexicalScopes LS;
2206af859dcSJeremy Morse   LS.initialize(*MF);
2216af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
2226af859dcSJeremy Morse   auto &Children = FuncScope->getChildren();
2236af859dcSJeremy Morse   ASSERT_EQ(Children.size(), 1u);
2246af859dcSJeremy Morse   auto *BlockScope = Children[0];
2256af859dcSJeremy Morse   auto &BlockChildren = BlockScope->getChildren();
2266af859dcSJeremy Morse   ASSERT_EQ(BlockChildren.size(), 1u);
2276af859dcSJeremy Morse   auto *InlinedScope = BlockChildren[0];
2286af859dcSJeremy Morse 
2296af859dcSJeremy Morse   EXPECT_FALSE(InlinedScope->isAbstractScope());
2306af859dcSJeremy Morse   EXPECT_EQ(InlinedScope->getInlinedAt(), InlinedLoc.getInlinedAt());
2316af859dcSJeremy Morse   EXPECT_EQ(InlinedScope->getDesc(), InlinedLoc.getScope());
2326af859dcSJeremy Morse   EXPECT_EQ(InlinedScope->getChildren().size(), 0u);
2336af859dcSJeremy Morse 
2346af859dcSJeremy Morse   EXPECT_EQ(FuncScope->getParent(), nullptr);
2356af859dcSJeremy Morse   EXPECT_EQ(BlockScope->getParent(), FuncScope);
2366af859dcSJeremy Morse   EXPECT_EQ(InlinedScope->getParent(), BlockScope);
2376af859dcSJeremy Morse 
2386af859dcSJeremy Morse   const auto &AbstractScopes = LS.getAbstractScopesList();
2396af859dcSJeremy Morse   ASSERT_EQ(AbstractScopes.size(), 1u);
2406af859dcSJeremy Morse   const auto &AbstractScope = *AbstractScopes[0];
2416af859dcSJeremy Morse   EXPECT_TRUE(AbstractScope.isAbstractScope());
2426af859dcSJeremy Morse   EXPECT_EQ(AbstractScope.getDesc(), InlinedLoc.getScope());
2436af859dcSJeremy Morse   EXPECT_EQ(AbstractScope.getInlinedAt(), nullptr);
2446af859dcSJeremy Morse   EXPECT_EQ(AbstractScope.getParent(), nullptr);
2456af859dcSJeremy Morse }
2466af859dcSJeremy Morse 
2476af859dcSJeremy Morse // Test behaviour in a function that has empty DebugLocs.
2486af859dcSJeremy Morse TEST_F(LexicalScopesTest, FuncWithEmptyGap) {
2496af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), OutermostLoc, BeanInst);
2506af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), DebugLoc(), BeanInst);
2516af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), DebugLoc(), BeanInst);
2526af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), OutermostLoc, BeanInst);
2536af859dcSJeremy Morse 
2546af859dcSJeremy Morse   LexicalScopes LS;
2556af859dcSJeremy Morse   LS.initialize(*MF);
2566af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
2576af859dcSJeremy Morse 
2586af859dcSJeremy Morse   // A gap in a range that contains no other location, is not actually a
2596af859dcSJeremy Morse   // gap as far as lexical scopes are concerned.
2606af859dcSJeremy Morse   auto &Ranges = FuncScope->getRanges();
2616af859dcSJeremy Morse   ASSERT_EQ(Ranges.size(), 1u);
2626af859dcSJeremy Morse   EXPECT_EQ(Ranges[0].first, &*MF->begin()->begin());
2636af859dcSJeremy Morse   auto BBIt = MF->end();
2646af859dcSJeremy Morse   BBIt = std::prev(BBIt);
2656af859dcSJeremy Morse   EXPECT_EQ(Ranges[0].second, &*BBIt->begin());
2666af859dcSJeremy Morse }
2676af859dcSJeremy Morse 
2686af859dcSJeremy Morse // Now a function with intervening not-in-scope instructions.
2696af859dcSJeremy Morse TEST_F(LexicalScopesTest, FuncWithRealGap) {
2706af859dcSJeremy Morse   MachineInstr *FirstI = BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
2716af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), OutermostLoc, BeanInst);
2726af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), OutermostLoc, BeanInst);
2736af859dcSJeremy Morse   MachineInstr *LastI = BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
2746af859dcSJeremy Morse 
2756af859dcSJeremy Morse   LexicalScopes LS;
2766af859dcSJeremy Morse   LS.initialize(*MF);
2776af859dcSJeremy Morse   LexicalScope *BlockScope = LS.findLexicalScope(InBlockLoc.get());
2786af859dcSJeremy Morse   ASSERT_NE(BlockScope, nullptr);
2796af859dcSJeremy Morse 
2806af859dcSJeremy Morse   // Within the block scope, there's a gap between the first and last
2816af859dcSJeremy Morse   // block / instruction, where it's only the outermost scope.
2826af859dcSJeremy Morse   auto &Ranges = BlockScope->getRanges();
2836af859dcSJeremy Morse   ASSERT_EQ(Ranges.size(), 2u);
2846af859dcSJeremy Morse   EXPECT_EQ(Ranges[0].first, FirstI);
2856af859dcSJeremy Morse   EXPECT_EQ(Ranges[0].second, FirstI);
2866af859dcSJeremy Morse   EXPECT_EQ(Ranges[1].first, LastI);
2876af859dcSJeremy Morse   EXPECT_EQ(Ranges[1].second, LastI);
2886af859dcSJeremy Morse 
2896af859dcSJeremy Morse   // The outer function scope should cover the whole function, including
2906af859dcSJeremy Morse   // blocks the lexicalblock covers.
2916af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
2926af859dcSJeremy Morse   auto &FuncRanges = FuncScope->getRanges();
2936af859dcSJeremy Morse   ASSERT_EQ(FuncRanges.size(), 1u);
2946af859dcSJeremy Morse   EXPECT_NE(FuncRanges[0].first, FuncRanges[0].second);
2956af859dcSJeremy Morse   EXPECT_EQ(FuncRanges[0].first, FirstI);
2966af859dcSJeremy Morse   EXPECT_EQ(FuncRanges[0].second, LastI);
2976af859dcSJeremy Morse }
2986af859dcSJeremy Morse 
2996af859dcSJeremy Morse // Examine the relationship between two scopes that don't nest (are siblings).
3006af859dcSJeremy Morse TEST_F(LexicalScopesTest, NotNested) {
3016af859dcSJeremy Morse   MachineInstr *FirstI = BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
3026af859dcSJeremy Morse   MachineInstr *SecondI =
3036af859dcSJeremy Morse       BuildMI(*MBB2, MBB2->end(), NotNestedBlockLoc, BeanInst);
3046af859dcSJeremy Morse   MachineInstr *ThirdI =
3056af859dcSJeremy Morse       BuildMI(*MBB3, MBB3->end(), NotNestedBlockLoc, BeanInst);
3066af859dcSJeremy Morse   MachineInstr *FourthI = BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
3076af859dcSJeremy Morse 
3086af859dcSJeremy Morse   LexicalScopes LS;
3096af859dcSJeremy Morse   LS.initialize(*MF);
3106af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
3116af859dcSJeremy Morse   LexicalScope *BlockScope = LS.findLexicalScope(InBlockLoc.get());
3126af859dcSJeremy Morse   LexicalScope *OtherBlockScope = LS.findLexicalScope(NotNestedBlockLoc.get());
3136af859dcSJeremy Morse   ASSERT_NE(FuncScope, nullptr);
3146af859dcSJeremy Morse   ASSERT_NE(BlockScope, nullptr);
3156af859dcSJeremy Morse   ASSERT_NE(OtherBlockScope, nullptr);
3166af859dcSJeremy Morse 
3176af859dcSJeremy Morse   // The function should cover everything; the two blocks are distinct and
3186af859dcSJeremy Morse   // should not.
3196af859dcSJeremy Morse   auto &FuncRanges = FuncScope->getRanges();
3206af859dcSJeremy Morse   ASSERT_EQ(FuncRanges.size(), 1u);
3216af859dcSJeremy Morse   EXPECT_EQ(FuncRanges[0].first, FirstI);
3226af859dcSJeremy Morse   EXPECT_EQ(FuncRanges[0].second, FourthI);
3236af859dcSJeremy Morse 
3246af859dcSJeremy Morse   // Two ranges, start and end instructions.
3256af859dcSJeremy Morse   auto &BlockRanges = BlockScope->getRanges();
3266af859dcSJeremy Morse   ASSERT_EQ(BlockRanges.size(), 2u);
3276af859dcSJeremy Morse   EXPECT_EQ(BlockRanges[0].first, FirstI);
3286af859dcSJeremy Morse   EXPECT_EQ(BlockRanges[0].second, FirstI);
3296af859dcSJeremy Morse   EXPECT_EQ(BlockRanges[1].first, FourthI);
3306af859dcSJeremy Morse   EXPECT_EQ(BlockRanges[1].second, FourthI);
3316af859dcSJeremy Morse 
3326af859dcSJeremy Morse   // One inner range, covering the two inner blocks.
3336af859dcSJeremy Morse   auto &OtherBlockRanges = OtherBlockScope->getRanges();
3346af859dcSJeremy Morse   ASSERT_EQ(OtherBlockRanges.size(), 1u);
3356af859dcSJeremy Morse   EXPECT_EQ(OtherBlockRanges[0].first, SecondI);
3366af859dcSJeremy Morse   EXPECT_EQ(OtherBlockRanges[0].second, ThirdI);
3376af859dcSJeremy Morse }
3386af859dcSJeremy Morse 
3396af859dcSJeremy Morse // Test the scope-specific and block-specific dominates methods.
3406af859dcSJeremy Morse TEST_F(LexicalScopesTest, TestDominates) {
3416af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
3426af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), NotNestedBlockLoc, BeanInst);
3436af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), NotNestedBlockLoc, BeanInst);
3446af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
3456af859dcSJeremy Morse 
3466af859dcSJeremy Morse   LexicalScopes LS;
3476af859dcSJeremy Morse   LS.initialize(*MF);
3486af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
3496af859dcSJeremy Morse   LexicalScope *BlockScope = LS.findLexicalScope(InBlockLoc.get());
3506af859dcSJeremy Morse   LexicalScope *OtherBlockScope = LS.findLexicalScope(NotNestedBlockLoc.get());
3516af859dcSJeremy Morse   ASSERT_NE(FuncScope, nullptr);
3526af859dcSJeremy Morse   ASSERT_NE(BlockScope, nullptr);
3536af859dcSJeremy Morse   ASSERT_NE(OtherBlockScope, nullptr);
3546af859dcSJeremy Morse 
3556af859dcSJeremy Morse   EXPECT_TRUE(FuncScope->dominates(BlockScope));
3566af859dcSJeremy Morse   EXPECT_TRUE(FuncScope->dominates(OtherBlockScope));
3576af859dcSJeremy Morse   EXPECT_FALSE(BlockScope->dominates(FuncScope));
3586af859dcSJeremy Morse   EXPECT_FALSE(BlockScope->dominates(OtherBlockScope));
3596af859dcSJeremy Morse   EXPECT_FALSE(OtherBlockScope->dominates(FuncScope));
3606af859dcSJeremy Morse   EXPECT_FALSE(OtherBlockScope->dominates(BlockScope));
3616af859dcSJeremy Morse 
3626af859dcSJeremy Morse   // Outermost scope dominates everything, as all insts are within it.
3636af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB1));
3646af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB2));
3656af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB3));
3666af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB4));
3676af859dcSJeremy Morse 
3686af859dcSJeremy Morse   // One inner block dominates the outer pair of blocks,
3696af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(InBlockLoc.get(), MBB1));
3706af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(InBlockLoc.get(), MBB2));
3716af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(InBlockLoc.get(), MBB3));
3726af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(InBlockLoc.get(), MBB4));
3736af859dcSJeremy Morse 
3746af859dcSJeremy Morse   // While the other dominates the inner two blocks.
3756af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(NotNestedBlockLoc.get(), MBB1));
3766af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(NotNestedBlockLoc.get(), MBB2));
3776af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(NotNestedBlockLoc.get(), MBB3));
3786af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(NotNestedBlockLoc.get(), MBB4));
3796af859dcSJeremy Morse }
3806af859dcSJeremy Morse 
3816af859dcSJeremy Morse // Test getMachineBasicBlocks returns all dominated blocks.
3826af859dcSJeremy Morse TEST_F(LexicalScopesTest, TestGetBlocks) {
3836af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
3846af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), NotNestedBlockLoc, BeanInst);
3856af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), NotNestedBlockLoc, BeanInst);
3866af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
3876af859dcSJeremy Morse 
3886af859dcSJeremy Morse   LexicalScopes LS;
3896af859dcSJeremy Morse   LS.initialize(*MF);
3906af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
3916af859dcSJeremy Morse   LexicalScope *BlockScope = LS.findLexicalScope(InBlockLoc.get());
3926af859dcSJeremy Morse   LexicalScope *OtherBlockScope = LS.findLexicalScope(NotNestedBlockLoc.get());
3936af859dcSJeremy Morse   ASSERT_NE(FuncScope, nullptr);
3946af859dcSJeremy Morse   ASSERT_NE(BlockScope, nullptr);
3956af859dcSJeremy Morse   ASSERT_NE(OtherBlockScope, nullptr);
3966af859dcSJeremy Morse 
3976af859dcSJeremy Morse   SmallPtrSet<const MachineBasicBlock *, 4> OutermostBlocks, InBlockBlocks,
3986af859dcSJeremy Morse       NotNestedBlockBlocks;
3996af859dcSJeremy Morse   LS.getMachineBasicBlocks(OutermostLoc.get(), OutermostBlocks);
4006af859dcSJeremy Morse   LS.getMachineBasicBlocks(InBlockLoc.get(), InBlockBlocks);
4016af859dcSJeremy Morse   LS.getMachineBasicBlocks(NotNestedBlockLoc.get(), NotNestedBlockBlocks);
4026af859dcSJeremy Morse 
4036af859dcSJeremy Morse   EXPECT_EQ(OutermostBlocks.count(MBB1), 1u);
4046af859dcSJeremy Morse   EXPECT_EQ(OutermostBlocks.count(MBB2), 1u);
4056af859dcSJeremy Morse   EXPECT_EQ(OutermostBlocks.count(MBB3), 1u);
4066af859dcSJeremy Morse   EXPECT_EQ(OutermostBlocks.count(MBB4), 1u);
4076af859dcSJeremy Morse 
4086af859dcSJeremy Morse   EXPECT_EQ(InBlockBlocks.count(MBB1), 1u);
4096af859dcSJeremy Morse   EXPECT_EQ(InBlockBlocks.count(MBB2), 0u);
4106af859dcSJeremy Morse   EXPECT_EQ(InBlockBlocks.count(MBB3), 0u);
4116af859dcSJeremy Morse   EXPECT_EQ(InBlockBlocks.count(MBB4), 1u);
4126af859dcSJeremy Morse 
4136af859dcSJeremy Morse   EXPECT_EQ(NotNestedBlockBlocks.count(MBB1), 0u);
4146af859dcSJeremy Morse   EXPECT_EQ(NotNestedBlockBlocks.count(MBB2), 1u);
4156af859dcSJeremy Morse   EXPECT_EQ(NotNestedBlockBlocks.count(MBB3), 1u);
4166af859dcSJeremy Morse   EXPECT_EQ(NotNestedBlockBlocks.count(MBB4), 0u);
4176af859dcSJeremy Morse }
4186af859dcSJeremy Morse 
4196af859dcSJeremy Morse TEST_F(LexicalScopesTest, TestMetaInst) {
4206af859dcSJeremy Morse   // Instruction Layout looks like this, where 'F' means funcscope, and
4216af859dcSJeremy Morse   // 'B' blockscope:
4226af859dcSJeremy Morse   // bb1:
4236af859dcSJeremy Morse   //   F: bean
4246af859dcSJeremy Morse   //   B: bean
4256af859dcSJeremy Morse   // bb2:
4266af859dcSJeremy Morse   //   F: bean
4276af859dcSJeremy Morse   //   B: DBG_VALUE
4286af859dcSJeremy Morse   // bb3:
4296af859dcSJeremy Morse   //   F: bean
4306af859dcSJeremy Morse   //   B: DBG_VALUE
4316af859dcSJeremy Morse   // bb4:
4326af859dcSJeremy Morse   //   F: bean
4336af859dcSJeremy Morse   //   B: bean
4346af859dcSJeremy Morse   // The block / 'B' should only dominate bb1 and bb4. DBG_VALUE is a meta
4356af859dcSJeremy Morse   // instruction, and shouldn't contribute to scopes.
4366af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), OutermostLoc, BeanInst);
4376af859dcSJeremy Morse   BuildMI(*MBB1, MBB1->end(), InBlockLoc, BeanInst);
4386af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), OutermostLoc, BeanInst);
4396af859dcSJeremy Morse   BuildMI(*MBB2, MBB2->end(), InBlockLoc, DbgValueInst);
4406af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), OutermostLoc, BeanInst);
4416af859dcSJeremy Morse   BuildMI(*MBB3, MBB3->end(), InBlockLoc, DbgValueInst);
4426af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), OutermostLoc, BeanInst);
4436af859dcSJeremy Morse   BuildMI(*MBB4, MBB4->end(), InBlockLoc, BeanInst);
4446af859dcSJeremy Morse 
4456af859dcSJeremy Morse   LexicalScopes LS;
4466af859dcSJeremy Morse   LS.initialize(*MF);
4476af859dcSJeremy Morse   LexicalScope *FuncScope = LS.getCurrentFunctionScope();
4486af859dcSJeremy Morse   LexicalScope *BlockScope = LS.findLexicalScope(InBlockLoc.get());
4496af859dcSJeremy Morse   ASSERT_NE(FuncScope, nullptr);
4506af859dcSJeremy Morse   ASSERT_NE(BlockScope, nullptr);
4516af859dcSJeremy Morse 
4526af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB1));
4536af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB2));
4546af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB3));
4556af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(OutermostLoc.get(), MBB4));
4566af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(InBlockLoc.get(), MBB1));
4576af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(InBlockLoc.get(), MBB2));
4586af859dcSJeremy Morse   EXPECT_FALSE(LS.dominates(InBlockLoc.get(), MBB3));
4596af859dcSJeremy Morse   EXPECT_TRUE(LS.dominates(InBlockLoc.get(), MBB4));
4606af859dcSJeremy Morse }
4616af859dcSJeremy Morse 
4626af859dcSJeremy Morse } // anonymous namespace
463