Skip to content

Commit 45efcf0

Browse files
committedMay 8, 2017
Use the frame index side table for byval and inalloca arguments
Summary: For inalloca functions, this is a very common code pattern: %argpack = type <{ i32, i32, i32 }> define void @f(%argpack* inalloca %args) { entry: %a = getelementptr inbounds %argpack, %argpack* %args, i32 0, i32 0 %b = getelementptr inbounds %argpack, %argpack* %args, i32 0, i32 1 %c = getelementptr inbounds %argpack, %argpack* %args, i32 0, i32 2 tail call void @llvm.dbg.declare(metadata i32* %a, ... "a") tail call void @llvm.dbg.declare(metadata i32* %c, ... "b") tail call void @llvm.dbg.declare(metadata i32* %b, ... "c") Even though these GEPs can be simplified to a constant offset from EBP or RSP, we don't do that at -O0, and each GEP is computed into a register. Registers used to compute argument addresses are typically spilled and clobbered very quickly after the initial computation, so live debug variable tracking loses information very quickly if we use DBG_VALUE instructions. This change moves processing of dbg.declare between argument lowering and basic block isel, so that we can ask if an argument has a frame index or not. If the argument lives in a register as is the case for byval arguments on some targets, then we don't put it in the side table and during ISel we emit DBG_VALUE instructions. Reviewers: aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D32980 llvm-svn: 302483
1 parent 9c52c76 commit 45efcf0

File tree

8 files changed

+284
-108
lines changed

8 files changed

+284
-108
lines changed
 

‎llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -1150,16 +1150,16 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) {
11501150
return true;
11511151
}
11521152

1153-
unsigned Offset = 0;
1153+
// Byval arguments with frame indices were already handled after argument
1154+
// lowering and before isel.
1155+
const auto *Arg =
1156+
dyn_cast<Argument>(Address->stripInBoundsConstantOffsets());
1157+
if (Arg && FuncInfo.getArgumentFrameIndex(Arg) != INT_MAX)
1158+
return true;
1159+
11541160
Optional<MachineOperand> Op;
1155-
if (const auto *Arg = dyn_cast<Argument>(Address))
1156-
// Some arguments' frame index is recorded during argument lowering.
1157-
Offset = FuncInfo.getArgumentFrameIndex(Arg);
1158-
if (Offset)
1159-
Op = MachineOperand::CreateFI(Offset);
1160-
if (!Op)
1161-
if (unsigned Reg = lookUpRegForValue(Address))
1162-
Op = MachineOperand::CreateReg(Reg, false);
1161+
if (unsigned Reg = lookUpRegForValue(Address))
1162+
Op = MachineOperand::CreateReg(Reg, false);
11631163

11641164
// If we have a VLA that has a "use" in a metadata node that's then used
11651165
// here but it has no other uses, then we have a problem. E.g.,

‎llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp

+2-31
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
8585
MF = &mf;
8686
TLI = MF->getSubtarget().getTargetLowering();
8787
RegInfo = &MF->getRegInfo();
88-
MachineModuleInfo &MMI = MF->getMMI();
8988
const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
9089
unsigned StackAlign = TFI->getStackAlignment();
9190

@@ -214,33 +213,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
214213
if (!isa<AllocaInst>(I) || !StaticAllocaMap.count(cast<AllocaInst>(&I)))
215214
InitializeRegForValue(&I);
216215

