diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt index cda288e01292..73d295751653 100644 --- a/llvm/lib/Target/AMDGPU/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt @@ -172,6 +172,7 @@ add_llvm_target(AMDGPUCodeGen SILowerWWMCopies.cpp SILowerSGPRSpills.cpp SIMachineFunctionInfo.cpp + SISpillUtils.cpp SIMachineScheduler.cpp SIMemoryLegalizer.cpp SIModeRegister.cpp diff --git a/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp b/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp index 9ee9e63fdab2..638b56965a24 100644 --- a/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIFrameLowering.cpp @@ -12,6 +12,7 @@ #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "SIMachineFunctionInfo.h" +#include "SISpillUtils.h" #include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" @@ -1518,23 +1519,8 @@ void SIFrameLowering::processFunctionBeforeFrameFinalized( MBB.sortUniqueLiveIns(); - if (!SpillFIs.empty() && SeenDbgInstr) { - // FIXME: The dead frame indices are replaced with a null register from - // the debug value instructions. We should instead, update it with the - // correct register value. But not sure the register value alone is - for (MachineInstr &MI : MBB) { - if (MI.isDebugValue()) { - uint32_t StackOperandIdx = MI.isDebugValueList() ? 2 : 0; - if (MI.getOperand(StackOperandIdx).isFI() && - !MFI.isFixedObjectIndex( - MI.getOperand(StackOperandIdx).getIndex()) && - SpillFIs[MI.getOperand(StackOperandIdx).getIndex()]) { - MI.getOperand(StackOperandIdx) - .ChangeToRegister(Register(), false /*isDef*/); - } - } - } - } + if (!SpillFIs.empty() && SeenDbgInstr) + clearDebugInfoForSpillFIs(MFI, MBB, SpillFIs); } } diff --git a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp index 196e55193265..06b221e171fd 100644 --- a/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp +++ b/llvm/lib/Target/AMDGPU/SILowerSGPRSpills.cpp @@ -20,6 +20,7 @@ #include "GCNSubtarget.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" #include "SIMachineFunctionInfo.h" +#include "SISpillUtils.h" #include "llvm/CodeGen/LiveIntervals.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -524,24 +525,8 @@ bool SILowerSGPRSpills::run(MachineFunction &MF) { FuncInfo->updateNonWWMRegMask(NonWwmRegMask); } - for (MachineBasicBlock &MBB : MF) { - // FIXME: The dead frame indices are replaced with a null register from - // the debug value instructions. We should instead, update it with the - // correct register value. But not sure the register value alone is - // adequate to lower the DIExpression. It should be worked out later. - for (MachineInstr &MI : MBB) { - if (MI.isDebugValue()) { - uint32_t StackOperandIdx = MI.isDebugValueList() ? 2 : 0; - if (MI.getOperand(StackOperandIdx).isFI() && - !MFI.isFixedObjectIndex( - MI.getOperand(StackOperandIdx).getIndex()) && - SpillFIs[MI.getOperand(StackOperandIdx).getIndex()]) { - MI.getOperand(StackOperandIdx) - .ChangeToRegister(Register(), false /*isDef*/); - } - } - } - } + for (MachineBasicBlock &MBB : MF) + clearDebugInfoForSpillFIs(MFI, MBB, SpillFIs); // All those frame indices which are dead by now should be removed from the // function frame. Otherwise, there is a side effect such as re-mapping of diff --git a/llvm/lib/Target/AMDGPU/SISpillUtils.cpp b/llvm/lib/Target/AMDGPU/SISpillUtils.cpp new file mode 100644 index 000000000000..b2d2e5a4cab6 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/SISpillUtils.cpp @@ -0,0 +1,34 @@ +//===- SISpillUtils.cpp - SI spill helper functions -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "SISpillUtils.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" + +using namespace llvm; + +void llvm::clearDebugInfoForSpillFIs(MachineFrameInfo &MFI, + MachineBasicBlock &MBB, + const BitVector &SpillFIs) { + // FIXME: The dead frame indices are replaced with a null register from the + // debug value instructions. We should instead update it with the correct + // register value. But not sure the register value alone is adequate to lower + // the DIExpression. It should be worked out later. + for (MachineInstr &MI : MBB) { + if (!MI.isDebugValue()) + continue; + + for (MachineOperand &Op : MI.debug_operands()) { + if (Op.isFI() && !MFI.isFixedObjectIndex(Op.getIndex()) && + SpillFIs[Op.getIndex()]) { + Op.ChangeToRegister(Register(), /*isDef=*/false); + } + } + } +} diff --git a/llvm/lib/Target/AMDGPU/SISpillUtils.h b/llvm/lib/Target/AMDGPU/SISpillUtils.h new file mode 100644 index 000000000000..aa2e88dc8982 --- /dev/null +++ b/llvm/lib/Target/AMDGPU/SISpillUtils.h @@ -0,0 +1,25 @@ +//===- SISpillUtils.h - SI spill helper functions ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_AMDGPU_SISPILLUTILS_H +#define LLVM_LIB_TARGET_AMDGPU_SISPILLUTILS_H + +namespace llvm { + +class BitVector; +class MachineBasicBlock; +class MachineFrameInfo; + +/// Replace frame index operands with null registers in debug value instructions +/// for the specified spill frame indices. +void clearDebugInfoForSpillFIs(MachineFrameInfo &MFI, MachineBasicBlock &MBB, + const BitVector &SpillFIs); + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_AMDGPU_SISPILLUTILS_H diff --git a/llvm/test/CodeGen/AMDGPU/dead-frame-index-dbg-value.ll b/llvm/test/CodeGen/AMDGPU/dead-frame-index-dbg-value.ll new file mode 100644 index 000000000000..235c4414ba64 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/dead-frame-index-dbg-value.ll @@ -0,0 +1,36 @@ +; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 < %s | FileCheck %s +; RUN: llc -O0 -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 < %s | FileCheck %s + +; Check that debug values referencing eliminated frame indices don't crash. +; The AMDGPU backend can eliminate spill slots during frame finalization +; (e.g., SGPR spills to VGPR lanes). Debug values referencing these eliminated +; frame indices need to be cleaned up to avoid assertions in PrologEpilogInserter. + +%struct.Buffer = type { [8 x i64] } + +; CHECK-LABEL: test_dbg_value_dead_frame_idx: +; CHECK: ;DEBUG_VALUE: test_dbg_value_dead_frame_idx:slot <- [DW_OP_LLVM_arg 0, DW_OP_LLVM_arg 1, DW_OP_constu 64, DW_OP_mul, DW_OP_plus, DW_OP_stack_value] {{.*}} +; CHECK: s_endpgm +define amdgpu_kernel void @test_dbg_value_dead_frame_idx(ptr addrspace(1) %out, i64 %idx) !dbg !10 { +entry: + #dbg_value(!DIArgList(ptr addrspace(1) %out, i64 %idx), !15, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 64, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), !17) + %ptr = getelementptr %struct.Buffer, ptr addrspace(1) %out, i64 %idx + store i64 0, ptr addrspace(1) %ptr, align 8 + ret void +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "test.cpp", directory: "/tmp") +!2 = !{} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"amdhsa_code_object_version", i32 500} +!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, dwarfAddressSpace: 1) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Buffer", file: !1, line: 1, size: 512, flags: DIFlagTypePassByValue, elements: !2) +!10 = distinct !DISubprogram(name: "test_dbg_value_dead_frame_idx", scope: !1, file: !1, line: 10, type: !11, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0) +!11 = !DISubroutineType(types: !12) +!12 = !{null, !6} +!15 = !DILocalVariable(name: "slot", scope: !10, file: !1, line: 11, type: !6) +!17 = !DILocation(line: 11, column: 1, scope: !10)