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