From 1e702fd9054b0c7b66e16c5e3d67ed75f44b3a22 Mon Sep 17 00:00:00 2001 From: Bjorn Pettersson Date: Thu, 2 Nov 2017 11:55:14 +0000 Subject: [PATCH] [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 --- lib/Transforms/Utils/SimplifyCFG.cpp | 12 ++- .../SimplifyCFG/speculate-dbgvalue.ll | 83 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 test/Transforms/SimplifyCFG/speculate-dbgvalue.ll diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index c71cc764e6d..3c4dae92ebf 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1920,6 +1920,8 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB, // - All of their uses are in CondBB. SmallDenseMap SinkCandidateUseCounts; + SmallVector SpeculatedDbgIntrinsics; + unsigned SpeculationCost = 0; Value *SpeculatedStoreValue = nullptr; StoreInst *SpeculatedStore = nullptr; @@ -1928,8 +1930,10 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB, BBI != BBE; ++BBI) { Instruction *I = &*BBI; // Skip debug info. - if (isa(I)) + if (isa(I)) { + SpeculatedDbgIntrinsics.push_back(I); continue; + } // Only speculatively execute a single instruction (not counting the // terminator) for now. @@ -2074,6 +2078,12 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *ThenBB, 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; return true; } diff --git a/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll b/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll new file mode 100644 index 00000000000..40c5f484e62 --- /dev/null +++ b/test/Transforms/SimplifyCFG/speculate-dbgvalue.ll @@ -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) -- 2.40.0