Skip to content

Commit 359c704

Browse files
Handle #dbg_values in SROA. (#94070)
This patch properly handles #dbg_values in SROA by making sure that any #dbg_values get moved to before a store just like #dbg_declares do, or the #dbg_value is correctly updated with the right alloca after an aggregate alloca is broken up. The issue stems from swift where #dbg_values are emitted and not dbg.declares, the SROA pass doesn't handle the #dbg_values correctly and it causes them to all have undefs If we look at this simple-ish testcase (This is all I could reduce it down to, and I am still relatively bad at writing llvm IR by hand so I apologize in advance): ``` %T4main1TV13TangentVectorV = type <{ %T4main1UV13TangentVectorV, [7 x i8], %T4main1UV13TangentVectorV }> %T4main1UV13TangentVectorV = type <{ %T1M1SVySfG, [7 x i8], %T4main1VV13TangentVectorV }> %T1M1SVySfG = type <{ ptr, %Ts4Int8V }> %Ts4Int8V = type <{ i8 }> %T4main1VV13TangentVectorV = type <{ %T1M1SVySfG }> define hidden swiftcc void @"$s4main1TV13TangentVectorV1poiyA2E_AEtFZ"(ptr noalias nocapture sret(%T4main1TV13TangentVectorV) %0, ptr noalias nocapture dereferenceable(57) %1, ptr noalias nocapture dereferenceable(57) %2) #0 !dbg !44 { entry: %3 = alloca %T4main1VV13TangentVectorV %4 = alloca %T4main1UV13TangentVectorV %5 = alloca %T4main1VV13TangentVectorV %6 = alloca %T4main1UV13TangentVectorV %7 = alloca %T4main1VV13TangentVectorV %8 = alloca %T4main1UV13TangentVectorV %9 = alloca %T4main1VV13TangentVectorV %10 = alloca %T4main1UV13TangentVectorV call void @llvm.lifetime.start.p0(i64 9, ptr %3) call void @llvm.lifetime.start.p0(i64 25, ptr %4) call void @llvm.lifetime.start.p0(i64 9, ptr %5) call void @llvm.lifetime.start.p0(i64 25, ptr %6) call void @llvm.lifetime.start.p0(i64 9, ptr %7) call void @llvm.lifetime.start.p0(i64 25, ptr %8) call void @llvm.lifetime.start.p0(i64 9, ptr %9) call void @llvm.lifetime.start.p0(i64 25, ptr %10) %.u1 = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %1, i32 0, i32 0 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %4, ptr align 8 %.u1, i64 25, i1 false) %.u11 = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %2, i32 0, i32 0 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %6, ptr align 8 %.u11, i64 25, i1 false) call void @llvm.dbg.value(metadata ptr %4, metadata !62, metadata !DIExpression(DW_OP_deref)), !dbg !75 %.s = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %4, i32 0, i32 0 %.s.c = getelementptr inbounds %T1M1SVySfG, ptr %.s, i32 0, i32 0 %11 = load ptr, ptr %.s.c %.s.b = getelementptr inbounds %T1M1SVySfG, ptr %.s, i32 0, i32 1 %.s.b._value = getelementptr inbounds %Ts4Int8V, ptr %.s.b, i32 0, i32 0 %12 = load i8, ptr %.s.b._value %.s2 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %6, i32 0, i32 0 %.s2.c = getelementptr inbounds %T1M1SVySfG, ptr %.s2, i32 0, i32 0 %13 = load ptr, ptr %.s2.c %.s2.b = getelementptr inbounds %T1M1SVySfG, ptr %.s2, i32 0, i32 1 %.s2.b._value = getelementptr inbounds %Ts4Int8V, ptr %.s2.b, i32 0, i32 0 %14 = load i8, ptr %.s2.b._value %.v = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %4, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %3, ptr align 8 %.v, i64 9, i1 false) %.v3 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %6, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %5, ptr align 8 %.v3, i64 9, i1 false) %.s4 = getelementptr inbounds %T4main1VV13TangentVectorV, ptr %3, i32 0, i32 0 %.s4.c = getelementptr inbounds %T1M1SVySfG, ptr %.s4, i32 0, i32 0 %18 = load ptr, ptr %.s4.c %.s5 = getelementptr inbounds %T4main1VV13TangentVectorV, ptr %5, i32 0, i32 0 %.s5.c = getelementptr inbounds %T1M1SVySfG, ptr %.s5, i32 0, i32 0 %20 = load ptr, ptr %.s5.c %.u2 = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %1, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %8, ptr align 8 %.u2, i64 25, i1 false) %.u26 = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %2, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %10, ptr align 8 %.u26, i64 25, i1 false) %.s7 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %8, i32 0, i32 0 %.s7.c = getelementptr inbounds %T1M1SVySfG, ptr %.s7, i32 0, i32 0 %25 = load ptr, ptr %.s7.c %.s7.b = getelementptr inbounds %T1M1SVySfG, ptr %.s7, i32 0, i32 1 %.s7.b._value = getelementptr inbounds %Ts4Int8V, ptr %.s7.b, i32 0, i32 0 %26 = load i8, ptr %.s7.b._value %.s8 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %10, i32 0, i32 0 %.s8.c = getelementptr inbounds %T1M1SVySfG, ptr %.s8, i32 0, i32 0 %27 = load ptr, ptr %.s8.c %.s8.b = getelementptr inbounds %T1M1SVySfG, ptr %.s8, i32 0, i32 1 %.s8.b._value = getelementptr inbounds %Ts4Int8V, ptr %.s8.b, i32 0, i32 0 %28 = load i8, ptr %.s8.b._value %.v9 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %8, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %7, ptr align 8 %.v9, i64 9, i1 false) %.v10 = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %10, i32 0, i32 2 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %9, ptr align 8 %.v10, i64 9, i1 false) %.s11 = getelementptr inbounds %T4main1VV13TangentVectorV, ptr %7, i32 0, i32 0 %.s11.c = getelementptr inbounds %T1M1SVySfG, ptr %.s11, i32 0, i32 0 %32 = load ptr, ptr %.s11.c %.s12 = getelementptr inbounds %T4main1VV13TangentVectorV, ptr %9, i32 0, i32 0 %.s12.c = getelementptr inbounds %T1M1SVySfG, ptr %.s12, i32 0, i32 0 %34 = load ptr, ptr %.s12.c call void @llvm.lifetime.end.p0(i64 25, ptr %10) call void @llvm.lifetime.end.p0(i64 9, ptr %9) call void @llvm.lifetime.end.p0(i64 25, ptr %8) call void @llvm.lifetime.end.p0(i64 9, ptr %7) call void @llvm.lifetime.end.p0(i64 25, ptr %6) call void @llvm.lifetime.end.p0(i64 9, ptr %5) call void @llvm.lifetime.end.p0(i64 25, ptr %4) call void @llvm.lifetime.end.p0(i64 9, ptr %3) ret void } !llvm.module.flags = !{!0, !1, !2, !3, !4, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15} !swift.module.flags = !{!33} !llvm.linker.options = !{!34, !35, !36, !37, !38, !39, !40, !41, !42, !43} !0 = !{i32 2, !"SDK Version", [2 x i32] [i32 14, i32 4]} !1 = !{i32 1, !"Objective-C Version", i32 2} !2 = !{i32 1, !"Objective-C Image Info Version", i32 0} !3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA, no_dead_strip"} !4 = !{i32 1, !"Objective-C Garbage Collection", i8 0} !6 = !{i32 7, !"Dwarf Version", i32 4} !7 = !{i32 2, !"Debug Info Version", i32 3} !8 = !{i32 1, !"wchar_size", i32 4} !9 = !{i32 8, !"PIC Level", i32 2} !10 = !{i32 7, !"uwtable", i32 1} !11 = !{i32 7, !"frame-pointer", i32 1} !12 = !{i32 1, !"Swift Version", i32 7} !13 = !{i32 1, !"Swift ABI Version", i32 7} !14 = !{i32 1, !"Swift Major Version", i8 6} !15 = !{i32 1, !"Swift Minor Version", i8 0} !16 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !17, imports: !18, sdk: "MacOSX14.4.sdk") !17 = !DIFile(filename: "/Users/emilpedersen/swift2/swift/test/IRGen/debug_scope_distinct.swift", directory: "/Users/emilpedersen/swift2") !18 = !{!19, !21, !23, !25, !27, !29, !31} !19 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !20, file: !17) !20 = !DIModule(scope: null, name: "main", includePath: "/Users/emilpedersen/swift2/swift/test/IRGen") !21 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !22, file: !17) !22 = !DIModule(scope: null, name: "Swift", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/Swift.swiftmodule/arm64-apple-macos.swiftmodule") !23 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !24, line: 60) !24 = !DIModule(scope: null, name: "_Differentiation", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_Differentiation.swiftmodule/arm64-apple-macos.swiftmodule") !25 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !26, line: 61) !26 = !DIModule(scope: null, name: "M", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/test-macosx-arm64/IRGen/Output/debug_scope_distinct.swift.tmp/M.swiftmodule") !27 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !28, file: !17) !28 = !DIModule(scope: null, name: "_StringProcessing", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_StringProcessing.swiftmodule/arm64-apple-macos.swiftmodule") !29 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !30, file: !17) !30 = !DIModule(scope: null, name: "_SwiftConcurrencyShims", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/shims") !31 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !32, file: !17) !32 = !DIModule(scope: null, name: "_Concurrency", includePath: "/Users/emilpedersen/swift2/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_Concurrency.swiftmodule/arm64-apple-macos.swiftmodule") !33 = !{i1 false} !34 = !{!"-lswiftCore"} !35 = !{!"-lswift_StringProcessing"} !36 = !{!"-lswift_Differentiation"} !37 = !{!"-lswiftDarwin"} !38 = !{!"-lswift_Concurrency"} !39 = !{!"-lswiftSwiftOnoneSupport"} !40 = !{!"-lobjc"} !41 = !{!"-lswiftCompatibilityConcurrency"} !42 = !{!"-lswiftCompatibility56"} !43 = !{!"-lswiftCompatibilityPacks"} !44 = distinct !DISubprogram( unit: !16, declaration: !52, retainedNodes: !53) !45 = !DIFile(filename: "<compiler-generated>", directory: "/") !46 = !DICompositeType(tag: DW_TAG_structure_type, scope: !47, elements: !48, identifier: "$s4main1TV13TangentVectorVD") !47 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1TVD") !48 = !{} !49 = !DISubroutineType(types: !50) !50 = !{!51} !51 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1TV13TangentVectorVXMtD") !52 = !DISubprogram( file: !45, type: !49, spFlags: DISPFlagOptimized) !53 = !{!54, !56, !57} !54 = !DILocalVariable( scope: !44, type: !55, flags: DIFlagArtificial) !55 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !46) !56 = !DILocalVariable( scope: !44, flags: DIFlagArtificial) !57 = !DILocalVariable( scope: !44, type: !58, flags: DIFlagArtificial) !58 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !51) !62 = !DILocalVariable( scope: !63, type: !72, flags: DIFlagArtificial) !63 = distinct !DISubprogram( type: !66, unit: !16, declaration: !69, retainedNodes: !70) !64 = !DICompositeType(tag: DW_TAG_structure_type, scope: !65, identifier: "$s4main1UV13TangentVectorVD") !65 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1UVD") !66 = !DISubroutineType(types: !67) !67 = !{!68} !68 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1UV13TangentVectorVXMtD") !69 = !DISubprogram( spFlags: DISPFlagOptimized) !70 = !{!71, !73} !71 = !DILocalVariable( scope: !63, flags: DIFlagArtificial) !72 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !64) !73 = !DILocalVariable( scope: !63, type: !74, flags: DIFlagArtificial) !74 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !68) !75 = !DILocation( scope: !63, inlinedAt: !76) !76 = distinct !DILocation( scope: !44) ``` if we run ` opt -S -passes=sroa file.ll -o -` With this patch we will see ``` %.sroa.5.sroa.021 = alloca [7 x i8], align 8 tail call void @llvm.dbg.value(metadata ptr %.sroa.5.sroa.021, metadata !59, metadata !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 72, 56)), !dbg !72 %.sroa.5.sroa.014 = alloca [7 x i8], align 8 ``` Without this patch we will see: ``` %.sroa.5.sroa.021 = alloca [7 x i8], align 8 %.sroa.5.sroa.014 = alloca [7 x i8], align 8 ``` Thus this patch ensures that llvm.dbg.values that use allocas that are broken up still have the correct metadata and debug information is preserved This is part of a stack of patches and is preceded by: #94068
1 parent e2b97f3 commit 359c704

