diff --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h index 44ab3ba4784d..1c5137f305b6 100644 --- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h +++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h @@ -1066,31 +1066,33 @@ public: /// 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 index 48b2aa40cab6..1e923185de2e 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -1462,7 +1462,7 @@ void MachineBasicBlock::replacePhiUsesWith(MachineBasicBlock *Old, } } -/// 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) { @@ -1481,13 +1481,15 @@ DebugLoc MachineBasicBlock::rfindDebugLoc(reverse_instr_iterator MBBI) { 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 index a4d761bee5a4..f3a5b0f8e75d 100644 --- a/llvm/unittests/CodeGen/CMakeLists.txt +++ b/llvm/unittests/CodeGen/CMakeLists.txt @@ -28,6 +28,7 @@ add_llvm_unittest(CodeGenTests 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 index 000000000000..e88b21c2d679 --- /dev/null +++ b/llvm/unittests/CodeGen/MachineBasicBlockTest.cpp @@ -0,0 +1,107 @@ +//===- 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); + DebugLoc DL3 = DILocation::get(Ctx, 3, 0, OurFunc); + + // Test using and empty MBB. + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_end())); + + // FIXME: This would crash (see https://reviews.llvm.org/D150577). + //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 DL3. + // Also add a DBG_VALUE with a different DebugLoc in between. + MCInstrDesc COPY = {TargetOpcode::COPY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + MCInstrDesc DBG = {TargetOpcode::DBG_VALUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + auto MI3 = MF->CreateMachineInstr(COPY, DL3); + MBB.insert(MBB.begin(), MI3); + auto MI2 = MF->CreateMachineInstr(DBG, DL2); + MBB.insert(MBB.begin(), MI2); + auto MI1 = MF->CreateMachineInstr(COPY, DL1); + MBB.insert(MBB.begin(), MI1); + + // Test using two MIs with a debug instruction in between. + EXPECT_EQ(DL1, MBB.findDebugLoc(MBB.instr_begin())); + EXPECT_EQ(DL1, MBB.findDebugLoc(MI1)); + EXPECT_EQ(DL3, MBB.findDebugLoc(MI2)); + EXPECT_EQ(DL3, MBB.findDebugLoc(MI3)); + EXPECT_EQ(DL0, MBB.findDebugLoc(MBB.instr_end())); + + // FIXME: This would crash (see https://reviews.llvm.org/D150577). + //EXPECT_EQ(DL1, MBB.rfindDebugLoc(MBB.instr_rend())); + EXPECT_EQ(DL1, MBB.rfindDebugLoc(MI1)); + EXPECT_EQ(DL3, MBB.rfindDebugLoc(MI2)); + EXPECT_EQ(DL3, MBB.rfindDebugLoc(MI3)); + EXPECT_EQ(DL3, 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(DL1, MBB.findPrevDebugLoc(MI3)); + EXPECT_EQ(DL3, 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(MI3)); + 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 index 26dfe98049c0..a2565b2dd81c 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/CodeGen/BUILD.gn @@ -31,6 +31,7 @@ unittest("CodeGenTests") { "LexicalScopesTest.cpp", "LowLevelTypeTest.cpp", "MLRegallocDevelopmentFeatures.cpp", + "MachineBasicBlockTest.cpp", "MachineInstrBundleIteratorTest.cpp", "MachineInstrTest.cpp", "MachineOperandTest.cpp",