[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

llvm-svn: 317198
This commit is contained in:
Bjorn Pettersson 2017-11-02 11:55:14 +00:00
parent 242052c6b4
commit e73b85d1ab
2 changed files with 94 additions and 1 deletions

View File

@ -1920,6 +1920,8 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
// - All of their uses are in CondBB. // - All of their uses are in CondBB.
SmallDenseMap<Instruction *, unsigned, 4> SinkCandidateUseCounts; SmallDenseMap<Instruction *, unsigned, 4> SinkCandidateUseCounts;
SmallVector<Instruction *, 4> SpeculatedDbgIntrinsics;
unsigned SpeculationCost = 0; unsigned SpeculationCost = 0;
Value *SpeculatedStoreValue = nullptr; Value *SpeculatedStoreValue = nullptr;
StoreInst *SpeculatedStore = nullptr; StoreInst *SpeculatedStore = nullptr;
@ -1928,8 +1930,10 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
BBI != BBE; ++BBI) { BBI != BBE; ++BBI) {
Instruction *I = &*BBI; Instruction *I = &*BBI;
// Skip debug info. // Skip debug info.
if (isa<DbgInfoIntrinsic>(I)) if (isa<DbgInfoIntrinsic>(I)) {
SpeculatedDbgIntrinsics.push_back(I);
continue; continue;
}
// Only speculatively execute a single instruction (not counting the // Only speculatively execute a single instruction (not counting the
// terminator) for now. // terminator) for now.
@ -2074,6 +2078,12 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB,
PN->setIncomingValue(ThenI, V); PN->setIncomingValue(ThenI, V);
} }
// Remove speculated dbg intrinsics.
// FIXME: Is it possible to do this in a more elegant way? Moving/merging the
// dbg value for the different flows and inserting it after the select.
for (Instruction *I : SpeculatedDbgIntrinsics)
I->eraseFromParent();
++NumSpeculations; ++NumSpeculations;
return true; return true;
} }

View File

@ -0,0 +1,83 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -S -simplifycfg | FileCheck %s
; This test case was generated from speculate-dbgvalue.c:
;
; int test1(int getdirt, int dirt) {
; int result = 100;
; if (getdirt != 0)
; result = dirt;
; return result;
; }
;
; using
; clang speculate-dbgvalue.c -S -emit-llvm -g -O3 -mllvm -disable-llvm-optzns -o - | opt -mem2reg -S
; Function Attrs: nounwind uwtable
define i32 @test1(i32 %getdirt, i32 %dirt) #0 !dbg !7 {
; CHECK-LABEL: @test1(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[GETDIRT:%.*]], metadata !12, metadata !DIExpression()), !dbg !15
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[DIRT:%.*]], metadata !13, metadata !DIExpression()), !dbg !16
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[GETDIRT]], 0, !dbg !18
; *** We used to get an incorrect "call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14, metadata !DIExpression()), !dbg !17" here, before the select. ***
; CHECK-NOT: call void @llvm.dbg.value(metadata i32 [[DIRT]], metadata !14
; CHECK-NEXT: [[RESULT:%.*]] = select i1 [[CMP]], i32 [[DIRT]], i32 100, !dbg !20
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[RESULT]], metadata !14, metadata !DIExpression()), !dbg !17
; CHECK-NEXT: ret i32 [[RESULT]], !dbg !21
; CHECK: !12 = !DILocalVariable(name: "getdirt"
; CHECK: !13 = !DILocalVariable(name: "dirt"
; CHECK: !14 = !DILocalVariable(name: "result"
;
entry:
call void @llvm.dbg.value(metadata i32 %getdirt, metadata !12, metadata !DIExpression()), !dbg !15
call void @llvm.dbg.value(metadata i32 %dirt, metadata !13, metadata !DIExpression()), !dbg !16
call void @llvm.dbg.value(metadata i32 100, metadata !14, metadata !DIExpression()), !dbg !17
%cmp = icmp ne i32 %getdirt, 0, !dbg !18
br i1 %cmp, label %if.then, label %if.end, !dbg !20
if.then: ; preds = %entry
call void @llvm.dbg.value(metadata i32 %dirt, metadata !14, metadata !DIExpression()), !dbg !17
br label %if.end, !dbg !21
if.end: ; preds = %if.then, %entry
%result.0 = phi i32 [ %dirt, %if.then ], [ 100, %entry ]
call void @llvm.dbg.value(metadata i32 %result.0, metadata !14, metadata !DIExpression()), !dbg !17
ret i32 %result.0, !dbg !22
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
attributes #0 = { nounwind 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_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "speculate-dbgvalue.c", directory: "/foo")
!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 6.0.0"}
!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)
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !10, !10}
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!11 = !{!12, !13, !14}
!12 = !DILocalVariable(name: "getdirt", arg: 1, scope: !7, file: !1, line: 1, type: !10)
!13 = !DILocalVariable(name: "dirt", arg: 2, scope: !7, file: !1, line: 1, type: !10)
!14 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 2, type: !10)
!15 = !DILocation(line: 1, column: 15, scope: !7)
!16 = !DILocation(line: 1, column: 28, scope: !7)
!17 = !DILocation(line: 2, column: 7, scope: !7)
!18 = !DILocation(line: 3, column: 15, scope: !19)
!19 = distinct !DILexicalBlock(scope: !7, file: !1, line: 3, column: 7)
!20 = !DILocation(line: 3, column: 7, scope: !7)
!21 = !DILocation(line: 4, column: 5, scope: !19)
!22 = !DILocation(line: 5, column: 3, scope: !7)