Skip to content

Commit fd8fa31

Browse files
authoredDec 13, 2023
[RemoveDIs] Update Coroutine passes to handle DPValues (#74480)
As part of the RemoveDIs project, transitioning to non-instruction debug info, all debug intrinsic handling code needs to be duplicated to handle DPValues. --try-experimental-debuginfo-iterators enables the new debug mode in tests if the CMake option has been enabled. `getInsertPtAfterFramePtr` now returns an iterator so we don't lose debug-info-communicating bits. --- Depends on #73500, #74090, #74091.
1 parent e418988 commit fd8fa31

13 files changed

+197
-61
lines changed
 

‎llvm/lib/IR/BasicBlock.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,8 @@ void BasicBlock::insertDPValueBefore(DPValue *DPV,
10911091
// shouldn't be generated at times when there's no terminator.
10921092
assert(Where != end());
10931093
assert(Where->getParent() == this);
1094+
if (!Where->DbgMarker)
1095+
createMarker(Where);
10941096
bool InsertAtHead = Where.getHeadBit();
10951097
Where->DbgMarker->insertDPValue(DPV, InsertAtHead);
10961098
}

‎llvm/lib/Transforms/Coroutines/CoroFrame.cpp

+146-44
Original file line numberDiff line numberDiff line change
@@ -964,12 +964,17 @@ static void cacheDIVar(FrameDataInfo &FrameData,
964964
continue;
965965

966966
SmallVector<DbgDeclareInst *, 1> DDIs;
967-
findDbgDeclares(DDIs, V);
968-
auto *I = llvm::find_if(DDIs, [](DbgDeclareInst *DDI) {
969-
return DDI->getExpression()->getNumElements() == 0;
970-
});
971-
if (I != DDIs.end())
972-
DIVarCache.insert({V, (*I)->getVariable()});
967+
SmallVector<DPValue *, 1> DPVs;
968+
findDbgDeclares(DDIs, V, &DPVs);
969+
auto CacheIt = [&DIVarCache, V](auto &Container) {
970+
auto *I = llvm::find_if(Container, [](auto *DDI) {
971+
return DDI->getExpression()->getNumElements() == 0;
972+
});
973+
if (I != Container.end())
974+
DIVarCache.insert({V, (*I)->getVariable()});
975+
};
976+
CacheIt(DDIs);
977+
CacheIt(DPVs);
973978
}
974979
}
975980

@@ -1121,15 +1126,25 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
11211126
"Coroutine with switch ABI should own Promise alloca");
11221127

11231128
SmallVector<DbgDeclareInst *, 1> DIs;
1124-
findDbgDeclares(DIs, PromiseAlloca);
1125-
if (DIs.empty())
1129+
SmallVector<DPValue *, 1> DPVs;
1130+
findDbgDeclares(DIs, PromiseAlloca, &DPVs);
1131+
1132+
DILocalVariable *PromiseDIVariable = nullptr;
1133+
DILocation *DILoc = nullptr;
1134+
if (!DIs.empty()) {
1135+
DbgDeclareInst *PromiseDDI = DIs.front();
1136+
PromiseDIVariable = PromiseDDI->getVariable();
1137+
DILoc = PromiseDDI->getDebugLoc().get();
1138+
} else if (!DPVs.empty()) {
1139+
DPValue *PromiseDPV = DPVs.front();
1140+
PromiseDIVariable = PromiseDPV->getVariable();
1141+
DILoc = PromiseDPV->getDebugLoc().get();
1142+
} else {
11261143
return;
1144+
}
11271145

1128-
DbgDeclareInst *PromiseDDI = DIs.front();
1129-
DILocalVariable *PromiseDIVariable = PromiseDDI->getVariable();
11301146
DILocalScope *PromiseDIScope = PromiseDIVariable->getScope();
11311147
DIFile *DFile = PromiseDIScope->getFile();
1132-
DILocation *DILoc = PromiseDDI->getDebugLoc().get();
11331148
unsigned LineNum = PromiseDIVariable->getLine();
11341149

