[llvm] AMDGPU/GlobalISel: RegBankLegalize rules for G_ABS (PR #192760)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 17 18:01:23 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: vangthao95
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/192760.diff
6 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.cpp (+56)
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.h (+2)
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp (+7-1)
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.h (+3-1)
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.abs.ll (+14-9)
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-abs.mir (+1-2)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.cpp
index 63a940ab5d29b..3626d60ba6cde 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.cpp
@@ -1083,6 +1083,58 @@ bool RegBankLegalizeHelper::lowerInsVecEltTo32(MachineInstr &MI) {
return true;
}
+bool RegBankLegalizeHelper::lowerAbsToNegMax(MachineInstr &MI) {
+ // Lower divergent G_ABS to smax(x, 0 - x) in the VGPR bank:
+ // zero = 0
+ // neg = G_SUB zero, x
+ // dst = G_SMAX x, neg
+ //
+ // There is no integer v_abs instruction on AMDGPU, so divergent G_ABS is
+ // expanded to this sub/smax pair.
+ Register DstReg = MI.getOperand(0).getReg();
+ Register SrcReg = MI.getOperand(1).getReg();
+ LLT Ty = MRI.getType(DstReg);
+
+ Register Zero;
+ if (Ty == V2S16) {
+ // buildConstant cannot produce a V2S16 directly; pack two S16 zeros.
+ Register Zero16 = B.buildConstant({VgprRB, S16}, 0).getReg(0);
+ Zero = B.buildBuildVector({VgprRB, Ty}, {Zero16, Zero16}).getReg(0);
+ } else {
+ assert((Ty == S32 || Ty == S16) && "unexpected type for AbsToNegMax");
+ Zero = B.buildConstant({VgprRB, Ty}, 0).getReg(0);
+ }
+
+ auto Neg = B.buildSub({VgprRB, Ty}, Zero, SrcReg);
+ B.buildSMax(DstReg, SrcReg, Neg);
+ MI.eraseFromParent();
+ return true;
+}
+
+bool RegBankLegalizeHelper::lowerAbsToS32(MachineInstr &MI) {
+ // Lower uniform V2S16 abs by unpacking to two S32 lanes and re-emitting
+ // G_ABS on each lane:
+ // packed = bitcast <2 x s16> src to s32
+ // lo = sext_inreg packed, 16
+ // hi = ashr packed, 16
+ // dst = build_vector_trunc G_ABS(lo), G_ABS(hi)
+ //
+ // SALU only has s_abs_i32, with no direct uniform V2S16 abs. The
+ // re-emitted G_ABS(SgprRB, S32) selects to s_abs_i32 on each value.
+ auto Bitcast = B.buildBitcast({SgprRB, S32}, MI.getOperand(1).getReg());
+ auto SextInReg = B.buildSExtInReg({SgprRB, S32}, Bitcast, 16);
+ auto ShiftHi =
+ B.buildAShr({SgprRB, S32}, Bitcast, B.buildConstant({SgprRB, S32}, 16));
+
+ auto AbsLo = B.buildInstr(AMDGPU::G_ABS, {{SgprRB, S32}}, {SextInReg});
+ auto AbsHi = B.buildInstr(AMDGPU::G_ABS, {{SgprRB, S32}}, {ShiftHi});
+ B.buildBuildVectorTrunc(MI.getOperand(0).getReg(),
+ {AbsLo.getReg(0), AbsHi.getReg(0)});
+
+ MI.eraseFromParent();
+ return true;
+}
+
bool RegBankLegalizeHelper::lower(MachineInstr &MI,
const RegBankLLTMapping &Mapping,
WaterfallInfo &WFI) {
@@ -1365,6 +1417,10 @@ bool RegBankLegalizeHelper::lower(MachineInstr &MI,
return lowerInsVecEltToSel(MI);
case InsVecEltTo32:
return lowerInsVecEltTo32(MI);
+ case AbsToNegMax:
+ return lowerAbsToNegMax(MI);
+ case AbsToS32:
+ return lowerAbsToS32(MI);
}
if (!WFI.SgprWaterfallOperandRegs.empty()) {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.h b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.h
index 57df192832dc6..4bfb322ca7985 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeHelper.h
@@ -144,6 +144,8 @@ class RegBankLegalizeHelper {
bool lowerExtrVecEltTo32(MachineInstr &MI);
bool lowerInsVecEltToSel(MachineInstr &MI);
bool lowerInsVecEltTo32(MachineInstr &MI);
+ bool lowerAbsToNegMax(MachineInstr &MI);
+ bool lowerAbsToS32(MachineInstr &MI);
bool applyRegisterBanksINTRIN_IMAGE(MachineInstr &MI);
};
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
index 03b9ea9397650..112ba7f5e12bc 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1234,7 +1234,13 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
.Any({{UniP3}, {{SgprP3}, {SgprP3, Sgpr32}}})
.Any({{DivP3}, {{VgprP3}, {VgprP3, Vgpr32}}});
- addRulesForGOpcs({G_ABS}, Standard).Uni(S16, {{Sgpr32Trunc}, {Sgpr32SExt}});
+ addRulesForGOpcs({G_ABS}, Standard)
+ .Uni(S16, {{Sgpr32Trunc}, {Sgpr32SExt}})
+ .Div(S16, {{Vgpr16}, {Vgpr16}, AbsToNegMax})
+ .Uni(S32, {{Sgpr32}, {Sgpr32}})
+ .Div(S32, {{Vgpr32}, {Vgpr32}, AbsToNegMax})
+ .Uni(V2S16, {{SgprV2S16}, {SgprV2S16}, AbsToS32})
+ .Div(V2S16, {{VgprV2S16}, {VgprV2S16}, AbsToNegMax});
addRulesForGOpcs({G_BITREVERSE}, Standard)
.Uni(S32, {{Sgpr32}, {Sgpr32}})
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.h b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.h
index 3d282220d8611..f4bbac114d00c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.h
@@ -296,7 +296,9 @@ enum LoweringMethodID {
ExtrVecEltToSel,
ExtrVecEltTo32,
InsVecEltToSel,
- InsVecEltTo32
+ InsVecEltTo32,
+ AbsToNegMax,
+ AbsToS32
};
enum FastRulesTypes {
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.abs.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.abs.ll
index 239408d31482f..ada49d85b463d 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.abs.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.abs.ll
@@ -1,9 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -global-isel -mtriple=amdgcn -mcpu=tahiti -o - < %s | FileCheck %s --check-prefixes=GFX,GFX6
-; RUN: llc -global-isel -mtriple=amdgcn -mcpu=fiji -o - < %s | FileCheck %s --check-prefixes=GFX,GFX8
-; RUN: llc -global-isel -mtriple=amdgcn -mcpu=gfx1010 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX10
-; RUN: llc -global-isel -mtriple=amdgcn -mcpu=gfx1250 -mattr=-real-true16 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX1250,GFX1250-FAKE16
-; RUN: llc -global-isel -mtriple=amdgcn -mcpu=gfx1250 -mattr=+real-true16 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX1250,GFX1250-REAL16
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mcpu=tahiti -o - < %s | FileCheck %s --check-prefixes=GFX,GFX6
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mcpu=fiji -o - < %s | FileCheck %s --check-prefixes=GFX,GFX8
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mcpu=gfx1010 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX10
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mcpu=gfx1250 -mattr=-real-true16 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX1250,GFX1250-FAKE16
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mcpu=gfx1250 -mattr=+real-true16 -o - < %s | FileCheck %s --check-prefixes=GFX,GFX1250,GFX1250-REAL16
declare i16 @llvm.abs.i16(i16, i1)
declare i32 @llvm.abs.i32(i32, i1)
@@ -730,21 +730,26 @@ define <3 x i16> @abs_vgpr_v3i16(<3 x i16> %arg) {
; GFX10-LABEL: abs_vgpr_v3i16:
; GFX10: ; %bb.0:
; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: v_sub_nc_u16 v2, 0, v1
+; GFX10-NEXT: v_max_i16 v1, v1, v2
; GFX10-NEXT: v_pk_sub_i16 v2, 0, v0
-; GFX10-NEXT: v_sub_nc_u16 v3, 0, v1
+; GFX10-NEXT: v_and_b32_e32 v1, 0xffff, v1
; GFX10-NEXT: v_pk_max_i16 v0, v0, v2
-; GFX10-NEXT: v_max_i16 v1, v1, v3
+; GFX10-NEXT: v_lshl_or_b32 v1, s4, 16, v1
; GFX10-NEXT: s_setpc_b64 s[30:31]
;
; GFX1250-FAKE16-LABEL: abs_vgpr_v3i16:
; GFX1250-FAKE16: ; %bb.0:
; GFX1250-FAKE16-NEXT: s_wait_loadcnt_dscnt 0x0
; GFX1250-FAKE16-NEXT: s_wait_kmcnt 0x0
+; GFX1250-FAKE16-NEXT: v_sub_nc_u16 v2, 0, v1
+; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; GFX1250-FAKE16-NEXT: v_max_i16 v1, v1, v2
; GFX1250-FAKE16-NEXT: v_pk_sub_i16 v2, 0, v0
-; GFX1250-FAKE16-NEXT: v_sub_nc_u16 v3, 0, v1
+; GFX1250-FAKE16-NEXT: v_and_b32_e32 v1, 0xffff, v1
; GFX1250-FAKE16-NEXT: s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
; GFX1250-FAKE16-NEXT: v_pk_max_i16 v0, v0, v2
-; GFX1250-FAKE16-NEXT: v_max_i16 v1, v1, v3
+; GFX1250-FAKE16-NEXT: v_lshl_or_b32 v1, s0, 16, v1
; GFX1250-FAKE16-NEXT: s_set_pc_i64 s[30:31]
;
; GFX1250-REAL16-LABEL: abs_vgpr_v3i16:
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-abs.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-abs.mir
index 7f7f8b0121567..dc73f1061dac8 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-abs.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/regbankselect-abs.mir
@@ -1,5 +1,5 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple=amdgcn -mcpu=gfx1010 -run-pass=regbankselect %s -verify-machineinstrs -o - | FileCheck %s
+# RUN: llc -mtriple=amdgcn -mcpu=gfx1010 -run-pass='amdgpu-regbankselect,amdgpu-regbanklegalize' %s -o - | FileCheck %s
---
name: abs_sgpr_s16
@@ -16,7 +16,6 @@ body: |
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:sgpr(s16) = G_TRUNC [[COPY]](s32)
; CHECK-NEXT: [[SEXT:%[0-9]+]]:sgpr(s32) = G_SEXT [[TRUNC]](s16)
; CHECK-NEXT: [[ABS:%[0-9]+]]:sgpr(s32) = G_ABS [[SEXT]]
- ; CHECK-NEXT: [[TRUNC1:%[0-9]+]]:sgpr(s16) = G_TRUNC [[ABS]](s32)
%1:_(s32) = COPY $sgpr0
%2:_(s16) = G_TRUNC %1
%5:_(s16) = G_ABS %2
``````````
</details>
https://github.com/llvm/llvm-project/pull/192760
More information about the llvm-commits
mailing list