Skip to content

Commit e28dac0

Browse files
[SelectionDAG][DebugInfo] Handle entry_value dbg.value DIExprs earlier
When SelectiondDAG converts dbg.value intrinsics, it first ensures we have already generated code for the value operator of the intrinsic. The rationale being that if we haven't had the need to generate code for this value, it won't be a debug value that causes the generation. For example, if the first use the physical register of an argument is a dbg.value, we are going to hit this code path. However, this is irrelevant for entry value expressions: by definition we are not interested in the _current_ value of the physical register, but rather on its value at the start of the function. To deal with this, this patch changes lowering to handle this case as early as possible. Differential Revision: https://reviews.llvm.org/D158649 (cherry picked from commit 35f4ef1)
1 parent 1d91d38 commit e28dac0

File tree

3 files changed

+89
-20
lines changed

3 files changed

+89
-20
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5845,26 +5845,6 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
58455845
if (!Op)
58465846
return false;
58475847

5848-
// If the expression refers to the entry value of an Argument, use the
5849-
// corresponding livein physical register. As per the Verifier, this is only
5850-
// allowed for swiftasync Arguments.
5851-
if (Op->isReg() && Expr->isEntryValue()) {
5852-
assert(Arg->hasAttribute(Attribute::AttrKind::SwiftAsync));
5853-
auto OpReg = Op->getReg();
5854-
for (auto [PhysReg, VirtReg] : FuncInfo.RegInfo->liveins())
5855-
if (OpReg == VirtReg || OpReg == PhysReg) {
5856-
SDDbgValue *SDV = DAG.getVRegDbgValue(
5857-
Variable, Expr, PhysReg,
5858-
Kind != FuncArgumentDbgValueKind::Value /*is indirect*/, DL,
5859-
SDNodeOrder);
5860-
DAG.AddDbgValue(SDV, false /*treat as dbg.declare byval parameter*/);
5861-
return true;
5862-
}
5863-
LLVM_DEBUG(dbgs() << "Dropping dbg.value: expression is entry_value but "
5864-
"couldn't find a physical register\n");
5865-
return true;
5866-
}
5867-
58685848
assert(Variable->isValidLocationForIntrinsic(DL) &&
58695849
"Expected inlined-at fields to agree");
58705850
MachineInstr *NewMI = nullptr;
@@ -5953,6 +5933,41 @@ static const CallBase *FindPreallocatedCall(const Value *PreallocatedSetup) {
59535933
llvm_unreachable("expected corresponding call to preallocated setup/arg");
59545934
}
59555935

