Skip to content

Commit acd26d1

Browse files
rastogishubhamfelipepiovezan
authored andcommitted
Add support for llvm.dbg.declare_value in the CoroSplitter pass. (llvm#168134)
Make sure the CoroSplitter pass correctly handles `#dbg_declare_value` intrinsics. Which means, it should identify them, and convert them to `#dbg_declares` so that any subsequent passes do not need to be amended to support the `#dbg_declare_value` intrinsic. More information here: https://discourse.llvm.org/t/rfc-introduce-new-llvm-dbg-coroframe-entry-intrinsic/88269 This patch is the second and last in a stack of patches, with the one preceding it being: llvm#168132 (cherry picked from commit 79c56e8)
1 parent 8ca72ae commit acd26d1

File tree

2 files changed

+129
-5
lines changed

2 files changed

+129
-5
lines changed

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ static void cacheDIVar(FrameDataInfo &FrameData,
555555
};
556556
CacheIt(findDbgDeclares(V));
557557
CacheIt(findDVRDeclares(V));
558+
CacheIt(findDVRDeclareValues(V));
558559
}
559560
}
560561

@@ -1156,6 +1157,47 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
11561157
for_each(DVRs, SalvageOne);
11571158
}
11581159

1160+
TinyPtrVector<DbgVariableRecord *> DVRDeclareValues =
1161+
findDVRDeclareValues(Def);
1162+
// Try best to find dbg.declare_value. If the spill is a temp, there may
1163+
// not be a direct dbg.declare_value. Walk up the load chain to find one
1164+
// from an alias.
1165+
if (F->getSubprogram()) {
1166+
auto *CurDef = Def;
1167+
while (DVRDeclareValues.empty() && isa<LoadInst>(CurDef)) {
1168+
auto *LdInst = cast<LoadInst>(CurDef);
1169+
// Only consider ptr to ptr same type load.
1170+
if (LdInst->getPointerOperandType() != LdInst->getType())
1171+
break;
1172+
CurDef = LdInst->getPointerOperand();
1173+
if (!isa<AllocaInst, LoadInst>(CurDef))
1174+
break;
1175+
DVRDeclareValues = findDVRDeclareValues(CurDef);
1176+
}
1177+
}
1178+
1179+
auto SalvageOneCoro = [&](auto *DDI) {
1180+
// This dbg.declare_value is preserved for all coro-split function
1181+
// fragments. It will be unreachable in the main function, and
1182+
// processed by coro::salvageDebugInfo() by the Cloner. However, convert
1183+
// it to a dbg.declare to make sure future passes don't have to deal
1184+
// with a dbg.declare_value.
1185+
auto *VAM = ValueAsMetadata::get(CurrentReload);
1186+
Type *Ty = VAM->getValue()->getType();
1187+
// If the metadata type is not a pointer, emit a dbg.value instead.
1188+
DbgVariableRecord *NewDVR = new DbgVariableRecord(
1189+
ValueAsMetadata::get(CurrentReload), DDI->getVariable(),
1190+
DDI->getExpression(), DDI->getDebugLoc(),
1191+
Ty->isPointerTy() ? DbgVariableRecord::LocationType::Declare
1192+
: DbgVariableRecord::LocationType::Value);
1193+
Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1194+
NewDVR, Builder.GetInsertPoint());
1195+
// This dbg.declare_value is for the main function entry point. It
1196+
// will be deleted in all coro-split functions.
1197+
coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/);
1198+
};
1199+
for_each(DVRDeclareValues, SalvageOneCoro);
1200+
11591201
// If we have a single edge PHINode, remove it and replace it with a
11601202
// reload from the coroutine frame. (We already took care of multi edge
11611203
// PHINodes by normalizing them in the rewritePHIs function).
@@ -1982,7 +2024,7 @@ void coro::salvageDebugInfo(
19822024
Function *F = DVR.getFunction();
19832025
// Follow the pointer arithmetic all the way to the incoming
19842026
// function argument and convert into a DIExpression.
1985-
bool SkipOutermostLoad = DVR.isDbgDeclare();
2027+
bool SkipOutermostLoad = DVR.isDbgDeclare() || DVR.isDbgDeclareValue();
19862028
Value *OriginalStorage = DVR.getVariableLocationOp(0);
19872029

19882030
auto SalvagedInfo =
@@ -1996,10 +2038,11 @@ void coro::salvageDebugInfo(
19962038

19972039
DVR.replaceVariableLocationOp(OriginalStorage, Storage);
19982040
DVR.setExpression(Expr);
1999-
// We only hoist dbg.declare today since it doesn't make sense to hoist
2000-
// dbg.value since it does not have the same function wide guarantees that
2001-
// dbg.declare does.
2002-
if (DVR.getType() == DbgVariableRecord::LocationType::Declare) {
2041+
// We only hoist dbg.declare and dbg.declare_value today since it doesn't make
2042+
// sense to hoist dbg.value since it does not have the same function wide
2043+
// guarantees that dbg.declare does.
2044+
if (DVR.getType() == DbgVariableRecord::LocationType::Declare ||
2045+
DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
20032046
std::optional<BasicBlock::iterator> InsertPt;
20042047
if (auto *I = dyn_cast<Instruction>(Storage)) {
20052048
InsertPt = I->getInsertionPointAfterDef();
@@ -2014,6 +2057,19 @@ void coro::salvageDebugInfo(
20142057
InsertPt = F->getEntryBlock().begin();
20152058
if (InsertPt) {
20162059
DVR.removeFromParent();
2060+
// If there is a dbg.declare_value being reinserted, insert it as a
2061+
// dbg.declare instead, so that subsequent passes don't have to deal with
2062+
// a dbg.declare_value.
2063+
if (DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
2064+
auto *MD = DVR.getRawLocation();
2065+
if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
2066+
Type *Ty = VAM->getValue()->getType();
2067+
if (Ty->isPointerTy())
2068+
DVR.Type = DbgVariableRecord::LocationType::Declare;
2069+
else
2070+
DVR.Type = DbgVariableRecord::LocationType::Value;
2071+
}
2072+
}
20172073
(*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
20182074
}
20192075
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
;RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s
2+
3+
; CHECK: %.debug = alloca double, align 8
4+
; CHECK-NEXT: #dbg_declare(ptr %{{.*}}, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}})
5+
; CHECK-NEXT: store double %{{[0-9]+}}, ptr %{{.*}}, align 8
6+
; CHECK-NEXT: #dbg_declare(ptr %arg, !{{[0-9]+}}, !DIExpression(DW_OP_plus_uconst, 24), !{{[0-9]+}})
7+
8+
; ModuleID = '/Users/srastogi/Development/llvm-project-2/llvm/test/Transforms/Coroutines/declare-value.ll'
9+
source_filename = "/Users/srastogi/Development/llvm-project-2/llvm/test/Transforms/Coroutines/declare-value.ll"
10+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
11+
target triple = "arm64-unknown"
12+
13+
@coroutineATu = global <{ i32, i32 }> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @coroutineA to i64), i64 ptrtoint (ptr @coroutineATu to i64)) to i32), i32 16 }>, align 8
14+
15+
; Function Attrs: presplitcoroutine
16+
define swifttailcc void @coroutineA(ptr swiftasync %arg, double %0) #0 !dbg !1 {
17+
%var_with_dbg_value = alloca ptr, align 8
18+
%var_with_dbg_declare = alloca ptr, align 8
19+
#dbg_declare(ptr %var_with_dbg_declare, !5, !DIExpression(), !7)
20+
#dbg_declare_value(double %0, !5, !DIExpression(), !7)
21+
%i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineATu)
22+
%i3 = call ptr @llvm.coro.begin(token %i2, ptr null)
23+
%i7 = call ptr @llvm.coro.async.resume(), !dbg !7
24+
%i10 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %i7, ptr nonnull @__swift_async_resume_get_context, ptr nonnull @coroutineA.1, ptr %i7, i64 0, i64 0, ptr %arg), !dbg !7
25+
call void @dont_optimize(ptr %var_with_dbg_value, ptr %var_with_dbg_declare), !dbg !7
26+
unreachable, !dbg !7
27+
}
28+
29+
define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) !dbg !8 {
30+
ret ptr %arg, !dbg !9
31+
}
32+
33+
define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) !dbg !10 {
34+
ret void, !dbg !11
35+
}
36+
37+
declare void @dont_optimize(ptr, ptr)
38+
39+
; Function Attrs: nomerge nounwind
40+
declare ptr @llvm.coro.async.resume() #1
41+
42+
; Function Attrs: nounwind
43+
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
44+
45+
; Function Attrs: nounwind
46+
declare token @llvm.coro.id.async(i32, i32, i32, ptr) #2
47+
48+
; Function Attrs: nomerge nounwind
49+
declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #1
50+
51+
attributes #0 = { presplitcoroutine }
52+
attributes #1 = { nomerge nounwind }
53+
attributes #2 = { nounwind }
54+
55+
!llvm.module.flags = !{!0}
56+
57+
!0 = !{i32 2, !"Debug Info Version", i32 3}
58+
!1 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4)
59+
!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
60+
!3 = !DIFile(filename: "blah", directory: "")
61+
!4 = !{}
62+
!5 = !DILocalVariable(scope: !1, type: !6)
63+
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Klass")
64+
!7 = !DILocation(line: 0, scope: !1)
65+
!8 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2)
66+
!9 = !DILocation(line: 0, scope: !8)
67+
!10 = distinct !DISubprogram(scope: null, spFlags: DISPFlagDefinition, unit: !2)
68+
!11 = !DILocation(line: 0, scope: !10)

0 commit comments

Comments
 (0)