mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-20 19:42:54 +02:00
eca70845a6
LiveDebugVariables uses interval maps to explicitly represent DBG_VALUE intervals. DBG_VALUEs are filtered into an interval map based on their { Variable, DIExpression }. The interval map will coalesce adjacent entries that use the same { Location }. Under this model, DBG_VALUEs which refer to the same bits of the same variable will be filtered into different interval maps if they have different DIExpressions which means the original intervals will not be properly preserved. This patch fixes the problem by using { Variable, Fragment } to filter the DBG_VALUEs into maps, and coalesces adjacent entries iff they have the same { Location, DIExpression } pair. The solution is not perfect because we see the similar issues appear when partially overlapping fragments are encountered, but is far simpler than a complete solution (i.e. D70121). Fixes: pr41992, pr43957 Reviewed By: aprantl Differential Revision: https://reviews.llvm.org/D74053
155 lines
8.1 KiB
YAML
155 lines
8.1 KiB
YAML
# These tests check that DBG_VALUE intervals are correctly coalesced (or not) in
|
|
# LiveDebugVariables.
|
|
# NOTE: We do not currently handle partially overlapping fragments in LDV.
|
|
#
|
|
# The IR in this file has been modified by hand, generated from this source:
|
|
# void escape(int *);
|
|
# extern int global;
|
|
# void f(int x) {
|
|
# escape(&x);
|
|
# x = 1;
|
|
# global = x;
|
|
# x = 2;
|
|
# escape(&x);
|
|
# }
|
|
|
|
# RUN: llc %s -start-before=machine-scheduler -stop-after=virtregrewriter -o - \
|
|
# RUN: | FileCheck %s --implicit-check-not=DBG_VALUE
|
|
|
|
# Verify that DBG_VALUEs with same { Variable, Fragment } but different DIExpressions
|
|
# are not coalesced.
|
|
#
|
|
# DV1 %0 "x" (deref) --+-- Do not coalesce these because DV2 refers to the same bits.
|
|
# DV2 %0 "x" () |
|
|
# DV3 %0 "x" (deref) --+
|
|
#
|
|
# CHECK: name: f1
|
|
# CHECK: DBG_VALUE %stack.0.x.addr, $noreg, ![[VAR:[0-9]+]], !DIExpression(DW_OP_deref)
|
|
# CHECK: DBG_VALUE %stack.0.x.addr, $noreg, ![[VAR]], !DIExpression()
|
|
# CHECK: DBG_VALUE %stack.0.x.addr, $noreg, ![[VAR]], !DIExpression(DW_OP_deref)
|
|
|
|
# Verify that DBG_VALUEs with same { Variable, Fragment } and { Location, DIExpression } are
|
|
# coalesced if there are no intervening DBG_VALUEs with the same { Variable, Fragment }.
|
|
#
|
|
# DV1 %0 "x" (fragment 00 16) --+-- Coalesce these because DV2 refers to different bits.
|
|
# DV2 %0 "x" (fragment 16 16) |
|
|
# DV3 %0 "x" (fragment 00 16) --+
|
|
#
|
|
# CHECK: name: f2
|
|
# CHECK: DBG_VALUE %stack.0.x.addr, $noreg, ![[VAR:[0-9]+]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 16)
|
|
# CHECK: DBG_VALUE %stack.0.x.addr, $noreg, ![[VAR]], !DIExpression(DW_OP_LLVM_fragment, 16, 16)
|
|
|
|
--- |
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
@global = external global i32, align 4
|
|
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
|
declare void @escape(i32*)
|
|
|
|
define void @f1(i32 %x) !dbg !6 {
|
|
entry:
|
|
%x.addr = alloca i32, align 4
|
|
store i32 %x, i32* %x.addr, align 4
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !11, metadata !DIExpression(DW_OP_deref)), !dbg !12
|
|
call void @escape(i32* %x.addr), !dbg !12
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !11, metadata !DIExpression()), !dbg !12
|
|
store i32 1, i32* @global, align 4, !dbg !12
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !11, metadata !DIExpression(DW_OP_deref)), !dbg !12
|
|
store i32 2, i32* %x.addr, align 4, !dbg !12
|
|
call void @escape(i32* %x.addr), !dbg !12
|
|
ret void, !dbg !12
|
|
}
|
|
|
|
define void @f2(i32 %x) !dbg !13 {
|
|
entry:
|
|
%x.addr = alloca i32, align 4
|
|
store i32 %x, i32* %x.addr, align 4
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !14, metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 16)), !dbg !15
|
|
call void @escape(i32* %x.addr)
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !14, metadata !DIExpression(DW_OP_LLVM_fragment, 16, 16)), !dbg !15
|
|
store i32 1, i32* @global, align 4
|
|
call void @llvm.dbg.value(metadata i32* %x.addr, metadata !14, metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 16)), !dbg !15
|
|
store i32 2, i32* %x.addr, align 4
|
|
call void @escape(i32* %x.addr)
|
|
ret void
|
|
}
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
!llvm.module.flags = !{!3, !4}
|
|
!llvm.ident = !{!5}
|
|
|
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 11.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
|
!1 = !DIFile(filename: "test.c", directory: "")
|
|
!2 = !{}
|
|
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
|
!5 = !{!"clang version 11.0.0 "}
|
|
!6 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
|
|
!7 = !DISubroutineType(types: !8)
|
|
!8 = !{null, !9}
|
|
!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
!10 = !{!11}
|
|
!11 = !DILocalVariable(name: "x", arg: 1, scope: !6, file: !1, line: 3, type: !9)
|
|
!12 = !DILocation(line: 3, column: 12, scope: !6)
|
|
!13 = distinct !DISubprogram(name: "f2", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10)
|
|
!14 = !DILocalVariable(name: "x", arg: 1, scope: !13, file: !1, line: 21, type: !9)
|
|
!15 = !DILocation(line: 23, column: 12, scope: !13)
|
|
|
|
...
|
|
---
|
|
name: f1
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, name: x.addr, type: default, offset: 0, size: 4, alignment: 4,
|
|
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
|
|
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
|
body: |
|
|
bb.0.entry:
|
|
liveins: $edi
|
|
%0:gr32 = COPY $edi
|
|
MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %0 :: (store 4 into %ir.x.addr)
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !11, !DIExpression(DW_OP_deref), debug-location !12
|
|
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !12
|
|
%1:gr64 = LEA64r %stack.0.x.addr, 1, $noreg, 0, $noreg
|
|
$rdi = COPY %1, debug-location !12
|
|
CALL64pcrel32 @escape, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, debug-location !12
|
|
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !12
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !11, !DIExpression(), debug-location !12
|
|
MOV32mi $rip, 1, $noreg, @global, $noreg, 1, debug-location !12 :: (store 4 into @global)
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !11, !DIExpression(DW_OP_deref), debug-location !12
|
|
MOV32mi %stack.0.x.addr, 1, $noreg, 0, $noreg, 2, debug-location !12 :: (store 4 into %ir.x.addr)
|
|
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !12
|
|
$rdi = COPY %1, debug-location !12
|
|
CALL64pcrel32 @escape, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, debug-location !12
|
|
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp, debug-location !12
|
|
RET 0, debug-location !12
|
|
...
|
|
---
|
|
name: f2
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, name: x.addr, type: default, offset: 0, size: 4, alignment: 4,
|
|
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
|
|
debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
|
|
body: |
|
|
bb.0.entry:
|
|
liveins: $edi
|
|
%0:gr32 = COPY $edi
|
|
MOV32mr %stack.0.x.addr, 1, $noreg, 0, $noreg, %0 :: (store 4 into %ir.x.addr)
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !14, !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 16), debug-location !15
|
|
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
|
%1:gr64 = LEA64r %stack.0.x.addr, 1, $noreg, 0, $noreg
|
|
$rdi = COPY %1
|
|
CALL64pcrel32 @escape, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
|
|
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !14, !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !15
|
|
MOV32mi $rip, 1, $noreg, @global, $noreg, 1 :: (store 4 into @global)
|
|
DBG_VALUE %stack.0.x.addr, $noreg, !14, !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 16), debug-location !15
|
|
MOV32mi %stack.0.x.addr, 1, $noreg, 0, $noreg, 2 :: (store 4 into %ir.x.addr)
|
|
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
|
$rdi = COPY %1
|
|
CALL64pcrel32 @escape, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
|
|
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
|
|
RET 0
|
|
...
|