[llvm] AMDGPU/GlobalISel: Implement RegBankLegalizeRules for amdgcn_log, amdgcn_rcp, and amdgcn_sqrt (PR #195099)
via llvm-commits
llvm-commits at lists.llvm.org
Wed May 6 08:00:17 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: anjenner
<details>
<summary>Changes</summary>
This depends on https://github.com/llvm/llvm-project/pull/187672 . I'm also not sure if GISel is generating the correct code here: for example the v_amdgcn_sqrt_f16 test in pseudo-scalar-transcendental.ll is not generating s_wait_alu and s_delay_alu instructions for GISel but it is for SDAG - I will look into the cause of the discrepancy there but any insights would be appreciated.
---
Full diff: https://github.com/llvm/llvm-project/pull/195099.diff
2 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp (+1-1)
- (modified) llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll (+124-68)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
index 118d75dd6bbe3..9327935b5f105 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1939,7 +1939,7 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
.Uni(S32, {{Sgpr32}, {IntrId, Sgpr32}}, hasPST)
.Uni(S32, {{UniInVgprS32}, {IntrId, Vgpr32}}, !hasPST);
- addRulesForIOpcs({amdgcn_sqrt}, Standard)
+ addRulesForIOpcs({amdgcn_log, amdgcn_rcp, amdgcn_sqrt}, Standard)
.Div(S16, {{Vgpr16}, {IntrId, Vgpr16}})
.Uni(S16, {{Sgpr16}, {IntrId, Sgpr16}}, hasPST)
.Uni(S16, {{UniInVgprS16}, {IntrId, Vgpr16}}, !hasPST)
diff --git a/llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll b/llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll
index f001b26030896..f3b825c5f42c1 100644
--- a/llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll
+++ b/llvm/test/CodeGen/AMDGPU/pseudo-scalar-transcendental.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -global-isel=0 -mtriple=amdgcn -mcpu=gfx1200 < %s | FileCheck -check-prefixes=GFX12,GFX12-SDAG %s
-; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 < %s | FileCheck -check-prefixes=GFX12,GFX12-GISEL %s
+; RUN: llc -global-isel=1 -mtriple=amdgcn -mcpu=gfx1200 -new-reg-bank-select < %s | FileCheck -check-prefixes=GFX12,GFX12-GISEL %s
; TODO: GlobalISel should avoid generating v_ldexp_f32.
define amdgpu_cs float @v_s_exp_f32(float inreg %src) {
@@ -35,13 +35,18 @@ define amdgpu_cs float @v_s_exp_f32(float inreg %src) {
}
define amdgpu_cs half @v_s_exp_f16(half inreg %src) {
-; GFX12-LABEL: v_s_exp_f16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_s_exp_f16 s0, s0
-; GFX12-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-NEXT: v_mov_b32_e32 v0, s0
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: v_s_exp_f16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_s_exp_f16 s0, s0
+; GFX12-SDAG-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-SDAG-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: v_s_exp_f16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_exp_f16_e32 v0.l, s0
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%result = call half @llvm.exp2.f16(half %src)
ret half %result
}
@@ -88,29 +93,39 @@ define amdgpu_cs float @v_s_log_f32(float inreg %src) {
; GFX12-GISEL-LABEL: v_s_log_f32:
; GFX12-GISEL: ; %bb.0:
; GFX12-GISEL-NEXT: s_cmp_lt_f32 s0, 0x800000
+; GFX12-GISEL-NEXT: s_cselect_b32 s2, 1, 0
; GFX12-GISEL-NEXT: s_cselect_b32 s1, 1, 0
-; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_3) | instid1(VALU_DEP_1)
-; GFX12-GISEL-NEXT: s_lshl_b32 s2, s1, 5
+; GFX12-GISEL-NEXT: s_lshl_b32 s2, s2, 5
; GFX12-GISEL-NEXT: s_cmp_lg_u32 s1, 0
; GFX12-GISEL-NEXT: v_ldexp_f32 v0, s0, s2
-; GFX12-GISEL-NEXT: s_cselect_b32 s0, 0x42000000, 0
-; GFX12-GISEL-NEXT: v_log_f32_e32 v0, v0
+; GFX12-GISEL-NEXT: s_cselect_b32 s1, 0x42000000, 0
+; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX12-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-GISEL-NEXT: v_s_log_f32 s0, s0
; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
-; GFX12-GISEL-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-GISEL-NEXT: v_subrev_f32_e32 v0, s0, v0
+; GFX12-GISEL-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_2)
+; GFX12-GISEL-NEXT: s_sub_f32 s0, s0, s1
+; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
+; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s0
; GFX12-GISEL-NEXT: ; return to shader part epilog
%result = call float @llvm.log2.f32(float %src)
ret float %result
}
define amdgpu_cs half @v_s_log_f16(half inreg %src) {
-; GFX12-LABEL: v_s_log_f16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_s_log_f16 s0, s0
-; GFX12-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-NEXT: v_mov_b32_e32 v0, s0
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: v_s_log_f16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_s_log_f16 s0, s0
+; GFX12-SDAG-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-SDAG-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: v_s_log_f16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_log_f16_e32 v0.l, s0
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%result = call half @llvm.log2.f16(half %src)
ret half %result
}
@@ -188,13 +203,18 @@ define amdgpu_cs float @v_s_rsq_f32(float inreg %src) {
}
define amdgpu_cs half @v_s_rsq_f16(half inreg %src) {
-; GFX12-LABEL: v_s_rsq_f16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_s_rsq_f16 s0, s0
-; GFX12-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-NEXT: v_mov_b32_e32 v0, s0
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: v_s_rsq_f16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_s_rsq_f16 s0, s0
+; GFX12-SDAG-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-SDAG-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: v_s_rsq_f16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_rsq_f16_e32 v0.l, s0
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%sqrt = call fast half @llvm.sqrt.f16(half %src)
%result = fdiv fast half 1.0, %sqrt
ret half %result
@@ -260,16 +280,17 @@ define amdgpu_cs float @v_s_sqrt_f32(float inreg %src) {
; GFX12-GISEL-NEXT: s_fmac_f32 s6, s7, s2
; GFX12-GISEL-NEXT: s_cselect_b32 s2, s3, s2
; GFX12-GISEL-NEXT: s_cmp_gt_f32 s6, 0
+; GFX12-GISEL-NEXT: v_cmp_class_f32_e64 s3, s0, 0x260
; GFX12-GISEL-NEXT: s_cselect_b32 s2, s5, s2
; GFX12-GISEL-NEXT: s_cmp_lg_u32 s1, 0
-; GFX12-GISEL-NEXT: s_mul_f32 s3, s2, 0x37800000
-; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_3) | instskip(SKIP_4) | instid1(VALU_DEP_1)
-; GFX12-GISEL-NEXT: s_cselect_b32 s1, s3, s2
+; GFX12-GISEL-NEXT: s_mul_f32 s4, s2, 0x37800000
+; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_3)
+; GFX12-GISEL-NEXT: s_cselect_b32 s1, s4, s2
+; GFX12-GISEL-NEXT: s_cmp_lg_u32 s3, 0
; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
-; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s1
-; GFX12-GISEL-NEXT: v_cmp_class_f32_e64 s1, s0, 0x260
-; GFX12-GISEL-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-GISEL-NEXT: v_cndmask_b32_e64 v0, v0, s0, s1
+; GFX12-GISEL-NEXT: s_cselect_b32 s0, s0, s1
+; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
+; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s0
; GFX12-GISEL-NEXT: ; return to shader part epilog
%result = call float @llvm.sqrt.f32(float %src)
ret float %result
@@ -331,17 +352,23 @@ define amdgpu_cs float @srcmods_abs_f32(float inreg %src) {
; GFX12-GISEL-LABEL: srcmods_abs_f32:
; GFX12-GISEL: ; %bb.0:
; GFX12-GISEL-NEXT: s_and_b32 s1, s0, 0x7fffffff
-; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1)
+; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
; GFX12-GISEL-NEXT: s_cmp_lt_f32 s1, 0x800000
+; GFX12-GISEL-NEXT: s_cselect_b32 s2, 1, 0
; GFX12-GISEL-NEXT: s_cselect_b32 s1, 1, 0
-; GFX12-GISEL-NEXT: s_lshl_b32 s2, s1, 5
+; GFX12-GISEL-NEXT: s_lshl_b32 s2, s2, 5
; GFX12-GISEL-NEXT: s_cmp_lg_u32 s1, 0
; GFX12-GISEL-NEXT: v_ldexp_f32 v0, |s0|, s2
-; GFX12-GISEL-NEXT: s_cselect_b32 s0, 0x42000000, 0
-; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(TRANS32_DEP_1)
-; GFX12-GISEL-NEXT: v_log_f32_e32 v0, v0
+; GFX12-GISEL-NEXT: s_cselect_b32 s1, 0x42000000, 0
+; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX12-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-GISEL-NEXT: v_s_log_f32 s0, s0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
+; GFX12-GISEL-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_2)
+; GFX12-GISEL-NEXT: s_sub_f32 s0, s0, s1
; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
-; GFX12-GISEL-NEXT: v_subrev_f32_e32 v0, s0, v0
+; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s0
; GFX12-GISEL-NEXT: ; return to shader part epilog
%abs = call float @llvm.fabs.f32(float %src)
%result = call float @llvm.log2.f32(float %abs)
@@ -367,17 +394,23 @@ define amdgpu_cs float @srcmods_neg_f32(float inreg %src) {
; GFX12-GISEL-LABEL: srcmods_neg_f32:
; GFX12-GISEL: ; %bb.0:
; GFX12-GISEL-NEXT: s_xor_b32 s1, s0, 0x80000000
-; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_1)
+; GFX12-GISEL-NEXT: s_delay_alu instid0(SALU_CYCLE_1)
; GFX12-GISEL-NEXT: s_cmp_lt_f32 s1, 0x800000
+; GFX12-GISEL-NEXT: s_cselect_b32 s2, 1, 0
; GFX12-GISEL-NEXT: s_cselect_b32 s1, 1, 0
-; GFX12-GISEL-NEXT: s_lshl_b32 s2, s1, 5
+; GFX12-GISEL-NEXT: s_lshl_b32 s2, s2, 5
; GFX12-GISEL-NEXT: s_cmp_lg_u32 s1, 0
; GFX12-GISEL-NEXT: v_ldexp_f32 v0, -s0, s2
-; GFX12-GISEL-NEXT: s_cselect_b32 s0, 0x42000000, 0
-; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(TRANS32_DEP_1)
-; GFX12-GISEL-NEXT: v_log_f32_e32 v0, v0
+; GFX12-GISEL-NEXT: s_cselect_b32 s1, 0x42000000, 0
+; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX12-GISEL-NEXT: v_readfirstlane_b32 s0, v0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-GISEL-NEXT: v_s_log_f32 s0, s0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
+; GFX12-GISEL-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_2)
+; GFX12-GISEL-NEXT: s_sub_f32 s0, s0, s1
; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
-; GFX12-GISEL-NEXT: v_subrev_f32_e32 v0, s0, v0
+; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s0
; GFX12-GISEL-NEXT: ; return to shader part epilog
%neg = fneg float %src
%result = call float @llvm.log2.f32(float %neg)
@@ -385,26 +418,36 @@ define amdgpu_cs float @srcmods_neg_f32(float inreg %src) {
}
define amdgpu_cs half @srcmods_abs_f16(half inreg %src) {
-; GFX12-LABEL: srcmods_abs_f16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_s_log_f16 s0, |s0|
-; GFX12-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-NEXT: v_mov_b32_e32 v0, s0
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: srcmods_abs_f16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_s_log_f16 s0, |s0|
+; GFX12-SDAG-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-SDAG-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: srcmods_abs_f16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_log_f16_e64 v0.l, |s0|
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%abs = call half @llvm.fabs.f16(half %src)
%result = call half @llvm.log2.f16(half %abs)
ret half %result
}
define amdgpu_cs half @srcmods_neg_f16(half inreg %src) {
-; GFX12-LABEL: srcmods_neg_f16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_s_log_f16 s0, -s0
-; GFX12-NEXT: s_wait_alu depctr_va_sdst(0)
-; GFX12-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
-; GFX12-NEXT: v_mov_b32_e32 v0, s0
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: srcmods_neg_f16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_s_log_f16 s0, -s0
+; GFX12-SDAG-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-SDAG-NEXT: s_delay_alu instid0(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: srcmods_neg_f16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_log_f16_e64 v0.l, -s0
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%neg = fneg half %src
%result = call half @llvm.log2.f16(half %neg)
ret half %result
@@ -436,13 +479,26 @@ define amdgpu_cs float @fdiv_f32_i32(float inreg %a, i32 inreg %b) {
}
define amdgpu_cs half @fdiv_f16_i16(half inreg %a, i16 inreg %b) {
-; GFX12-LABEL: fdiv_f16_i16:
-; GFX12: ; %bb.0:
-; GFX12-NEXT: v_cvt_f16_u16_e32 v0.l, s1
-; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(TRANS32_DEP_1)
-; GFX12-NEXT: v_rcp_f16_e32 v0.l, v0.l
-; GFX12-NEXT: v_mul_f16_e32 v0.l, s0, v0.l
-; GFX12-NEXT: ; return to shader part epilog
+; GFX12-SDAG-LABEL: fdiv_f16_i16:
+; GFX12-SDAG: ; %bb.0:
+; GFX12-SDAG-NEXT: v_cvt_f16_u16_e32 v0.l, s1
+; GFX12-SDAG-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(TRANS32_DEP_1)
+; GFX12-SDAG-NEXT: v_rcp_f16_e32 v0.l, v0.l
+; GFX12-SDAG-NEXT: v_mul_f16_e32 v0.l, s0, v0.l
+; GFX12-SDAG-NEXT: ; return to shader part epilog
+;
+; GFX12-GISEL-LABEL: fdiv_f16_i16:
+; GFX12-GISEL: ; %bb.0:
+; GFX12-GISEL-NEXT: v_cvt_f16_u16_e32 v0.l, s1
+; GFX12-GISEL-NEXT: s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX12-GISEL-NEXT: v_readfirstlane_b32 s1, v0
+; GFX12-GISEL-NEXT: s_wait_alu depctr_va_sdst(0)
+; GFX12-GISEL-NEXT: v_s_rcp_f16 s1, s1
+; GFX12-GISEL-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_2)
+; GFX12-GISEL-NEXT: s_mul_f16 s0, s0, s1
+; GFX12-GISEL-NEXT: s_wait_alu depctr_sa_sdst(0)
+; GFX12-GISEL-NEXT: v_mov_b32_e32 v0, s0
+; GFX12-GISEL-NEXT: ; return to shader part epilog
%uint = uitofp i16 %b to half
%result = fdiv afn half %a, %uint
ret half %result
``````````
</details>
https://github.com/llvm/llvm-project/pull/195099
More information about the llvm-commits
mailing list