diff options
author | Vedant Kumar <vsk@apple.com> | 2018-04-17 22:03:08 +0000 |
---|---|---|
committer | Vedant Kumar <vsk@apple.com> | 2018-04-17 22:03:08 +0000 |
commit | b0585893ccb78508e900754c4974b0e95aafd4bf (patch) | |
tree | 653e6048c34ad70f5b280b4a6601d3f7f7beaf2c | |
parent | 4b29172d095d5aed0d4efd014a70dddd06dfe125 (diff) | |
download | bcm5719-llvm-b0585893ccb78508e900754c4974b0e95aafd4bf.tar.gz bcm5719-llvm-b0585893ccb78508e900754c4974b0e95aafd4bf.zip |
[Mem2Reg] Create merged debug locations for inserted phis
Track the debug locations of the incoming values to newly-created phis,
and apply merged debug locations to the phis.
A merged location will be on line 0, but will have the correct scope
set. This improves crash reporting when an inlined instruction with a
merged location triggers a machine exception. A debugger will be able to
narrow down the crash to the correct inlined scope, instead of simply
pointing to the outer scope of the caller.
Taken together with a change allows generating merged line-0 locations
for instructions which aren't calls, this results in a 0.5% increase in
the uncompressed size of the .debug_line section of a stage2+Release
build of clang (-O3 -g).
rdar://33858697
Differential Revision: https://reviews.llvm.org/D45397
llvm-svn: 330227
-rw-r--r-- | llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 38 | ||||
-rw-r--r-- | llvm/test/Transforms/Mem2Reg/dbg-inline-scope-for-phi.ll | 110 |
2 files changed, 142 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index a0b68b6b8fe..562242e08ea 100644 --- a/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -167,13 +167,15 @@ struct AllocaInfo { /// Data package used by RenamePass(). struct RenamePassData { using ValVector = std::vector<Value *>; + using LocationVector = std::vector<DebugLoc>; - RenamePassData(BasicBlock *B, BasicBlock *P, ValVector V) - : BB(B), Pred(P), Values(std::move(V)) {} + RenamePassData(BasicBlock *B, BasicBlock *P, ValVector V, LocationVector L) + : BB(B), Pred(P), Values(std::move(V)), Locations(std::move(L)) {} BasicBlock *BB; BasicBlock *Pred; ValVector Values; + LocationVector Locations; }; /// \brief This assigns and keeps a per-bb relative ordering of load/store @@ -302,6 +304,7 @@ private: SmallPtrSetImpl<BasicBlock *> &LiveInBlocks); void RenamePass(BasicBlock *BB, BasicBlock *Pred, RenamePassData::ValVector &IncVals, + RenamePassData::LocationVector &IncLocs, std::vector<RenamePassData> &Worklist); bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version); }; @@ -652,15 +655,20 @@ void PromoteMem2Reg::run() { for (unsigned i = 0, e = Allocas.size(); i != e; ++i) Values[i] = UndefValue::get(Allocas[i]->getAllocatedType()); + // When handling debug info, treat all incoming values as if they have unknown + // locations until proven otherwise. + RenamePassData::LocationVector Locations(Allocas.size()); + // Walks all basic blocks in the function performing the SSA rename algorithm // and inserting the phi nodes we marked as necessary std::vector<RenamePassData> RenamePassWorkList; - RenamePassWorkList.emplace_back(&F.front(), nullptr, std::move(Values)); + RenamePassWorkList.emplace_back(&F.front(), nullptr, std::move(Values), + std::move(Locations)); do { RenamePassData RPD = std::move(RenamePassWorkList.back()); RenamePassWorkList.pop_back(); // RenamePass may add new worklist entries. - RenamePass(RPD.BB, RPD.Pred, RPD.Values, RenamePassWorkList); + RenamePass(RPD.BB, RPD.Pred, RPD.Values, RPD.Locations, RenamePassWorkList); } while (!RenamePassWorkList.empty()); // The renamer uses the Visited set to avoid infinite loops. Clear it now. @@ -867,6 +875,16 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo, return true; } +/// Update the debug location of a phi. \p ApplyMergedLoc indicates whether to +/// create a merged location incorporating \p DL, or to set \p DL directly. +static void updateForIncomingValueLocation(PHINode *PN, DebugLoc DL, + bool ApplyMergedLoc) { + if (ApplyMergedLoc) + PN->applyMergedLocation(PN->getDebugLoc(), DL); + else + PN->setDebugLoc(DL); +} + /// \brief Recursively traverse the CFG of the function, renaming loads and /// stores to the allocas which we are promoting. /// @@ -874,6 +892,7 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo, /// predecessor block Pred. void PromoteMem2Reg::RenamePass(BasicBlock *BB, BasicBlock *Pred, RenamePassData::ValVector &IncomingVals, + RenamePassData::LocationVector &IncomingLocs, std::vector<RenamePassData> &Worklist) { NextIteration: // If we are inserting any phi nodes into this BB, they will already be in the @@ -898,6 +917,10 @@ NextIteration: do { unsigned AllocaNo = PhiToAllocaMap[APN]; + // Update the location of the phi node. + updateForIncomingValueLocation(APN, IncomingLocs[AllocaNo], + APN->getNumIncomingValues() > 0); + // Add N incoming values to the PHI node. for (unsigned i = 0; i != NumEdges; ++i) APN->addIncoming(IncomingVals[AllocaNo], Pred); @@ -959,8 +982,11 @@ NextIteration: continue; // what value were we writing? - IncomingVals[ai->second] = SI->getOperand(0); + unsigned AllocaNo = ai->second; + IncomingVals[AllocaNo] = SI->getOperand(0); + // Record debuginfo for the store before removing it. + IncomingLocs[AllocaNo] = SI->getDebugLoc(); for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[ai->second]) ConvertDebugDeclareToDebugValue(DII, SI, DIB); BB->getInstList().erase(SI); @@ -983,7 +1009,7 @@ NextIteration: for (; I != E; ++I) if (VisitedSuccs.insert(*I).second) - Worklist.emplace_back(*I, Pred, IncomingVals); + Worklist.emplace_back(*I, Pred, IncomingVals, IncomingLocs); goto NextIteration; } diff --git a/llvm/test/Transforms/Mem2Reg/dbg-inline-scope-for-phi.ll b/llvm/test/Transforms/Mem2Reg/dbg-inline-scope-for-phi.ll new file mode 100644 index 00000000000..680f2dd2833 --- /dev/null +++ b/llvm/test/Transforms/Mem2Reg/dbg-inline-scope-for-phi.ll @@ -0,0 +1,110 @@ +; RUN: opt -S < %s -mem2reg -verify | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.13.0" + +; Original source (with some whitespace removed): +; +; extern int *getp(); +; extern int cond(); +; int get1() { return *getp(); } +; int get2(int *p) { return *p; } +; int bug(int *p) { +; if (cond()) return get1(); +; else return get2(p); +; } + +define i32 @get1() !dbg !8 { + %1 = call i32* (...) @getp(), !dbg !12 + %2 = load i32, i32* %1, align 4, !dbg !13 + ret i32 %2, !dbg !14 +} + +declare i32* @getp(...) + +define i32 @get2(i32*) !dbg !15 { + %2 = alloca i32*, align 8 + store i32* %0, i32** %2, align 8 + call void @llvm.dbg.declare(metadata i32** %2, metadata !19, metadata !DIExpression()), !dbg !20 + %3 = load i32*, i32** %2, align 8, !dbg !21 + %4 = load i32, i32* %3, align 4, !dbg !22 + ret i32 %4, !dbg !23 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +; CHECK-LABEL: define i32 @bug +define i32 @bug(i32*) !dbg !24 { + %2 = alloca i32, align 4 + %3 = alloca i32*, align 8 + store i32* %0, i32** %3, align 8 + call void @llvm.dbg.declare(metadata i32** %3, metadata !25, metadata !DIExpression()), !dbg !26 + %4 = call i32 (...) @cond(), !dbg !27 + %5 = icmp ne i32 %4, 0, !dbg !27 + br i1 %5, label %6, label %8, !dbg !29 + +; <label>:6: ; preds = %1 + %7 = call i32 @get1(), !dbg !30 + store i32 %7, i32* %2, align 4, !dbg !31 + br label %11, !dbg !31 + +; <label>:8: ; preds = %1 + %9 = load i32*, i32** %3, align 8, !dbg !32 + %10 = call i32 @get2(i32* %9), !dbg !33 + store i32 %10, i32* %2, align 4, !dbg !34 + br label %11, !dbg !34 + +; <label>:11: ; preds = %8, %6 + %12 = load i32, i32* %2, align 4, !dbg !35 + ret i32 %12, !dbg !35 + + ; CHECK: [[phi:%.*]] = phi i32 [ {{.*}} ], [ {{.*}} ], !dbg [[mergedLoc:![0-9]+]] + ; CHECK-NEXT: ret i32 [[phi]], !dbg [[retLoc:![0-9]+]] +} + +; CHECK: [[commonScope:![0-9]+]] = distinct !DILexicalBlock(scope: {{.*}}, file: !1, line: 15, column: 7) +; CHECK: [[mergedLoc]] = !DILocation(line: 0, scope: [[commonScope]]) +; CHECK: [[retLoc]] = !DILocation(line: 23, column: 1 + +declare i32 @cond(...) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "Apple LLVM version 9.1.0 (clang-902.2.37.2)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "bug.c", directory: "/bug") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"PIC Level", i32 2} +!7 = !{!"Apple LLVM version 9.1.0 (clang-902.2.37.2)"} +!8 = distinct !DISubprogram(name: "get1", scope: !1, file: !1, line: 6, type: !9, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: false, unit: !0, variables: !2) +!9 = !DISubroutineType(types: !10) +!10 = !{!11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !DILocation(line: 7, column: 11, scope: !8) +!13 = !DILocation(line: 7, column: 10, scope: !8) +!14 = !DILocation(line: 7, column: 3, scope: !8) +!15 = distinct !DISubprogram(name: "get2", scope: !1, file: !1, line: 10, type: !16, isLocal: false, isDefinition: true, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!16 = !DISubroutineType(types: !17) +!17 = !{!11, !18} +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64) +!19 = !DILocalVariable(name: "p", arg: 1, scope: !15, file: !1, line: 10, type: !18) +!20 = !DILocation(line: 10, column: 15, scope: !15) +!21 = !DILocation(line: 11, column: 11, scope: !15) +!22 = !DILocation(line: 11, column: 10, scope: !15) +!23 = !DILocation(line: 11, column: 3, scope: !15) +!24 = distinct !DISubprogram(name: "bug", scope: !1, file: !1, line: 14, type: !16, isLocal: false, isDefinition: true, scopeLine: 14, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!25 = !DILocalVariable(name: "p", arg: 1, scope: !24, file: !1, line: 14, type: !18) +!26 = !DILocation(line: 14, column: 14, scope: !24) +!27 = !DILocation(line: 15, column: 7, scope: !28) +!28 = distinct !DILexicalBlock(scope: !24, file: !1, line: 15, column: 7) +!29 = !DILocation(line: 15, column: 7, scope: !24) +!30 = !DILocation(line: 16, column: 12, scope: !28) +!31 = !DILocation(line: 16, column: 5, scope: !28) +!32 = !DILocation(line: 18, column: 17, scope: !28) +!33 = !DILocation(line: 18, column: 12, scope: !28) +!34 = !DILocation(line: 18, column: 5, scope: !28) +!35 = !DILocation(line: 23, column: 1, scope: !24) |