Don't generate line&scope debug info for meta-instructions.

MachineInstructions that don't generate any code (such as
IMPLICIT_DEFs) should not generate any debug info either.

Fixes PR33107.

https://bugs.llvm.org/show_bug.cgi?id=33107

This reapplies r303566 without any modifications. The stage2 build
failures persisted even after reverting this patch, and looking back
through history, it looks like these tests are flaky.

llvm-svn: 303575
This commit is contained in:
Adrian Prantl 2017-05-22 20:47:09 +00:00
parent 553a8bb424
commit a76db201ad
6 changed files with 155 additions and 23 deletions

View File

@ -826,20 +826,12 @@ public:
getOperand(0).getSubReg() == getOperand(1).getSubReg();
}
/// Return true if this is a transient instruction that is
/// either very likely to be eliminated during register allocation (such as
/// copy-like instructions), or if this instruction doesn't have an
/// execution-time cost.
bool isTransient() const {
switch(getOpcode()) {
default: return false;
// Copy-like instructions are usually eliminated during register allocation.
case TargetOpcode::PHI:
case TargetOpcode::COPY:
case TargetOpcode::INSERT_SUBREG:
case TargetOpcode::SUBREG_TO_REG:
case TargetOpcode::REG_SEQUENCE:
// Pseudo-instructions that don't produce any real output.
/// Return true if this instruction doesn't produce any output in the form of
/// executable instructions.
bool isMetaInstruction() const {
switch (getOpcode()) {
default:
return false;
case TargetOpcode::IMPLICIT_DEF:
case TargetOpcode::KILL:
case TargetOpcode::CFI_INSTRUCTION:
@ -850,6 +842,23 @@ public:
}
}
/// Return true if this is a transient instruction that is either very likely
/// to be eliminated during register allocation (such as copy-like
/// instructions), or if this instruction doesn't have an execution-time cost.
bool isTransient() const {
switch (getOpcode()) {
default:
return isMetaInstruction();
// Copy-like instructions are usually eliminated during register allocation.
case TargetOpcode::PHI:
case TargetOpcode::COPY:
case TargetOpcode::INSERT_SUBREG:
case TargetOpcode::SUBREG_TO_REG:
case TargetOpcode::REG_SEQUENCE:
return true;
}
}
/// Return the number of instructions inside the MI bundle, excluding the
/// bundle header.
///

View File

@ -1025,11 +1025,11 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
bool EmptyPrologue = true;
for (const auto &MBB : *MF) {
for (const auto &MI : MBB) {
if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) &&
MI.getDebugLoc()) {
PrologEndLoc = MI.getDebugLoc();
break;
} else if (!MI.isDebugValue()) {
} else if (!MI.isMetaInstruction()) {
EmptyPrologue = false;
}
}

View File

@ -223,9 +223,9 @@ void DebugHandlerBase::endInstruction() {
return;
assert(CurMI != nullptr);
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
if (!CurMI->isDebugValue()) {
// Don't create a new label after DBG_VALUE and other instructions that don't
// generate code.
if (!CurMI->isMetaInstruction()) {
PrevLabel = nullptr;
PrevInstBB = CurMI->getParent();
}

View File

@ -1029,7 +1029,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
assert(CurMI);
// Check if source location changes, but ignore DBG_VALUE and CFI locations.
if (MI->isDebugValue() || MI->isCFIInstruction())
if (MI->isMetaInstruction())
return;
const DebugLoc &DL = MI->getDebugLoc();
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
@ -1111,7 +1111,7 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
// the beginning of the function body.
for (const auto &MBB : *MF)
for (const auto &MI : MBB)
if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) &&
if (!MI.isMetaInstruction() && !MI.getFlag(MachineInstr::FrameSetup) &&
MI.getDebugLoc())
return MI.getDebugLoc();
return DebugLoc();

View File

@ -86,8 +86,9 @@ void LexicalScopes::extractLexicalScopes(
continue;
}
// Ignore DBG_VALUE. It does not contribute to any instruction in output.
if (MInsn.isDebugValue())
// Ignore DBG_VALUE and similar instruction that do not contribute to any
// instruction in the output.
if (MInsn.isMetaInstruction())
continue;
if (RangeBeginMI) {

View File

@ -0,0 +1,122 @@
# RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s
#
# This testcase has an implicit def pseudo-iunstruction with a debug location.
#
# CHECK: .debug_info contents:
# CHECK: DW_TAG_subprogram
# CHECK: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
# CHECK-NOT: DW_TAG
# CHECK: DW_AT_specification {{.*}} "_ZN1C5m_fn3Ev"
# CHECK-NOT: DW_TAG
# Here should not be an inlined subroutine with 0 length.
# CHECK: NULL
#
# CHECK: Address Line Column File ISA Discriminator Flags
# CHECK-NEXT: ---
# CHECK-NEXT: 25 0 1 0 0 is_stmt
# CHECK-NEXT: 29 28 1 0 0 is_stmt prologue_end
# CHECK-NEXT: 29 28 1 0 0 is_stmt end_sequence
--- |
source_filename = "t.ll"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx"
%class.E = type { %class.D }
%class.D = type { %class.B }
%class.B = type { %class.A, %class.A }
%class.A = type { i8 }
%class.C = type <{ %class.E*, %class.B, [2 x i8] }>
@a = local_unnamed_addr global %class.E* null, align 4
define i32 @_ZN1C5m_fn3Ev(%class.C* nocapture) local_unnamed_addr align 2 !dbg !6 {
%2 = alloca %class.B, align 1
%3 = load %class.E*, %class.E** @a, align 4
%4 = icmp eq %class.E* %3, null
br i1 %4, label %10, label %5
; <label>:5: ; preds = %1
%6 = bitcast %class.C* %0 to %class.D**
%7 = load %class.D*, %class.D** %6, align 4
%8 = bitcast %class.D* %7 to i8*
%9 = load i8, i8* %8, align 1
br label %10
; <label>:10: ; preds = %5, %1
%11 = phi i8 [ %9, %5 ], [ undef, %1 ], !dbg !10
%12 = getelementptr inbounds %class.C, %class.C* %0, i32 0, i32 1, i32 0, i32 0
store i8 %11, i8* %12, align 1, !dbg !14
ret i32 undef
}
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "Apple LLVM version 8.1.0 (clang-802.0.30.3)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !2)
!1 = !DIFile(filename: "test.ii", directory: "/")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"PIC Level", i32 2}
!6 = distinct !DISubprogram(name: "m_fn3", linkageName: "_ZN1C5m_fn3Ev", scope: !7, file: !1, line: 25, type: !8, isLocal: false, isDefinition: true, scopeLine: 25, flags: DIFlagPrototyped, isOptimized: true, unit: !0, declaration: !9, variables: !2)
!7 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C", file: !1, line: 14, size: 64, align: 32, elements: !2, identifier: "_ZTS1C")
!8 = !DISubroutineType(types: !2)
!9 = !DISubprogram(name: "m_fn3", linkageName: "_ZN1C5m_fn3Ev", scope: !7, file: !1, line: 15, type: !8, isLocal: false, isDefinition: false, scopeLine: 15, flags: DIFlagPrototyped, isOptimized: true)
!10 = !DILocation(line: 99, column: 9, scope: !11, inlinedAt: !14)
!11 = distinct !DISubprogram(name: "m_fn1", linkageName: "_ZN1A5m_fn1Ev", scope: !12, file: !1, line: 5, type: !8, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: true, unit: !0, declaration: !13, variables: !2)
!12 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", file: !1, line: 1, size: 8, align: 8, elements: !2, identifier: "_ZTS1A")
!13 = !DISubprogram(name: "m_fn1", linkageName: "_ZN1A5m_fn1Ev", scope: !12, file: !1, line: 5, type: !8, isLocal: false, isDefinition: false, scopeLine: 5, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: true)
!14 = !DILocation(line: 29, column: 28, scope: !6)
...
---
name: _ZN1C5m_fn3Ev
alignment: 4
exposesReturnsTwice: false
noVRegs: true
legalized: false
regBankSelected: false
selected: false
tracksRegLiveness: true
liveins:
- { reg: '%rdi' }
frameInfo:
isFrameAddressTaken: false
isReturnAddressTaken: false
hasStackMap: false
hasPatchPoint: false
stackSize: 0
offsetAdjustment: 0
maxAlignment: 8
adjustsStack: false
hasCalls: false
maxCallFrameSize: 0
hasOpaqueSPAdjustment: false
hasVAStart: false
hasMustTailInVarArgFunc: false
#stack:
# - { id: 0, name: '<unnamed alloca>', offset: -16, size: 2, alignment: 8 }
body: |
bb.0 (%ir-block.1):
successors: %bb.1(0x30000000), %bb.2(0x50000000)
liveins: %rdi
CMP64mi8 %rip, 1, _, @a, _, 0, implicit-def %eflags :: (dereferenceable load 8 from @a, align 4)
JE_1 %bb.1, implicit %eflags
bb.2 (%ir-block.5):
liveins: %rdi
%rax = MOV64rm %rdi, 1, _, 0, _ :: (load 8 from %ir.6, align 4)
%al = MOV8rm killed %rax, 1, _, 0, _ :: (load 1 from %ir.8)
MOV8mr killed %rdi, 1, _, 8, _, killed %al, debug-location !14 :: (store 1 into %ir.12)
RETQ undef %eax
bb.1:
liveins: %rdi
%al = IMPLICIT_DEF debug-location !10
MOV8mr killed %rdi, 1, _, 8, _, killed %al, debug-location !14 :: (store 1 into %ir.12)
RETQ undef %eax
...