217-
// Collect llvm.dbg.declare information. This is done now instead of
218-
// during the initial isel pass through the IR so that it is done
219-
// in a predictable order.
220-
if (const DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(&I)) {
221-
assert(DI->getVariable() && "Missing variable");
222-
assert(DI->getDebugLoc() && "Missing location");
223-
if (MMI.hasDebugInfo()) {
224-
// Don't handle byval struct arguments or VLAs, for example.
225-
// Non-byval arguments are handled here (they refer to the stack
226-
// temporary alloca at this point).
227-
const Value *Address = DI->getAddress();
228-
if (Address) {
229-
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
230-
Address = BCI->getOperand(0);
231-
if (const AllocaInst *AI = dyn_cast<AllocaInst>(Address)) {
232-
DenseMap<const AllocaInst *, int>::iterator SI =
233-
StaticAllocaMap.find(AI);
234-
if (SI != StaticAllocaMap.end()) { // Check for VLAs.
235-
int FI = SI->second;
236-
MF->setVariableDbgInfo(DI->getVariable(), DI->getExpression(),
237-
FI, DI->getDebugLoc());
238-
}
239-
}
240-
}
241-
}
242-
}
243-
244216
// Decide the preferred extend type for a value.
245217
PreferredExtendType[&I] = getPreferredExtendForValue(&I);
246218
}
@@ -510,12 +482,11 @@ void FunctionLoweringInfo::setArgumentFrameIndex(const Argument *A,
510482
/// If the argument does not have any assigned frame index then 0 is
511483
/// returned.
512484
int FunctionLoweringInfo::getArgumentFrameIndex(const Argument *A) {
513-
DenseMap<const Argument *, int>::iterator I =
514-
ByValArgFrameIndexMap.find(A);
485+
auto I = ByValArgFrameIndexMap.find(A);
515486
if (I != ByValArgFrameIndexMap.end())
516487
return I->second;
517488
DEBUG(dbgs() << "Argument does not have assigned frame index!\n");
518-
return 0;
489+
return INT_MAX;
519490
}
520491

521492
unsigned FunctionLoweringInfo::getCatchPadExceptionPointerVReg(

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+9-1
Original file line numberDiff line numberDiff line change
@@ -4676,7 +4676,8 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
46764676
bool IsIndirect = false;
46774677
Optional<MachineOperand> Op;
46784678
// Some arguments' frame index is recorded during argument lowering.
4679-
if (int FI = FuncInfo.getArgumentFrameIndex(Arg))
4679+
int FI = FuncInfo.getArgumentFrameIndex(Arg);
4680+
if (FI != INT_MAX)
46804681
Op = MachineOperand::CreateFI(FI);
46814682

46824683
if (!Op && N.getNode()) {
@@ -4927,6 +4928,13 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
49274928
return nullptr;
49284929
}
49294930

4931+
// Byval arguments with frame indices were already handled after argument
4932+
// lowering and before isel.
4933+
const auto *Arg =
4934+
dyn_cast<Argument>(Address->stripInBoundsConstantOffsets());
4935+
if (Arg && FuncInfo.getArgumentFrameIndex(Arg) != INT_MAX)
4936+
return nullptr;
4937+
49304938
SDValue &N = NodeMap[Address];
49314939
if (!N.getNode() && isa<Argument>(Address))
49324940
// Check unused arguments map.

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "llvm/CodeGen/MachineInstr.h"
3939
#include "llvm/CodeGen/MachineInstrBuilder.h"
4040
#include "llvm/CodeGen/MachineMemOperand.h"
41+
#include "llvm/CodeGen/MachineModuleInfo.h"
4142
#include "llvm/CodeGen/MachineOperand.h"
4243
#include "llvm/CodeGen/MachinePassRegistry.h"
4344
#include "llvm/CodeGen/MachineRegisterInfo.h"
@@ -1145,6 +1146,51 @@ static void createSwiftErrorEntriesInEntryBlock(FunctionLoweringInfo *FuncInfo,
11451146
}
11461147
}
11471148

1149+
/// Collect llvm.dbg.declare information. This is done after argument lowering
1150+
/// in case the declarations refer to arguments.
1151+
static void processDbgDeclares(FunctionLoweringInfo *FuncInfo) {
1152+
MachineFunction *MF = FuncInfo->MF;
1153+
const DataLayout &DL = MF->getDataLayout();
1154+
for (const BasicBlock &BB : *FuncInfo->Fn) {
1155+
for (const Instruction &I : BB) {
1156+
const DbgDeclareInst *DI = dyn_cast<DbgDeclareInst>(&I);
1157+
if (!DI)
1158+
continue;
1159+
1160+
assert(DI->getVariable() && "Missing variable");
1161+
assert(DI->getDebugLoc() && "Missing location");
1162+
const Value *Address = DI->getAddress();
1163+
if (!Address)
1164+
continue;
1165+
1166+
// Look through casts and constant offset GEPs. These mostly come from
1167+
// inalloca.
1168+
APInt Offset(DL.getPointerSizeInBits(0), 0);
1169+
Address = Address->stripAndAccumulateInBoundsConstantOffsets(DL, Offset);
1170+
1171+
// Check if the variable is a static alloca or a byval or inalloca
1172+
// argument passed in memory. If it is not, then we will ignore this
1173+
// intrinsic and handle this during isel like dbg.value.
1174+
int FI = INT_MAX;
1175+
if (const auto *AI = dyn_cast<AllocaInst>(Address)) {
1176+
auto SI = FuncInfo->StaticAllocaMap.find(AI);
1177+
if (SI != FuncInfo->StaticAllocaMap.end())
1178+
FI = SI->second;
1179+
} else if (const auto *Arg = dyn_cast<Argument>(Address))
1180+
FI = FuncInfo->getArgumentFrameIndex(Arg);
1181+
1182+
if (FI == INT_MAX)
1183+
continue;
1184+
1185+
DIExpression *Expr = DI->getExpression();
1186+
if (Offset.getBoolValue())
1187+
Expr = DIExpression::prepend(Expr, DIExpression::NoDeref,
1188+
Offset.getZExtValue());
1189+
MF->setVariableDbgInfo(DI->getVariable(), Expr, FI, DI->getDebugLoc());
1190+
}
1191+
}
1192+
}
1193+
11481194
/// Propagate swifterror values through the machine function CFG.
11491195
static void propagateSwiftErrorVRegs(FunctionLoweringInfo *FuncInfo) {
11501196
auto *TLI = FuncInfo->TLI;
@@ -1317,6 +1363,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
13171363
}
13181364
createSwiftErrorEntriesInEntryBlock(FuncInfo, FastIS, TLI, TII, SDB);
13191365

1366+
processDbgDeclares(FuncInfo);
1367+
13201368
// Iterate over all basic blocks in the function.
13211369
for (const BasicBlock *LLVMBB : RPOT) {
13221370
if (OptLevel != CodeGenOpt::None) {

‎llvm/test/CodeGen/X86/2010-01-18-DbgValue.ll

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
; RUN: llc -march=x86 -O0 < %s | FileCheck %s
2-
; Currently, dbg.declare generates a DEBUG_VALUE comment. Eventually it will
3-
; generate DWARF and this test will need to be modified or removed.
1+
; RUN: llc -march=x86 -O0 < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s
42

3+
; CHECK-LABEL: .debug_info contents:
4+
5+
; CHECK-LABEL: DW_TAG_subprogram
6+
; CHECK: DW_AT_name [DW_FORM_strp] ( {{.*}}"foo")
7+
; CHECK: DW_TAG_formal_parameter
8+
; CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (<0x2> 91 08 )
9+
; CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}}"my_r0")
510