11351150
DICompositeType *FrameDITy = DBuilder.createStructType(
@@ -1243,7 +1258,7 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
12431258
auto *FrameDIVar = DBuilder.createAutoVariable(PromiseDIScope, "__coro_frame",
12441259
DFile, LineNum, FrameDITy,
12451260
true, DINode::FlagArtificial);
1246-
assert(FrameDIVar->isValidLocationForIntrinsic(PromiseDDI->getDebugLoc()));
1261+
assert(FrameDIVar->isValidLocationForIntrinsic(DILoc));
12471262

12481263
// Subprogram would have ContainedNodes field which records the debug
12491264
// variables it contained. So we need to add __coro_frame to the
@@ -1261,9 +1276,17 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
12611276
7, (MDTuple::get(F.getContext(), RetainedNodesVec)));
12621277
}
12631278

1264-
DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar,
1265-
DBuilder.createExpression(), DILoc,
1266-
Shape.getInsertPtAfterFramePtr());
1279+
if (UseNewDbgInfoFormat) {
1280+
DPValue *NewDPV = new DPValue(ValueAsMetadata::get(Shape.FramePtr),
1281+
FrameDIVar, DBuilder.createExpression(),
1282+
DILoc, DPValue::LocationType::Declare);
1283+
BasicBlock::iterator It = Shape.getInsertPtAfterFramePtr();
1284+
It->getParent()->insertDPValueBefore(NewDPV, It);
1285+
} else {
1286+
DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar,
1287+
DBuilder.createExpression(), DILoc,
1288+
&*Shape.getInsertPtAfterFramePtr());
1289+
}
12671290
}
12681291

12691292
// Build a struct that will keep state for an active coroutine.
@@ -1771,7 +1794,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
17711794
if (auto *Arg = dyn_cast<Argument>(Def)) {
17721795
// For arguments, we will place the store instruction right after
17731796
// the coroutine frame pointer instruction, i.e. coro.begin.
1774-
InsertPt = Shape.getInsertPtAfterFramePtr()->getIterator();
1797+
InsertPt = Shape.getInsertPtAfterFramePtr();
17751798

17761799
// If we're spilling an Argument, make sure we clear 'nocapture'
17771800
// from the coroutine function.
@@ -1788,7 +1811,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
17881811
if (!DT.dominates(CB, I)) {
17891812
// If it is not dominated by CoroBegin, then spill should be
17901813
// inserted immediately after CoroFrame is computed.
1791-
InsertPt = Shape.getInsertPtAfterFramePtr()->getIterator();
1814+
InsertPt = Shape.getInsertPtAfterFramePtr();
17921815
} else if (auto *II = dyn_cast<InvokeInst>(I)) {
17931816
// If we are spilling the result of the invoke instruction, split
17941817
// the normal edge and insert the spill in the new block.
@@ -1843,7 +1866,8 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
18431866
SpillAlignment, E.first->getName() + Twine(".reload"));
18441867

18451868
SmallVector<DbgDeclareInst *, 1> DIs;
1846-
findDbgDeclares(DIs, Def);
1869+
SmallVector<DPValue *, 1> DPVs;
1870+
findDbgDeclares(DIs, Def, &DPVs);
18471871
// Try best to find dbg.declare. If the spill is a temp, there may not
18481872
// be a direct dbg.declare. Walk up the load chain to find one from an
18491873
// alias.
@@ -1858,24 +1882,36 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
18581882
if (!isa<AllocaInst, LoadInst>(CurDef))
18591883
break;
18601884
DIs.clear();
1861-
findDbgDeclares(DIs, CurDef);
1885+
DPVs.clear();
1886+
findDbgDeclares(DIs, CurDef, &DPVs);
18621887
}
18631888
}
18641889

