[BranchFolding] Salvage DBG_VALUE instructions from empty blocks
Summary:
This patch will introduce copying of DBG_VALUE instructions
from an otherwise empty basic block to predecessor/successor
blocks in case the empty block is eliminated/bypassed. It
is currently only done in one identified situation in the
BranchFolding pass, before optimizing on empty block.
It can be seen as a light variant of the propagation done
by the LiveDebugValues pass, which unfortunately is executed
after the BranchFolding pass.
We only propagate (copy) DBG_VALUE instructions in a limited
number of situations:
a) If the empty BB is the only predecessor of a successor
we can copy the DBG_VALUE instruction to the beginning of
the successor (because the DBG_VALUE instruction is always
part of the flow between the blocks).
b) If the empty BB is the only successor of a predecessor
we can copy the DBG_VALUE instruction to the end of the
predecessor (because the DBG_VALUE instruction is always
part of the flow between the blocks). In this case we add
the DBG_VALUE just before the first terminator (assuming
that the terminators do not impact the DBG_VALUE).
A future solution, to handle more situations, could perhaps
be to run the LiveDebugValues pass before branch folding?
This fix is related to PR37234. It is expected to resolve
the problem seen, when applied together with the fix in
SelectionDAG from here: https://reviews.llvm.org/D46129
Reviewers: #debug-info, aprantl, rnk
Reviewed By: #debug-info, aprantl
Subscribers: ormris, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D46184
llvm-svn: 331183
2018-04-30 22:37:46 +08:00
|
|
|
; RUN: llc %s -o - | FileCheck %s
|
|
|
|
|
|
|
|
; This test case was generated by running
|
|
|
|
;
|
|
|
|
; clang++ -O2 -g PR37234.cpp -S -save-temps
|
|
|
|
; opt -O2 -S PR37234.bc -o PR37234.ll
|
|
|
|
;
|
|
|
|
; using the following PR37234.cpp program
|
|
|
|
;
|
|
|
|
; int main() {
|
|
|
|
; const char* buffer = "aaa";
|
|
|
|
; unsigned aa = 0;
|
|
|
|
; while (char c = *buffer++) {
|
|
|
|
; if (c == 'a')
|
|
|
|
; ++aa; // DexWatch('aa')
|
|
|
|
; }
|
|
|
|
; return aa;
|
|
|
|
; }
|
|
|
|
|
|
|
|
|
|
|
|
; CHECK-LABEL: # %bb.{{.*}}:
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- 0
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG:[0-9a-z]+]]
|
|
|
|
; CHECK: jmp .LBB0_1
|
|
|
|
; CHECK: .LBB0_3:
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
|
|
|
|
; CHECK: incl %[[REG]]
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
|
|
|
|
; CHECK: .LBB0_1:
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
|
|
|
|
; CHECK: je .LBB0_4
|
|
|
|
; CHECK: # %bb.{{.*}}:
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
|
|
|
|
; CHECK: jne .LBB0_1
|
|
|
|
; CHECK: jmp .LBB0_3
|
|
|
|
; CHECK: .LBB0_4:
|
|
|
|
; CHECK: #DEBUG_VALUE: main:aa <- $[[REG]]
|
|
|
|
; CHECK: retq
|
|
|
|
|
|
|
|
source_filename = "PR37234.cpp"
|
|
|
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|
|
|
target triple = "x86_64-unknown-linux-gnu"
|
|
|
|
|
|
|
|
@.str = private unnamed_addr constant [4 x i8] c"aaa\00", align 1
|
|
|
|
|
|
|
|
; Function Attrs: norecurse nounwind readonly uwtable
|
|
|
|
define dso_local i32 @main() local_unnamed_addr #0 !dbg !7 {
|
|
|
|
entry:
|
|
|
|
call void @llvm.dbg.value(metadata i32 0, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
br label %while.cond.outer, !dbg !20
|
|
|
|
|
|
|
|
while.cond.outer: ; preds = %if.then, %entry
|
|
|
|
%buffer.0.ph = phi i8* [ %incdec.ptr, %if.then ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), %entry ]
|
|
|
|
%aa.0.ph = phi i32 [ %inc, %if.then ], [ 0, %entry ]
|
|
|
|
br label %while.cond, !dbg !21
|
|
|
|
|
|
|
|
while.cond: ; preds = %while.cond.outer, %while.cond
|
|
|
|
%buffer.0 = phi i8* [ %incdec.ptr, %while.cond ], [ %buffer.0.ph, %while.cond.outer ], !dbg !22
|
|
|
|
call void @llvm.dbg.value(metadata i32 %aa.0.ph, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
call void @llvm.dbg.value(metadata i8* %buffer.0, metadata !12, metadata !DIExpression()), !dbg !23
|
|
|
|
%incdec.ptr = getelementptr inbounds i8, i8* %buffer.0, i64 1, !dbg !21
|
|
|
|
call void @llvm.dbg.value(metadata i8* %incdec.ptr, metadata !12, metadata !DIExpression()), !dbg !23
|
|
|
|
%0 = load i8, i8* %buffer.0, align 1, !dbg !24, !tbaa !25
|
|
|
|
call void @llvm.dbg.value(metadata i8 %0, metadata !18, metadata !DIExpression()), !dbg !28
|
|
|
|
switch i8 %0, label %while.cond [
|
|
|
|
i8 0, label %while.end
|
|
|
|
i8 97, label %if.then
|
|
|
|
], !dbg !20
|
|
|
|
|
|
|
|
if.then: ; preds = %while.cond
|
|
|
|
%inc = add i32 %aa.0.ph, 1, !dbg !29
|
|
|
|
call void @llvm.dbg.value(metadata i32 %inc, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
br label %while.cond.outer, !dbg !29
|
|
|
|
|
|
|
|
while.end: ; preds = %while.cond
|
|
|
|
call void @llvm.dbg.value(metadata i32 %aa.0.ph, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
call void @llvm.dbg.value(metadata i32 %aa.0.ph, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
call void @llvm.dbg.value(metadata i32 %aa.0.ph, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
call void @llvm.dbg.value(metadata i32 %aa.0.ph, metadata !16, metadata !DIExpression()), !dbg !19
|
|
|
|
ret i32 %aa.0.ph, !dbg !32
|
|
|
|
}
|
|
|
|
|
|
|
|
; Function Attrs: nounwind readnone speculatable
|
|
|
|
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
|
|
|
|
|
|
|
|
attributes #0 = { norecurse nounwind readonly uwtable }
|
|
|
|
attributes #1 = { nounwind readnone speculatable }
|
|
|
|
|
|
|
|
!llvm.dbg.cu = !{!0}
|
|
|
|
!llvm.module.flags = !{!3, !4, !5}
|
|
|
|
!llvm.ident = !{!6}
|
|
|
|
|
|
|
|
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 7.0.0 (trunk 330946) (llvm/trunk 330952)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
|
|
|
!1 = !DIFile(filename: "PR37234.cpp", directory: "")
|
|
|
|
!2 = !{}
|
|
|
|
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
|
|
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
|
|
|
!5 = !{i32 1, !"wchar_size", i32 4}
|
|
|
|
!6 = !{!"clang version 7.0.0 (trunk 330946) (llvm/trunk 330952)"}
|
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 10:40:45 +08:00
|
|
|
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !11)
|
[BranchFolding] Salvage DBG_VALUE instructions from empty blocks
Summary:
This patch will introduce copying of DBG_VALUE instructions
from an otherwise empty basic block to predecessor/successor
blocks in case the empty block is eliminated/bypassed. It
is currently only done in one identified situation in the
BranchFolding pass, before optimizing on empty block.
It can be seen as a light variant of the propagation done
by the LiveDebugValues pass, which unfortunately is executed
after the BranchFolding pass.
We only propagate (copy) DBG_VALUE instructions in a limited
number of situations:
a) If the empty BB is the only predecessor of a successor
we can copy the DBG_VALUE instruction to the beginning of
the successor (because the DBG_VALUE instruction is always
part of the flow between the blocks).
b) If the empty BB is the only successor of a predecessor
we can copy the DBG_VALUE instruction to the end of the
predecessor (because the DBG_VALUE instruction is always
part of the flow between the blocks). In this case we add
the DBG_VALUE just before the first terminator (assuming
that the terminators do not impact the DBG_VALUE).
A future solution, to handle more situations, could perhaps
be to run the LiveDebugValues pass before branch folding?
This fix is related to PR37234. It is expected to resolve
the problem seen, when applied together with the fix in
SelectionDAG from here: https://reviews.llvm.org/D46129
Reviewers: #debug-info, aprantl, rnk
Reviewed By: #debug-info, aprantl
Subscribers: ormris, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D46184
llvm-svn: 331183
2018-04-30 22:37:46 +08:00
|
|
|
!8 = !DISubroutineType(types: !9)
|
|
|
|
!9 = !{!10}
|
|
|
|
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
|
|
|
!11 = !{!12, !16, !18}
|
|
|
|
!12 = !DILocalVariable(name: "buffer", scope: !7, file: !1, line: 2, type: !13)
|
|
|
|
!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64)
|
|
|
|
!14 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !15)
|
|
|
|
!15 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
|
|
|
!16 = !DILocalVariable(name: "aa", scope: !7, file: !1, line: 3, type: !17)
|
|
|
|
!17 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
|
|
|
|
!18 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 4, type: !15)
|
|
|
|
!19 = !DILocation(line: 3, column: 18, scope: !7)
|
|
|
|
!20 = !DILocation(line: 4, column: 9, scope: !7)
|
|
|
|
!21 = !DILocation(line: 4, column: 32, scope: !7)
|
|
|
|
!22 = !DILocation(line: 0, scope: !7)
|
|
|
|
!23 = !DILocation(line: 2, column: 21, scope: !7)
|
|
|
|
!24 = !DILocation(line: 4, column: 25, scope: !7)
|
|
|
|
!25 = !{!26, !26, i64 0}
|
|
|
|
!26 = !{!"omnipotent char", !27, i64 0}
|
|
|
|
!27 = !{!"Simple C++ TBAA"}
|
|
|
|
!28 = !DILocation(line: 4, column: 21, scope: !7)
|
|
|
|
!29 = !DILocation(line: 6, column: 25, scope: !30)
|
|
|
|
!30 = distinct !DILexicalBlock(scope: !31, file: !1, line: 5, column: 21)
|
|
|
|
!31 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 36)
|
|
|
|
!32 = !DILocation(line: 9, column: 1, scope: !7)
|