[llvm] d74c1b7 - [AMDGPU] Unify liveness guard to prevent SCC clobber in frame index lowering in scaling path (#223789)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 07:12:23 PDT 2026
Author: Domenic Nutile
Date: 2026-09-22T10:12:13-04:00
New Revision: d74c1b77c61492ef6c5dc95bcd2b23685509379b
URL: https://github.com/llvm/llvm-project/commit/d74c1b77c61492ef6c5dc95bcd2b23685509379b
DIFF: https://github.com/llvm/llvm-project/commit/d74c1b77c61492ef6c5dc95bcd2b23685509379b.diff
LOG: [AMDGPU] Unify liveness guard to prevent SCC clobber in frame index lowering in scaling path (#223789)
eliminateFrameIndex has two lowering strategies, but only one has the
proper handling for checking SCC-liveness to prevent clobbering. Unify
them with a helper function to ensure both paths handle the same
Added:
Modified:
llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
llvm/test/CodeGen/AMDGPU/eliminate-frame-index-scalar-scc-clobber.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
index bf5c821611dd8..7cad384c98a8d 100644
--- a/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp
@@ -2541,6 +2541,13 @@ static bool foldingOffsetChangesCarry(const MachineOperand &OtherOp,
: FrameReg.isValid();
}
+// Is SCC live into MI, so that frame index lowering must not clobber it?
+static bool isSCCLiveInto(const RegScavenger &RS, const MachineInstr &MI) {
+ return (RS.isRegUsed(AMDGPU::SCC) &&
+ !MI.definesRegister(AMDGPU::SCC, /*TRI=*/nullptr)) ||
+ MI.readsRegister(AMDGPU::SCC, /*TRI=*/nullptr);
+}
+
bool SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
@@ -3267,9 +3274,7 @@ bool SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
return false;
}
- bool NeedSaveSCC = (RS->isRegUsed(AMDGPU::SCC) &&
- !MI->definesRegister(AMDGPU::SCC, /*TRI=*/nullptr)) ||
- MI->readsRegister(AMDGPU::SCC, /*TRI=*/nullptr);
+ bool NeedSaveSCC = isSCCLiveInto(*RS, *MI);
Register TmpSReg =
UseSGPR ? TmpReg
@@ -3403,8 +3408,7 @@ bool SIRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
// Convert to a swizzled stack address by scaling by the wave size.
// In an entry function/kernel the offset is already swizzled.
bool IsSALU = isSGPRClass(TII->getRegClass(MI->getDesc(), FIOperandNum));
- bool LiveSCC = RS->isRegUsed(AMDGPU::SCC) &&
- !MI->definesRegister(AMDGPU::SCC, /*TRI=*/nullptr);
+ bool LiveSCC = isSCCLiveInto(*RS, *MI);
const TargetRegisterClass *RC = IsSALU && !LiveSCC
? &AMDGPU::SReg_32RegClass
: &AMDGPU::VGPR_32RegClass;
diff --git a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-scalar-scc-clobber.mir b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-scalar-scc-clobber.mir
index 26e1242c91c81..1b02930287fdb 100644
--- a/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-scalar-scc-clobber.mir
+++ b/llvm/test/CodeGen/AMDGPU/eliminate-frame-index-scalar-scc-clobber.mir
@@ -60,8 +60,9 @@ body: |
; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
; MUBUF-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
- ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def $scc
- ; MUBUF-NEXT: $sgpr5 = S_ADD_I32 killed $sgpr5, 64, implicit-def $scc
+ ; MUBUF-NEXT: $vgpr0 = V_LSHRREV_B32_e64 6, $sgpr32, implicit $exec
+ ; MUBUF-NEXT: $vgpr0 = V_ADD_U32_e32 64, killed $vgpr0, implicit $exec
+ ; MUBUF-NEXT: $sgpr5 = V_READFIRSTLANE_B32 $vgpr0, implicit $exec
; MUBUF-NEXT: renamable $sgpr4 = S_CSELECT_B32 killed $sgpr5, $sgpr6, implicit $scc
; MUBUF-NEXT: SI_RETURN implicit $sgpr4
renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
@@ -75,6 +76,10 @@ body: |
# S_ADDC_U32 with a frame index source-operand, preceded by S_AND_B64 which
# produces SCC. S_ADDC_U32 reads SCC, so frame index elimination must use the
# ADDC+BITCMP1+BITSET0 sequence to preserve the incoming SCC value.
+#
+# S_ADDC_U32 both reads and defines SCC, so this also covers the read-and-define
+# case: the incoming carry must survive frame index lowering even though the
+# instruction goes on to overwrite SCC.
name: s_addc_u32_fi_after_and_scc_producer
tracksRegLiveness: true
stack:
@@ -127,8 +132,9 @@ body: |
; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
; MUBUF-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
- ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def $scc
- ; MUBUF-NEXT: $sgpr5 = S_ADD_I32 killed $sgpr5, 64, implicit-def $scc
+ ; MUBUF-NEXT: $vgpr0 = V_LSHRREV_B32_e64 6, $sgpr32, implicit $exec
+ ; MUBUF-NEXT: $vgpr0 = V_ADD_U32_e32 64, killed $vgpr0, implicit $exec
+ ; MUBUF-NEXT: $sgpr5 = V_READFIRSTLANE_B32 $vgpr0, implicit $exec
; MUBUF-NEXT: renamable $sgpr4 = S_ADDC_U32 killed $sgpr5, $sgpr6, implicit-def $scc, implicit $scc
; MUBUF-NEXT: SI_RETURN implicit $sgpr4
renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
@@ -136,3 +142,336 @@ body: |
SI_RETURN implicit $sgpr4
...
+
+---
+# S_CSELECT_B32 with a ZERO-offset frame index, preceded by S_AND_B64 which
+# produces SCC. %stack.0 is at offset 0, so eliminateFrameIndex takes the
+# Offset == 0 path, which scales FrameReg with a bare S_LSHR_B32 instead of the
+# ADDC sequence. S_LSHR_B32 writes SCC, so on targets that need the wave-size
+# scaling it must not land between the SCC producer and the S_CSELECT_B32 that
+# consumes it.
+name: s_cselect_b32_zero_offset_fi_after_scc_producer
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr4, $sgpr5, $sgpr6
+
+ ; FLATSCRW64-LABEL: name: s_cselect_b32_zero_offset_fi_after_scc_producer
+ ; FLATSCRW64: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW64-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_CSELECT_B32 $sgpr32, $sgpr6, implicit $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; FLATSCRW32-LABEL: name: s_cselect_b32_zero_offset_fi_after_scc_producer
+ ; FLATSCRW32: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW32-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_CSELECT_B32 $sgpr32, $sgpr6, implicit $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; MUBUF-LABEL: name: s_cselect_b32_zero_offset_fi_after_scc_producer
+ ; MUBUF: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; MUBUF-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; MUBUF-NEXT: $vgpr0 = V_LSHRREV_B32_e64 6, $sgpr32, implicit $exec
+ ; MUBUF-NEXT: $sgpr5 = V_READFIRSTLANE_B32 $vgpr0, implicit $exec
+ ; MUBUF-NEXT: renamable $sgpr4 = S_CSELECT_B32 killed $sgpr5, $sgpr6, implicit $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4
+ renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ renamable $sgpr4 = S_CSELECT_B32 %stack.0, $sgpr6, implicit $scc
+ SI_RETURN implicit $sgpr4
+...
+
+---
+# Negative case for the ADDC path: same S_AND_B64 SCC producer as
+# s_cselect_b32_fi_after_scc_producer, but the frame index user is S_AND_B32
+# which defines SCC instead of reading it, so lowering is free to clobber SCC
+name: s_and_b32_fi_after_scc_producer_scc_not_live_in
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+ - { id: 1, size: 4, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr4, $sgpr5, $sgpr6
+
+ ; FLATSCRW64-LABEL: name: s_and_b32_fi_after_scc_producer_scc_not_live_in
+ ; FLATSCRW64: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW64-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW64-NEXT: $sgpr5 = S_ADD_I32 $sgpr32, 64, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; FLATSCRW32-LABEL: name: s_and_b32_fi_after_scc_producer_scc_not_live_in
+ ; FLATSCRW32: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW32-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW32-NEXT: $sgpr5 = S_ADD_I32 $sgpr32, 64, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; MUBUF-LABEL: name: s_and_b32_fi_after_scc_producer_scc_not_live_in
+ ; MUBUF: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; MUBUF-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def $scc
+ ; MUBUF-NEXT: $sgpr5 = S_ADD_I32 killed $sgpr5, 64, implicit-def $scc
+ ; MUBUF-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4
+ renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ renamable $sgpr4 = S_AND_B32 %stack.1, $sgpr6, implicit-def $scc
+ SI_RETURN implicit $sgpr4
+...
+
+---
+# Negative case for the Offset == 0 scaling path: same shape as
+# s_cselect_b32_zero_offset_fi_after_scc_producer, but S_AND_B32 defines SCC
+# rather than reading it, so SCC is not live into the frame index user.
+name: s_and_b32_zero_offset_fi_after_scc_producer_scc_not_live_in
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr4, $sgpr5, $sgpr6
+
+ ; FLATSCRW64-LABEL: name: s_and_b32_zero_offset_fi_after_scc_producer_scc_not_live_in
+ ; FLATSCRW64: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW64-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; FLATSCRW32-LABEL: name: s_and_b32_zero_offset_fi_after_scc_producer_scc_not_live_in
+ ; FLATSCRW32: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW32-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; MUBUF-LABEL: name: s_and_b32_zero_offset_fi_after_scc_producer_scc_not_live_in
+ ; MUBUF: liveins: $sgpr4, $sgpr5, $sgpr6
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; MUBUF-NEXT: renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def dead $scc
+ ; MUBUF-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4
+ renamable $sgpr4_sgpr5 = S_AND_B64 killed renamable $sgpr4_sgpr5, $exec, implicit-def $scc
+ renamable $sgpr4 = S_AND_B32 %stack.0, $sgpr6, implicit-def $scc
+ SI_RETURN implicit $sgpr4
+...
+
+---
+# Negative case with no SCC producer at all: nothing defines SCC ahead of the
+# frame index user and the user does not read SCC, so there's no restrictions
+name: s_and_b32_zero_offset_fi_no_scc_producer
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr6
+
+ ; FLATSCRW64-LABEL: name: s_and_b32_zero_offset_fi_no_scc_producer
+ ; FLATSCRW64: liveins: $sgpr6
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; FLATSCRW32-LABEL: name: s_and_b32_zero_offset_fi_no_scc_producer
+ ; FLATSCRW32: liveins: $sgpr6
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4
+ ;
+ ; MUBUF-LABEL: name: s_and_b32_zero_offset_fi_no_scc_producer
+ ; MUBUF: liveins: $sgpr6
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def dead $scc
+ ; MUBUF-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4
+ renamable $sgpr4 = S_AND_B32 %stack.0, $sgpr6, implicit-def $scc
+ SI_RETURN implicit $sgpr4
+...
+
+---
+# SCC live ACROSS the frame index user. S_MOV_B32 neither reads nor defines
+# SCC, S_CMP_EQ_U32 produces SCC and the later S_CSELECT_B32 consumes it,
+# so SCC is still live when the frame index is lowered. The wave-size
+# scaling must not clobber it.
+name: s_mov_b32_fi_scc_live_across
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr6, $sgpr7
+
+ ; FLATSCRW64-LABEL: name: s_mov_b32_fi_scc_live_across
+ ; FLATSCRW64: liveins: $sgpr6, $sgpr7
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW64-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_MOV_B32 $sgpr32
+ ; FLATSCRW64-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ ;
+ ; FLATSCRW32-LABEL: name: s_mov_b32_fi_scc_live_across
+ ; FLATSCRW32: liveins: $sgpr6, $sgpr7
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW32-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_MOV_B32 $sgpr32
+ ; FLATSCRW32-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ ;
+ ; MUBUF-LABEL: name: s_mov_b32_fi_scc_live_across
+ ; MUBUF: liveins: $sgpr6, $sgpr7
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; MUBUF-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; MUBUF-NEXT: $vgpr0 = V_LSHRREV_B32_e64 6, $sgpr32, implicit $exec
+ ; MUBUF-NEXT: $sgpr4 = V_READFIRSTLANE_B32 $vgpr0, implicit $exec
+ ; MUBUF-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ renamable $sgpr4 = S_MOV_B32 %stack.0
+ renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ SI_RETURN implicit $sgpr4, implicit $sgpr5
+...
+
+---
+# Negative version of s_mov_b32_fi_scc_live_across: SCC is live across the
+# frame index user in the same way, but S_AND_B32 defines SCC itself, so the
+# incoming value is dead at the user.
+name: s_and_b32_fi_defines_scc_live_after
+tracksRegLiveness: true
+stack:
+ - { id: 0, size: 64, alignment: 4 }
+machineFunctionInfo:
+ scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+ frameOffsetReg: '$sgpr33'
+ stackPtrOffsetReg: '$sgpr32'
+body: |
+ bb.0:
+ liveins: $sgpr6, $sgpr7
+
+ ; FLATSCRW64-LABEL: name: s_and_b32_fi_defines_scc_live_after
+ ; FLATSCRW64: liveins: $sgpr6, $sgpr7
+ ; FLATSCRW64-NEXT: {{ $}}
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x36, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW64-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW64-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW64-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; FLATSCRW64-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ ;
+ ; FLATSCRW32-LABEL: name: s_and_b32_fi_defines_scc_live_after
+ ; FLATSCRW32: liveins: $sgpr6, $sgpr7
+ ; FLATSCRW32-NEXT: {{ $}}
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION escape 0x0f, 0x09, 0x90, 0x40, 0x94, 0x04, 0x35, 0x24, 0x36, 0xe9, 0x02
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; FLATSCRW32-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; FLATSCRW32-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr4 = S_AND_B32 $sgpr32, $sgpr6, implicit-def $scc
+ ; FLATSCRW32-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; FLATSCRW32-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ ;
+ ; MUBUF-LABEL: name: s_and_b32_fi_defines_scc_live_after
+ ; MUBUF: liveins: $sgpr6, $sgpr7
+ ; MUBUF-NEXT: {{ $}}
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_def_aspace_cfa $sgpr32, 0, 6
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION llvm_register_pair $pc_reg, $sgpr30, 32, $sgpr31, 32
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr4
+ ; MUBUF-NEXT: frame-setup CFI_INSTRUCTION undefined $sgpr5
+ ; MUBUF-NEXT: S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ ; MUBUF-NEXT: $sgpr5 = S_LSHR_B32 $sgpr32, 6, implicit-def dead $scc
+ ; MUBUF-NEXT: renamable $sgpr4 = S_AND_B32 killed $sgpr5, $sgpr6, implicit-def $scc
+ ; MUBUF-NEXT: renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ ; MUBUF-NEXT: SI_RETURN implicit $sgpr4, implicit $sgpr5
+ S_CMP_EQ_U32 renamable $sgpr6, 0, implicit-def $scc
+ renamable $sgpr4 = S_AND_B32 %stack.0, $sgpr6, implicit-def $scc
+ renamable $sgpr5 = S_CSELECT_B32 renamable $sgpr6, renamable $sgpr7, implicit $scc
+ SI_RETURN implicit $sgpr4, implicit $sgpr5
+...
More information about the llvm-commits
mailing list