https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/225738
>From 8e4e5f90f190d72b6965ec5610c8c3d9f961ad0e Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Wed, 23 Sep 2026 12:26:51 +0200 Subject: [PATCH] AMDGPU: Mark dead carry-out when rewriting scalar carry op to VALU 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) <[email protected]> --- llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 11 ++ .../test/CodeGen/AMDGPU/change-scc-to-vcc.mir | 4 +- .../move-scalar-carry-to-valu-dead-vcc.mir | 116 ++++++++++++++++++ ...si-instr-info-correct-implicit-operands.ll | 2 +- 4 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/AMDGPU/move-scalar-carry-to-valu-dead-vcc.mir diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp index f584e7d67dd73f..f0428b68f2cacd 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/change-scc-to-vcc.mir b/llvm/test/CodeGen/AMDGPU/change-scc-to-vcc.mir index 37f5a3b29f2add..7ca5754c7a0cf9 100644 --- a/llvm/test/CodeGen/AMDGPU/change-scc-to-vcc.mir +++ b/llvm/test/CodeGen/AMDGPU/change-scc-to-vcc.mir @@ -22,7 +22,7 @@ body: | ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY killed [[DEF3]] ; GCN-NEXT: [[V_ADDC_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 killed [[DEF2]], [[COPY1]], implicit-def $vcc_lo, implicit $vcc_lo, implicit $exec ; GCN-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY [[S_MOV_B32_2]] - ; GCN-NEXT: [[V_ADDC_U32_e32_1:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 [[V_MUL_HI_U32_U24_e64_]], [[COPY2]], implicit-def $vcc_lo, implicit $vcc_lo, implicit $exec + ; GCN-NEXT: [[V_ADDC_U32_e32_1:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 [[V_MUL_HI_U32_U24_e64_]], [[COPY2]], implicit-def dead $vcc_lo, implicit $vcc_lo, implicit $exec %0:sreg_32 = S_MOV_B32 681 %1:sreg_32 = IMPLICIT_DEF %2:sreg_32 = IMPLICIT_DEF @@ -55,7 +55,7 @@ body: | ; GCN-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY killed [[DEF4]] ; GCN-NEXT: [[V_ADDC_U32_e32_:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 killed [[DEF3]], [[COPY]], implicit-def $vcc_lo, implicit $vcc_lo, implicit $exec ; GCN-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY [[DEF5]] - ; GCN-NEXT: [[V_ADDC_U32_e32_1:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 killed [[V_ADDC_U32_e32_1]], [[COPY1]], implicit-def $vcc_lo, implicit $vcc_lo, implicit $exec + ; GCN-NEXT: [[V_ADDC_U32_e32_1:%[0-9]+]]:vgpr_32 = V_ADDC_U32_e32 killed [[V_ADDC_U32_e32_1]], [[COPY1]], implicit-def dead $vcc_lo, implicit $vcc_lo, implicit $exec %0:vgpr_32 = IMPLICIT_DEF %1:vgpr_32 = IMPLICIT_DEF %2:sreg_32 = IMPLICIT_DEF 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 00000000000000..00ad65fac0fc43 --- /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/si-instr-info-correct-implicit-operands.ll b/llvm/test/CodeGen/AMDGPU/si-instr-info-correct-implicit-operands.ll index d5f1b1a3a60633..4cdf8054fb8789 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: _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
