Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6215,14 +6215,18 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(

if (!Op) {
// Create a DBG_VALUE for each decomposed value in ArgRegs to cover Reg
auto splitMultiRegDbgValue = [&](ArrayRef<std::pair<Register, TypeSize>>
SplitRegs) {
auto splitMultiRegDbgValue =
[&](ArrayRef<std::pair<Register, TypeSize>> SplitRegs) -> bool {
unsigned Offset = 0;
for (const auto &RegAndSize : SplitRegs) {
for (const auto [Reg, RegSizeInBits] : SplitRegs) {
// FIXME: Scalable sizes are not supported in fragment expressions.
if (RegSizeInBits.isScalable())
return false;

// If the expression is already a fragment, the current register
// offset+size might extend beyond the fragment. In this case, only
// the register bits that are inside the fragment are relevant.
int RegFragmentSizeInBits = RegAndSize.second;
int RegFragmentSizeInBits = RegSizeInBits.getFixedValue();
if (auto ExprFragmentInfo = Expr->getFragmentInfo()) {
uint64_t ExprFragmentSizeInBits = ExprFragmentInfo->SizeInBits;
// The register is entirely outside the expression fragment,
Expand All @@ -6238,7 +6242,7 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(

auto FragmentExpr = DIExpression::createFragmentExpression(
Expr, Offset, RegFragmentSizeInBits);
Offset += RegAndSize.second;
Offset += RegSizeInBits.getFixedValue();
// If a valid fragment expression cannot be created, the variable's
// correct value cannot be determined and so it is set as poison.
if (!FragmentExpr) {
Expand All @@ -6247,11 +6251,12 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
DAG.AddDbgValue(SDV, false);
continue;
}
MachineInstr *NewMI =
MakeVRegDbgValue(RegAndSize.first, *FragmentExpr,
Kind != FuncArgumentDbgValueKind::Value);
MachineInstr *NewMI = MakeVRegDbgValue(
Reg, *FragmentExpr, Kind != FuncArgumentDbgValueKind::Value);
FuncInfo.ArgDbgValues.push_back(NewMI);
}

return true;
};

// Check if ValueMap has reg number.
Expand All @@ -6261,18 +6266,15 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
const auto &TLI = DAG.getTargetLoweringInfo();
RegsForValue RFV(V->getContext(), TLI, DAG.getDataLayout(), VMI->second,
V->getType(), std::nullopt);
if (RFV.occupiesMultipleRegs()) {
splitMultiRegDbgValue(RFV.getRegsAndSizes());
return true;
}
if (RFV.occupiesMultipleRegs())
return splitMultiRegDbgValue(RFV.getRegsAndSizes());

Op = MachineOperand::CreateReg(VMI->second, false);
IsIndirect = Kind != FuncArgumentDbgValueKind::Value;
} else if (ArgRegsAndSizes.size() > 1) {
// This was split due to the calling convention, and no virtual register
// mapping exists for the value.
splitMultiRegDbgValue(ArgRegsAndSizes);
return true;
return splitMultiRegDbgValue(ArgRegsAndSizes);
}
}

Expand Down
48 changes: 48 additions & 0 deletions llvm/test/CodeGen/AArch64/pr161289.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc -verify-machineinstrs < %s -mattr=+sme | FileCheck %s

target triple = "aarch64-unknown-linux-gnu"

; FIXME: This is from https://github.com/llvm/llvm-project/issues/161289. The argument (%arg) is <vscale x 16 x half>,
; which is passed as two <vscale x 8 x half> registers. LLVM wants to describe this as two DW_OP_LLVM_fragment fragments,
; but currently, that opcode has no notion of scalable type sizes.
;
; We are currently working around this by dropping the debug info for %arg (so it is 'undef' below).

define <vscale x 16 x half> @scalable_vector_debug_info(<vscale x 16 x half> %arg) "aarch64_pstate_sm_enabled" !dbg !7 {
; CHECK-LABEL: scalable_vector_debug_info:
; CHECK: .Lfunc_begin0:
; CHECK-NEXT: .file 1 "/tmp" "scalable-vector-debug.c"
; CHECK-NEXT: .loc 1 1 0 // scalable-vector-debug.c:1:0
; CHECK-NEXT: .cfi_startproc
; CHECK-NEXT: // %bb.0:
; CHECK-NEXT: //DEBUG_VALUE: scalable_vector_debug_info:arg <- undef
; CHECK-NEXT: .loc 1 1 0 prologue_end // scalable-vector-debug.c:1:0
; CHECK-NEXT: ret
#dbg_value(<vscale x 16 x half> %arg, !13, !DIExpression(), !14)
%extract = tail call <vscale x 8 x half> @llvm.vector.extract.nxv8f16.nxv16f16(<vscale x 16 x half> %arg, i64 0)
ret <vscale x 16 x half> %arg
}

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5, !6}

!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "scalable-vector-debug.c", directory: "/tmp")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{i32 7, !"frame-pointer", i32 2}
!7 = distinct !DISubprogram(name: "scalable_vector_debug_info", scope: !1, file: !1, line: 1, type: !8, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
!8 = !DISubroutineType(types: !9)
!9 = !{!10, !10}
!10 = !DIBasicType(name: "svfloat16_t", size: 16, encoding: DW_ATE_float)
!11 = !DIBasicType(name: "__fp16", size: 16, encoding: DW_ATE_float)
!12 = !{!13}
!13 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 1, type: !10)
!14 = !DILocation(line: 0, scope: !7)
!15 = distinct !DISubprogram(name: "streaming_sve_debug_info", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !18)
!16 = !DILocalVariable(name: "arg", arg: 1, scope: !15, file: !1, line: 5, type: !10)
!17 = !DILocation(line: 0, scope: !15)
!18 = !{!16}
Loading