[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