Skip to content

Commit bf82ff6

Browse files
committed
Teach SROA to handle allocas with more than one dbg.declare.
It is technically legal for optimizations to create an alloca that is used by more than one dbg.declare, if one or both of them are inlined instances of aliasing variables. Differential Revision: https://reviews.llvm.org/D85172
1 parent f50b3ff commit bf82ff6

File tree

2 files changed

+89
-9
lines changed

2 files changed

+89
-9
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4476,10 +4476,8 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
44764476
// Migrate debug information from the old alloca to the new alloca(s)
44774477
// and the individual partitions.
44784478
TinyPtrVector<DbgVariableIntrinsic *> DbgDeclares = FindDbgAddrUses(&AI);
4479-
if (!DbgDeclares.empty()) {
4480-
auto *Var = DbgDeclares.front()->getVariable();
4481-
auto *Expr = DbgDeclares.front()->getExpression();
4482-
auto VarSize = Var->getSizeInBits();
4479+
for (DbgVariableIntrinsic *DbgDeclare : DbgDeclares) {
4480+
auto *Expr = DbgDeclare->getExpression();
44834481
DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false);
44844482
uint64_t AllocaSize =
44854483
DL.getTypeSizeInBits(AI.getAllocatedType()).getFixedSize();
@@ -4510,6 +4508,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
45104508
}
45114509

45124510
// The alloca may be larger than the variable.
4511+
auto VarSize = DbgDeclare->getVariable()->getSizeInBits();
45134512
if (VarSize) {
45144513
if (Size > *VarSize)
45154514
Size = *VarSize;
@@ -4527,12 +4526,21 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
45274526
}
45284527
}
45294528

4530-
// Remove any existing intrinsics describing the same alloca.
4531-
for (DbgVariableIntrinsic *OldDII : FindDbgAddrUses(Fragment.Alloca))
4532-
OldDII->eraseFromParent();
4529+
// Remove any existing intrinsics on the new alloca describing
4530+
// the variable fragment.
4531+
for (DbgVariableIntrinsic *OldDII : FindDbgAddrUses(Fragment.Alloca)) {
4532+
auto SameVariableFragment = [](const DbgVariableIntrinsic *LHS,
4533+
const DbgVariableIntrinsic *RHS) {
4534+
return LHS->getVariable() == RHS->getVariable() &&
4535+
LHS->getDebugLoc()->getInlinedAt() ==
4536+
RHS->getDebugLoc()->getInlinedAt();
4537+
};
4538+
if (SameVariableFragment(OldDII, DbgDeclare))
4539+
OldDII->eraseFromParent();
4540+
}
45334541

