diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -1066,31 +1066,33 @@ /// instead of basic block \p Old. void replacePhiUsesWith(MachineBasicBlock *Old, MachineBasicBlock *New); - /// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE - /// and DBG_LABEL instructions. Return UnknownLoc if there is none. + /// Find the next valid DebugLoc starting at MBBI, skipping any debug + /// instructions. Return UnknownLoc if there is none. DebugLoc findDebugLoc(instr_iterator MBBI); DebugLoc findDebugLoc(iterator MBBI) { return findDebugLoc(MBBI.getInstrIterator()); } - /// Has exact same behavior as @ref findDebugLoc (it also - /// searches from the first to the last MI of this MBB) except - /// that this takes reverse iterator. + /// Has exact same behavior as @ref findDebugLoc (it also searches towards the + /// end of this MBB) except that this function takes a reverse iterator to + /// identify the starting MI. DebugLoc rfindDebugLoc(reverse_instr_iterator MBBI); DebugLoc rfindDebugLoc(reverse_iterator MBBI) { return rfindDebugLoc(MBBI.getInstrIterator()); } - /// Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE - /// instructions. Return UnknownLoc if there is none. + /// Find the previous valid DebugLoc preceding MBBI, skipping any debug + /// instructions. It is possible to find the last DebugLoc in the MBB using + /// findPrevDebugLoc(instr_end()). Return UnknownLoc if there is none. DebugLoc findPrevDebugLoc(instr_iterator MBBI); DebugLoc findPrevDebugLoc(iterator MBBI) { return findPrevDebugLoc(MBBI.getInstrIterator()); } - /// Has exact same behavior as @ref findPrevDebugLoc (it also - /// searches from the last to the first MI of this MBB) except - /// that this takes reverse iterator. + /// Has exact same behavior as @ref findPrevDebugLoc (it also searches towards + /// the beginning of this MBB) except that this function takes reverse + /// iterator to identify the starting MI. A minor difference compared to + /// findPrevDebugLoc is that we can't start scanning at "instr_end". DebugLoc rfindPrevDebugLoc(reverse_instr_iterator MBBI); DebugLoc rfindPrevDebugLoc(reverse_iterator MBBI) { return rfindPrevDebugLoc(MBBI.getInstrIterator()); diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -1391,7 +1391,7 @@ } } -/// Find the next valid DebugLoc starting at MBBI, skipping any DBG_VALUE +/// Find the next valid DebugLoc starting at MBBI, skipping any debug /// instructions. Return UnknownLoc if there is none. DebugLoc MachineBasicBlock::findDebugLoc(instr_iterator MBBI) { @@ -1403,6 +1403,8 @@ } DebugLoc MachineBasicBlock::rfindDebugLoc(reverse_instr_iterator MBBI) { + if (MBBI == instr_rend()) + return findDebugLoc(instr_begin()); // Skip debug declarations, we don't want a DebugLoc from them. MBBI = skipDebugInstructionsBackward(MBBI, instr_rbegin()); if (!MBBI->isDebugInstr()) @@ -1410,13 +1412,15 @@ return {}; } -/// Find the previous valid DebugLoc preceding MBBI, skipping and DBG_VALUE +/// Find the previous valid DebugLoc preceding MBBI, skipping any debug /// instructions. Return UnknownLoc if there is none. DebugLoc MachineBasicBlock::findPrevDebugLoc(instr_iterator MBBI) { - if (MBBI == instr_begin()) return {}; + if (MBBI == instr_begin()) + return {}; // Skip debug instructions, we don't want a DebugLoc from them. MBBI = prev_nodbg(MBBI, instr_begin()); - if (!MBBI->isDebugInstr()) return MBBI->getDebugLoc(); + if (!MBBI->isDebugInstr()) + return MBBI->getDebugLoc(); return {}; } diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt --- a/llvm/unittests/CodeGen/CMakeLists.txt +++ b/llvm/unittests/CodeGen/CMakeLists.txt @@ -27,6 +27,7 @@ InstrRefLDVTest.cpp LowLevelTypeTest.cpp LexicalScopesTest.cpp + MachineBasicBlockTest.cpp MachineInstrBundleIteratorTest.cpp MachineInstrTest.cpp MachineOperandTest.cpp diff --git a/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp b/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp @@ -0,0 +1,93 @@ +//===- MachineBasicBlockTest.cpp ------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Target/TargetMachine.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { +// Include helper functions to ease the manipulation of MachineFunctions. +#include "MFCommon.inc" + +TEST(FindDebugLocTest, DifferentIterators) { + LLVMContext Ctx; + Module Mod("Module", Ctx); + auto MF = createMachineFunction(Ctx, Mod); + auto &MBB = *MF->CreateMachineBasicBlock(); + + // Create metadata: CU, subprogram, some blocks and an inline function + // scope. + DIBuilder DIB(Mod); + DIFile *OurFile = DIB.createFile("foo.c", "/bar"); + DICompileUnit *OurCU = + DIB.createCompileUnit(dwarf::DW_LANG_C99, OurFile, "", false, "", 0); + auto OurSubT = + DIB.createSubroutineType(DIB.getOrCreateTypeArray(std::nullopt)); + DISubprogram *OurFunc = + DIB.createFunction(OurCU, "bees", "", OurFile, 1, OurSubT, 1, + DINode::FlagZero, DISubprogram::SPFlagDefinition); + + DebugLoc DL0; + DebugLoc DL1 = DILocation::get(Ctx, 1, 0, OurFunc); + DebugLoc DL2 = DILocation::get(Ctx, 2, 0, OurFunc); + + // Test with empty MBB. + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_end())); + EXPECT_EQ(DL0, MBB.rfindDebugLoc(MBB.instr_rbegin())); + EXPECT_EQ(DL0, MBB.rfindDebugLoc(MBB.instr_rend())); + EXPECT_EQ(DL0, MBB.findPrevDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL0, MBB.findPrevDebugLoc(MBB.instr_end())); + EXPECT_EQ(DL0, MBB.rfindPrevDebugLoc(MBB.instr_rbegin())); + EXPECT_EQ(DL0, MBB.rfindPrevDebugLoc(MBB.instr_rend())); + + // Insert two MIs with DebugLoc DL1 and DL2. + MCInstrDesc MCID = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + auto MI2 = MF->CreateMachineInstr(MCID, DL2); + MBB.insert(MBB.begin(), MI2); + auto MI1 = MF->CreateMachineInstr(MCID, DL1); + MBB.insert(MBB.begin(), MI1); + + // Test involving two MIs. + EXPECT_EQ(DL1, MBB.findDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL1, MBB.findDebugLoc(MI1)); + EXPECT_EQ(DL2, MBB.findDebugLoc(MI2)); + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_end())); + + EXPECT_EQ(DL1, MBB.rfindDebugLoc(MBB.instr_rend())); + EXPECT_EQ(DL1, MBB.rfindDebugLoc(MI1)); + EXPECT_EQ(DL2, MBB.rfindDebugLoc(MI2)); + EXPECT_EQ(DL2, MBB.rfindDebugLoc(MBB.instr_rbegin())); + + EXPECT_EQ(DL0, MBB.findPrevDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL0, MBB.findPrevDebugLoc(MI1)); + EXPECT_EQ(DL1, MBB.findPrevDebugLoc(MI2)); + EXPECT_EQ(DL2, MBB.findPrevDebugLoc(MBB.instr_end())); + + EXPECT_EQ(DL0, MBB.rfindPrevDebugLoc(MBB.instr_rend())); + EXPECT_EQ(DL0, MBB.rfindPrevDebugLoc(MI1)); + EXPECT_EQ(DL1, MBB.rfindPrevDebugLoc(MI2)); + EXPECT_EQ(DL1, MBB.rfindPrevDebugLoc(MBB.instr_rbegin())); +} + +} // end namespace diff --git a/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn @@ -30,6 +30,7 @@ "LexicalScopesTest.cpp", "LowLevelTypeTest.cpp", "MLRegallocDevelopmentFeatures.cpp", + "MachineBasicBlockTest.cpp", "MachineInstrBundleIteratorTest.cpp", "MachineInstrTest.cpp", "MachineOperandTest.cpp",