forked from OSchip/llvm-project
[Debug] Retain both sets of debug intrinsics in HoistThenElseCodeToIf
When hoisting common code from the "then" and "else" branches of a condition to before the "if", there is no need to require that debug intrinsics match before moving them (and merging them). Instead, we can simply always keep all debug intrinsics from both sides of the "if". This fixes PR36410, which describes a problem where as a result of the attempt to merge debug locations for two debug intrinsics we end up with an invalid intrinsic, where the scope indicated in the !dbg location no longer matches the scope of the variable tracked by the intrinsic. In addition, this has the benefit that we no longer throw away information that is actually still valid, helping to generate better debug data. Reviewed By: vsk Differential Revision: https://reviews.llvm.org/D44312 llvm-svn: 327175
This commit is contained in:
parent
735817aa1a
commit
fa4e63c0d6
|
@ -1254,23 +1254,23 @@ static bool HoistThenElseCodeToIf(BranchInst *BI,
|
|||
BasicBlock::iterator BB2_Itr = BB2->begin();
|
||||
|
||||
Instruction *I1 = &*BB1_Itr++, *I2 = &*BB2_Itr++;
|
||||
// Skip debug info if it is not identical.
|
||||
DbgInfoIntrinsic *DBI1 = dyn_cast<DbgInfoIntrinsic>(I1);
|
||||
DbgInfoIntrinsic *DBI2 = dyn_cast<DbgInfoIntrinsic>(I2);
|
||||
if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) {
|
||||
while (isa<DbgInfoIntrinsic>(I1))
|
||||
I1 = &*BB1_Itr++;
|
||||
while (isa<DbgInfoIntrinsic>(I2))
|
||||
I2 = &*BB2_Itr++;
|
||||
}
|
||||
if (isa<PHINode>(I1) || !I1->isIdenticalToWhenDefined(I2) ||
|
||||
(isa<InvokeInst>(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2)))
|
||||
return false;
|
||||
|
||||
BasicBlock *BIParent = BI->getParent();
|
||||
|
||||
bool Changed = false;
|
||||
do {
|
||||
for (;;) {
|
||||
// Move over debug info from both sides unchanged.
|
||||
while (isa<DbgInfoIntrinsic>(I1)) {
|
||||
BIParent->getInstList().splice(BI->getIterator(), BB1->getInstList(), I1);
|
||||
I1 = &*BB1_Itr++;
|
||||
}
|
||||
while (isa<DbgInfoIntrinsic>(I2)) {
|
||||
BIParent->getInstList().splice(BI->getIterator(), BB2->getInstList(), I2);
|
||||
I2 = &*BB2_Itr++;
|
||||
}
|
||||
|
||||
if (isa<PHINode>(I1) || !I1->isIdenticalToWhenDefined(I2))
|
||||
return Changed;
|
||||
|
||||
// If we are hoisting the terminator instruction, don't move one (making a
|
||||
// broken BB), instead clone it, and remove BI.
|
||||
if (isa<TerminatorInst>(I1))
|
||||
|
@ -1318,18 +1318,7 @@ static bool HoistThenElseCodeToIf(BranchInst *BI,
|
|||
|
||||
I1 = &*BB1_Itr++;
|
||||
I2 = &*BB2_Itr++;
|
||||
// Skip debug info if it is not identical.
|
||||
DbgInfoIntrinsic *DBI1 = dyn_cast<DbgInfoIntrinsic>(I1);
|
||||
DbgInfoIntrinsic *DBI2 = dyn_cast<DbgInfoIntrinsic>(I2);
|
||||
if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) {
|
||||
while (isa<DbgInfoIntrinsic>(I1))
|
||||
I1 = &*BB1_Itr++;
|
||||
while (isa<DbgInfoIntrinsic>(I2))
|
||||
I2 = &*BB2_Itr++;
|
||||
}
|
||||
} while (I1->isIdenticalToWhenDefined(I2));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HoistTerminator:
|
||||
// It may not be possible to hoist an invoke.
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
; RUN: opt -simplifycfg -S < %s | FileCheck %s
|
||||
; Verify that we don't crash due an invalid !dbg location on the hoisted llvm.dbg.value
|
||||
|
||||
define i64 @caller(i64* %ptr, i64 %flag) !dbg !10 {
|
||||
init:
|
||||
%v9 = icmp eq i64 %flag, 0
|
||||
br i1 %v9, label %a, label %b
|
||||
|
||||
; CHECK: %vala = load i64, i64* %ptr
|
||||
; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD:![0-9]*]]
|
||||
; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD]]
|
||||
; CHECK-NEXT: %valbmasked = and i64 %vala, 1
|
||||
|
||||
a: ; preds = %init
|
||||
%vala = load i64, i64* %ptr, align 8
|
||||
call void @llvm.dbg.value(metadata i64 %vala, metadata !8, metadata !DIExpression()), !dbg !12
|
||||
br label %test.exit
|
||||
|
||||
b: ; preds = %init
|
||||
%valb = load i64, i64* %ptr, align 8
|
||||
call void @llvm.dbg.value(metadata i64 %valb, metadata !8, metadata !DIExpression()), !dbg !13
|
||||
%valbmasked = and i64 %valb, 1
|
||||
br label %test.exit
|
||||
|
||||
test.exit: ; preds = %a, %b
|
||||
%retv = phi i64 [ %vala, %a ], [ %valbmasked, %b ]
|
||||
ret i64 %retv
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable
|
||||
declare void @llvm.dbg.value(metadata, metadata, metadata) #0
|
||||
|
||||
attributes #0 = { nounwind readnone speculatable }
|
||||
|
||||
!llvm.module.flags = !{!0}
|
||||
!llvm.dbg.cu = !{!1}
|
||||
|
||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
|
||||
!2 = !DIFile(filename: "optbug", directory: "")
|
||||
!3 = !{}
|
||||
!4 = distinct !DISubprogram(name: "callee", scope: !2, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !1, variables: !7)
|
||||
!5 = !DISubroutineType(types: !6)
|
||||
!6 = !{null}
|
||||
!7 = !{!8}
|
||||
!8 = !DILocalVariable(name: "var", scope: !4, file: !2, type: !9)
|
||||
!9 = !DIBasicType(name: "var_t", size: 64, encoding: DW_ATE_unsigned)
|
||||
!10 = distinct !DISubprogram(name: "caller", scope: !2, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !1, variables: !3)
|
||||
!11 = distinct !DILocation(line: 6, scope: !10)
|
||||
!12 = !DILocation(line: 2, scope: !4, inlinedAt: !11)
|
||||
!13 = !DILocation(line: 3, scope: !4, inlinedAt: !11)
|
Loading…
Reference in New Issue