[llvm] Create llvm.dbg.declare_value and add it to the CoroSplitter Pass (PR #164953)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 24 03:37:44 PDT 2025
https://github.com/rastogishubham updated https://github.com/llvm/llvm-project/pull/164953
>From b427b5a5aef1aab801eea51096201d721dceb2ca Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Fri, 19 Sep 2025 13:06:08 -0700
Subject: [PATCH 1/2] Add new llvm.dbg.declare_value intrinsic.
For swift async code, we need to use a debug intrinsic that behaves like
an llvm.dbg.declare but can take any location type rather than just a
pointer or integer.
To solve this, a new debug instrinsic called llvm.dbg.declare_value
has been created, which behaves exactly like an llvm.dbg.declare but
can take non pointer and integer location types.
---
llvm/include/llvm/Bitcode/LLVMBitCodes.h | 2 ++
llvm/include/llvm/IR/DIBuilder.h | 12 ++++++++++
llvm/include/llvm/IR/DebugInfo.h | 2 ++
.../include/llvm/IR/DebugProgramInstruction.h | 9 ++++++++
llvm/include/llvm/IR/IntrinsicInst.h | 21 +++++++++++++++++
llvm/include/llvm/IR/Intrinsics.td | 4 ++++
llvm/lib/AsmParser/LLLexer.cpp | 1 +
llvm/lib/AsmParser/LLParser.cpp | 6 +++--
llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp | 1 +
llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 8 +++++++
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +++
llvm/lib/IR/AsmWriter.cpp | 3 +++
llvm/lib/IR/AutoUpgrade.cpp | 5 ++++
llvm/lib/IR/DIBuilder.cpp | 18 +++++++++++++++
llvm/lib/IR/DebugInfo.cpp | 17 ++++++++++++++
llvm/lib/IR/DebugProgramInstruction.cpp | 23 +++++++++++++++++++
llvm/lib/IR/Verifier.cpp | 4 ++++
17 files changed, 137 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
index 1c7d3462b6bae..b6b61ede2cb03 100644
--- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -688,6 +688,8 @@ enum FunctionCodes {
FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE =
64, // [DILocation, DILocalVariable, DIExpression, Value]
FUNC_CODE_DEBUG_RECORD_LABEL = 65, // [DILocation, DILabel]
+ FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE =
+ 66, // [DILocation, DILocalVariable, DIExpression, ValueAsMetadata]
};
enum UseListCodes {
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 25cbc38b61272..9b13fc1745150 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -1150,6 +1150,18 @@ namespace llvm {
DIExpression *Expr, const DILocation *DL,
InsertPosition InsertPt);
+ /// Insert a new llvm.dbg.declare_value intrinsic call.
+ /// \param Storage llvm::Value of the variable
+ /// \param VarInfo Variable's debug info descriptor.
+ /// \param Expr A complex location expression.
+ /// \param DL Debug info location.
+ /// \param InsertPt Location for the new intrinsic.
+ LLVM_ABI DbgInstPtr insertDeclareValue(llvm::Value *Storage,
+ DILocalVariable *VarInfo,
+ DIExpression *Expr,
+ const DILocation *DL,
+ InsertPosition InsertPt);
+
/// Insert a new llvm.dbg.label intrinsic call.
/// \param LabelInfo Label's debug info descriptor.
/// \param DL Debug info location.
diff --git a/llvm/include/llvm/IR/DebugInfo.h b/llvm/include/llvm/IR/DebugInfo.h
index 220e4c1cad4f7..d75820add7254 100644
--- a/llvm/include/llvm/IR/DebugInfo.h
+++ b/llvm/include/llvm/IR/DebugInfo.h
@@ -44,6 +44,8 @@ class Module;
LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V);
/// As above, for DVRValues.
LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRValues(Value *V);
+/// As above, for DVRCoroFrameEntrys.
+LLVM_ABI TinyPtrVector<DbgVariableRecord *> findDVRDeclareValues(Value *V);
/// Finds the debug info records describing a value.
LLVM_ABI void
diff --git a/llvm/include/llvm/IR/DebugProgramInstruction.h b/llvm/include/llvm/IR/DebugProgramInstruction.h
index e0292c2b8d2d2..f6a45bb9b9653 100644
--- a/llvm/include/llvm/IR/DebugProgramInstruction.h
+++ b/llvm/include/llvm/IR/DebugProgramInstruction.h
@@ -282,6 +282,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
Declare,
Value,
Assign,
+ DeclareValue,
End, ///< Marks the end of the concrete types.
Any, ///< To indicate all LocationTypes in searches.
@@ -364,6 +365,13 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
createDVRDeclare(Value *Address, DILocalVariable *DV, DIExpression *Expr,
const DILocation *DI, DbgVariableRecord &InsertBefore);
+ LLVM_ABI static DbgVariableRecord *
+ createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr,
+ const DILocation *DI);
+ LLVM_ABI static DbgVariableRecord *
+ createDVRDeclareValue(Value *Address, DILocalVariable *DV, DIExpression *Expr,
+ const DILocation *DI, DbgVariableRecord &InsertBefore);
+
/// Iterator for ValueAsMetadata that internally uses direct pointer iteration
/// over either a ValueAsMetadata* or a ValueAsMetadata**, dereferencing to the
/// ValueAsMetadata .
@@ -414,6 +422,7 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
bool isDbgDeclare() const { return Type == LocationType::Declare; }
bool isDbgValue() const { return Type == LocationType::Value; }
+ bool isDbgDeclareValue() const { return Type == LocationType::DeclareValue; }
/// Get the locations corresponding to the variable referenced by the debug
/// info intrinsic. Depending on the intrinsic, this could be the
diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h
index eb0440f500735..3709d77e4df78 100644
--- a/llvm/include/llvm/IR/IntrinsicInst.h
+++ b/llvm/include/llvm/IR/IntrinsicInst.h
@@ -428,6 +428,7 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_assign:
+ case Intrinsic::dbg_declare_value:
return true;
default:
return false;
@@ -464,6 +465,26 @@ class DbgDeclareInst : public DbgVariableIntrinsic {
/// @}
};
+/// This represents the llvm.dbg.declare_value instruction.
+class DbgDeclareValueInst : public DbgVariableIntrinsic {
+public:
+ Value *getAddress() const {
+ assert(getNumVariableLocationOps() == 1 &&
+ "dbg.declare_value must have exactly 1 location operand.");
+ return getVariableLocationOp(0);
+ }
+
+ /// \name Casting methods
+ /// @{
+ static bool classof(const IntrinsicInst *I) {
+ return I->getIntrinsicID() == Intrinsic::dbg_declare_value;
+ }
+ static bool classof(const Value *V) {
+ return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
+ }
+ /// @}
+};
+
/// This represents the llvm.dbg.value instruction.
class DbgValueInst : public DbgVariableIntrinsic {
public:
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 96da698538314..573ba168475a6 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -1447,6 +1447,10 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
llvm_metadata_ty]>;
def int_dbg_label : DefaultAttrsIntrinsic<[],
[llvm_metadata_ty]>;
+ def int_dbg_declare_value : DefaultAttrsIntrinsic<[],
+ [llvm_metadata_ty,
+ llvm_metadata_ty,
+ llvm_metadata_ty]>;
}
//===------------------ Exception Handling Intrinsics----------------------===//
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index f6937d38eb38c..80df42c215d22 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -1002,6 +1002,7 @@ lltok::Kind LLLexer::LexIdentifier() {
DBGRECORDTYPEKEYWORD(declare);
DBGRECORDTYPEKEYWORD(assign);
DBGRECORDTYPEKEYWORD(label);
+ DBGRECORDTYPEKEYWORD(declare_value);
#undef DBGRECORDTYPEKEYWORD
if (Keyword.starts_with("DIFlag")) {
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 897e679095906..3cba07f66283d 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -7075,7 +7075,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) {
.Case("declare", RecordKind::ValueKind)
.Case("value", RecordKind::ValueKind)
.Case("assign", RecordKind::ValueKind)
- .Case("label", RecordKind::LabelKind);
+ .Case("label", RecordKind::LabelKind)
+ .Case("declare_value", RecordKind::ValueKind);
// Parsing labels is trivial; parse here and early exit, otherwise go into the
// full DbgVariableRecord processing stage.
@@ -7100,7 +7101,8 @@ bool LLParser::parseDebugRecord(DbgRecord *&DR, PerFunctionState &PFS) {
LocType ValueType = StringSwitch<LocType>(Lex.getStrVal())
.Case("declare", LocType::Declare)
.Case("value", LocType::Value)
- .Case("assign", LocType::Assign);
+ .Case("assign", LocType::Assign)
+ .Case("declare_value", LocType::DeclareValue);
Lex.Lex();
if (parseToken(lltok::lparen, "Expected '(' here"))
diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
index fe9e0ddca7091..911ec7501eb8b 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp
@@ -272,6 +272,7 @@ GetCodeName(unsigned CodeID, unsigned BlockID,
STRINGIFY_CODE(FUNC_CODE, INST_CALLBR)
STRINGIFY_CODE(FUNC_CODE, BLOCKADDR_USERS)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE)
+ STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_DECLARE_VALUE)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_ASSIGN)
STRINGIFY_CODE(FUNC_CODE, DEBUG_RECORD_VALUE_SIMPLE)
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 832aa9ff7ed3d..6816ec9a48828 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -6651,6 +6651,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
case bitc::FUNC_CODE_DEBUG_RECORD_VALUE_SIMPLE:
case bitc::FUNC_CODE_DEBUG_RECORD_VALUE:
case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE:
+ case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE:
case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
// DbgVariableRecords are placed after the Instructions that they are
// attached to.
@@ -6667,6 +6668,8 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
// ..., Value
// dbg_declare (FUNC_CODE_DEBUG_RECORD_DECLARE)
// ..., LocationMetadata
+ // dbg_declare_value (FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE)
+ // ..., LocationMetadata
// dbg_assign (FUNC_CODE_DEBUG_RECORD_ASSIGN)
// ..., LocationMetadata, DIAssignID, DIExpression, LocationMetadata
unsigned Slot = 0;
@@ -6708,6 +6711,11 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
DVR = new DbgVariableRecord(RawLocation, Var, Expr, DIL,
DbgVariableRecord::LocationType::Declare);
break;
+ case bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE:
+ DVR = new DbgVariableRecord(
+ RawLocation, Var, Expr, DIL,
+ DbgVariableRecord::LocationType::DeclareValue);
+ break;
case bitc::FUNC_CODE_DEBUG_RECORD_ASSIGN: {
DIAssignID *ID = cast<DIAssignID>(getFnMetadataByID(Record[Slot++]));
DIExpression *AddrExpr =
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index c4070e1f44688..6a46ebb33bdc6 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -3824,6 +3824,9 @@ void ModuleBitcodeWriter::writeFunction(
} else if (DVR.isDbgDeclare()) {
Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE, Vals);
+ } else if (DVR.isDbgDeclareValue()) {
+ Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
+ Stream.EmitRecord(bitc::FUNC_CODE_DEBUG_RECORD_DECLARE_VALUE, Vals);
} else {
assert(DVR.isDbgAssign() && "Unexpected DbgRecord kind");
Vals.push_back(VE.getMetadataID(DVR.getRawLocation()));
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 1a518305cffbe..181dbca22d988 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -4896,6 +4896,9 @@ void AssemblyWriter::printDbgVariableRecord(const DbgVariableRecord &DVR) {
case DbgVariableRecord::LocationType::Declare:
Out << "declare";
break;
+ case DbgVariableRecord::LocationType::DeclareValue:
+ Out << "declare_value";
+ break;
case DbgVariableRecord::LocationType::Assign:
Out << "assign";
break;
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index f28b98957cae4..a49af55cd4bb7 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -4601,6 +4601,11 @@ static void upgradeDbgIntrinsicToDbgRecord(StringRef Name, CallBase *CI) {
DbgVariableRecord::LocationType::Declare, unwrapMAVMetadataOp(CI, 0),
unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2), nullptr, nullptr, nullptr,
getDebugLocSafe(CI));
+ } else if (Name == "declare_value") {
+ DR = DbgVariableRecord::createUnresolvedDbgVariableRecord(
+ DbgVariableRecord::LocationType::DeclareValue,
+ unwrapMAVMetadataOp(CI, 0), unwrapMAVOp(CI, 1), unwrapMAVOp(CI, 2),
+ nullptr, nullptr, nullptr, getDebugLocSafe(CI));
} else if (Name == "addr") {
// Upgrade dbg.addr to dbg.value with DW_OP_deref.
MDNode *ExprNode = unwrapMAVOp(CI, 2);
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 1344df9298c80..76585560a4965 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -1140,6 +1140,24 @@ DbgInstPtr DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
return DVR;
}
+DbgInstPtr DIBuilder::insertDeclareValue(Value *Storage,
+ DILocalVariable *VarInfo,
+ DIExpression *Expr,
+ const DILocation *DL,
+ InsertPosition InsertPt) {
+ assert(VarInfo &&
+ "empty or invalid DILocalVariable* passed to dbg.declare_value");
+ assert(DL && "Expected debug loc");
+ assert(DL->getScope()->getSubprogram() ==
+ VarInfo->getScope()->getSubprogram() &&
+ "Expected matching subprograms");
+
+ DbgVariableRecord *DVR =
+ DbgVariableRecord::createDVRDeclareValue(Storage, VarInfo, Expr, DL);
+ insertDbgVariableRecord(DVR, InsertPt);
+ return DVR;
+}
+
void DIBuilder::insertDbgVariableRecord(DbgVariableRecord *DVR,
InsertPosition InsertPt) {
assert(InsertPt.isValid());
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index f9ded507f8328..37dcee8250fab 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -63,6 +63,23 @@ TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
return Declares;
}
+TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclareValues(Value *V) {
+ // This function is hot. Check whether the value has any metadata to avoid a
+ // DenseMap lookup. This check is a bitfield datamember lookup.
+ if (!V->isUsedByMetadata())
+ return {};
+ auto *L = ValueAsMetadata::getIfExists(V);
+ if (!L)
+ return {};
+
+ TinyPtrVector<DbgVariableRecord *> Coros;
+ for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers())
+ if (DVR->getType() == DbgVariableRecord::LocationType::DeclareValue)
+ Coros.push_back(DVR);
+
+ return Coros;
+}
+
TinyPtrVector<DbgVariableRecord *> llvm::findDVRValues(Value *V) {
// This function is hot. Check whether the value has any metadata to avoid a
// DenseMap lookup. This check is a bitfield datamember lookup.
diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp
index 2b9b0f958a171..0ab526b263911 100644
--- a/llvm/lib/IR/DebugProgramInstruction.cpp
+++ b/llvm/lib/IR/DebugProgramInstruction.cpp
@@ -41,6 +41,9 @@ DbgVariableRecord::DbgVariableRecord(const DbgVariableIntrinsic *DVI)
case Intrinsic::dbg_declare:
Type = LocationType::Declare;
break;
+ case Intrinsic::dbg_declare_value:
+ Type = LocationType::DeclareValue;
+ break;
case Intrinsic::dbg_assign: {
Type = LocationType::Assign;
const DbgAssignIntrinsic *Assign =
@@ -209,6 +212,22 @@ DbgVariableRecord::createDVRDeclare(Value *Address, DILocalVariable *DV,
return NewDVRDeclare;
}
+DbgVariableRecord *
+DbgVariableRecord::createDVRDeclareValue(Value *Address, DILocalVariable *DV,
+ DIExpression *Expr,
+ const DILocation *DI) {
+ return new DbgVariableRecord(ValueAsMetadata::get(Address), DV, Expr, DI,
+ LocationType::DeclareValue);
+}
+
+DbgVariableRecord *DbgVariableRecord::createDVRDeclareValue(
+ Value *Address, DILocalVariable *DV, DIExpression *Expr,
+ const DILocation *DI, DbgVariableRecord &InsertBefore) {
+ auto *NewDVRCoro = createDVRDeclareValue(Address, DV, Expr, DI);
+ NewDVRCoro->insertBefore(&InsertBefore);
+ return NewDVRCoro;
+}
+
DbgVariableRecord *DbgVariableRecord::createDVRAssign(
Value *Val, DILocalVariable *Variable, DIExpression *Expression,
DIAssignID *AssignID, Value *Address, DIExpression *AddressExpression,
@@ -416,6 +435,10 @@ DbgVariableRecord::createDebugIntrinsic(Module *M,
case DbgVariableRecord::LocationType::Declare:
IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare);
break;
+ case DbgVariableRecord::LocationType::DeclareValue:
+ IntrinsicFn =
+ Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_declare_value);
+ break;
case DbgVariableRecord::LocationType::Value:
IntrinsicFn = Intrinsic::getOrInsertDeclaration(M, Intrinsic::dbg_value);
break;
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 8c03d6f809d50..2f64eca065d83 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -192,6 +192,9 @@ struct VerifierSupport {
case DbgVariableRecord::LocationType::Declare:
*OS << "declare";
break;
+ case DbgVariableRecord::LocationType::DeclareValue:
+ *OS << "declare_value";
+ break;
case DbgVariableRecord::LocationType::Assign:
*OS << "assign";
break;
@@ -7002,6 +7005,7 @@ void Verifier::visit(DbgVariableRecord &DVR) {
CheckDI(DVR.getType() == DbgVariableRecord::LocationType::Value ||
DVR.getType() == DbgVariableRecord::LocationType::Declare ||
+ DVR.getType() == DbgVariableRecord::LocationType::DeclareValue ||
DVR.getType() == DbgVariableRecord::LocationType::Assign,
"invalid #dbg record type", &DVR, DVR.getType(), BB, F);
>From f1358b190cc71955b74a91ba086d7cc6c2ff7a55 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Fri, 3 Oct 2025 11:46:10 -0700
Subject: [PATCH 2/2] 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.
---
llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 66 ++++++++++++++++++--
1 file changed, 61 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 0accb225122be..441d6fcce4162 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -554,6 +554,7 @@ static void cacheDIVar(FrameDataInfo &FrameData,
DIVarCache.insert({V, (*I)->getVariable()});
};
CacheIt(findDVRDeclares(V));
+ CacheIt(findDVRDeclareValues(V));
}
}
@@ -1138,6 +1139,47 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
for_each(DVRs, SalvageOne);
}
+ TinyPtrVector<DbgVariableRecord *> DVRDeclareValues =
+ findDVRDeclareValues(Def);
+ // Try best to find dbg.declare_value. If the spill is a temp, there may
+ // not be a direct dbg.declare_value. Walk up the load chain to find one
+ // from an alias.
+ if (F->getSubprogram()) {
+ auto *CurDef = Def;
+ while (DVRDeclareValues.empty() && isa<LoadInst>(CurDef)) {
+ auto *LdInst = cast<LoadInst>(CurDef);
+ // Only consider ptr to ptr same type load.
+ if (LdInst->getPointerOperandType() != LdInst->getType())
+ break;
+ CurDef = LdInst->getPointerOperand();
+ if (!isa<AllocaInst, LoadInst>(CurDef))
+ break;
+ DVRDeclareValues = findDVRDeclareValues(CurDef);
+ }
+ }
+
+ auto SalvageOneCoro = [&](auto *DDI) {
+ // This dbg.declare_value is preserved for all coro-split function
+ // fragments. It will be unreachable in the main function, and
+ // processed by coro::salvageDebugInfo() by the Cloner. However, convert
+ // it to a dbg.declare to make sure future passes don't have to deal
+ // with a dbg.declare_value.
+ auto *VAM = ValueAsMetadata::get(CurrentReload);
+ Type *Ty = VAM->getValue()->getType();
+ // If the metadata type is not a pointer, emit a dbg.value instead.
+ DbgVariableRecord *NewDVR = new DbgVariableRecord(
+ ValueAsMetadata::get(CurrentReload), DDI->getVariable(),
+ DDI->getExpression(), DDI->getDebugLoc(),
+ Ty->isPointerTy() ? DbgVariableRecord::LocationType::Declare
+ : DbgVariableRecord::LocationType::Value);
+ Builder.GetInsertPoint()->getParent()->insertDbgRecordBefore(
+ NewDVR, Builder.GetInsertPoint());
+ // This dbg.declare_value is for the main function entry point. It
+ // will be deleted in all coro-split functions.
+ coro::salvageDebugInfo(ArgToAllocaMap, *DDI, false /*UseEntryValue*/);
+ };
+ for_each(DVRDeclareValues, SalvageOneCoro);
+
// If we have a single edge PHINode, remove it and replace it with a
// reload from the coroutine frame. (We already took care of multi edge
// PHINodes by normalizing them in the rewritePHIs function).
@@ -1921,7 +1963,7 @@ void coro::salvageDebugInfo(
Function *F = DVR.getFunction();
// Follow the pointer arithmetic all the way to the incoming
// function argument and convert into a DIExpression.
- bool SkipOutermostLoad = DVR.isDbgDeclare();
+ bool SkipOutermostLoad = DVR.isDbgDeclare() || DVR.isDbgDeclareValue();
Value *OriginalStorage = DVR.getVariableLocationOp(0);
auto SalvagedInfo =
@@ -1935,10 +1977,11 @@ void coro::salvageDebugInfo(
DVR.replaceVariableLocationOp(OriginalStorage, Storage);
DVR.setExpression(Expr);
- // We only hoist dbg.declare today since it doesn't make sense to hoist
- // dbg.value since it does not have the same function wide guarantees that
- // dbg.declare does.
- if (DVR.getType() == DbgVariableRecord::LocationType::Declare) {
+ // We only hoist dbg.declare and dbg.declare_value today since it doesn't make
+ // sense to hoist dbg.value since it does not have the same function wide
+ // guarantees that dbg.declare does.
+ if (DVR.getType() == DbgVariableRecord::LocationType::Declare ||
+ DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
std::optional<BasicBlock::iterator> InsertPt;
if (auto *I = dyn_cast<Instruction>(Storage)) {
InsertPt = I->getInsertionPointAfterDef();
@@ -1953,6 +1996,19 @@ void coro::salvageDebugInfo(
InsertPt = F->getEntryBlock().begin();
if (InsertPt) {
DVR.removeFromParent();
+ // If there is a dbg.declare_value being reinserted, insert it as a
+ // dbg.declare instead, so that subsequent passes don't have to deal with
+ // a dbg.declare_value.
+ if (DVR.getType() == DbgVariableRecord::LocationType::DeclareValue) {
+ auto *MD = DVR.getRawLocation();
+ if (auto *VAM = dyn_cast<ValueAsMetadata>(MD)) {
+ Type *Ty = VAM->getValue()->getType();
+ if (Ty->isPointerTy())
+ DVR.Type = DbgVariableRecord::LocationType::Declare;
+ else
+ DVR.Type = DbgVariableRecord::LocationType::Value;
+ }
+ }
(*InsertPt)->getParent()->insertDbgRecordBefore(&DVR, *InsertPt);
}
}
More information about the llvm-commits
mailing list