5936+
/// If DI is a debug value with an EntryValue expression, lower it using the
5937+
/// corresponding physical register of the associated Argument value
5938+
/// (guaranteed to exist by the verifier).
5939+
bool SelectionDAGBuilder::visitEntryValueDbgValue(const DbgValueInst &DI) {
5940+
DILocalVariable *Variable = DI.getVariable();
5941+
DIExpression *Expr = DI.getExpression();
5942+
if (!Expr->isEntryValue() || !hasSingleElement(DI.getValues()))
5943+
return false;
5944+
5945+
// These properties are guaranteed by the verifier.
5946+
Argument *Arg = cast<Argument>(DI.getValue(0));
5947+
assert(Arg->hasAttribute(Attribute::AttrKind::SwiftAsync));
5948+
5949+
auto ArgIt = FuncInfo.ValueMap.find(Arg);
5950+
if (ArgIt == FuncInfo.ValueMap.end()) {
5951+
LLVM_DEBUG(
5952+
dbgs() << "Dropping dbg.value: expression is entry_value but "
5953+
"couldn't find an associated register for the Argument\n");
5954+
return true;
5955+
}
5956+
Register ArgVReg = ArgIt->getSecond();
5957+
5958+
for (auto [PhysReg, VirtReg] : FuncInfo.RegInfo->liveins())
5959+
if (ArgVReg == VirtReg || ArgVReg == PhysReg) {
5960+
SDDbgValue *SDV =
5961+
DAG.getVRegDbgValue(Variable, Expr, PhysReg, false /*IsIndidrect*/,
5962+
DI.getDebugLoc(), SDNodeOrder);
5963+
DAG.AddDbgValue(SDV, false /*treat as dbg.declare byval parameter*/);
5964+
return true;
5965+
}
5966+
LLVM_DEBUG(dbgs() << "Dropping dbg.value: expression is entry_value but "
5967+
"couldn't find a physical register\n");
5968+
return true;
5969+
}
5970+
59565971
/// Lower the call to the specified intrinsic function.
59575972
void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
59585973
unsigned Intrinsic) {
@@ -6284,6 +6299,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
62846299
DIExpression *Expression = DI.getExpression();
62856300
dropDanglingDebugInfo(Variable, Expression);
62866301

6302+
if (visitEntryValueDbgValue(DI))
6303+
return;
6304+
62876305
if (DI.isKillLocation()) {
62886306
handleKillDebugValue(Variable, Expression, DI.getDebugLoc(), SDNodeOrder);
62896307
return;

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,8 @@ class SelectionDAGBuilder {
630630

631631
void visitInlineAsm(const CallBase &Call,
632632
const BasicBlock *EHPadBB = nullptr);
633+
634+
bool visitEntryValueDbgValue(const DbgValueInst &I);
633635
void visitIntrinsicCall(const CallInst &I, unsigned Intrinsic);
634636
void visitTargetIntrinsic(const CallInst &I, unsigned Intrinsic);
635637
void visitConstrainedFPIntrinsic(const ConstrainedFPIntrinsic &FPI);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
; RUN: llc --mtriple="aarch64-" -O0 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=AARCH
2+
; RUN: llc --mtriple="aarch64-" -O0 -fast-isel=false -global-isel=false -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=AARCH
3+
; RUN: llc --mtriple="aarch64-" -O0 -fast-isel -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=AARCH
4+
5+
6+
; RUN: llc --mtriple="x86_64-" -O0 -fast-isel=false -global-isel=false -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=X86
7+
; RUN: llc --mtriple="x86_64-" -O0 -fast-isel -stop-after=finalize-isel %s -o - | FileCheck %s --check-prefix=X86
8+
9+
; AARCH-NOT: DBG_VALUE
10+
; AARCH: DBG_VALUE $x22, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
11+
; AARCH-NEXT: DBG_VALUE $x22, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
12+
; AARCH-NOT: DBG_VALUE
13+
14+
; X86-NOT: DBG_VALUE
15+
; X86: DBG_VALUE $r14, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
16+
; X86-NEXT: DBG_VALUE $r14, $noreg, !{{.*}}, !DIExpression(DW_OP_LLVM_entry_value, 1)
17+
; X86-NOT: DBG_VALUE
18+
19+
20+
define void @foo(ptr %unused_arg, ptr swiftasync %async_arg) !dbg !6 {
21+
entry:
22+
br label %other
23+
24+
other:
25+
call void @llvm.dbg.value(metadata ptr %async_arg, metadata !12, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !14
26+
call void @llvm.dbg.value(metadata ptr %async_arg, metadata !12, metadata !DIExpression(DW_OP_LLVM_entry_value, 1)), !dbg !14
27+
call void @consume(ptr %async_arg)
28+
ret void, !dbg !15
29+
}
30+
31+
declare void @llvm.dbg.value(metadata, metadata, metadata)
32+
declare void @consume(ptr %ptr)
33+
34+
!llvm.dbg.cu = !{!0}
35+
!llvm.module.flags = !{!3, !4}
36+
37+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
38+
!1 = !DIFile(filename: "x.c", directory: "/")
39+
!3 = !{i32 2, !"Dwarf Version", i32 4}
40+
!4 = !{i32 2, !"Debug Info Version", i32 3}
41+
!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, unit: !0)
42+
!7 = !DISubroutineType(types: !8)
43+
!8 = !{null, !9, !9, !9}
44+
!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
45+
!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
46+
!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
47+
!12 = !DILocalVariable(name: "a", scope: !6, file: !1, line: 1, type: !9)
48+
!14 = !DILocation(line: 1, column: 29, scope: !6)
49+
!15 = !DILocation(line: 1, column: 37, scope: !6)

0 commit comments

Comments
 (0)