Skip to content

Commit 0a69cd4

Browse files
authored
[JumpThreading][DebugInfo] Propagate DebugLocs when simplifying loads (#157683)
In simplifyPartiallyRedundantLoad we may replace a load with a PHI of available values in predecessor blocks. As part of this process, we may need to cast those values, which we do by inserting a new cast at the end of the predecessor. These cast instructions should take their debug location from the load instruction, just as the PHI does; we make an exception if the predecessor does not unconditionally branch to the load's block, as in that case we are not guaranteed to reach the load and must therefore drop its debug location. Found using llvm/llvm-project#107279.
1 parent e2d9420 commit 0a69cd4

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

llvm/lib/Transforms/Scalar/JumpThreading.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1437,9 +1437,18 @@ bool JumpThreadingPass::simplifyPartiallyRedundantLoad(LoadInst *LoadI) {
14371437
// AvailablePreds vector as we go so that all of the PHI entries for this
14381438
// predecessor use the same bitcast.
14391439
Value *&PredV = I->second;
1440-
if (PredV->getType() != LoadI->getType())
1440+
if (PredV->getType() != LoadI->getType()) {
14411441
PredV = CastInst::CreateBitOrPointerCast(
14421442
PredV, LoadI->getType(), "", P->getTerminator()->getIterator());
1443+
// The new cast is producing the value used to replace the load
1444+
// instruction, so uses the load's debug location. If P does not always
1445+
// branch to the load BB however then the debug location must be dropped,
1446+
// as it is hoisted past a conditional branch.
1447+
DebugLoc DL = P->getTerminator()->getNumSuccessors() == 1
1448+
? LoadI->getDebugLoc()
1449+
: DebugLoc::getDropped();
1450+
cast<CastInst>(PredV)->setDebugLoc(DL);
1451+
}
14431452

14441453
PN->addIncoming(PredV, I->first);
14451454
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
; RUN: opt -S -passes=jump-threading < %s | FileCheck %s
2+
3+
;; Check that when we simplify the load of %p by replacing it with 0 when coming
4+
;; from %left, the inttoptr cast instruction is assigned the DILocation from the
5+
;; load instruction.
6+
7+
; CHECK-LABEL: define void @foo(
8+
9+
; CHECK-NEXT: [[ENTRY:.*:]]
10+
; CHECK-NEXT: [[P:%.*]] = alloca i32, align 8
11+
; CHECK-NEXT: br i1 {{.*}}, label %[[LEFT:.*]], label %[[RIGHT:.*]]
12+
13+
;; Cast in "left" should have the load's debug location.
14+
; CHECK: [[LEFT]]:
15+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 0, i64 8, i1 false)
16+
; CHECK-NEXT: [[TMP0:%.*]] = inttoptr i64 0 to ptr, !dbg [[LOAD_LOC:![0-9]+]]
17+
; CHECK-NEXT: br label %[[END:.*]]
18+
19+
; CHECK: [[RIGHT]]:
20+
; CHECK-NEXT: br i1 {{.*}}, label %[[RIGHT_LEFT:.*]], label %[[ENDTHREAD_PRE_SPLIT:.*]]
21+
22+
;; Cast in "right.left" should not have a debug location, as we are not
23+
;; guaranteed to reach the load's original position.
24+
; CHECK: [[RIGHT_LEFT]]:
25+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P]], i8 0, i64 8, i1 false)
26+
; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 0 to ptr
27+
; CHECK-NEXT: br i1 {{.*}}, label %[[END]], label %[[EXIT:.*]]
28+
29+
;; Load in "right.right" should have the load's debug location.
30+
; CHECK: [[ENDTHREAD_PRE_SPLIT]]:
31+
; CHECK-NEXT: [[DOTPR:%.*]] = load ptr, ptr [[P]], align 8, !dbg [[LOAD_LOC]]
32+
; CHECK-NEXT: br label %[[END]], !dbg [[LOAD_LOC]]
33+
34+
;; Finally, the PHI node should also have the load's debug location.
35+
; CHECK: [[END]]:
36+
; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[DOTPR]], %[[ENDTHREAD_PRE_SPLIT]] ], [ [[TMP1]], %[[RIGHT_LEFT]] ], [ [[TMP0]], %[[LEFT]] ], !dbg [[LOAD_LOC]]
37+
38+
; CHECK: [[LOAD_LOC]] = !DILocation(line: 1, column: 1,
39+
40+
define void @foo(i1 %b, i1 %c, i1 %d) !dbg !5 {
41+
entry:
42+
%p = alloca i32, align 8
43+
br i1 %b, label %left, label %right
44+
45+
left:
46+
call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 8, i1 false)
47+
br label %end
48+
49+
right:
50+
br i1 %c, label %right.left, label %right.right
51+
52+
right.left:
53+
call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 8, i1 false)
54+
br i1 %d, label %end, label %exit
55+
56+
right.right:
57+
br label %end
58+
59+
end:
60+
%0 = load ptr, ptr %p, align 8, !dbg !8
61+
%isnull = icmp eq ptr %0, null
62+
br i1 %isnull, label %exit, label %notnull
63+
64+
notnull:
65+
br label %exit
66+
67+
exit:
68+
ret void
69+
}
70+
71+
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
72+
declare void @llvm.memset.p0.i64(ptr writeonly captures(none), i8, i64, i1 immarg) #0
73+
74+
attributes #0 = { nocallback nofree nounwind willreturn memory(argmem: write) }
75+
76+
!llvm.dbg.cu = !{!0}
77+
!llvm.debugify = !{!2, !3}
78+
!llvm.module.flags = !{!4}
79+
80+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
81+
!1 = !DIFile(filename: "simplify-partially-redundant-load-debugloc.ll", directory: "/")
82+
!2 = !{i32 13}
83+
!3 = !{i32 0}
84+
!4 = !{i32 2, !"Debug Info Version", i32 3}
85+
!5 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !0, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
86+
!6 = !DISubroutineType(types: !7)
87+
!7 = !{}
88+
!8 = !DILocation(line: 1, column: 1, scope: !5)

0 commit comments

Comments
 (0)