Index: llvm/trunk/lib/CodeGen/BranchFolding.h =================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.h +++ llvm/trunk/lib/CodeGen/BranchFolding.h @@ -153,6 +153,7 @@ MachineBasicBlock *SuccBB, unsigned maxCommonTailLength, unsigned &commonTailIndex); + void MergeCommonTailDebugLocs(unsigned commonTailIndex); bool OptimizeBranches(MachineFunction &MF); bool OptimizeBlock(MachineBasicBlock *MBB); Index: llvm/trunk/lib/CodeGen/BranchFolding.cpp =================================================================== --- llvm/trunk/lib/CodeGen/BranchFolding.cpp +++ llvm/trunk/lib/CodeGen/BranchFolding.cpp @@ -32,6 +32,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -753,6 +754,45 @@ return true; } +/// MergeCommonTailDebugLocs - Create merged DebugLocs of identical instructions +/// across SameTails and assign it to the instruction in common tail. +void BranchFolder::MergeCommonTailDebugLocs(unsigned commonTailIndex) { + MachineBasicBlock *MBB = SameTails[commonTailIndex].getBlock(); + + std::vector NextCommonInsts(SameTails.size()); + for (unsigned int i = 0 ; i != SameTails.size() ; ++i) { + if (i != commonTailIndex) + NextCommonInsts[i] = SameTails[i].getTailStartPos(); + else { + assert(SameTails[i].getTailStartPos() == MBB->begin() && + "MBB is not a common tail only block"); + } + } + + for (auto &MI : *MBB) { + if (MI.isDebugValue()) + continue; + DebugLoc DL = MI.getDebugLoc(); + for (unsigned int i = 0 ; i < NextCommonInsts.size() ; i++) { + if (i == commonTailIndex) + continue; + + auto &Pos = NextCommonInsts[i]; + assert(Pos != SameTails[i].getBlock()->end() && + "Reached BB end within common tail"); + while (Pos->isDebugValue()) { + ++Pos; + assert(Pos != SameTails[i].getBlock()->end() && + "Reached BB end within common tail"); + } + assert(MI.isIdenticalTo(*Pos) && "Expected matching MIIs!"); + DL = DILocation::getMergedLocation(DL, Pos->getDebugLoc()); + NextCommonInsts[i] = ++Pos; + } + MI.setDebugLoc(DL); + } +} + static void mergeOperations(MachineBasicBlock::iterator MBBIStartPos, MachineBasicBlock &MBBCommon) { @@ -905,10 +945,8 @@ // Recompute common tail MBB's edge weights and block frequency. setCommonTailEdgeWeights(*MBB); - // Remove the original debug location from the common tail. - for (auto &MI : *MBB) - if (!MI.isDebugValue()) - MI.setDebugLoc(DebugLoc()); + // Merge debug locations across identical instructions for common tail + MergeCommonTailDebugLocs(commonTailIndex); // MBB is common tail. Adjust all other BB's to jump to this one. // Traversal must be forwards so erases work. Index: llvm/trunk/test/CodeGen/X86/tail-merge-debugloc.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/tail-merge-debugloc.ll +++ llvm/trunk/test/CodeGen/X86/tail-merge-debugloc.ll @@ -0,0 +1,42 @@ +; RUN: llc -stop-after=branch-folder < %s | FileCheck %s +; +; bb2 and bb3 in the IR below will be tail-merged into a single basic block. +; As br instructions in bb2 and bb3 have the same debug location, make sure that +; the branch instruction in the merged basic block still maintains the debug +; location info. +; +; CHECK: [[DLOC:![0-9]+]] = !DILocation(line: 2, column: 2, scope: !{{[0-9]+}}) +; CHECK: TEST64rr{{.*}}%rsi, %rsi, implicit-def %eflags +; CHECK-NEXT: JNE_1{{.*}}, debug-location [[DLOC]] + +target triple = "x86_64-unknown-linux-gnu" + +define i32 @foo(i1 %b, i8* %p) { +bb1: + br i1 %b, label %bb2, label %bb3 + +bb2: + %a1 = icmp eq i8* %p, null + br i1 %a1, label %bb4, label %bb5, !dbg !6 + +bb3: + %a2 = icmp eq i8* %p, null + br i1 %a2, label %bb4, label %bb5, !dbg !6 + +bb4: + ret i32 1 + +bb5: + ret i32 0 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1) +!1 = !DIFile(filename: "foo.c", directory: "b/") +!2 = !{i32 2, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0) +!5 = distinct !DILexicalBlock(scope: !4, file: !1, line: 1, column: 1) +!6 = !DILocation(line: 2, column: 2, scope: !5)