4534-
DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr,
4535-
DbgDeclares.front()->getDebugLoc(), &AI);
4542+
DIB.insertDeclare(Fragment.Alloca, DbgDeclare->getVariable(), FragmentExpr,
4543+
DbgDeclare->getDebugLoc(), &AI);
45364544
}
45374545
}
45384546
return Changed;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
; Test that SROA can deal with allocas that have more than one
2+
; dbg.declare hanging off of it.
3+
4+
; RUN: opt < %s -sroa -S | FileCheck %s
5+
source_filename = "/tmp/inlinesplit.cpp"
6+
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
7+
target triple = "x86_64-apple-macosx10.15.0"
8+
9+
%struct.pair = type { i64, i64 }
10+
11+
; Function Attrs: noinline optnone ssp uwtable
12+
define i64 @_Z1g4pair(i64 %p.coerce0, i64 %p.coerce1) #0 !dbg !8 {
13+
entry:
14+
%p = alloca %struct.pair, align 8
15+
%0 = getelementptr inbounds %struct.pair, %struct.pair* %p, i32 0, i32 0
16+
store i64 %p.coerce0, i64* %0, align 8
17+
%1 = getelementptr inbounds %struct.pair, %struct.pair* %p, i32 0, i32 1
18+
store i64 %p.coerce1, i64* %1, align 8
19+
; CHECK-DAG: call void @llvm.dbg.value(metadata i64 %p.coerce0, metadata ![[VAR:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg ![[LOC:[0-9]+]]
20+
; CHECK-DAG: call void @llvm.dbg.value(metadata i64 %p.coerce1, metadata ![[VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg ![[LOC]]
21+
; CHECK-DAG: call void @llvm.dbg.value(metadata i64 %p.coerce0, metadata ![[INLINED_VAR:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_fragment, 0, 64)), !dbg ![[INLINED_LOC:[0-9]+]]
22+
; CHECK-DAG: call void @llvm.dbg.value(metadata i64 %p.coerce1, metadata ![[INLINED_VAR]], metadata !DIExpression(DW_OP_LLVM_fragment, 64, 64)), !dbg ![[INLINED_LOC]]
23+
call void @llvm.dbg.declare(metadata %struct.pair* %p, metadata !17, metadata !DIExpression()), !dbg !18
24+
call void @llvm.dbg.declare(metadata %struct.pair* %p, metadata !21, metadata !DIExpression()), !dbg !23
25+
%a.i = getelementptr inbounds %struct.pair, %struct.pair* %p, i32 0, i32 0, !dbg !25
26+
%x2 = load i64, i64* %0, align 8, !dbg !25
27+
ret i64 %x2, !dbg !26
28+
}
29+
30+
; Function Attrs: nounwind readnone speculatable willreturn
31+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
32+
33+
; Function Attrs: argmemonly nounwind willreturn
34+
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #2
35+
36+
attributes #0 = { noinline ssp uwtable }
37+
attributes #1 = { nounwind readnone speculatable willreturn }
38+
attributes #2 = { argmemonly nounwind willreturn }
39+
40+
!llvm.dbg.cu = !{!0}
41+
!llvm.module.flags = !{!3, !4, !5, !6}
42+
43+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 ([email protected]:llvm/llvm-project 5110fd0343c2d06c8ae538741fbef13ece5e68de)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None, sysroot: "/")
44+
!1 = !DIFile(filename: "/tmp/inlinesplit.cpp", directory: "/Volumes/Data/llvm-project")
45+
!2 = !{}
46+
!3 = !{i32 7, !"Dwarf Version", i32 4}
47+
!4 = !{i32 2, !"Debug Info Version", i32 3}
48+
!5 = !{i32 1, !"wchar_size", i32 4}
49+
!6 = !{i32 7, !"PIC Level", i32 2}
50+
!8 = distinct !DISubprogram(name: "g", linkageName: "_Z1g4pair", scope: !9, file: !9, line: 9, type: !10, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
51+
!9 = !DIFile(filename: "/tmp/inlinesplit.cpp", directory: "")
52+
!10 = !DISubroutineType(types: !11)
53+
!11 = !{!12, !13}
54+
!12 = !DIBasicType(name: "long long unsigned int", size: 64, encoding: DW_ATE_unsigned)
55+
!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "pair", file: !9, line: 1, size: 128, flags: DIFlagTypePassByValue, elements: !14, identifier: "_ZTS4pair")
56+
!14 = !{!15, !16}
57+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !9, line: 1, baseType: !12, size: 64)
58+
!16 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !13, file: !9, line: 1, baseType: !12, size: 64, offset: 64)
59+
!17 = !DILocalVariable(name: "p", arg: 1, scope: !8, file: !9, line: 9, type: !13)
60+
; CHECK: ![[LOC]] = !DILocation
61+
; CHECK-NOT: inlinedAt
62+
; CHECK: =
63+
!18 = !DILocation(line: 9, column: 27, scope: !8)
64+
!19 = !DILocation(line: 10, column: 12, scope: !8)
65+
!20 = !DILocation(line: 10, column: 10, scope: !8)
66+
!21 = !DILocalVariable(name: "p", arg: 1, scope: !22, file: !9, line: 5, type: !13)
67+
!22 = distinct !DISubprogram(name: "f", linkageName: "_ZL1f4pair", scope: !9, file: !9, line: 5, type: !10, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !2)
68+
; CHECK: ![[INLINED_LOC]] = !DILocation({{.*}}inlinedAt
69+
!23 = !DILocation(line: 5, column: 27, scope: !22, inlinedAt: !24)
70+
!24 = distinct !DILocation(line: 10, column: 10, scope: !8)
71+
!25 = !DILocation(line: 6, column: 12, scope: !22, inlinedAt: !24)
72+
!26 = !DILocation(line: 10, column: 3, scope: !8)

0 commit comments

Comments
 (0)