[llvm] AMDGPU: Mark the carry-out of the scalar abs expansion dead (PR #226046)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 00:22:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Matt Arsenault (arsenm)
<details>
<summary>Changes</summary>
lowerScalarAbs and lowerScalarAbsDiff build V_SUB_CO_U32_e32 on targets
without the carry-less add/sub instructions. The carry-out is never read,
but it was left without a dead flag. Fix the missing flag to reduce
implicit dependence on LiveVariables introducing dead flags.
Co-Authored-By: Claude Opus 5 <noreply@<!-- -->anthropic.com>
---
Full diff: https://github.com/llvm/llvm-project/pull/226046.diff
2 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/SIInstrInfo.cpp (+20-11)
- (modified) llvm/test/CodeGen/AMDGPU/move-to-valu-absdiff.mir (+24-2)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index b042a7c164a37..16ee5f5698680 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -9119,12 +9119,14 @@ void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
- unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
- : AMDGPU::V_SUB_CO_U32_e32;
+ bool HasCarryOut = !ST.hasAddNoCarryInsts();
+ unsigned SubOp =
+ HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
- BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
- .addImm(0)
- .addReg(Src.getReg());
+ MachineInstrBuilder Sub =
+ BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(Src.getReg());
+ if (HasCarryOut)
+ Sub.setOperandDead(3); // Dead vcc
BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
.addReg(Src.getReg())
@@ -9148,14 +9150,21 @@ void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
- unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
- : AMDGPU::V_SUB_CO_U32_e32;
+ bool HasCarryOut = !ST.hasAddNoCarryInsts();
+ unsigned SubOp =
+ HasCarryOut ? AMDGPU::V_SUB_CO_U32_e32 : AMDGPU::V_SUB_U32_e32;
- BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
- .addReg(Src1.getReg())
- .addReg(Src2.getReg());
+ MachineInstrBuilder Sub1 = BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
+ .addReg(Src1.getReg())
+ .addReg(Src2.getReg());
- BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
+ MachineInstrBuilder Sub2 =
+ BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);
+
+ if (HasCarryOut) {
+ Sub1.setOperandDead(3); // Dead vcc
+ Sub2.setOperandDead(3); // Dead vcc
+ }
BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
.addReg(SubResultReg)
diff --git a/llvm/test/CodeGen/AMDGPU/move-to-valu-absdiff.mir b/llvm/test/CodeGen/AMDGPU/move-to-valu-absdiff.mir
index a73d3a2c2d1e2..39a7948600d98 100644
--- a/llvm/test/CodeGen/AMDGPU/move-to-valu-absdiff.mir
+++ b/llvm/test/CodeGen/AMDGPU/move-to-valu-absdiff.mir
@@ -12,8 +12,8 @@ body: |
; GFX8-NEXT: {{ $}}
; GFX8-NEXT: [[V_LSHL_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_LSHL_ADD_U32_e64 $vgpr0, $vgpr1, $vgpr2, implicit $exec
; GFX8-NEXT: [[S_MOV_B32_:%[0-9]+]]:sreg_32 = S_MOV_B32 10
- ; GFX8-NEXT: [[V_SUB_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 [[S_MOV_B32_]], [[V_LSHL_ADD_U32_e64_]], implicit-def $vcc, implicit $exec
- ; GFX8-NEXT: [[V_SUB_CO_U32_e32_1:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 0, [[V_SUB_CO_U32_e32_]], implicit-def $vcc, implicit $exec
+ ; GFX8-NEXT: [[V_SUB_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 [[S_MOV_B32_]], [[V_LSHL_ADD_U32_e64_]], implicit-def dead $vcc, implicit $exec
+ ; GFX8-NEXT: [[V_SUB_CO_U32_e32_1:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 0, [[V_SUB_CO_U32_e32_]], implicit-def dead $vcc, implicit $exec
; GFX8-NEXT: [[V_MAX_I32_e64_:%[0-9]+]]:vgpr_32 = V_MAX_I32_e64 [[V_SUB_CO_U32_e32_]], [[V_SUB_CO_U32_e32_1]], implicit $exec
;
; GFX12-LABEL: name: absdiff_i32
@@ -29,3 +29,25 @@ body: |
%2:sreg_32 = S_MOV_B32 10
%3:sreg_32 = S_ABSDIFF_I32 killed %2:sreg_32, %1:sreg_32, implicit-def dead $scc
...
+---
+name: abs_i32
+body: |
+ bb.0:
+ liveins: $vgpr0, $vgpr1, $vgpr2
+ ; GFX8-LABEL: name: abs_i32
+ ; GFX8: liveins: $vgpr0, $vgpr1, $vgpr2
+ ; GFX8-NEXT: {{ $}}
+ ; GFX8-NEXT: [[V_LSHL_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_LSHL_ADD_U32_e64 $vgpr0, $vgpr1, $vgpr2, implicit $exec
+ ; GFX8-NEXT: [[V_SUB_CO_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_CO_U32_e32 0, [[V_LSHL_ADD_U32_e64_]], implicit-def dead $vcc, implicit $exec
+ ; GFX8-NEXT: [[V_MAX_I32_e64_:%[0-9]+]]:vgpr_32 = V_MAX_I32_e64 [[V_LSHL_ADD_U32_e64_]], [[V_SUB_CO_U32_e32_]], implicit $exec
+ ;
+ ; GFX12-LABEL: name: abs_i32
+ ; GFX12: liveins: $vgpr0, $vgpr1, $vgpr2
+ ; GFX12-NEXT: {{ $}}
+ ; GFX12-NEXT: [[V_LSHL_ADD_U32_e64_:%[0-9]+]]:vgpr_32 = V_LSHL_ADD_U32_e64 $vgpr0, $vgpr1, $vgpr2, implicit $exec
+ ; GFX12-NEXT: [[V_SUB_U32_e32_:%[0-9]+]]:vgpr_32 = V_SUB_U32_e32 0, [[V_LSHL_ADD_U32_e64_]], implicit $exec
+ ; GFX12-NEXT: [[V_MAX_I32_e64_:%[0-9]+]]:vgpr_32 = V_MAX_I32_e64 [[V_LSHL_ADD_U32_e64_]], [[V_SUB_U32_e32_]], implicit $exec
+ %0:vgpr_32 = V_LSHL_ADD_U32_e64 $vgpr0, $vgpr1, $vgpr2, implicit $exec
+ %1:sreg_32 = COPY %0:vgpr_32
+ %2:sreg_32 = S_ABS_I32 %1:sreg_32, implicit-def dead $scc
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/226046
More information about the llvm-commits
mailing list