Skip to content

Commit 1e702fd

Browse files
committed
[SimplifyCFG] Discard speculated dbg intrinsics
Summary: SpeculativelyExecuteBB can flatten the CFG by doing speculative execution followed by a select instruction. When the speculatively executed BB contained dbg intrinsics the result could be a little bit weird, since those dbg intrinsics were inserted before the select in the flattened CFG. So when single stepping in the debugger, printing the value of the variable referenced in the dbg intrinsic, it could happen that it looked like the variable had values that never actually were assigned to the variable. This patch simply discards all dbg intrinsics that were found in the speculatively executed BB. Reviewers: aprantl, chandlerc, craig.topper Reviewed By: aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D39494 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317198 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent b7c0518 commit 1e702fd

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed

lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,8 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
19201920
// - All of their uses are in CondBB.
19211921
SmallDenseMap<Instruction *, unsigned, 4> SinkCandidateUseCounts;
19221922

1923+
SmallVector<Instruction *, 4> SpeculatedDbgIntrinsics;
1924+
19231925
unsigned SpeculationCost = 0;
19241926
Value *SpeculatedStoreValue = nullptr;
19251927
StoreInst *SpeculatedStore = nullptr;
@@ -1928,8 +1930,10 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
19281930
BBI != BBE; ++BBI) {
19291931
Instruction *I = &*BBI;
19301932
// Skip debug info.
1931-
if (isa<DbgInfoIntrinsic>(I))
1933+
if (isa<DbgInfoIntrinsic>(I)) {
1934+
SpeculatedDbgIntrinsics.push_back(I);
19321935
continue;
1936+
}
19331937

19341938
// Only speculatively execute a single instruction (not counting the
19351939
// terminator) for now.
@@ -2074,6 +2078,12 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
20742078
PN->setIncomingValue(ThenI, V);
20752079
}
20762080

2081+
// Remove speculated dbg intrinsics.
2082+
// FIXME: Is it possible to do this in a more elegant way? Moving/merging the
2083+
// dbg value for the different flows and inserting it after the select.
2084+
for (Instruction *I : SpeculatedDbgIntrinsics)
2085+
I->eraseFromParent();
2086+
20772087
++NumSpeculations;
20782088
return true;
20792089
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -S -simplifycfg | FileCheck %s
3+
4+
; This test case was generated from speculate-dbgvalue.c:
5+
;
6+
; int test1(int getdirt, int dirt) {
7+
; int result = 100;
8+
; if (getdirt != 0)
9+
; result = dirt;
10+
; return result;
11+
; }
12+
;
13+
; using
14+
; clang speculate-dbgvalue.c -S -emit-llvm -g -O3 -mllvm -disable-llvm-optzns -o - | opt -mem2reg -S
15+
16+
17+
; Function Attrs: nounwind uwtable
18+
define i32 @test1(i32 %getdirt, i32 %dirt) #0 !dbg !7 {
19+
; CHECK-LABEL: @test1(
20+
; CHECK-NEXT: entry:
21+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[GETDIRT:%.*]], metadata !12, metadata !DIExpression()), !dbg !15
22+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[DIRT:%.*]], metadata !13, metadata !DIExpression()), !dbg !16
23+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
24+
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[GETDIRT]], 0, !dbg !18
25+
; *** We used to get an incorrect "call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14, metadata !DIExpression()), !dbg !17" here, before the select. ***
26+
; CHECK-NOT: call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14
27+
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP]], i32 [[DIRT]], i32 100, !dbg !20
28+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[RESULT]], metadata !14, metadata !DIExpression()), !dbg !17
29+
; CHECK-NEXT: ret i32 [[RESULT]], !dbg !21
30+
; CHECK: !12 = !DILocalVariable(name: "getdirt"
31+
; CHECK: !13 = !DILocalVariable(name: "dirt"
32+
; CHECK: !14 = !DILocalVariable(name: "result"
33+
;
34+
entry:
35+
call void @llvm.dbg.value(metadata i32 %getdirt, metadata !12, metadata !DIExpression()), !dbg !15
36+
call void @llvm.dbg.value(metadata i32 %dirt, metadata !13, metadata !DIExpression()), !dbg !16
37+
call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
38+
%cmp = icmp ne i32 %getdirt, 0, !dbg !18
39+
br i1 %cmp, label %if.then, label %if.end, !dbg !20
40+
41+
if.then: ; preds = %entry
42+
call void @llvm.dbg.value(metadata i32 %dirt, metadata !14, metadata !DIExpression()), !dbg !17
43+
br label %if.end, !dbg !21
44+
45+
if.end: ; preds = %if.then, %entry
46+
%result.0 = phi i32 [ %dirt, %if.then ], [ 100, %entry ]
47+
call void @llvm.dbg.value(metadata i32 %result.0, metadata !14, metadata !DIExpression()), !dbg !17
48+
ret i32 %result.0, !dbg !22
49+
}
50+
51+
; Function Attrs: nounwind readnone speculatable
52+
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
53+
54+
attributes #0 = { nounwind uwtable }
55+
attributes #1 = { nounwind readnone speculatable }
56+
57+
!llvm.dbg.cu = !{!0}
58+
!llvm.module.flags = !{!3, !4, !5}
59+
!llvm.ident = !{!6}
60+
61+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
62+
!1 = !DIFile(filename: "speculate-dbgvalue.c", directory: "/foo")
63+
!2 = !{}
64+
!3 = !{i32 2, !"Dwarf Version", i32 4}
65+
!4 = !{i32 2, !"Debug Info Version", i32 3}
66+
!5 = !{i32 1, !"wchar_size", i32 4}
67+
!6 = !{!"clang version 6.0.0"}
68+
!7 = distinct !DISubprogram(name: "test1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11)
69+
!8 = !DISubroutineType(types: !9)
70+
!9 = !{!10, !10, !10}
71+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
72+
!11 = !{!12, !13, !14}
73+
!12 = !DILocalVariable(name: "getdirt", arg: 1, scope: !7, file: !1, line: 1, type: !10)
74+
!13 = !DILocalVariable(name: "dirt", arg: 2, scope: !7, file: !1, line: 1, type: !10)
75+
!14 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 2, type: !10)
76+
!15 = !DILocation(line: 1, column: 15, scope: !7)
77+
!16 = !DILocation(line: 1, column: 28, scope: !7)
78+
!17 = !DILocation(line: 2, column: 7, scope: !7)
79+
!18 = !DILocation(line: 3, column: 15, scope: !19)
80+
!19 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 7)
81+
!20 = !DILocation(line: 3, column: 7, scope: !7)
82+
!21 = !DILocation(line: 4, column: 5, scope: !19)
83+
!22 = !DILocation(line: 5, column: 3, scope: !7)

0 commit comments

Comments
 (0)