611
%struct.Pt = type { double, double }
712
%struct.Rect = type { %struct.Pt, %struct.Pt }
813

914
define double @foo(%struct.Rect* byval %my_r0) nounwind ssp !dbg !1 {
1015
entry:
11-
;CHECK: DEBUG_VALUE
1216
%retval = alloca double ; <double*> [#uses=2]
1317
%0 = alloca double ; <double*> [#uses=2]
1418
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]

‎llvm/test/CodeGen/X86/2012-11-30-handlemove-dbg.ll

-51
This file was deleted.

‎llvm/test/CodeGen/X86/dbg-baseptr.ll

+50-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: llc -o - %s | FileCheck %s
2+
; RUN: llc -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF
23
; This test checks that parameters on the stack pointer are correctly
34
; referenced by debug info.
45
target triple = "x86_64--"
@@ -7,24 +8,54 @@ target triple = "x86_64--"
78
@ptr = external global i32*
89
%struct.s = type { i32, i32, i32, i32, i32 }
910

11+
; Simple case: no FP, use offset from RSP.
12+
1013
; CHECK-LABEL: f0:
11-
; CHECK: DEBUG_VALUE: f:input <- [%RSP+8]
14+
; CHECK-NOT: pushq
15+
; CHECK: movl $42, %eax
16+
; CHECK: retq
1217
define i32 @f0(%struct.s* byval align 8 %input) !dbg !8 {
1318
call void @llvm.dbg.declare(metadata %struct.s* %input, metadata !4, metadata !17), !dbg !18
14-
ret i32 42
19+
ret i32 42, !dbg !18
1520
}
1621

22+
; DWARF-LABEL: .debug_info contents:
23+
24+
; DWARF-LABEL: DW_TAG_subprogram
25+
; DWARF: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 57 )
26+
; 0x57 -> RSP
27+
; DWARF: DW_AT_name [DW_FORM_strp] ( {{.*}}"f0")
28+
; DWARF: DW_TAG_formal_parameter
29+
; DWARF-NEXT: DW_AT_location [DW_FORM_exprloc] (<0x2> 91 08 )
30+
; DW_OP_fbreg (0x91) 0x08
31+
; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}}"input")
32+
33+
34+
; Dynamic alloca forces the use of RBP as the base pointer
35+
1736
; CHECK-LABEL: f1:
18-
; CHECK: DEBUG_VALUE: f:input <- [%RBP+16]
37+
; CHECK: pushq %rbp
38+
; CHECK: movl $42, %eax
39+
; CHECK: popq %rbp
40+
; CHECK: retq
1941
define i32 @f1(%struct.s* byval align 8 %input) !dbg !19 {
2042
%val = load i64, i64* @glob
2143
; this alloca should force FP usage.
2244
%stackspace = alloca i32, i64 %val, align 1
2345
store i32* %stackspace, i32** @ptr
2446
call void @llvm.dbg.declare(metadata %struct.s* %input, metadata !20, metadata !17), !dbg !21
25-
ret i32 42
47+
ret i32 42, !dbg !21
2648
}
2749

