[llvm] [AMDGPU] Do not forward reserved aperture registers into wider copies (PR #220517)
Arseniy Obolenskiy via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 06:04:41 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/220517
>From 26cdf4980548bc8ad3f5a3c270730f6bfbc0392f Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 2 Sep 2026 10:41:17 +0200
Subject: [PATCH] [AMDGPU] Do not forward reserved aperture registers into
wider copies
src_shared_base/src_private_base have no addressable high half, so MachineCopyPropagation must not forward them into a copy that later splits into subregisters
SIInstrInfo::copyPhysReg now reports an error instead of asserting if asked to do so anyway
---
llvm/lib/CodeGen/MachineCopyPropagation.cpp | 22 +++++++++++++
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 9 ++++++
.../AMDGPU/illegal-aperture-reg-copy.mir | 14 ++++++++
.../CodeGen/AMDGPU/machine-cp-aperture-reg.ll | 15 +++++++++
.../CodeGen/AMDGPU/machine-cp-propagation.mir | 32 +++++++++++++++++++
5 files changed, 92 insertions(+)
create mode 100644 llvm/test/CodeGen/AMDGPU/illegal-aperture-reg-copy.mir
create mode 100644 llvm/test/CodeGen/AMDGPU/machine-cp-aperture-reg.ll
diff --git a/llvm/lib/CodeGen/MachineCopyPropagation.cpp b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
index 0568890583c1d..2d165e7c59a47 100644
--- a/llvm/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/llvm/lib/CodeGen/MachineCopyPropagation.cpp
@@ -821,6 +821,20 @@ bool MachineCopyPropagation::canUpdateSrcUsers(const MachineInstr &Copy,
return true;
}
+/// Return true if \p NewReg has a non-artificial subregister for every
+/// subregister index where \p OldReg has one.
+static bool hasMatchingSubRegs(MCRegister OldReg, MCRegister NewReg,
+ const TargetRegisterInfo *TRI) {
+ for (MCSubRegIndexIterator SRI(OldReg, TRI); SRI.isValid(); ++SRI) {
+ if (TRI->isArtificial(SRI.getSubReg()))
+ continue;
+ MCRegister Sub = TRI->getSubReg(NewReg, SRI.getSubRegIndex());
+ if (!Sub || TRI->isArtificial(Sub))
+ return false;
+ }
+ return true;
+}
+
/// Look for available copies whose destination register is used by \p MI and
/// replace the use in \p MI with the copy's source register.
void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
@@ -879,6 +893,14 @@ void MachineCopyPropagation::forwardUses(MachineInstr &MI) {
if (MRI->isReserved(CopySrc) && !MRI->isConstantPhysReg(CopySrc))
continue;
+ // A reserved source may lack subregs the copy is later split into.
+ if (MRI->isReserved(CopySrc) && isCopyInstr(MI, *TII, UseCopyInstr) &&
+ !hasMatchingSubRegs(MOUse.getReg().asMCReg(), ForwardedReg, TRI)) {
+ LLVM_DEBUG(dbgs() << "MCP: Copy source is missing subregisters of "
+ << printReg(MOUse.getReg(), TRI) << '\n');
+ continue;
+ }
+
if (!isForwardableRegClassCopy(*Copy, MI, OpIdx))
continue;
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index 3094c1390e9cf..db3fdf0ea8147 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -1189,6 +1189,15 @@ void SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);
+ // Report rather than assert if a register is missing a required subreg.
+ for (int16_t SubIdx : SubIndices) {
+ if (!RI.getSubReg(DestReg, SubIdx) || !RI.getSubReg(SrcReg, SubIdx)) {
+ reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
+ "Cannot decompose copy into subregister moves!");
+ return;
+ }
+ }
+
// If there is an overlap, we can't kill the super-register on the last
// instruction, since it will also kill the components made live by this def.
const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
diff --git a/llvm/test/CodeGen/AMDGPU/illegal-aperture-reg-copy.mir b/llvm/test/CodeGen/AMDGPU/illegal-aperture-reg-copy.mir
new file mode 100644
index 0000000000000..e3c5ac9abbe7f
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/illegal-aperture-reg-copy.mir
@@ -0,0 +1,14 @@
+# RUN: not llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -run-pass=postrapseudos -o /dev/null %s 2>&1 | FileCheck %s
+
+# src_shared_base has no addressable high half. copyPhysReg must not assert.
+
+# CHECK: error: {{.*}} in function illegal_aperture_reg_copy void (): Cannot decompose copy into subregister moves!
+
+---
+name: illegal_aperture_reg_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ renamable $vgpr0_vgpr1 = COPY $src_shared_base
+ S_ENDPGM 0, implicit $vgpr0_vgpr1
+...
diff --git a/llvm/test/CodeGen/AMDGPU/machine-cp-aperture-reg.ll b/llvm/test/CodeGen/AMDGPU/machine-cp-aperture-reg.ll
new file mode 100644
index 0000000000000..9e44e9e72973b
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/machine-cp-aperture-reg.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -global-isel < %s | FileCheck %s
+
+; src_shared_base has no addressable high half. Must not forward into VGPRs.
+
+ at lds = internal addrspace(3) global [32 x float] poison, align 4
+
+; CHECK-LABEL: aperture_copy_to_vgpr_pair:
+; CHECK: s_mov_b64 s[{{[0-9]+}}:{{[0-9]+}}], src_shared_base
+define float @aperture_copy_to_vgpr_pair(i32 %i) {
+ %idx = zext i32 %i to i64
+ %gep = getelementptr float, ptr addrspacecast (ptr addrspace(3) @lds to ptr), i64 %idx
+ %cast = addrspacecast ptr %gep to ptr addrspace(3)
+ %v = load float, ptr addrspace(3) %cast, align 4
+ ret float %v
+}
diff --git a/llvm/test/CodeGen/AMDGPU/machine-cp-propagation.mir b/llvm/test/CodeGen/AMDGPU/machine-cp-propagation.mir
index f8630245b6938..8cbd8cac4c588 100644
--- a/llvm/test/CodeGen/AMDGPU/machine-cp-propagation.mir
+++ b/llvm/test/CodeGen/AMDGPU/machine-cp-propagation.mir
@@ -34,3 +34,35 @@ body: |
S_ENDPGM 0
...
+
+# src_shared_base has no addressable high half. machine-cp must not forward it.
+
+---
+name: no_forward_aperture_into_vgpr_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: no_forward_aperture_into_vgpr_copy
+ ; CHECK: renamable $sgpr0_sgpr1 = COPY $src_shared_base
+ ; CHECK-NEXT: renamable $vgpr0_vgpr1 = COPY killed renamable $sgpr0_sgpr1
+ ; CHECK-NEXT: S_ENDPGM 0, implicit $vgpr0_vgpr1
+ renamable $sgpr0_sgpr1 = COPY $src_shared_base
+ renamable $vgpr0_vgpr1 = COPY killed renamable $sgpr0_sgpr1
+ S_ENDPGM 0, implicit $vgpr0_vgpr1
+...
+
+---
+name: forward_sgpr_into_vgpr_copy
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $sgpr4_sgpr5
+ ; CHECK-LABEL: name: forward_sgpr_into_vgpr_copy
+ ; CHECK: liveins: $sgpr4_sgpr5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $vgpr0_vgpr1 = COPY $sgpr4_sgpr5
+ ; CHECK-NEXT: S_ENDPGM 0, implicit $vgpr0_vgpr1
+ renamable $sgpr0_sgpr1 = COPY $sgpr4_sgpr5
+ renamable $vgpr0_vgpr1 = COPY killed renamable $sgpr0_sgpr1
+ S_ENDPGM 0, implicit $vgpr0_vgpr1
+...
More information about the llvm-commits
mailing list