File tree

12 files changed

+313
-82
lines changed

12 files changed

+313
-82
lines changed

llvm/include/llvm/IR/DebugInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ class Module;
4343
TinyPtrVector<DbgDeclareInst *> findDbgDeclares(Value *V);
4444
/// As above, for DVRDeclares.
4545
TinyPtrVector<DbgVariableRecord *> findDVRDeclares(Value *V);
46+
/// As above, for DVRValues.
47+
TinyPtrVector<DbgVariableRecord *> findDVRValues(Value *V);
4648

4749
/// Finds the llvm.dbg.value intrinsics describing a value.
4850
void findDbgValues(

llvm/include/llvm/IR/DebugProgramInstruction.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@ class DbgVariableRecord : public DbgRecord, protected DebugValueUser {
427427
/// Does this describe the address of a local variable. True for dbg.addr
428428
/// and dbg.declare, but not dbg.value, which describes its value.
429429
bool isAddressOfVariable() const { return Type == LocationType::Declare; }
430+
431+
/// Determine if this describes the value of a local variable. It is false for
432+
/// dbg.declare, but true for dbg.value, which describes its value.
433+
bool isValueOfVariable() const { return Type == LocationType::Value; }
434+
430435
LocationType getType() const { return Type; }
431436

432437
void setKillLocation();

llvm/include/llvm/IR/IntrinsicInst.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,14 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {
344344
return getIntrinsicID() == Intrinsic::dbg_declare;
345345
}
346346

347+
/// Determine if this describes the value of a local variable. It is true for
348+
/// dbg.value, but false for dbg.declare, which describes its address, and
349+
/// false for dbg.assign, which describes a combination of the variable's
350+
/// value and address.
351+
bool isValueOfVariable() const {
352+
return getIntrinsicID() == Intrinsic::dbg_value;
353+
}
354+
347355
void setKillLocation() {
348356
// TODO: When/if we remove duplicate values from DIArgLists, we don't need
349357
// this set anymore.

llvm/include/llvm/Transforms/Utils/Local.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ CallInst *changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr);
259259
/// Dbg Intrinsic utilities
260260
///
261261

262+
/// Creates and inserts a dbg_value record intrinsic before a store
263+
/// that has an associated llvm.dbg.value intrinsic.
264+
void InsertDebugValueAtStoreLoc(DbgVariableRecord *DVR, StoreInst *SI,
265+
DIBuilder &Builder);
266+
267+
/// Creates and inserts an llvm.dbg.value intrinsic before a store
268+
/// that has an associated llvm.dbg.value intrinsic.
269+
void InsertDebugValueAtStoreLoc(DbgVariableIntrinsic *DII, StoreInst *SI,
270+
DIBuilder &Builder);
271+
262272
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
263273
/// that has an associated llvm.dbg.declare intrinsic.
264274
void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,

llvm/lib/IR/DebugInfo.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ using namespace llvm::dwarf;
4646

4747
TinyPtrVector<DbgDeclareInst *> llvm::findDbgDeclares(Value *V) {
4848
// This function is hot. Check whether the value has any metadata to avoid a
49-
// DenseMap lookup.
49+
// DenseMap lookup. This check is a bitfield datamember lookup.
5050
if (!V->isUsedByMetadata())
5151
return {};
5252
auto *L = LocalAsMetadata::getIfExists(V);
@@ -65,7 +65,7 @@ TinyPtrVector<DbgDeclareInst *> llvm::findDbgDeclares(Value *V) {
6565
}
6666
TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
6767
// This function is hot. Check whether the value has any metadata to avoid a
68-
// DenseMap lookup.
68+
// DenseMap lookup. This check is a bitfield datamember lookup.
6969
if (!V->isUsedByMetadata())
7070
return {};
7171
auto *L = LocalAsMetadata::getIfExists(V);
@@ -80,6 +80,23 @@ TinyPtrVector<DbgVariableRecord *> llvm::findDVRDeclares(Value *V) {
8080
return Declares;
8181
}
8282

83+
TinyPtrVector<DbgVariableRecord *> llvm::findDVRValues(Value *V) {
84+
// This function is hot. Check whether the value has any metadata to avoid a
85+
// DenseMap lookup. This check is a bitfield datamember lookup.
86+
if (!V->isUsedByMetadata())
87+
return {};
88+
auto *L = LocalAsMetadata::getIfExists(V);
89+
if (!L)
90+
return {};
91+
92+
TinyPtrVector<DbgVariableRecord *> Values;
93+
for (DbgVariableRecord *DVR : L->getAllDbgVariableRecordUsers())
94+
if (DVR->isValueOfVariable())
95+
Values.push_back(DVR);
96+
97+
return Values;
98+
}
99+
83100
template <typename IntrinsicT, bool DbgAssignAndValuesOnly>
84101
static void
85102
findDbgIntrinsics(SmallVectorImpl<IntrinsicT *> &Result, Value *V,

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4977,8 +4977,6 @@ const Value *getAddress(const DbgVariableIntrinsic *DVI) {
49774977
}
49784978

49794979
const Value *getAddress(const DbgVariableRecord *DVR) {
4980-
assert(DVR->getType() == DbgVariableRecord::LocationType::Declare ||
4981-
DVR->getType() == DbgVariableRecord::LocationType::Assign);
49824980
return DVR->getAddress();
49834981
}
49844982

@@ -4989,8 +4987,6 @@ bool isKillAddress(const DbgVariableIntrinsic *DVI) {
49894987
}
49904988

49914989
bool isKillAddress(const DbgVariableRecord *DVR) {
4992-
assert(DVR->getType() == DbgVariableRecord::LocationType::Declare ||
4993-
DVR->getType() == DbgVariableRecord::LocationType::Assign);
49944990
if (DVR->getType() == DbgVariableRecord::LocationType::Assign)
49954991
return DVR->isKillAddress();
49964992
return DVR->isKillLocation();
@@ -5003,8 +4999,6 @@ const DIExpression *getAddressExpression(const DbgVariableIntrinsic *DVI) {
50034999
}
50045000

50055001
const DIExpression *getAddressExpression(const DbgVariableRecord *DVR) {
5006-
assert(DVR->getType() == DbgVariableRecord::LocationType::Declare ||
5007-
DVR->getType() == DbgVariableRecord::LocationType::Assign);
50085002
if (DVR->getType() == DbgVariableRecord::LocationType::Assign)
50095003
return DVR->getAddressExpression();
50105004
return DVR->getExpression();
@@ -5187,6 +5181,19 @@ insertNewDbgInst(DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr,
51875181
return;
51885182
}
51895183

5184+
if (Orig->isDbgValue()) {
5185+
DbgVariableRecord *DVR = DbgVariableRecord::createDbgVariableRecord(
5186+
NewAddr, Orig->getVariable(), NewFragmentExpr, Orig->getDebugLoc());
5187+
// Drop debug information if the expression doesn't start with a
5188+
// DW_OP_deref. This is because without a DW_OP_deref, the #dbg_value
5189+
// describes the address of alloca rather than the value inside the alloca.
5190+
if (!NewFragmentExpr->startsWithDeref())
5191+
DVR->setKillAddress();
5192+
BeforeInst->getParent()->insertDbgRecordBefore(DVR,
5193+
BeforeInst->getIterator());
5194+
return;
5195+
}
5196+
51905197
// Apply a DIAssignID to the store if it doesn't already have it.
51915198
if (!NewAddr->hasMetadata(LLVMContext::MD_DIAssignID)) {
51925199
NewAddr->setMetadata(LLVMContext::MD_DIAssignID,
@@ -5389,7 +5396,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
53895396
};
53905397
for_each(findDbgDeclares(Fragment.Alloca), RemoveOne);
53915398
for_each(findDVRDeclares(Fragment.Alloca), RemoveOne);
5392-
5399+
for_each(findDVRValues(Fragment.Alloca), RemoveOne);
53935400
insertNewDbgInst(DIB, DbgVariable, Fragment.Alloca, NewExpr, &AI,
53945401
NewDbgFragment, BitExtractOffset);
53955402
}
@@ -5399,6 +5406,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
53995406
// and the individual partitions.
54005407
for_each(findDbgDeclares(&AI), MigrateOne);
54015408
for_each(findDVRDeclares(&AI), MigrateOne);
5409+
for_each(findDVRValues(&AI), MigrateOne);
54025410
for_each(at::getAssignmentMarkers(&AI), MigrateOne);
54035411
for_each(at::getDVRAssignmentMarkers(&AI), MigrateOne);
54045412

@@ -5545,7 +5553,6 @@ bool SROA::deleteDeadInstructions(
55455553
}
55465554
return Changed;
55475555
}
5548-
55495556
/// Promote the allocas, using the best available technique.
55505557
///
55515558
/// This attempts to promote whatever allocas have been identified as viable in

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,26 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
17311731
SI->getIterator());
17321732
}
17331733

1734+
static DIExpression *dropInitialDeref(const DIExpression *DIExpr) {
1735+
int NumEltDropped = DIExpr->getElements()[0] == dwarf::DW_OP_LLVM_arg ? 3 : 1;
1736+
return DIExpression::get(DIExpr->getContext(),
1737+
DIExpr->getElements().drop_front(NumEltDropped));
1738+
}
1739+
1740+
void llvm::InsertDebugValueAtStoreLoc(DbgVariableIntrinsic *DII, StoreInst *SI,
1741+
DIBuilder &Builder) {
1742+
auto *DIVar = DII->getVariable();
1743+
assert(DIVar && "Missing variable");
1744+
auto *DIExpr = DII->getExpression();
1745+
DIExpr = dropInitialDeref(DIExpr);
1746+
Value *DV = SI->getValueOperand();
1747+
1748+
DebugLoc NewLoc = getDebugValueLoc(DII);
1749+
1750+
insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc,
1751+
SI->getIterator());
1752+
}
1753+
17341754
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
17351755
/// that has an associated llvm.dbg.declare intrinsic.
17361756
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,
@@ -1805,6 +1825,20 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgVariableRecord *DVR,
18051825
SI->getParent()->insertDbgRecordBefore(NewDVR, SI->getIterator());
18061826
}
18071827

1828+
void llvm::InsertDebugValueAtStoreLoc(DbgVariableRecord *DVR, StoreInst *SI,
1829+
DIBuilder &Builder) {
1830+
auto *DIVar = DVR->getVariable();
1831+
assert(DIVar && "Missing variable");
1832+
auto *DIExpr = DVR->getExpression();
1833+
DIExpr = dropInitialDeref(DIExpr);
1834+
Value *DV = SI->getValueOperand();
1835+
1836+
DebugLoc NewLoc = getDebugValueLoc(DVR);
1837+
1838+
insertDbgValueOrDbgVariableRecord(Builder, DV, DIVar, DIExpr, NewLoc,
1839+
SI->getIterator());
1840+
}
1841+
18081842
/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
18091843
/// llvm.dbg.declare intrinsic.
18101844
void llvm::ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII,

llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,10 @@ rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info, LargeBlockInfo &LBI,
596596
if (DbgItem->isAddressOfVariable()) {
597597
ConvertDebugDeclareToDebugValue(DbgItem, Info.OnlyStore, DIB);
598598
DbgItem->eraseFromParent();
599+
} else if (DbgItem->isValueOfVariable() &&
600+
DbgItem->getExpression()->startsWithDeref()) {
601+
InsertDebugValueAtStoreLoc(DbgItem, Info.OnlyStore, DIB);
602+
DbgItem->eraseFromParent();
599603
} else if (DbgItem->getExpression()->startsWithDeref()) {
600604
DbgItem->eraseFromParent();
601605
}

llvm/test/DebugInfo/Generic/mem2reg-promote-alloca-1.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
; CHECK: define dso_local void @fun(i32 %param)
2222
; CHECK-NEXT: entry:
2323
; CHECK-NEXT: #dbg_value(i32 %param, ![[PARAM:[0-9]+]], !DIExpression(),
24-
; CHECK-NOT: #dbg_value({{.*}}, ![[PARAM]]
24+
; CHECK-NEXT: #dbg_value(i32 %param, ![[PARAM]], !DIExpression(),
2525
; CHECK: ![[PARAM]] = !DILocalVariable(name: "param",
2626

2727
@g = dso_local global i32 0, align 4, !dbg !0
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
; This test was obtained from swift source code and then automatically reducing it via Delta.
2+
; The swift source code was from the test test/DebugInfo/debug_scope_distinct.swift.
3+
4+
; RUN: opt %s -S -p=sroa -o - | FileCheck %s
5+
6+
; CHECK: [[SROA_5_SROA_21:%.*]] = alloca [7 x i8], align 8
7+
; CHECK-NEXT: #dbg_value(ptr [[SROA_5_SROA_21]], !59, !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 72, 56), [[DBG72:![0-9]+]])
8+
9+
; CHECK: #dbg_value(ptr [[REG1:%[0-9]+]], [[META54:![0-9]+]], !DIExpression(DW_OP_deref), [[DBG78:![0-9]+]])
10+
; CHECK-NEXT: #dbg_value(ptr [[REG2:%[0-9]+]], [[META56:![0-9]+]], !DIExpression(DW_OP_deref), [[DBG78]])
11+
; CHECK-NEXT: #dbg_value(i64 0, [[META57:![0-9]+]], !DIExpression(), [[DBG78]])
12+
13+
; CHECK: [[SROA_418_SROA_COPYLOAD:%.*]] = load i8, ptr [[SROA_418_0_U1_IDX:%.*]], align 8, !dbg [[DBG78]]
14+
; CHECK-NEXT #dbg_value(i8 [[SROA_418_SROA_COPYLOAD]], [[META59]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 64, 8), [[DBG72]])
15+
16+
%T4main1TV13TangentVectorV = type <{ %T4main1UV13TangentVectorV, [7 x i8], %T4main1UV13TangentVectorV }>
17+
%T4main1UV13TangentVectorV = type <{ %T1M1SVySfG, [7 x i8], %T4main1VV13TangentVectorV }>
18+
%T1M1SVySfG = type <{ ptr, %Ts4Int8V }>
19+
%Ts4Int8V = type <{ i8 }>
20+
%T4main1VV13TangentVectorV = type <{ %T1M1SVySfG }>
21+
define hidden swiftcc void @"$s4main1TV13TangentVectorV1poiyA2E_AEtFZ"(ptr noalias nocapture sret(%T4main1TV13TangentVectorV) %0, ptr noalias nocapture dereferenceable(57) %1, ptr noalias nocapture dereferenceable(57) %2) #0 !dbg !44 {
22+
entry:
23+
%3 = alloca %T4main1VV13TangentVectorV
24+
%4 = alloca %T4main1UV13TangentVectorV
25+
call void @llvm.dbg.value(metadata ptr %1, metadata !54, metadata !DIExpression(DW_OP_deref)), !dbg !61
26+
call void @llvm.dbg.value(metadata ptr %2, metadata !56, metadata !DIExpression(DW_OP_deref)), !dbg !61
27+
call void @llvm.dbg.value(metadata i64 0, metadata !57, metadata !DIExpression()), !dbg !61
28+
%.u1 = getelementptr inbounds %T4main1TV13TangentVectorV, ptr %1, i32 0, i32 0
29+
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %4, ptr align 8 %.u1, i64 25, i1 false), !dbg !61
30+
call void @llvm.dbg.value(metadata ptr %4, metadata !62, metadata !DIExpression(DW_OP_deref)), !dbg !75
31+
%.s = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %4, i32 0, i32 0
32+
%.s.b = getelementptr inbounds %T1M1SVySfG, ptr %.s, i32 0, i32 1
33+
%.s.b._value = getelementptr inbounds %Ts4Int8V, ptr %.s.b, i32 0, i32 0
34+
%12 = load i8, ptr %.s.b._value
35+
%.v = getelementptr inbounds %T4main1UV13TangentVectorV, ptr %4, i32 0, i32 2
36+
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %3, ptr align 8 %.v, i64 9, i1 false)
37+
%.s4 = getelementptr inbounds %T4main1VV13TangentVectorV, ptr %3, i32 0, i32 0
38+
%.s4.c = getelementptr inbounds %T1M1SVySfG, ptr %.s4, i32 0, i32 0
39+
%18 = load ptr, ptr %.s4.c
40+
ret void
41+
}
42+
!llvm.module.flags = !{!0, !1, !2, !3, !4, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15}
43+
!swift.module.flags = !{!33}
44+
!llvm.linker.options = !{!34, !35, !36, !37, !38, !39, !40, !41, !42, !43}
45+
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 14, i32 4]}
46+
!1 = !{i32 1, !"Objective-C Version", i32 2}
47+
!2 = !{i32 1, !"Objective-C Image Info Version", i32 0}
48+
!3 = !{i32 1, !"Objective-C Image Info Section", !"__DATA,no_dead_strip"}
49+
!4 = !{i32 1, !"Objective-C Garbage Collection", i8 0}
50+
!6 = !{i32 7, !"Dwarf Version", i32 4}
51+
!7 = !{i32 2, !"Debug Info Version", i32 3}
52+
!8 = !{i32 1, !"wchar_size", i32 4}
53+
!9 = !{i32 8, !"PIC Level", i32 2}
54+
!10 = !{i32 7, !"uwtable", i32 1}
55+
!11 = !{i32 7, !"frame-pointer", i32 1}
56+
!12 = !{i32 1, !"Swift Version", i32 7}
57+
!13 = !{i32 1, !"Swift ABI Version", i32 7}
58+
!14 = !{i32 1, !"Swift Major Version", i8 6}
59+
!15 = !{i32 1, !"Swift Minor Version", i8 0}
60+
!16 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !17, imports: !18, sdk: "MacOSX14.4.sdk")
61+
!17 = !DIFile(filename: "swift/swift/test/IRGen/debug_scope_distinct.swift", directory: "swift")
62+
!18 = !{!19, !21, !23, !25, !27, !29, !31}
63+
!19 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !20, file: !17)
64+
!20 = !DIModule(scope: null, name: "main", includePath: "swift/swift/test/IRGen")
65+
!21 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !22, file: !17)
66+
!22 = !DIModule(scope: null, name: "Swift", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/Swift.swiftmodule/arm64-apple-macos.swiftmodule")
67+
!23 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !24, line: 60)
68+
!24 = !DIModule(scope: null, name: "_Differentiation", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_Differentiation.swiftmodule/arm64-apple-macos.swiftmodule")
69+
!25 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !26, line: 61)
70+
!26 = !DIModule(scope: null, name: "M", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/test-macosx-arm64/IRGen/Output/debug_scope_distinct.swift.tmp/M.swiftmodule")
71+
!27 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !28, file: !17)
72+
!28 = !DIModule(scope: null, name: "_StringProcessing", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_StringProcessing.swiftmodule/arm64-apple-macos.swiftmodule")
73+
!29 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !30, file: !17)
74+
!30 = !DIModule(scope: null, name: "_SwiftConcurrencyShims", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/shims")
75+
!31 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !17, entity: !32, file: !17)
76+
!32 = !DIModule(scope: null, name: "_Concurrency", includePath: "swift/_build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-arm64/lib/swift/macosx/_Concurrency.swiftmodule/arm64-apple-macos.swiftmodule")
77+
!33 = !{ i1 false}
78+
!34 = !{!"-lswiftCore"}
79+
!35 = !{!"-lswift_StringProcessing"}
80+
!36 = !{!"-lswift_Differentiation"}
81+
!37 = !{!"-lswiftDarwin"}
82+
!38 = !{!"-lswift_Concurrency"}
83+
!39 = !{!"-lswiftSwiftOnoneSupport"}
84+
!40 = !{!"-lobjc"}
85+
!41 = !{!"-lswiftCompatibilityConcurrency"}
86+
!42 = !{!"-lswiftCompatibility56"}
87+
!43 = !{!"-lswiftCompatibilityPacks"}
88+
!44 = distinct !DISubprogram(file: !45, type: !49, unit: !16, declaration: !52, retainedNodes: !53)
89+
!45 = !DIFile(filename: "<compiler-generated>", directory: "/")
90+
!46 = !DICompositeType(tag: DW_TAG_structure_type, scope: !47, elements: !48, identifier: "$s4main1TV13TangentVectorVD")
91+
!47 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1TVD")
92+
!48 = !{}
93+
!49 = !DISubroutineType(types: !50)
94+
!50 = !{ !51}
95+
!51 = !DICompositeType(tag: DW_TAG_structure_type, identifier: "$s4main1TV13TangentVectorVXMtD")
96+
!52 = !DISubprogram(spFlags: DISPFlagOptimized)
97+
!53 = !{!54, !56, !57}
98+
!54 = !DILocalVariable(name: "a", scope: !44, flags: DIFlagArtificial)
99+
!55 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !46)
100+
!56 = !DILocalVariable(name: "b", scope: !44, type: !55, flags: DIFlagArtificial)
101+
!57 = !DILocalVariable(name: "c", scope: !44, type: !58, flags: DIFlagArtificial)
102+
!58 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !51)
103+
!61 = !DILocation(scope: !44)
104+
!62 = !DILocalVariable(name: "d", scope: !63, type: !72, flags: DIFlagArtificial)
105+
!63 = distinct !DISubprogram(unit: !16, retainedNodes: !70)
106+
!64 = !DICompositeType(tag: DW_TAG_structure_type, size: 200, identifier: "$s4main1UV13TangentVectorVD")
107+
!70 = !{}
108+
!72 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !64)
109+
!75 = !DILocation(scope: !63, inlinedAt: !76)
110+
!76 = distinct !DILocation(scope: !44)

0 commit comments

Comments
 (0)