Skip to content

Commit 8321f3c

Browse files
Add support for llvm.dbg.declare_value in the CoroSplitter pass.
Make sure the CoroSplitter pass correctly handles llvm.dbg.declare_value intrinsics. Also, convert them to llvm.dbg.declares so that any subsquent passes do not need to be amended to support the llvm.dbg.declare_value intrinsic.
1 parent 70c9f1a commit 8321f3c

File tree

2 files changed

+108
-5
lines changed

2 files changed

+108
-5
lines changed

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,7 @@ static void cacheDIVar(FrameDataInfo &FrameData,
554554
DIVarCache.insert({V, (*I)->getVariable()});
555555
};
556556
CacheIt(findDVRDeclares(V));
557+
CacheIt(findDVRDeclareValues(V));
557558
}
558559
}
559560

@@ -1142,6 +1143,47 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
11421143
for_each(DVRs, SalvageOne);
11431144
}
11441145

1146+
TinyPtrVector<DbgVariableRecord *> DVRDeclareValues =
1147+
findDVRDeclareValues(Def);
1148+
// Try best to find dbg.declare_value. If the spill is a temp, there may
1149+
// not be a direct dbg.declare_value. Walk up the load chain to find one
1150+
// from an alias.
1151+
if (F->getSubprogram()) {
1152+
auto *CurDef = Def;
1153+
while (DVRDeclareValues.empty() && isa<LoadInst>(CurDef)) {
1154+
auto *LdInst = cast<LoadInst>(CurDef);
1155+
// Only consider ptr to ptr same type load.
1156+
if (LdInst->getPointerOperandType() != LdInst->getType())
1157+
break;
1158+
CurDef = LdInst->getPointerOperand();
1159+
if (!isa<AllocaInst, LoadInst>(CurDef))
1160+
break;
1161+
DVRDeclareValues = findDVRDeclareValues(CurDef);
1162+
}
1163+
}
1164+
1165+
auto SalvageOneCoro = [&](auto *DDI) {
1166+
// This dbg.declare_value is preserved for all coro-split function
1167+
// fragments. It will be unreachable in the main function, and
1168+
// processed by coro::salvageDebugInfo() by the Cloner. However, convert
1169+
// it to a dbg.declare to make sure future passes don't have to deal
1170+
// with a dbg.declare_value.
1171+
auto *VAM = ValueAsMetadata::get(CurrentReload);
1172+
Type *Ty = VAM->getValue()->getType();
1173+
// If the metadata type is not a pointer, emit a dbg.value instead.
1174+
DbgVariableRecord *NewDVR = new DbgVariableRecord(
1175+
ValueAsMetadata::get(CurrentReload), DDI->getVariable(),
1176+
DDI->getExpression(), DDI->getDebugLoc(),
1177+
Ty->isPointerTy() ? DbgVariableRecord::LocationType::Declare
1178+
: DbgVariableRecord::LocationType::Value);
1179+
Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
1180+
NewDVR, Builder.GetInsertPoint());
1181+
// This dbg.declare_value is for the main function entry point. It
1182+
// will be deleted in all coro-split functions.
1183+
coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/);
1184+
};
1185+
for_each(DVRDeclareValues, SalvageOneCoro);
1186+
11451187
// If we have a single edge PHINode, remove it and replace it with a
11461188
// reload from the coroutine frame. (We already took care of multi edge
11471189
// PHINodes by normalizing them in the rewritePHIs function).
@@ -1925,7 +1967,7 @@ void coro::salvageDebugInfo(
19251967
Function *F = DVR.getFunction();
19261968
// Follow the pointer arithmetic all the way to the incoming
19271969
// function argument and convert into a DIExpression.
1928-
bool SkipOutermostLoad = DVR.isDbgDeclare();
1970+
bool SkipOutermostLoad = DVR.isDbgDeclare() || DVR.isDbgDeclareValue();
19291971
Value *OriginalStorage = DVR.getVariableLocationOp(0);
19301972

19311973
auto SalvagedInfo =
@@ -1939,10 +1981,11 @@ void coro::salvageDebugInfo(
19391981

19401982
DVR.replaceVariableLocationOp(OriginalStorage, Storage);
19411983
DVR.setExpression(Expr);
1942-
// We only hoist dbg.declare today since it doesn't make sense to hoist
1943-
// dbg.value since it does not have the same function wide guarantees that
1944-
// dbg.declare does.
1945-
if (DVR.getType() == DbgVariableRecord::LocationType::Declare) {
1984+
// We only hoist dbg.declare and dbg.declare_value today since it doesn't make
1985+
// sense to hoist dbg.value since it does not have the same function wide
1986+
// guarantees that dbg.declare does.
1987+
if (DVR.getType() == DbgVariableRecord::LocationType::Declare ||
1988+
DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
19461989
std::optional<BasicBlock::iterator> InsertPt;
19471990
if (auto *I = dyn_cast<Instruction>(Storage)) {
19481991
InsertPt = I->getInsertionPointAfterDef();
@@ -1957,6 +2000,19 @@ void coro::salvageDebugInfo(
19572000
InsertPt = F->getEntryBlock().begin();
19582001
if (InsertPt) {
19592002
DVR.removeFromParent();
2003+
// If there is a dbg.declare_value being reinserted, insert it as a
2004+
// dbg.declare instead, so that subsequent passes don't have to deal with
2005+
// a dbg.declare_value.
2006+
if (DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
2007+
auto *MD = DVR.getRawLocation();
2008+
if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
2009+
Type *Ty = VAM->getValue()->getType();
2010+
if (Ty->isPointerTy())
2011+
DVR.Type = DbgVariableRecord::LocationType::Declare;
2012+
else
2013+
DVR.Type = DbgVariableRecord::LocationType::Value;
2014+
}
2015+
}
19602016
(*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
19612017
}
19622018
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
;RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early)' -o - | FileCheck %s --check-prefix=EARLY
2+
;RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=SPLIT
3+
4+
5+
; EARLY: #dbg_declare_value(double %{{[0-9]+}}, !{{[0-9]+}}, !DIExpression(), !{{[0-9]+}})
6+
7+
; SPLIT: %.debug = alloca double, align 8
8+
; SPLIT-NEXT: #dbg_declare(ptr %{{.*}}, !{{[0-9]+}}, !DIExpression(DW_OP_deref), !{{[0-9]+}})
9+
; SPLIT-NEXT: store double %{{[0-9]+}}, ptr %{{.*}}, align 8
10+
; SPLIT-NEXT: #dbg_declare(ptr %arg, !{{[0-9]+}}, !DIExpression(DW_OP_plus_uconst, 24), !{{[0-9]+}})
11+
12+
define swifttailcc void @coroutineA(ptr swiftasync %arg, double %1) !dbg !48 {
13+
%var_with_dbg_value = alloca ptr, align 8
14+
%var_with_dbg_declare = alloca ptr, align 8
15+
call void @llvm.dbg.declare(metadata ptr %var_with_dbg_declare, metadata !500, metadata !DIExpression()), !dbg !54
16+
call void @llvm.dbg.declare_value(metadata double %1, metadata !50, metadata !DIExpression()), !dbg !54
17+
%i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineATu)
18+
%i3 = call ptr @llvm.coro.begin(token %i2, ptr null)
19+
%i7 = call ptr @llvm.coro.async.resume(), !dbg !54
20+
%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 !54
21+
call void @dont_optimize(ptr %var_with_dbg_value, ptr %var_with_dbg_declare), !dbg !100
22+
unreachable, !dbg !54
23+
}
24+
@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
25+
define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) !dbg !64 {
26+
ret ptr %arg, !dbg !65
27+
}
28+
define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) !dbg !66 {
29+
ret void, !dbg !67
30+
}
31+
declare void @dont_optimize(ptr, ptr)
32+
!llvm.module.flags = !{!7}
33+
!7 = !{i32 2, !"Debug Info Version", i32 3}
34+
!50 = !DILocalVariable(scope: !48, type: !53)
35+
!500 = !DILocalVariable(scope: !48, type: !53)
36+
!49 = !{}
37+
!16 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !17, emissionKind: FullDebug)
38+
!17 = !DIFile(filename: "blah", directory: "")
39+
!53 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Klass")
40+
!46 = !DISubroutineType(types: null)
41+
!64 = distinct !DISubprogram(unit: !16)
42+
!66 = distinct !DISubprogram(unit: !16)
43+
!48 = distinct !DISubprogram(unit: !16, retainedNodes: !49)
44+
!65 = !DILocation(scope: !64)
45+
!67 = !DILocation(scope: !66)
46+
!54 = !DILocation(scope: !48)
47+
!100 = !DILocation(scope: !48)

0 commit comments

Comments
 (0)