50+
; DWARF-LABEL: DW_TAG_subprogram
51+
; DWARF: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
52+
; 0x56 -> RBP
53+
; DWARF: DW_AT_name [DW_FORM_strp] ( {{.*}}"f1")
54+
; DWARF: DW_TAG_formal_parameter
55+
; DWARF-NEXT: DW_AT_location [DW_FORM_exprloc] (<0x2> 91 10 )
56+
; DW_OP_fbreg (0x91) 0x10
57+
; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}}"input")
58+
2859
; CHECK-LABEL: f2:
2960
; Just check that we are indeed aligning the stack and setting up a base pointer
3061
; in RBX.
@@ -34,33 +65,40 @@ define i32 @f1(%struct.s* byval align 8 %input) !dbg !19 {
3465
; CHECK: andq $-64, %rsp
3566
; CHECK: subq $64, %rsp
3667
; CHECK: movq %rsp, %rbx
37-
; The parameter should still be referenced through RBP though.
38-
; CHECK-NOT: DEBUG_VALUE: f:input <- [%RBX
39-
; CHECK: DEBUG_VALUE: f:input <- [%RBP+16]
4068
define i32 @f2(%struct.s* byval align 8 %input) !dbg !22 {
4169
%val = load i64, i64* @glob
4270
%stackspace = alloca i32, i64 %val, align 64
4371
store i32* %stackspace, i32** @ptr
4472
call void @llvm.dbg.declare(metadata %struct.s* %input, metadata !23, metadata !17), !dbg !24
45-
ret i32 42
73+
ret i32 42, !dbg !24
4674
}
4775

76+
; "input" should still be referred to through RBP.
77+
; DWARF-LABEL: DW_TAG_subprogram
78+
; DWARF: DW_AT_frame_base [DW_FORM_exprloc] (<0x1> 56 )
79+
; 0x56 -> RBP
80+
; DWARF: DW_AT_name [DW_FORM_strp] ( {{.*}}"f2")
81+
; DWARF: DW_TAG_formal_parameter
82+
; DWARF-NEXT: DW_AT_location [DW_FORM_exprloc] (<0x2> 91 10 )
83+
; DW_OP_fbreg (0x91) 0x10
84+
; DWARF-NEXT: DW_AT_name [DW_FORM_strp] ( {{.*}}"input")
85+
4886
declare void @llvm.dbg.declare(metadata, metadata, metadata)
4987

5088
!llvm.dbg.cu = !{!2}
5189
!llvm.module.flags = !{!0, !1}
5290

5391
!0 = !{i32 2, !"Dwarf Version", i32 4}
5492
!1 = !{i32 2, !"Debug Info Version", i32 3}
55-
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
93+
!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug)
5694
!3 = !DIFile(filename: "dbg-baseptr.ll", directory: "/")
5795
!4 = !DILocalVariable(name: "input", arg: 1, scope: !8, file: !3, line: 5, type: !9)
5896
!5 = !{}
5997

6098
!6 = !DISubroutineType(types: !7)
6199
!7 = !{!10, !9}
62100

63-
!8 = distinct !DISubprogram(name: "f", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, unit: !2, variables: !5)
101+
!8 = distinct !DISubprogram(name: "f0", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, unit: !2, variables: !5)
64102

65103
!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", elements: !11)
66104
!10 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
@@ -74,9 +112,9 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
74112
!17 = !DIExpression()
75113
!18 = !DILocation(line: 5, scope: !8)
76114

77-
!19 = distinct !DISubprogram(name: "f", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, unit: !2, variables: !5)
115+
!19 = distinct !DISubprogram(name: "f1", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, unit: !2, variables: !5)
78116
!20 = !DILocalVariable(name: "input", arg: 1, scope: !19, file: !3, line: 5, type: !9)
79117
!21 = !DILocation(line: 5, scope: !19)
80-
!22 = distinct !DISubprogram(name: "f", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, unit: !2, variables: !5)
118+
!22 = distinct !DISubprogram(name: "f2", file: !3, line: 5, type: !6, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, unit: !2, variables: !5)
81119
!23 = !DILocalVariable(name: "input", arg: 1, scope: !22, file: !3, line: 5, type: !9)
82120
!24 = !DILocation(line: 5, scope: !22)

0 commit comments

Comments
 (0)