forked from OSchip/llvm-project
[DebugInfo][InstrRef] Add a size operand to DBG_PHI
DBG_PHI instructions can refer to stack slots, to indicate that multiple values merge together on control flow joins in that slot. This is fine -- however the slot might be merged at a later date with a slot of a different size. In doing so, we lose information about the size the eliminated PHI. Later analysis passes have to guess. Improve this by attaching an optional "bit size" operand to DBG_PHI, which only gets added for stack slots, to let us know how large a size the value on the stack is. Differential Revision: https://reviews.llvm.org/D124184
This commit is contained in:
parent
00f0c805ff
commit
fda4305e53
|
@ -1293,41 +1293,16 @@ bool InstrRefBasedLDV::transferDebugPHI(MachineInstr &MI) {
|
|||
if (!SpillNo)
|
||||
return EmitBadPHI();
|
||||
|
||||
// Problem: what value should we extract from the stack? LLVM does not
|
||||
// record what size the last store to the slot was, and it would become
|
||||
// sketchy after stack slot colouring anyway. Take a look at what values
|
||||
// are stored on the stack, and pick the largest one that wasn't def'd
|
||||
// by a spill (i.e., the value most likely to have been def'd in a register
|
||||
// and then spilt.
|
||||
std::array<unsigned, 4> CandidateSizes = {64, 32, 16, 8};
|
||||
Optional<ValueIDNum> Result = None;
|
||||
Optional<LocIdx> SpillLoc = None;
|
||||
for (unsigned CS : CandidateSizes) {
|
||||
unsigned SpillID = MTracker->getLocID(*SpillNo, {CS, 0});
|
||||
SpillLoc = MTracker->getSpillMLoc(SpillID);
|
||||
ValueIDNum Val = MTracker->readMLoc(*SpillLoc);
|
||||
// If this value was defined in it's own position, then it was probably
|
||||
// an aliasing index of a small value that was spilt.
|
||||
if (Val.getLoc() != SpillLoc->asU64()) {
|
||||
Result = Val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Any stack location DBG_PHI should have an associate bit-size.
|
||||
assert(MI.getNumOperands() == 3 && "Stack DBG_PHI with no size?");
|
||||
unsigned slotBitSize = MI.getOperand(2).getImm();
|
||||
|
||||
// If we didn't find anything, we're probably looking at a PHI, or a memory
|
||||
// store folded into an instruction. FIXME: Take a guess that's it's 64
|
||||
// bits. This isn't ideal, but tracking the size that the spill is
|
||||
// "supposed" to be is more complex, and benefits a small number of
|
||||
// locations.
|
||||
if (!Result) {
|
||||
unsigned SpillID = MTracker->getLocID(*SpillNo, {64, 0});
|
||||
SpillLoc = MTracker->getSpillMLoc(SpillID);
|
||||
Result = MTracker->readMLoc(*SpillLoc);
|
||||
}
|
||||
unsigned SpillID = MTracker->getLocID(*SpillNo, {slotBitSize, 0});
|
||||
LocIdx SpillLoc = MTracker->getSpillMLoc(SpillID);
|
||||
ValueIDNum Result = MTracker->readMLoc(SpillLoc);
|
||||
|
||||
// Record this DBG_PHI for later analysis.
|
||||
auto DbgPHI =
|
||||
DebugPHIRecord({InstrNum, MI.getParent(), *Result, *SpillLoc});
|
||||
auto DbgPHI = DebugPHIRecord({InstrNum, MI.getParent(), Result, SpillLoc});
|
||||
DebugPHINumToValue.push_back(DbgPHI);
|
||||
} else {
|
||||
// Else: if the operand is neither a legal register or a stack slot, then
|
||||
|
|
|
@ -1850,16 +1850,33 @@ void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
|
|||
const TargetRegisterClass *TRC = MRI.getRegClass(Reg);
|
||||
unsigned SpillSize, SpillOffset;
|
||||
|
||||
// Test whether this location is legal with the given subreg.
|
||||
unsigned regSizeInBits = TRI->getRegSizeInBits(*TRC);
|
||||
if (SubReg)
|
||||
regSizeInBits = TRI->getSubRegIdxSize(SubReg);
|
||||
|
||||
// Test whether this location is legal with the given subreg. If the
|
||||
// subregister has a nonzero offset, drop this location, it's too complex
|
||||
// to describe. (TODO: future work).
|
||||
bool Success =
|
||||
TII->getStackSlotRange(TRC, SubReg, SpillSize, SpillOffset, *MF);
|
||||
|
||||
if (Success) {
|
||||
if (Success && SpillOffset == 0) {
|
||||
auto Builder = BuildMI(*OrigMBB, OrigMBB->begin(), DebugLoc(),
|
||||
TII->get(TargetOpcode::DBG_PHI));
|
||||
Builder.addFrameIndex(VRM->getStackSlot(Reg));
|
||||
Builder.addImm(InstNum);
|
||||
// Record how large the original value is. The stack slot might be
|
||||
// merged and altered during optimisation, but we will want to know how
|
||||
// large the value is, at this DBG_PHI.
|
||||
Builder.addImm(regSizeInBits);
|
||||
}
|
||||
|
||||
LLVM_DEBUG(
|
||||
if (SpillOffset != 0) {
|
||||
dbgs() << "DBG_PHI for Vreg " << Reg << " subreg " << SubReg <<
|
||||
" has nonzero offset\n";
|
||||
}
|
||||
);
|
||||
}
|
||||
// If there was no mapping for a value ID, it's optimized out. Create no
|
||||
// DBG_PHI, and any variables using this value will become optimized out.
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
|
||||
# RUN: -experimental-debug-variable-locations -run-pass=livedebugvalues\
|
||||
# RUN: | FileCheck %s
|
||||
#
|
||||
# Test that a DBG_INSTR_REF that refers to a DBG_PHI, will be translated into a
|
||||
# DBG_VALUE of the value read at that DBG_PHI -- in this test, when the value
|
||||
# is on the stack.
|
||||
#
|
||||
--- |
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define dso_local i32 @foo(i64 %bar, i64 %baz) !dbg !7 {
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
declare dso_local void @ext(i64)
|
||||
|
||||
declare dso_local i64 @getlong()
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.c", directory: "/tmp/out.c")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!""}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10, !11, !11}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DIBasicType(name: "long int", size: 64, encoding: DW_ATE_signed)
|
||||
!12 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 3, type: !11)
|
||||
!13 = !DILocation(line: 0, scope: !7)
|
||||
!14 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 3, type: !11)
|
||||
!19 = distinct !DILexicalBlock(scope: !7, file: !1, line: 8, column: 7)
|
||||
!26 = !DILocation(line: 13, column: 3, scope: !7)
|
||||
|
||||
...
|
||||
---
|
||||
name: foo
|
||||
alignment: 16
|
||||
tracksRegLiveness: true
|
||||
liveins:
|
||||
- { reg: '$rdi' }
|
||||
- { reg: '$rsi' }
|
||||
frameInfo:
|
||||
stackSize: 24
|
||||
offsetAdjustment: -24
|
||||
maxAlignment: 1
|
||||
adjustsStack: true
|
||||
hasCalls: true
|
||||
maxCallFrameSize: 0
|
||||
cvBytesOfCalleeSavedRegisters: 16
|
||||
fixedStack:
|
||||
- { id: 0, type: spill-slot, offset: -24, size: 8, alignment: 8, callee-saved-register: '$rbx' }
|
||||
- { id: 1, type: spill-slot, offset: -16, size: 8, alignment: 16, callee-saved-register: '$r14' }
|
||||
machineFunctionInfo: {}
|
||||
stack:
|
||||
- { id: 0, name: '', type: spill-slot, offset: 0, size: 8, alignment: 8,
|
||||
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
|
||||
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
||||
|
||||
body: |
|
||||
bb.0:
|
||||
liveins: $rdi, $rsi, $r14, $rbx
|
||||
; CHECK-LABEL: bb.0:
|
||||
|
||||
$r14 = MOV64rr $rsi
|
||||
$rbx = MOV64rr $rdi
|
||||
$rax = MOV64ri 0
|
||||
MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
|
||||
$rax = MOV64ri 0
|
||||
|
||||
;; A DBG_PHI of the stack should resolve to the stack location.
|
||||
DBG_PHI %stack.0, 1, 64
|
||||
|
||||
;; Reload value, clobber stack location.
|
||||
$rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
|
||||
MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
|
||||
|
||||
;; This should resolve to the loaded register.
|
||||
DBG_INSTR_REF 1, 0, !12, !DIExpression(), debug-location !13
|
||||
; CHECK: DBG_INSTR_REF 1, 0,
|
||||
; CHECK-NEXT: DBG_VALUE $rcx
|
||||
|
||||
;; And if we say it's a smaller size, we should be able to pick out smaller
|
||||
;; subregisters within the stack slot.
|
||||
DBG_PHI %stack.0, 2, 32
|
||||
$rax = MOV64ri 0
|
||||
$rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
|
||||
MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
|
||||
|
||||
;; This should pick out the 32 bit value.
|
||||
DBG_INSTR_REF 2, 0, !12, !DIExpression(), debug-location !13
|
||||
; CHECK: DBG_INSTR_REF 2, 0,
|
||||
; CHECK-NEXT: DBG_VALUE $ecx
|
||||
|
||||
;; Try all the other subregs.
|
||||
DBG_PHI %stack.0, 3, 16
|
||||
$rax = MOV64ri 0
|
||||
$rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
|
||||
MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
|
||||
|
||||
DBG_INSTR_REF 3, 0, !12, !DIExpression(), debug-location !13
|
||||
; CHECK: DBG_INSTR_REF 3, 0,
|
||||
; CHECK-NEXT: DBG_VALUE $cx
|
||||
|
||||
DBG_PHI %stack.0, 4, 8
|
||||
$rax = MOV64ri 0
|
||||
$rcx = MOV64rm $rsp, 1, $noreg, 8, $noreg :: (load 8 from %stack.0)
|
||||
MOV64mr $rsp, 1, $noreg, 16, $noreg, $rax :: (store 8 into %stack.0)
|
||||
|
||||
DBG_INSTR_REF 4, 0, !12, !DIExpression(), debug-location !13
|
||||
; CHECK: DBG_INSTR_REF 4, 0,
|
||||
; CHECK-NEXT: DBG_VALUE $cl
|
||||
|
||||
;; We can't, at this time, describe subregister fields with nonzero offset.
|
||||
;; It's easily achieved by attaching more data to stack DBG_PHIs, but it's
|
||||
;; not clear that LLVM will ever merge registers to generate such locations.
|
||||
|
||||
RET64 implicit $eax, debug-location !26
|
||||
|
||||
...
|
|
@ -0,0 +1,156 @@
|
|||
# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
|
||||
# RUN: -experimental-debug-variable-locations \
|
||||
# RUN: -start-before=phi-node-elimination -stop-after=virtregrewriter \
|
||||
# RUN: | FileCheck %s
|
||||
#
|
||||
# Like phi-through-regalloc.mir, pass a PHI node into register allocation, and
|
||||
# test that it correctly comes out, in a stack slot. In this test the desired
|
||||
# value is a 16 bit copy of an argument, and the PHI register class is 16 bits.
|
||||
# It's subsequently coalesced into a larger vreg, which is then spilt as a 32
|
||||
# bit value.
|
||||
# Test that the coalescing happens (32 bits stored and loaded), but that we
|
||||
# record in the relevant DBG_PHI that the original value was 16 bits in size.
|
||||
# This avoids later ambiguity about how large the value on the stack is.
|
||||
|
||||
--- |
|
||||
; ModuleID = 'promoted.ll'
|
||||
source_filename = "test.c"
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define dso_local i32 @foo(i32 %bar, i32 %baz) !dbg !7 {
|
||||
entry:
|
||||
ret i32 0, !dbg !19
|
||||
}
|
||||
|
||||
declare dso_local i32 @ext(i32)
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.c", directory: ".")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"."}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10, !10, !10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 2, type: !10)
|
||||
!12 = !DILocation(line: 0, scope: !7)
|
||||
!13 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 2, type: !10)
|
||||
!14 = !DILocalVariable(name: "either", scope: !7, file: !1, line: 3, type: !10)
|
||||
!15 = !DILocation(line: 4, column: 7, scope: !16)
|
||||
!16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 7)
|
||||
!17 = !DILocation(line: 4, column: 7, scope: !7)
|
||||
!18 = !DILocation(line: 0, scope: !16)
|
||||
!19 = !DILocation(line: 9, column: 3, scope: !7)
|
||||
|
||||
...
|
||||
---
|
||||
name: foo
|
||||
alignment: 16
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: gr16 }
|
||||
- { id: 1, class: gr32 }
|
||||
- { id: 2, class: gr32 }
|
||||
- { id: 3, class: gr32 }
|
||||
- { id: 4, class: gr32 }
|
||||
liveins:
|
||||
- { reg: '$edi', virtual-reg: '%1' }
|
||||
- { reg: '$esi', virtual-reg: '%2' }
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
hasCalls: true
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
; CHECK-LABEL: bb.0:
|
||||
; CHECK: MOV32mr %stack.0, 1, $noreg, 0, $noreg, $edi
|
||||
bb.0:
|
||||
successors: %bb.2(0x50000000), %bb.1(0x30000000)
|
||||
liveins: $edi, $esi
|
||||
|
||||
DBG_VALUE $edi, $noreg, !11, !DIExpression(), debug-location !12
|
||||
DBG_VALUE $esi, $noreg, !13, !DIExpression(), debug-location !12
|
||||
%2:gr32 = COPY killed $esi
|
||||
%1:gr32 = COPY killed $edi
|
||||
%5:gr16 = COPY %1.sub_16bit
|
||||
%6:gr16 = COPY %1.sub_16bit
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
|
||||
%3:gr32 = MOV32r0 implicit-def dead $eflags
|
||||
$edi = COPY killed %3, debug-location !15
|
||||
CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !15
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
|
||||
%4:gr32 = COPY killed $eax, debug-location !15
|
||||
%10:gr32 = MOV32ri 0
|
||||
%11:gr32 = MOV32ri 1
|
||||
%12:gr32 = MOV32ri 2
|
||||
%13:gr32 = MOV32ri 3
|
||||
%14:gr32 = MOV32ri 4
|
||||
%15:gr32 = MOV32ri 5
|
||||
%16:gr32 = MOV32ri 6
|
||||
%17:gr32 = MOV32ri 7
|
||||
%18:gr32 = MOV32ri 8
|
||||
%19:gr32 = MOV32ri 9
|
||||
%20:gr32 = MOV32ri 10
|
||||
%21:gr32 = MOV32ri 11
|
||||
%22:gr32 = MOV32ri 12
|
||||
%23:gr32 = MOV32ri 13
|
||||
%24:gr32 = MOV32ri 14
|
||||
TEST32rr killed %4, %4, implicit-def $eflags, debug-location !15
|
||||
JCC_1 %bb.2, 5, implicit killed $eflags, debug-location !17
|
||||
JMP_1 %bb.1, debug-location !17
|
||||
|
||||
bb.1:
|
||||
%30:gr32 = MOV32ri 0
|
||||
%31:gr32 = MOV32ri 1
|
||||
%32:gr32 = MOV32ri 2
|
||||
%33:gr32 = MOV32ri 3
|
||||
%34:gr32 = MOV32ri 4
|
||||
%35:gr32 = MOV32ri 5
|
||||
%36:gr32 = MOV32ri 6
|
||||
%37:gr32 = MOV32ri 7
|
||||
%38:gr32 = MOV32ri 8
|
||||
%39:gr32 = MOV32ri 9
|
||||
%40:gr32 = MOV32ri 10
|
||||
%41:gr32 = MOV32ri 11
|
||||
%42:gr32 = MOV32ri 12
|
||||
%43:gr32 = MOV32ri 13
|
||||
%44:gr32 = MOV32ri 14
|
||||
|
||||
; CHECK-LABEL: bb.2:
|
||||
bb.2:
|
||||
%0:gr16 = PHI %5, %bb.0, %6, %bb.1, debug-instr-number 1, debug-location !18
|
||||
%50:gr32 = PHI %10, %bb.0, %30, %bb.1, debug-location !18
|
||||
%51:gr32 = PHI %11, %bb.0, %31, %bb.1, debug-location !18
|
||||
%52:gr32 = PHI %12, %bb.0, %32, %bb.1, debug-location !18
|
||||
%53:gr32 = PHI %13, %bb.0, %33, %bb.1, debug-location !18
|
||||
%54:gr32 = PHI %14, %bb.0, %34, %bb.1, debug-location !18
|
||||
%55:gr32 = PHI %15, %bb.0, %35, %bb.1, debug-location !18
|
||||
%56:gr32 = PHI %16, %bb.0, %36, %bb.1, debug-location !18
|
||||
%57:gr32 = PHI %17, %bb.0, %37, %bb.1, debug-location !18
|
||||
%58:gr32 = PHI %18, %bb.0, %38, %bb.1, debug-location !18
|
||||
%59:gr32 = PHI %19, %bb.0, %39, %bb.1, debug-location !18
|
||||
%60:gr32 = PHI %20, %bb.0, %40, %bb.1, debug-location !18
|
||||
%61:gr32 = PHI %21, %bb.0, %41, %bb.1, debug-location !18
|
||||
%62:gr32 = PHI %22, %bb.0, %42, %bb.1, debug-location !18
|
||||
%63:gr32 = PHI %23, %bb.0, %43, %bb.1, debug-location !18
|
||||
%64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
|
||||
|
||||
INLINEASM &"", 1, 12, %50, 12, %51, 12, %52, 12, %53, 12, %54, 12, %55, 12, %56, 12, %57, 12, %58, 12, %59, 12, %60, 12, %61, 12, %62, 12, %63, 12, %64
|
||||
DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
|
||||
; CHECK: DBG_PHI %stack.0, 1, 16
|
||||
; CHECK: DBG_INSTR_REF 1, 0
|
||||
; CHECK: renamable $eax = MOV32rm %stack.0,
|
||||
$eax = COPY killed %0, debug-location !19
|
||||
RET 0, killed $eax, debug-location !19
|
||||
|
||||
...
|
|
@ -0,0 +1,155 @@
|
|||
# RUN: llc %s -o - -mtriple=x86_64-unknown-unknown \
|
||||
# RUN: -experimental-debug-variable-locations \
|
||||
# RUN: -start-before=phi-node-elimination -stop-after=virtregrewriter \
|
||||
# RUN: | FileCheck %s
|
||||
#
|
||||
# Pass a PHI node into register allocation, and test that it is correctly
|
||||
# dropped. In this test the desired value is an 8 bit copy of an argument,
|
||||
# but it's located in an upper subregister field. That coalesces back to the
|
||||
# whole argument, which is spilt to the stack.
|
||||
#
|
||||
# Currently, DBG_PHIs can't describe non-zero offsets in stack slots, therefore
|
||||
# no DBG_PHI should be emitted. (This means there is no value for that
|
||||
# instruction/operand number, and any DBG_INSTR_REF will become a
|
||||
# DBG_VALUE $noreg.
|
||||
|
||||
--- |
|
||||
; ModuleID = 'promoted.ll'
|
||||
source_filename = "test.c"
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define dso_local i32 @foo(i32 %bar, i32 %baz) !dbg !7 {
|
||||
entry:
|
||||
ret i32 0, !dbg !19
|
||||
}
|
||||
|
||||
declare dso_local i32 @ext(i32)
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.c", directory: ".")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"."}
|
||||
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10, !10, !10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "bar", arg: 1, scope: !7, file: !1, line: 2, type: !10)
|
||||
!12 = !DILocation(line: 0, scope: !7)
|
||||
!13 = !DILocalVariable(name: "baz", arg: 2, scope: !7, file: !1, line: 2, type: !10)
|
||||
!14 = !DILocalVariable(name: "either", scope: !7, file: !1, line: 3, type: !10)
|
||||
!15 = !DILocation(line: 4, column: 7, scope: !16)
|
||||
!16 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 7)
|
||||
!17 = !DILocation(line: 4, column: 7, scope: !7)
|
||||
!18 = !DILocation(line: 0, scope: !16)
|
||||
!19 = !DILocation(line: 9, column: 3, scope: !7)
|
||||
|
||||
...
|
||||
---
|
||||
name: foo
|
||||
alignment: 16
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: gr8 }
|
||||
- { id: 1, class: gr32_abcd }
|
||||
- { id: 2, class: gr32_abcd }
|
||||
- { id: 3, class: gr32 }
|
||||
- { id: 4, class: gr32 }
|
||||
liveins:
|
||||
- { reg: '$edi', virtual-reg: '%1' }
|
||||
- { reg: '$esi', virtual-reg: '%2' }
|
||||
frameInfo:
|
||||
maxAlignment: 1
|
||||
hasCalls: true
|
||||
machineFunctionInfo: {}
|
||||
body: |
|
||||
bb.0:
|
||||
successors: %bb.2(0x50000000), %bb.1(0x30000000)
|
||||
liveins: $edi, $esi
|
||||
|
||||
DBG_VALUE $edi, $noreg, !11, !DIExpression(), debug-location !12
|
||||
DBG_VALUE $esi, $noreg, !13, !DIExpression(), debug-location !12
|
||||
%2:gr32_abcd = COPY killed $esi
|
||||
%1:gr32_abcd = COPY killed $edi
|
||||
%5:gr8 = COPY %1.sub_8bit_hi
|
||||
%6:gr8 = COPY %1.sub_8bit_hi
|
||||
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
|
||||
%3:gr32 = MOV32r0 implicit-def dead $eflags
|
||||
$edi = COPY killed %3, debug-location !15
|
||||
CALL64pcrel32 @ext, csr_64, implicit $rsp, implicit $ssp, implicit killed $edi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax, debug-location !15
|
||||
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !15
|
||||
%4:gr32 = COPY killed $eax, debug-location !15
|
||||
%10:gr32 = MOV32ri 0
|
||||
%11:gr32 = MOV32ri 1
|
||||
%12:gr32 = MOV32ri 2
|
||||
%13:gr32 = MOV32ri 3
|
||||
%14:gr32 = MOV32ri 4
|
||||
%15:gr32 = MOV32ri 5
|
||||
%16:gr32 = MOV32ri 6
|
||||
%17:gr32 = MOV32ri 7
|
||||
%18:gr32 = MOV32ri 8
|
||||
%19:gr32 = MOV32ri 9
|
||||
%20:gr32 = MOV32ri 10
|
||||
%21:gr32 = MOV32ri 11
|
||||
%22:gr32 = MOV32ri 12
|
||||
%23:gr32 = MOV32ri 13
|
||||
%24:gr32 = MOV32ri 14
|
||||
TEST32rr killed %4, %4, implicit-def $eflags, debug-location !15
|
||||
JCC_1 %bb.2, 5, implicit killed $eflags, debug-location !17
|
||||
JMP_1 %bb.1, debug-location !17
|
||||
|
||||
bb.1:
|
||||
%30:gr32 = MOV32ri 0
|
||||
%31:gr32 = MOV32ri 1
|
||||
%32:gr32 = MOV32ri 2
|
||||
%33:gr32 = MOV32ri 3
|
||||
%34:gr32 = MOV32ri 4
|
||||
%35:gr32 = MOV32ri 5
|
||||
%36:gr32 = MOV32ri 6
|
||||
%37:gr32 = MOV32ri 7
|
||||
%38:gr32 = MOV32ri 8
|
||||
%39:gr32 = MOV32ri 9
|
||||
%40:gr32 = MOV32ri 10
|
||||
%41:gr32 = MOV32ri 11
|
||||
%42:gr32 = MOV32ri 12
|
||||
%43:gr32 = MOV32ri 13
|
||||
%44:gr32 = MOV32ri 14
|
||||
|
||||
; CHECK-LABEL: bb.2:
|
||||
bb.2:
|
||||
%0:gr8 = PHI %5, %bb.0, %6, %bb.1, debug-instr-number 1, debug-location !18
|
||||
%50:gr32 = PHI %10, %bb.0, %30, %bb.1, debug-location !18
|
||||
%51:gr32 = PHI %11, %bb.0, %31, %bb.1, debug-location !18
|
||||
%52:gr32 = PHI %12, %bb.0, %32, %bb.1, debug-location !18
|
||||
%53:gr32 = PHI %13, %bb.0, %33, %bb.1, debug-location !18
|
||||
%54:gr32 = PHI %14, %bb.0, %34, %bb.1, debug-location !18
|
||||
%55:gr32 = PHI %15, %bb.0, %35, %bb.1, debug-location !18
|
||||
%56:gr32 = PHI %16, %bb.0, %36, %bb.1, debug-location !18
|
||||
%57:gr32 = PHI %17, %bb.0, %37, %bb.1, debug-location !18
|
||||
%58:gr32 = PHI %18, %bb.0, %38, %bb.1, debug-location !18
|
||||
%59:gr32 = PHI %19, %bb.0, %39, %bb.1, debug-location !18
|
||||
%60:gr32 = PHI %20, %bb.0, %40, %bb.1, debug-location !18
|
||||
%61:gr32 = PHI %21, %bb.0, %41, %bb.1, debug-location !18
|
||||
%62:gr32 = PHI %22, %bb.0, %42, %bb.1, debug-location !18
|
||||
%63:gr32 = PHI %23, %bb.0, %43, %bb.1, debug-location !18
|
||||
%64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
|
||||
|
||||
INLINEASM &"", 1, 12, %50, 12, %51, 12, %52, 12, %53, 12, %54, 12, %55, 12, %56, 12, %57, 12, %58, 12, %59, 12, %60, 12, %61, 12, %62, 12, %63, 12, %64
|
||||
DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
|
||||
; CHECK-NOT: DBG_PHI
|
||||
; CHECK: DBG_INSTR_REF 1, 0
|
||||
; CHECK-NOT: DBG_PHI
|
||||
$eax = COPY killed %0, debug-location !19
|
||||
RET 0, killed $eax, debug-location !19
|
||||
|
||||
...
|
|
@ -140,7 +140,7 @@ body: |
|
|||
%64:gr32 = PHI %24, %bb.0, %44, %bb.1, debug-location !18
|
||||
|
||||
DBG_INSTR_REF 1, 0, !14, !DIExpression(), debug-location !12
|
||||
; CHECK: DBG_PHI %stack.1, 1
|
||||
; CHECK: DBG_PHI %stack.1, 1, 32
|
||||
; CHECK: renamable $eax = MOV32rm %stack.1,
|
||||
; CHECK: DBG_INSTR_REF 1, 0
|
||||
$eax = COPY killed %0, debug-location !19
|
||||
|
|
Loading…
Reference in New Issue