1865-
for (DbgDeclareInst *DDI : DIs) {
1890+
auto SalvageOne = [&](auto *DDI) {
18661891
bool AllowUnresolved = false;
18671892
// This dbg.declare is preserved for all coro-split function
18681893
// fragments. It will be unreachable in the main function, and
18691894
// processed by coro::salvageDebugInfo() by CoroCloner.
1870-
DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved)
1871-
.insertDeclare(CurrentReload, DDI->getVariable(),
1872-
DDI->getExpression(), DDI->getDebugLoc(),
1873-
&*Builder.GetInsertPoint());
1895+
if (UseNewDbgInfoFormat) {
1896+
DPValue *NewDPV =
1897+
new DPValue(ValueAsMetadata::get(CurrentReload),
1898+
DDI->getVariable(), DDI->getExpression(),
1899+
DDI->getDebugLoc(), DPValue::LocationType::Declare);
1900+
Builder.GetInsertPoint()->getParent()->insertDPValueBefore(
1901+
NewDPV, Builder.GetInsertPoint());
1902+
} else {
1903+
DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved)
1904+
.insertDeclare(CurrentReload, DDI->getVariable(),
1905+
DDI->getExpression(), DDI->getDebugLoc(),
1906+
&*Builder.GetInsertPoint());
1907+
}
18741908
// This dbg.declare is for the main function entry point. It
18751909
// will be deleted in all coro-split functions.
1876-
coro::salvageDebugInfo(ArgToAllocaMap, DDI, Shape.OptimizeFrame,
1910+
coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame,
18771911
false /*UseEntryValue*/);
1878-
}
1912+
};
1913+
for_each(DIs, SalvageOne);
1914+
for_each(DPVs, SalvageOne);
18791915
}
18801916

18811917
// If we have a single edge PHINode, remove it and replace it with a
@@ -1893,6 +1929,10 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
18931929
// Replace all uses of CurrentValue in the current instruction with
18941930
// reload.
18951931
U->replaceUsesOfWith(Def, CurrentReload);
1932+
// Instructions are added to Def's user list if the attached
1933+
// debug records use Def. Update those now.
1934+
for (auto &DPV : U->getDbgValueRange())
1935+
DPV.replaceVariableLocationOp(Def, CurrentReload, true);
18961936
}
18971937
}
18981938

@@ -1943,9 +1983,12 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
19431983
G->setName(Alloca->getName() + Twine(".reload.addr"));
19441984

19451985
SmallVector<DbgVariableIntrinsic *, 4> DIs;
1946-
findDbgUsers(DIs, Alloca);
1986+
SmallVector<DPValue *> DPValues;
1987+
findDbgUsers(DIs, Alloca, &DPValues);
19471988
for (auto *DVI : DIs)
19481989
DVI->replaceUsesOfWith(Alloca, G);
1990+
for (auto *DPV : DPValues)
1991+
DPV->replaceVariableLocationOp(Alloca, G);
19491992

19501993
for (Instruction *I : UsersToUpdate) {
19511994
// It is meaningless to retain the lifetime intrinsics refer for the
@@ -1959,7 +2002,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
19592002
I->replaceUsesOfWith(Alloca, G);
19602003
}
19612004
}
1962-
Builder.SetInsertPoint(Shape.getInsertPtAfterFramePtr());
2005+
Builder.SetInsertPoint(&*Shape.getInsertPtAfterFramePtr());
19632006
for (const auto &A : FrameData.Allocas) {
19642007
AllocaInst *Alloca = A.Alloca;
19652008
if (A.MayWriteBeforeCoroBegin) {
@@ -2020,7 +2063,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
20202063
isa<BitCastInst>(Inst);
20212064
});
20222065
if (HasAccessingPromiseBeforeCB) {
2023-
Builder.SetInsertPoint(Shape.getInsertPtAfterFramePtr());
2066+
Builder.SetInsertPoint(&*Shape.getInsertPtAfterFramePtr());
20242067
auto *G = GetFramePointer(PA);
20252068
auto *Value = Builder.CreateLoad(PA->getAllocatedType(), PA);
20262069
Builder.CreateStore(Value, G);
@@ -2802,21 +2845,16 @@ static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape,
28022845
Visitor.getMayWriteBeforeCoroBegin());
28032846
}
28042847

