[llvm] 4b8b168 - [AMDGPU] Add getRegisterByName support for src_flat_scratch_base (#220560)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 9 02:27:07 PDT 2026
Author: Andreas Leitner
Date: 2026-09-09T11:27:02+02:00
New Revision: 4b8b168e8b6897fe3816949a316002ee8aff2e98
URL: https://github.com/llvm/llvm-project/commit/4b8b168e8b6897fe3816949a316002ee8aff2e98
DIFF: https://github.com/llvm/llvm-project/commit/4b8b168e8b6897fe3816949a316002ee8aff2e98.diff
LOG: [AMDGPU] Add getRegisterByName support for src_flat_scratch_base (#220560)
Expose `src_flat_scratch_base`, `src_flat_scratch_base_lo`, and
`src_flat_scratch_base_hi` through `llvm.read_register` /
`llvm.write_register`.
The implementation is basically the same as the existing named-register
support for `flat_scratch`
It errors out on targets without `FeatureGloballyAddressableScratch`
(pre-gfx1250).
Added:
llvm/test/CodeGen/AMDGPU/read-register-src-flat-scratch-base.ll
llvm/test/CodeGen/AMDGPU/read-write-register-src-flat-scratch-base-invalid-subtarget.ll
llvm/test/CodeGen/AMDGPU/type-mismatch-src-flat-scratch-base.ll
llvm/test/CodeGen/AMDGPU/write-register-src-flat-scratch-base.ll
Modified:
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 4a3c9258f1770..deba185580571 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -5074,15 +5074,19 @@ Register SITargetLowering::getRegisterByName(const char *RegName, LLT VT,
const MachineFunction &MF) const {
const Function &Fn = MF.getFunction();
- Register Reg = StringSwitch<Register>(RegName)
- .Case("m0", AMDGPU::M0)
- .Case("exec", AMDGPU::EXEC)
- .Case("exec_lo", AMDGPU::EXEC_LO)
- .Case("exec_hi", AMDGPU::EXEC_HI)
- .Case("flat_scratch", AMDGPU::FLAT_SCR)
- .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
- .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
- .Default(Register());
+ Register Reg =
+ StringSwitch<Register>(RegName)
+ .Case("m0", AMDGPU::M0)
+ .Case("exec", AMDGPU::EXEC)
+ .Case("exec_lo", AMDGPU::EXEC_LO)
+ .Case("exec_hi", AMDGPU::EXEC_HI)
+ .Case("flat_scratch", AMDGPU::FLAT_SCR)
+ .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
+ .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
+ .Case("src_flat_scratch_base", AMDGPU::SRC_FLAT_SCRATCH_BASE)
+ .Case("src_flat_scratch_base_lo", AMDGPU::SRC_FLAT_SCRATCH_BASE_LO)
+ .Case("src_flat_scratch_base_hi", AMDGPU::SRC_FLAT_SCRATCH_BASE_HI)
+ .Default(Register());
if (!Reg)
return Reg;
@@ -5092,17 +5096,27 @@ Register SITargetLowering::getRegisterByName(const char *RegName, LLT VT,
"\" for subtarget."));
}
+ if (!Subtarget->hasGloballyAddressableScratch() &&
+ Subtarget->getRegisterInfo()->regsOverlap(
+ Reg, AMDGPU::SRC_FLAT_SCRATCH_BASE)) {
+ Fn.getContext().emitError(Twine("invalid register \"" + StringRef(RegName) +
+ "\" for subtarget."));
+ }
+
switch (Reg) {
case AMDGPU::M0:
case AMDGPU::EXEC_LO:
case AMDGPU::EXEC_HI:
case AMDGPU::FLAT_SCR_LO:
case AMDGPU::FLAT_SCR_HI:
+ case AMDGPU::SRC_FLAT_SCRATCH_BASE_LO:
+ case AMDGPU::SRC_FLAT_SCRATCH_BASE_HI:
if (VT.getSizeInBits() == 32)
return Reg;
break;
case AMDGPU::EXEC:
case AMDGPU::FLAT_SCR:
+ case AMDGPU::SRC_FLAT_SCRATCH_BASE:
if (VT.getSizeInBits() == 64)
return Reg;
break;
diff --git a/llvm/test/CodeGen/AMDGPU/read-register-src-flat-scratch-base.ll b/llvm/test/CodeGen/AMDGPU/read-register-src-flat-scratch-base.ll
new file mode 100644
index 0000000000000..6073c27cf09ce
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/read-register-src-flat-scratch-base.ll
@@ -0,0 +1,35 @@
+; RUN: llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck %s
+
+declare i32 @llvm.read_register.i32(metadata) #0
+declare i64 @llvm.read_register.i64(metadata) #0
+
+; CHECK-LABEL: {{^}}test_read_src_flat_scratch_base:
+; CHECK: v_mov_b64_e32 v{{\[[0-9]+:[0-9]+\]}}, src_flat_scratch_base_lo
+define amdgpu_kernel void @test_read_src_flat_scratch_base(ptr addrspace(1) %out) #0 {
+ %v = call i64 @llvm.read_register.i64(metadata !0)
+ store i64 %v, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK-LABEL: {{^}}test_read_src_flat_scratch_base_lo:
+; CHECK: v_{{(dual_)?}}mov_b32{{(_e32)?}} v{{[0-9]+}}, src_flat_scratch_base_lo
+define amdgpu_kernel void @test_read_src_flat_scratch_base_lo(ptr addrspace(1) %out) #0 {
+ %v = call i32 @llvm.read_register.i32(metadata !1)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK-LABEL: {{^}}test_read_src_flat_scratch_base_hi:
+; CHECK: v_{{(dual_)?}}mov_b32{{(_e32)?}} v{{[0-9]+}}, src_flat_scratch_base_hi
+define amdgpu_kernel void @test_read_src_flat_scratch_base_hi(ptr addrspace(1) %out) #0 {
+ %v = call i32 @llvm.read_register.i32(metadata !2)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+attributes #0 = { nounwind }
+
+!0 = !{!"src_flat_scratch_base"}
+!1 = !{!"src_flat_scratch_base_lo"}
+!2 = !{!"src_flat_scratch_base_hi"}
diff --git a/llvm/test/CodeGen/AMDGPU/read-write-register-src-flat-scratch-base-invalid-subtarget.ll b/llvm/test/CodeGen/AMDGPU/read-write-register-src-flat-scratch-base-invalid-subtarget.ll
new file mode 100644
index 0000000000000..b702a74e1031e
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/read-write-register-src-flat-scratch-base-invalid-subtarget.ll
@@ -0,0 +1,52 @@
+; RUN: not llc -mtriple=amdgpu12.00-amd-amdhsa -filetype=null %s 2>&1 | FileCheck %s
+
+; src_flat_scratch_base{,_lo,_hi} require globally-addressable-scratch (gfx1250+),
+; so named-register access to them should be rejected on earlier subtargets.
+
+declare i32 @llvm.read_register.i32(metadata) #0
+declare i64 @llvm.read_register.i64(metadata) #0
+declare void @llvm.write_register.i32(metadata, i32) #0
+declare void @llvm.write_register.i64(metadata, i64) #0
+
+; CHECK: error: invalid register "src_flat_scratch_base" for subtarget.
+define amdgpu_kernel void @test_read_src_flat_scratch_base(ptr addrspace(1) %out) nounwind {
+ %v = call i64 @llvm.read_register.i64(metadata !0)
+ store i64 %v, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: invalid register "src_flat_scratch_base_lo" for subtarget.
+define amdgpu_kernel void @test_read_src_flat_scratch_base_lo(ptr addrspace(1) %out) nounwind {
+ %v = call i32 @llvm.read_register.i32(metadata !1)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: invalid register "src_flat_scratch_base_hi" for subtarget.
+define amdgpu_kernel void @test_read_src_flat_scratch_base_hi(ptr addrspace(1) %out) nounwind {
+ %v = call i32 @llvm.read_register.i32(metadata !2)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+; CHECK: error: invalid register "src_flat_scratch_base" for subtarget.
+define amdgpu_kernel void @test_write_src_flat_scratch_base(i64 %val) nounwind {
+ call void @llvm.write_register.i64(metadata !0, i64 %val)
+ ret void
+}
+
+; CHECK: error: invalid register "src_flat_scratch_base_lo" for subtarget.
+define amdgpu_kernel void @test_write_src_flat_scratch_base_lo(i32 %val) nounwind {
+ call void @llvm.write_register.i32(metadata !1, i32 %val)
+ ret void
+}
+
+; CHECK: error: invalid register "src_flat_scratch_base_hi" for subtarget.
+define amdgpu_kernel void @test_write_src_flat_scratch_base_hi(i32 %val) nounwind {
+ call void @llvm.write_register.i32(metadata !2, i32 %val)
+ ret void
+}
+
+!0 = !{!"src_flat_scratch_base"}
+!1 = !{!"src_flat_scratch_base_lo"}
+!2 = !{!"src_flat_scratch_base_hi"}
diff --git a/llvm/test/CodeGen/AMDGPU/type-mismatch-src-flat-scratch-base.ll b/llvm/test/CodeGen/AMDGPU/type-mismatch-src-flat-scratch-base.ll
new file mode 100644
index 0000000000000..362ca5ce3e4be
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/type-mismatch-src-flat-scratch-base.ll
@@ -0,0 +1,92 @@
+; RUN: split-file %s %t
+
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/lo.ll 2>&1 | FileCheck --check-prefix=LO %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/lo.ll 2>&1 | FileCheck --check-prefix=LO %s
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/hi.ll 2>&1 | FileCheck --check-prefix=HI %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/hi.ll 2>&1 | FileCheck --check-prefix=HI %s
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/combined.ll 2>&1 | FileCheck --check-prefix=COMBINED %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/combined.ll 2>&1 | FileCheck --check-prefix=COMBINED %s
+
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-lo.ll 2>&1 | FileCheck --check-prefix=WRITE-LO %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-lo.ll 2>&1 | FileCheck --check-prefix=WRITE-LO %s
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-hi.ll 2>&1 | FileCheck --check-prefix=WRITE-HI %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-hi.ll 2>&1 | FileCheck --check-prefix=WRITE-HI %s
+; RUN: not --crash llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-combined.ll 2>&1 | FileCheck --check-prefix=WRITE-COMBINED %s
+; RUN: not --crash llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %t/write-combined.ll 2>&1 | FileCheck --check-prefix=WRITE-COMBINED %s
+
+; Requesting src_flat_scratch_base and its variants as a wrong type is expected to error out.
+
+;--- lo.ll
+declare i64 @llvm.read_register.i64(metadata) #0
+
+; LO: LLVM ERROR: invalid type for register "src_flat_scratch_base_lo".
+define amdgpu_kernel void @test_read_src_flat_scratch_base_lo_wrong_type(ptr addrspace(1) %out) #0 {
+ %v = call i64 @llvm.read_register.i64(metadata !0)
+ store i64 %v, ptr addrspace(1) %out
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base_lo"}
+
+;--- hi.ll
+declare i64 @llvm.read_register.i64(metadata) #0
+
+; HI: LLVM ERROR: invalid type for register "src_flat_scratch_base_hi".
+define amdgpu_kernel void @test_read_src_flat_scratch_base_hi_wrong_type(ptr addrspace(1) %out) #0 {
+ %v = call i64 @llvm.read_register.i64(metadata !0)
+ store i64 %v, ptr addrspace(1) %out
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base_hi"}
+
+;--- combined.ll
+declare i32 @llvm.read_register.i32(metadata) #0
+
+; COMBINED: LLVM ERROR: invalid type for register "src_flat_scratch_base".
+define amdgpu_kernel void @test_read_src_flat_scratch_base_wrong_type(ptr addrspace(1) %out) #0 {
+ %v = call i32 @llvm.read_register.i32(metadata !0)
+ store i32 %v, ptr addrspace(1) %out
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base"}
+
+;--- write-lo.ll
+declare void @llvm.write_register.i64(metadata, i64) #0
+
+; WRITE-LO: LLVM ERROR: invalid type for register "src_flat_scratch_base_lo".
+define amdgpu_kernel void @test_write_src_flat_scratch_base_lo_wrong_type(i64 %v) #0 {
+ call void @llvm.write_register.i64(metadata !0, i64 %v)
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base_lo"}
+
+;--- write-hi.ll
+declare void @llvm.write_register.i64(metadata, i64) #0
+
+; WRITE-HI: LLVM ERROR: invalid type for register "src_flat_scratch_base_hi".
+define amdgpu_kernel void @test_write_src_flat_scratch_base_hi_wrong_type(i64 %v) #0 {
+ call void @llvm.write_register.i64(metadata !0, i64 %v)
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base_hi"}
+
+;--- write-combined.ll
+declare void @llvm.write_register.i32(metadata, i32) #0
+
+; WRITE-COMBINED: LLVM ERROR: invalid type for register "src_flat_scratch_base".
+define amdgpu_kernel void @test_write_src_flat_scratch_base_wrong_type(i32 %v) #0 {
+ call void @llvm.write_register.i32(metadata !0, i32 %v)
+ ret void
+}
+
+attributes #0 = { nounwind }
+!0 = !{!"src_flat_scratch_base"}
diff --git a/llvm/test/CodeGen/AMDGPU/write-register-src-flat-scratch-base.ll b/llvm/test/CodeGen/AMDGPU/write-register-src-flat-scratch-base.ll
new file mode 100644
index 0000000000000..ffa3554ff2212
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/write-register-src-flat-scratch-base.ll
@@ -0,0 +1,38 @@
+; RUN: llc -global-isel=0 -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck %s
+
+; src_flat_scratch_base{,_lo,_hi} are isConstant register aliases, so writes to
+; them are dead and get silently eliminated rather than lowered to a copy.
+
+declare void @llvm.write_register.i32(metadata, i32) #0
+declare void @llvm.write_register.i64(metadata, i64) #0
+
+; CHECK-LABEL: {{^}}test_write_src_flat_scratch_base:{{.*$}}
+; CHECK-NOT: src_flat_scratch_base
+; CHECK: s_endpgm
+define amdgpu_kernel void @test_write_src_flat_scratch_base(i64 %val) #0 {
+ call void @llvm.write_register.i64(metadata !0, i64 %val)
+ ret void
+}
+
+; CHECK-LABEL: {{^}}test_write_src_flat_scratch_base_lo:{{.*$}}
+; CHECK-NOT: src_flat_scratch_base
+; CHECK: s_endpgm
+define amdgpu_kernel void @test_write_src_flat_scratch_base_lo(i32 %val) #0 {
+ call void @llvm.write_register.i32(metadata !1, i32 %val)
+ ret void
+}
+
+; CHECK-LABEL: {{^}}test_write_src_flat_scratch_base_hi:{{.*$}}
+; CHECK-NOT: src_flat_scratch_base
+; CHECK: s_endpgm
+define amdgpu_kernel void @test_write_src_flat_scratch_base_hi(i32 %val) #0 {
+ call void @llvm.write_register.i32(metadata !2, i32 %val)
+ ret void
+}
+
+attributes #0 = { nounwind }
+
+!0 = !{!"src_flat_scratch_base"}
+!1 = !{!"src_flat_scratch_base_lo"}
+!2 = !{!"src_flat_scratch_base_hi"}
More information about the llvm-commits
mailing list