[llvm-branch-commits] [llvm] AMDGPU: Mark dead carry-out when rewriting scalar carry op to VALU (PR #225738)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 23 04:55:08 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
If an operation is expanded with a dead scc def, the resultant vcc def will
also be dead, so preserve the dead flag. Reduces implicit reliance on
LiveVariables recomputing dead flags later.
Co-authored-by: Claude (Opus 4.8) <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/225738.diff
4 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/SIInstrInfo.cpp (+11)
- (added) llvm/test/CodeGen/AMDGPU/move-scalar-carry-to-valu-dead-vcc.mir (+116)
- (modified) llvm/test/CodeGen/AMDGPU/sdiv64.ll (+4-6)
- (modified) llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index f584e7d67dd73..f0428b68f2cac 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -8920,11 +8920,14 @@ void SIInstrInfo::moveToVALUImpl(
// Remove any references to SCC. Vector instructions can't read from it, and
// We're just about to add the implicit use / defs of VCC, and we don't want
// both.
+ bool DeadSCCDef = false;
for (MachineOperand &Op : Inst.implicit_operands()) {
if (Op.getReg() == AMDGPU::SCC) {
// Only propagate through live-def of SCC.
if (Op.isDef() && !Op.isDead())
addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
+ else if (Op.isDef())
+ DeadSCCDef = true;
if (Op.isUse())
addSCCDefsToVALUWorklist(NewInstr, Worklist);
}
@@ -8942,6 +8945,14 @@ void SIInstrInfo::moveToVALUImpl(
}
fixImplicitOperands(*NewInstr);
+ if (DeadSCCDef) {
+ // A scalar op with a dead SCC def lowers to a VALU op whose VCC def will
+ // also be dead.
+ if (MachineOperand *VCCDef =
+ NewInstr->findRegisterDefOperand(RI.getVCC(), &RI))
+ VCCDef->setIsDead();
+ }
+
// Legalize the operands
legalizeOperands(*NewInstr, MDT);
if (NewDstReg)
diff --git a/llvm/test/CodeGen/AMDGPU/move-scalar-carry-to-valu-dead-vcc.mir b/llvm/test/CodeGen/AMDGPU/move-scalar-carry-to-valu-dead-vcc.mir
new file mode 100644
index 0000000000000..00ad65fac0fc4
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/move-scalar-carry-to-valu-dead-vcc.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgpu8.03 -run-pass=si-fix-sgpr-copies -o - %s | FileCheck %s
+
+# When moveToVALU lowers a scalar op with a dead SCC def to a VALU op
+# the equivalent VCC def should inherit the dead flag.
+
+---
+name: s_add_i32_dead_carry
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: s_add_i32_dead_carry
+ ; CHECK: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:sreg_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[V_ADD_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_CO_U32_e32 [[DEF1]], [[DEF]], implicit-def dead $vcc, implicit $exec
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY [[V_ADD_CO_U32_e32_]]
+ ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY]]
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:sreg_32 = IMPLICIT_DEF
+ %2:sreg_32 = COPY %0:vgpr_32
+ %3:sreg_32 = S_ADD_I32 %1:sreg_32, %2:sreg_32, implicit-def dead $scc
+ %4:vgpr_32 = COPY %3:sreg_32
+ S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_sub_i32_dead_carry
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: s_sub_i32_dead_carry
+ ; CHECK: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:sreg_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[V_SUB_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 [[DEF1]], [[DEF]], implicit-def dead $vcc, implicit $exec
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY [[V_SUB_CO_U32_e32_]]
+ ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY]]
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:sreg_32 = IMPLICIT_DEF
+ %2:sreg_32 = COPY %0:vgpr_32
+ %3:sreg_32 = S_SUB_I32 %1:sreg_32, %2:sreg_32, implicit-def dead $scc
+ %4:vgpr_32 = COPY %3:sreg_32
+ S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_addc_u32_dead_carry
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: s_addc_u32_dead_carry
+ ; CHECK: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF2:%[0-9]+]]:sreg_64 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[V_ADD_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADD_CO_U32_e32 [[DEF2]].sub0, [[DEF]], implicit-def $vcc, implicit $exec
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY [[DEF2]].sub1
+ ; CHECK-NEXT: [[V_ADDC_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 [[COPY]], [[DEF1]], implicit-def dead $vcc, implicit $vcc, implicit $exec
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_ADD_CO_U32_e32_]], %subreg.sub0, [[V_ADDC_U32_e32_]], %subreg.sub1
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[REG_SEQUENCE]].sub1
+ ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY1]]
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vgpr_32 = IMPLICIT_DEF
+ %2:sreg_64 = IMPLICIT_DEF
+ %3:sreg_32 = COPY %0:vgpr_32
+ %4:sreg_32 = COPY %1:vgpr_32
+ %5:sreg_32 = S_ADD_U32 %2.sub0:sreg_64, %3:sreg_32, implicit-def $scc
+ %6:sreg_32 = S_ADDC_U32 %2.sub1:sreg_64, %4:sreg_32, implicit-def dead $scc, implicit $scc
+ %7:sreg_64 = REG_SEQUENCE %5:sreg_32, %subreg.sub0, %6:sreg_32, %subreg.sub1
+ %8:vgpr_32 = COPY %7.sub1:sreg_64
+ S_ENDPGM 0, implicit %8
+...
+
+---
+name: s_subb_u32_dead_carry
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: s_subb_u32_dead_carry
+ ; CHECK: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF2:%[0-9]+]]:sreg_64 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[V_SUB_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 [[DEF2]].sub0, [[DEF]], implicit-def $vcc, implicit $exec
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY [[DEF2]].sub1
+ ; CHECK-NEXT: [[V_SUBB_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUBB_U32_e32 [[COPY]], [[DEF1]], implicit-def dead $vcc, implicit $vcc, implicit $exec
+ ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_64 = REG_SEQUENCE [[V_SUB_CO_U32_e32_]], %subreg.sub0, [[V_SUBB_U32_e32_]], %subreg.sub1
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[REG_SEQUENCE]].sub1
+ ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY1]]
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:vgpr_32 = IMPLICIT_DEF
+ %2:sreg_64 = IMPLICIT_DEF
+ %3:sreg_32 = COPY %0:vgpr_32
+ %4:sreg_32 = COPY %1:vgpr_32
+ %5:sreg_32 = S_SUB_U32 %2.sub0:sreg_64, %3:sreg_32, implicit-def $scc
+ %6:sreg_32 = S_SUBB_U32 %2.sub1:sreg_64, %4:sreg_32, implicit-def dead $scc, implicit $scc
+ %7:sreg_64 = REG_SEQUENCE %5:sreg_32, %subreg.sub0, %6:sreg_32, %subreg.sub1
+ %8:vgpr_32 = COPY %7.sub1:sreg_64
+ S_ENDPGM 0, implicit %8
+...
+
+---
+name: s_and_b32_dead_scc_no_carry
+tracksRegLiveness: true
+body: |
+ bb.0:
+ ; CHECK-LABEL: name: s_and_b32_dead_scc_no_carry
+ ; CHECK: [[DEF:%[0-9]+]]:vgpr_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[DEF1:%[0-9]+]]:sreg_32 = IMPLICIT_DEF
+ ; CHECK-NEXT: [[V_AND_B32_e64_:%[0-9]+]]:vgpr_32 = V_AND_B32_e64 [[DEF1]], [[DEF]], implicit $exec
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY [[V_AND_B32_e64_]]
+ ; CHECK-NEXT: S_ENDPGM 0, implicit [[COPY]]
+ %0:vgpr_32 = IMPLICIT_DEF
+ %1:sreg_32 = IMPLICIT_DEF
+ %2:sreg_32 = COPY %0:vgpr_32
+ %3:sreg_32 = S_AND_B32 %1:sreg_32, %2:sreg_32, implicit-def dead $scc
+ %4:vgpr_32 = COPY %3:sreg_32
+ S_ENDPGM 0, implicit %4
+...
diff --git a/llvm/test/CodeGen/AMDGPU/sdiv64.ll b/llvm/test/CodeGen/AMDGPU/sdiv64.ll
index 9018259618f82..74ee61b676f0a 100644
--- a/llvm/test/CodeGen/AMDGPU/sdiv64.ll
+++ b/llvm/test/CodeGen/AMDGPU/sdiv64.ll
@@ -2369,9 +2369,8 @@ define i64 @v_test_sdiv24_pow2_k_num_i64(i64 %x) {
; GCN-NEXT: v_max_i32_e32 v0, v2, v0
; GCN-NEXT: v_cvt_f32_u32_e32 v2, v0
; GCN-NEXT: v_sub_i32_e32 v3, vcc, 0, v0
-; GCN-NEXT: s_mov_b32 s4, 0x8000
-; GCN-NEXT: v_rcp_f32_e32 v2, v2
; GCN-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+; GCN-NEXT: v_rcp_f32_e32 v2, v2
; GCN-NEXT: v_mul_f32_e32 v2, 0x4f7ffffe, v2
; GCN-NEXT: v_cvt_u32_f32_e32 v2, v2
; GCN-NEXT: v_mul_lo_u32 v3, v3, v2
@@ -2380,7 +2379,7 @@ define i64 @v_test_sdiv24_pow2_k_num_i64(i64 %x) {
; GCN-NEXT: v_lshrrev_b32_e32 v2, 17, v2
; GCN-NEXT: v_mul_u32_u24_e32 v3, v2, v0
; GCN-NEXT: v_add_i32_e32 v4, vcc, 1, v2
-; GCN-NEXT: v_sub_i32_e32 v3, vcc, s4, v3
+; GCN-NEXT: v_sub_i32_e32 v3, vcc, 0x8000, v3
; GCN-NEXT: v_cmp_ge_u32_e32 vcc, v3, v0
; GCN-NEXT: v_cndmask_b32_e32 v2, v2, v4, vcc
; GCN-NEXT: v_sub_i32_e64 v4, s[4:5], v3, v0
@@ -2401,9 +2400,8 @@ define i64 @v_test_sdiv24_pow2_k_num_i64(i64 %x) {
; GCN-IR-NEXT: v_max_i32_e32 v0, v2, v0
; GCN-IR-NEXT: v_cvt_f32_u32_e32 v2, v0
; GCN-IR-NEXT: v_sub_i32_e32 v3, vcc, 0, v0
-; GCN-IR-NEXT: s_mov_b32 s4, 0x8000
-; GCN-IR-NEXT: v_rcp_f32_e32 v2, v2
; GCN-IR-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+; GCN-IR-NEXT: v_rcp_f32_e32 v2, v2
; GCN-IR-NEXT: v_mul_f32_e32 v2, 0x4f7ffffe, v2
; GCN-IR-NEXT: v_cvt_u32_f32_e32 v2, v2
; GCN-IR-NEXT: v_mul_lo_u32 v3, v3, v2
@@ -2412,7 +2410,7 @@ define i64 @v_test_sdiv24_pow2_k_num_i64(i64 %x) {
; GCN-IR-NEXT: v_lshrrev_b32_e32 v2, 17, v2
; GCN-IR-NEXT: v_mul_u32_u24_e32 v3, v2, v0
; GCN-IR-NEXT: v_add_i32_e32 v4, vcc, 1, v2
-; GCN-IR-NEXT: v_sub_i32_e32 v3, vcc, s4, v3
+; GCN-IR-NEXT: v_sub_i32_e32 v3, vcc, 0x8000, v3
; GCN-IR-NEXT: v_cmp_ge_u32_e32 vcc, v3, v0
; GCN-IR-NEXT: v_cndmask_b32_e32 v2, v2, v4, vcc
; GCN-IR-NEXT: v_sub_i32_e64 v4, s[4:5], v3, v0
diff --git a/llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll b/llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll
index d5f1b1a3a6063..4cdf8054fb878 100644
--- a/llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll
+++ b/llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll
@@ -3,7 +3,7 @@
; register operands in the correct order when modifying the opcode of an
; instruction to V_ADD_CO_U32_e32.
-; CHECK: %{{[0-9]+}}:vgpr_32 = V_ADD_CO_U32_e32 %{{[0-9]+}}, %{{[0-9]+}}, implicit-def $vcc, implicit $exec
+; CHECK: %{{[0-9]+}}:vgpr_32 = V_ADD_CO_U32_e32 %{{[0-9]+}}, %{{[0-9]+}}, implicit-def dead $vcc, implicit $exec
define amdgpu_kernel void @test(ptr addrspace(1) %out, ptr addrspace(1) %in) {
entry:
``````````
</details>
https://github.com/llvm/llvm-project/pull/225738
More information about the llvm-branch-commits
mailing list