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