Skip to content

Commit d0e2808

Browse files
authored
[DebugInfo][LoopLoadElim] Fix missing debug location updates (#91839)
1 parent 7c16e7d commit d0e2808

File tree

2 files changed

+96
-1
lines changed

2 files changed

+96
-1
lines changed

llvm/lib/Transforms/Scalar/LoopLoadElimination.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ class LoadEliminationForLoop {
448448
new LoadInst(Cand.Load->getType(), InitialPtr, "load_initial",
449449
/* isVolatile */ false, Cand.Load->getAlign(),
450450
PH->getTerminator()->getIterator());
451+
// We don't give any debug location to Initial, because it is inserted
452+
// into the loop's preheader. A debug location inside the loop will cause
453+
// a misleading stepping when debugging. The test update-debugloc-store
454+
// -forwarded.ll checks this.
451455

452456
PHINode *PHI = PHINode::Create(Initial->getType(), 2, "store_forwarded");
453457
PHI->insertBefore(L->getHeader()->begin());
@@ -462,14 +466,20 @@ class LoadEliminationForLoop {
462466
"The type sizes should match!");
463467

464468
Value *StoreValue = Cand.Store->getValueOperand();
465-
if (LoadType != StoreType)
469+
if (LoadType != StoreType) {
466470
StoreValue = CastInst::CreateBitOrPointerCast(StoreValue, LoadType,
467471
"store_forward_cast",
468472
Cand.Store->getIterator());
473+
// Because it casts the old `load` value and is used by the new `phi`
474+
// which replaces the old `load`, we give the `load`'s debug location
475+
// to it.
476+
cast<Instruction>(StoreValue)->setDebugLoc(Cand.Load->getDebugLoc());
477+
}
469478

470479
PHI->addIncoming(StoreValue, L->getLoopLatch());
471480

472481
Cand.Load->replaceAllUsesWith(PHI);
482+
PHI->setDebugLoc(Cand.Load->getDebugLoc());
473483
}
474484

475485
/// Top-level driver for each loop: find store->load forwarding
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
; RUN: opt -passes=loop-load-elim -S < %s | FileCheck %s
2+
3+
; LoopLoadElimination's propagateStoredValueToLoadUsers() replaces the
4+
; `load` (`%a`) with a hoisted initial `load` and a `phi` that forwards
5+
; the stored value.
6+
; This test checks that the debug location is propagated to the new `phi`
7+
; from the original `load` it replaces in block `%for.body` and the debug
8+
; location drop of the hoisted `load` in block `%entry`.
9+
; Moreover, this test also checks the debug location update of the new
10+
; `bitcast` created when the `load` type is mismatched with the `store` type:
11+
; store i32 ...
12+
; %a = load float, ...
13+
; Because the `bitcast` casts the old `load` value, it has the same debug
14+
; location as the old `load` (ie., the same as the new `phi`).
15+
16+
; If the store and the load use different types, but have the same
17+
; size then we should still be able to forward the value.
18+
;
19+
; for (unsigned i = 0; i < 100; i++) {
20+
; A[i+1] = B[i] + 2;
21+
; C[i] = ((float*)A)[i] * 2;
22+
; }
23+
24+
define void @f(ptr noalias %A, ptr noalias %B, ptr noalias %C, i64 %N) !dbg !5 {
25+
; CHECK-LABEL: define void @f(
26+
; CHECK-NEXT: entry:
27+
; CHECK-NEXT: [[LOAD_INITIAL:%.*]] = load float, ptr {{.*}}, align 4{{$}}
28+
; CHECK: for.body:
29+
; CHECK-NEXT: [[STORE_FORWARDED:%.*]] = phi float [ [[LOAD_INITIAL]], %entry ], [ [[STORE_FORWARD_CAST:%.*]], %for.body ], !dbg [[DBG9:![0-9]+]]
30+
; CHECK: [[STORE_FORWARD_CAST]] = bitcast i32 {{.*}} to float, !dbg [[DBG9]]
31+
; CHECK: [[DBG9]] = !DILocation(line: 11,
32+
;
33+
entry:
34+
br label %for.body, !dbg !8
35+
36+
for.body: ; preds = %for.body, %entry
37+
%indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ], !dbg !9
38+
%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !10
39+
%Aidx_next = getelementptr inbounds i32, ptr %A, i64 %indvars.iv.next, !dbg !11
40+
%Bidx = getelementptr inbounds i32, ptr %B, i64 %indvars.iv, !dbg !12
41+
%Cidx = getelementptr inbounds i32, ptr %C, i64 %indvars.iv, !dbg !13
42+
%Aidx = getelementptr inbounds i32, ptr %A, i64 %indvars.iv, !dbg !14
43+
%b = load i32, ptr %Bidx, align 4, !dbg !15
44+
%a_p1 = add i32 %b, 2, !dbg !16
45+
store i32 %a_p1, ptr %Aidx_next, align 4, !dbg !17
46+
%a = load float, ptr %Aidx, align 4, !dbg !18
47+
%c = fmul float %a, 2.000000e+00, !dbg !19
48+
%c.int = fptosi float %c to i32, !dbg !20
49+
store i32 %c.int, ptr %Cidx, align 4, !dbg !21
50+
%exitcond = icmp eq i64 %indvars.iv.next, %N, !dbg !22
51+
br i1 %exitcond, label %for.end, label %for.body, !dbg !23
52+
53+
for.end: ; preds = %for.body
54+
ret void, !dbg !24
55+
}
56+
57+
!llvm.dbg.cu = !{!0}
58+
!llvm.debugify = !{!2, !3}
59+
!llvm.module.flags = !{!4}
60+
61+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
62+
!1 = !DIFile(filename: "type-mismatch.ll", directory: "/")
63+
!2 = !{i32 17}
64+
!3 = !{i32 0}
65+
!4 = !{i32 2, !"Debug Info Version", i32 3}
66+
!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0)
67+
!6 = !DISubroutineType(types: !7)
68+
!7 = !{}
69+
!8 = !DILocation(line: 1, column: 1, scope: !5)
70+
!9 = !DILocation(line: 2, column: 1, scope: !5)
71+
!10 = !DILocation(line: 3, column: 1, scope: !5)
72+
!11 = !DILocation(line: 4, column: 1, scope: !5)
73+
!12 = !DILocation(line: 5, column: 1, scope: !5)
74+
!13 = !DILocation(line: 6, column: 1, scope: !5)
75+
!14 = !DILocation(line: 7, column: 1, scope: !5)
76+
!15 = !DILocation(line: 8, column: 1, scope: !5)
77+
!16 = !DILocation(line: 9, column: 1, scope: !5)
78+
!17 = !DILocation(line: 10, column: 1, scope: !5)
79+
!18 = !DILocation(line: 11, column: 1, scope: !5)
80+
!19 = !DILocation(line: 12, column: 1, scope: !5)
81+
!20 = !DILocation(line: 13, column: 1, scope: !5)
82+
!21 = !DILocation(line: 14, column: 1, scope: !5)
83+
!22 = !DILocation(line: 15, column: 1, scope: !5)
84+
!23 = !DILocation(line: 16, column: 1, scope: !5)
85+
!24 = !DILocation(line: 17, column: 1, scope: !5)

0 commit comments

Comments
 (0)