2805-
void coro::salvageDebugInfo(
2806-
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
2807-
DbgVariableIntrinsic *DVI, bool OptimizeFrame, bool UseEntryValue) {
2808-
Function *F = DVI->getFunction();
2848+
static std::optional<std::pair<Value &, DIExpression &>>
2849+
salvageDebugInfoImpl(SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
2850+
bool OptimizeFrame, bool UseEntryValue, Function *F,
2851+
Value *Storage, DIExpression *Expr,
2852+
bool SkipOutermostLoad) {
28092853
IRBuilder<> Builder(F->getContext());
28102854
auto InsertPt = F->getEntryBlock().getFirstInsertionPt();
28112855
while (isa<IntrinsicInst>(InsertPt))
28122856
++InsertPt;
28132857
Builder.SetInsertPoint(&F->getEntryBlock(), InsertPt);
2814-
DIExpression *Expr = DVI->getExpression();
2815-
// Follow the pointer arithmetic all the way to the incoming
2816-
// function argument and convert into a DIExpression.
2817-
bool SkipOutermostLoad = !isa<DbgValueInst>(DVI);
2818-
Value *Storage = DVI->getVariableLocationOp(0);
2819-
Value *OriginalStorage = Storage;
28202858

28212859
while (auto *Inst = dyn_cast_or_null<Instruction>(Storage)) {
28222860
if (auto *LdInst = dyn_cast<LoadInst>(Inst)) {
@@ -2848,7 +2886,7 @@ void coro::salvageDebugInfo(
28482886
SkipOutermostLoad = false;
28492887
}
28502888
if (!Storage)
2851-
return;
2889+
return std::nullopt;
28522890

28532891
auto *StorageAsArg = dyn_cast<Argument>(Storage);
28542892
const bool IsSwiftAsyncArg =
@@ -2884,8 +2922,30 @@ void coro::salvageDebugInfo(
28842922
Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
28852923
}
28862924

2887-
DVI->replaceVariableLocationOp(OriginalStorage, Storage);
2888-
DVI->setExpression(Expr);
2925+
return {{*Storage, *Expr}};
2926+
}
2927+
2928+
void coro::salvageDebugInfo(
2929+
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
2930+
DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool UseEntryValue) {
2931+
2932+
Function *F = DVI.getFunction();
2933+
// Follow the pointer arithmetic all the way to the incoming
2934+
// function argument and convert into a DIExpression.
2935+
bool SkipOutermostLoad = !isa<DbgValueInst>(DVI);
2936+
Value *OriginalStorage = DVI.getVariableLocationOp(0);
2937+
2938+
auto SalvagedInfo = ::salvageDebugInfoImpl(
2939+
ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage,
2940+
DVI.getExpression(), SkipOutermostLoad);
2941+
if (!SalvagedInfo)
2942+
return;
2943+
2944+
Value *Storage = &SalvagedInfo->first;
2945+
DIExpression *Expr = &SalvagedInfo->second;
2946+
2947+
DVI.replaceVariableLocationOp(OriginalStorage, Storage);
2948+
DVI.setExpression(Expr);
28892949
// We only hoist dbg.declare today since it doesn't make sense to hoist
28902950
// dbg.value since it does not have the same function wide guarantees that
28912951
// dbg.declare does.
@@ -2896,7 +2956,44 @@ void coro::salvageDebugInfo(
28962956
else if (isa<Argument>(Storage))
28972957
InsertPt = F->getEntryBlock().begin();
28982958
if (InsertPt)
2899-
DVI->moveBefore(*(*InsertPt)->getParent(), *InsertPt);
2959+
DVI.moveBefore(*(*InsertPt)->getParent(), *InsertPt);
2960+
}
2961+
}
2962+
2963+
void coro::salvageDebugInfo(
2964+
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV,
2965+
bool OptimizeFrame, bool UseEntryValue) {
2966+
2967+
Function *F = DPV.getFunction();
2968+
// Follow the pointer arithmetic all the way to the incoming
2969+
// function argument and convert into a DIExpression.
2970+
bool SkipOutermostLoad = DPV.getType() == DPValue::LocationType::Declare;
2971+
Value *OriginalStorage = DPV.getVariableLocationOp(0);
2972+
2973+
auto SalvagedInfo = ::salvageDebugInfoImpl(
2974+
ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage,
2975+
DPV.getExpression(), SkipOutermostLoad);
2976+
if (!SalvagedInfo)
2977+
return;
2978+
2979+
Value *Storage = &SalvagedInfo->first;
2980+
DIExpression *Expr = &SalvagedInfo->second;
2981+
2982+
DPV.replaceVariableLocationOp(OriginalStorage, Storage);
2983+
DPV.setExpression(Expr);
2984+
// We only hoist dbg.declare today since it doesn't make sense to hoist
2985+
// dbg.value since it does not have the same function wide guarantees that
2986+
// dbg.declare does.
2987+
if (DPV.getType() == DPValue::LocationType::Declare) {
2988+
std::optional<BasicBlock::iterator> InsertPt;
2989+
if (auto *I = dyn_cast<Instruction>(Storage))
2990+
InsertPt = I->getInsertionPointAfterDef();
2991+
else if (isa<Argument>(Storage))
2992+
InsertPt = F->getEntryBlock().begin();
2993+
if (InsertPt) {
2994+
DPV.removeFromParent();
2995+
(*InsertPt)->getParent()->insertDPValueBefore(&DPV, *InsertPt);
2996+
}
29002997
}
29012998
}
29022999

@@ -3087,10 +3184,15 @@ void coro::buildCoroutineFrame(
30873184
for (auto &Iter : FrameData.Spills) {
30883185
auto *V = Iter.first;
30893186
SmallVector<DbgValueInst *, 16> DVIs;
3090-
findDbgValues(DVIs, V);
3187+
SmallVector<DPValue *, 16> DPVs;
3188+
findDbgValues(DVIs, V, &DPVs);
30913189
for (DbgValueInst *DVI : DVIs)
30923190
if (Checker.isDefinitionAcrossSuspend(*V, DVI))
30933191
FrameData.Spills[V].push_back(DVI);
3192+
// Add the instructions which carry debug info that is in the frame.
3193+
for (DPValue *DPV : DPVs)
3194+
if (Checker.isDefinitionAcrossSuspend(*V, DPV->Marker->MarkedInstr))
3195+
FrameData.Spills[V].push_back(DPV->Marker->MarkedInstr);
30943196
}
30953197

30963198
LLVM_DEBUG(dumpSpills("Spills", FrameData.Spills));

‎llvm/lib/Transforms/Coroutines/CoroInternal.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ void replaceCoroFree(CoroIdInst *CoroId, bool Elide);
3232
/// OptimizeFrame is false.
3333
void salvageDebugInfo(
3434
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap,
35-
DbgVariableIntrinsic *DVI, bool OptimizeFrame, bool IsEntryPoint);
35+
DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool IsEntryPoint);
36+
void salvageDebugInfo(
37+
SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV,
38+
bool OptimizeFrame, bool UseEntryValue);
3639

3740
// Keeps data and helper functions for lowering coroutine intrinsics.
3841
struct LowererBase {
@@ -240,10 +243,13 @@ struct LLVM_LIBRARY_VISIBILITY Shape {
240243
return nullptr;
241244
}
242245

243-
Instruction *getInsertPtAfterFramePtr() const {
244-
if (auto *I = dyn_cast<Instruction>(FramePtr))
245-
return I->getNextNode();
246-
return &cast<Argument>(FramePtr)->getParent()->getEntryBlock().front();
246+
BasicBlock::iterator getInsertPtAfterFramePtr() const {
247+
if (auto *I = dyn_cast<Instruction>(FramePtr)) {
248+
BasicBlock::iterator It = std::next(I->getIterator());
249+
It.setHeadBit(true); // Copy pre-RemoveDIs behaviour.
250+
return It;
251+
}
252+
return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin();
247253
}
248254

249255
/// Allocate memory according to the rules of the active lowering.

0 commit comments

Comments
 (0)
Please sign in to comment.