[llvm] [AMDGPU] Calculate div/rem with frcp more efficiently (PR #210684)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 20 04:03:28 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: LU-JOHN

<details>
<summary>Changes</summary>

Integer division q = a/b can be implemented by fp reciprocal with:
fq = fa * recip(fb)
fq is truncated to produce q. Due to fp rounding and reciprocal accuracy issues fq can be too small and truncation can produce a value too small by one.

If abs(a)<=0x400000, this underestimate can be guarded more efficiently by calculating:
fq=fa+1ulp/b
If abs(a)<=0x400000, adding 1 ulp will increase a by at most 0.5, so the calculated q will be the same. Adding 1ulp can be done with one integer add.

This change is analogous to the change done in https://github.com/llvm/llvm-project/pull/204950 but in AMDGPUISelLowering.cpp.

---

Patch is 37.05 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/210684.diff


6 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp (+16-51) 
- (modified) llvm/test/CodeGen/AMDGPU/div-rem-fast-path.ll (+47-98) 
- (modified) llvm/test/CodeGen/AMDGPU/med3-knownbits.ll (+7-13) 
- (modified) llvm/test/CodeGen/AMDGPU/sdiv.ll (+31-54) 
- (modified) llvm/test/CodeGen/AMDGPU/udiv.ll (+23-38) 
- (modified) llvm/test/CodeGen/AMDGPU/udivrem24.ll (+63-91) 


``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 1682739773b82..11407414730b3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -2059,28 +2059,28 @@ SDValue AMDGPUTargetLowering::LowerDIVREMToFloat(SDValue Op, SelectionDAG &DAG,
   ISD::NodeType ToFp = Sign ? ISD::SINT_TO_FP : ISD::UINT_TO_FP;
   ISD::NodeType ToInt = Sign ? ISD::FP_TO_SINT : ISD::FP_TO_UINT;
 
-  SDValue jq = DAG.getConstant(1, DL, IntVT);
-
-  if (Sign) {
-    // char|short jq = ia ^ ib;
-    jq = DAG.getNode(ISD::XOR, DL, VT, LHS, RHS);
-
-    // jq = jq >> (bitsize - 2)
-    jq = DAG.getNode(ISD::SRA, DL, VT, jq,
-                     DAG.getConstant(BitSize - 2, DL, VT));
-
-    // jq = jq | 0x1
-    jq = DAG.getNode(ISD::OR, DL, VT, jq, DAG.getConstant(1, DL, VT));
-  }
-
   // int ia = (int)LHS;
   SDValue ia = LHS;
 
   // int ib, (int)RHS;
   SDValue ib = RHS;
 
-  // float fa = (float)ia;
+  // The calculation:
+  //   fq = fa*recip(fb)
+  // may be too small due to the 1ulp accuracy in the recip
+  // operation and rounding issues.  Since fq is truncated to produce
+  // an integer value it may be too small by one.  This is
+  // dealt with by incrementing fa by 1ulp:
+  //   fq = (fa+1ulp)*recip(fb)
+  // This will increase fa's magnitude by at most 0.5
+  // (i.e. when fabs(fa)==0x400000 the LSB of the mantissa represents 0.5).
+  // Thus, this method is safe since fa must be incremented by at least 1.0
+  // for the quotient to increase by one.
   SDValue fa = DAG.getNode(ToFp, DL, FltVT, ia);
+  SDValue faAsInt = DAG.getNode(ISD::BITCAST, DL, MVT::i32, fa);
+  SDValue faIncremented = DAG.getNode(ISD::ADD, DL, MVT::i32, faAsInt,
+                                      DAG.getConstant(1, DL, MVT::i32));
+  fa = DAG.getNode(ISD::BITCAST, DL, FltVT, faIncremented);
 
   // float fb = (float)ib;
   SDValue fb = DAG.getNode(ToFp, DL, FltVT, ib);
@@ -2091,43 +2091,8 @@ SDValue AMDGPUTargetLowering::LowerDIVREMToFloat(SDValue Op, SelectionDAG &DAG,
   // fq = trunc(fq);
   fq = DAG.getNode(ISD::FTRUNC, DL, FltVT, fq);
 
-  // float fqneg = -fq;
-  SDValue fqneg = DAG.getNode(ISD::FNEG, DL, FltVT, fq);
-
-  MachineFunction &MF = DAG.getMachineFunction();
-
-  bool UseFmadFtz = false;
-  if (Subtarget->isGCN()) {
-    const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
-    UseFmadFtz =
-        MFI->getMode().FP32Denormals != DenormalMode::getPreserveSign();
-  }
-
-  // float fr = mad(fqneg, fb, fa);
-  unsigned OpCode = !Subtarget->hasMadMacF32Insts() ? (unsigned)ISD::FMA
-                    : UseFmadFtz ? (unsigned)AMDGPUISD::FMAD_FTZ
-                                 : (unsigned)ISD::FMAD;
-  SDValue fr = DAG.getNode(OpCode, DL, FltVT, fqneg, fb, fa);
-
   // int iq = (int)fq;
-  SDValue iq = DAG.getNode(ToInt, DL, IntVT, fq);
-
-  // fr = fabs(fr);
-  fr = DAG.getNode(ISD::FABS, DL, FltVT, fr);
-
-  // fb = fabs(fb);
-  fb = DAG.getNode(ISD::FABS, DL, FltVT, fb);
-
-  EVT SetCCVT = getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT);
-
-  // int cv = fr >= fb;
-  SDValue cv = DAG.getSetCC(DL, SetCCVT, fr, fb, ISD::SETOGE);
-
-  // jq = (cv ? jq : 0);
-  jq = DAG.getNode(ISD::SELECT, DL, VT, cv, jq, DAG.getConstant(0, DL, VT));
-
-  // dst = iq + jq;
-  SDValue Div = DAG.getNode(ISD::ADD, DL, VT, iq, jq);
+  SDValue Div = DAG.getNode(ToInt, DL, IntVT, fq);
 
   // Rem needs compensation, it's easier to recompute it
   SDValue Rem = DAG.getNode(ISD::MUL, DL, VT, Div, RHS);
diff --git a/llvm/test/CodeGen/AMDGPU/div-rem-fast-path.ll b/llvm/test/CodeGen/AMDGPU/div-rem-fast-path.ll
index cc75eb64878e8..28ed118b4332f 100644
--- a/llvm/test/CodeGen/AMDGPU/div-rem-fast-path.ll
+++ b/llvm/test/CodeGen/AMDGPU/div-rem-fast-path.ll
@@ -310,25 +310,17 @@ define amdgpu_kernel void @sdiv_i32_i16_fast_path(ptr addrspace(1) %out, i32 %in
 ; GFX950-NEXT:    s_load_dwordx2 s[0:1], s[4:5], 0x24
 ; GFX950-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX950-NEXT:    s_waitcnt lgkmcnt(0)
-; GFX950-NEXT:    s_sext_i32_i16 s2, s2
+; GFX950-NEXT:    s_sext_i32_i16 s4, s2
 ; GFX950-NEXT:    s_mov_b32 s3, 1
-; GFX950-NEXT:    s_or_b32 s6, s2, s3
-; GFX950-NEXT:    v_cvt_f32_i32_e64 v3, s6
-; GFX950-NEXT:    v_rcp_f32_e64 v1, v3
+; GFX950-NEXT:    s_or_b32 s2, s4, s3
+; GFX950-NEXT:    v_cvt_f32_i32_e64 v1, s4
+; GFX950-NEXT:    v_add_u32_e64 v1, v1, s3
 ; GFX950-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX950-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX950-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX950-NEXT:    s_nop 0
+; GFX950-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX950-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX950-NEXT:    v_fma_f32 v2, -v1, v3, v2
-; GFX950-NEXT:    v_cmp_ge_f32_e64 s[4:5], |v2|, |v3|
-; GFX950-NEXT:    s_xor_b32 s2, s2, s6
-; GFX950-NEXT:    s_mov_b32 s6, 30
-; GFX950-NEXT:    s_ashr_i32 s2, s2, s6
-; GFX950-NEXT:    s_or_b32 s2, s2, s3
-; GFX950-NEXT:    s_mov_b32 s3, 0
-; GFX950-NEXT:    s_and_b64 s[4:5], s[4:5], exec
-; GFX950-NEXT:    s_cselect_b32 s2, s2, s3
 ; GFX950-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX950-NEXT:    v_add_u32_e64 v1, v1, s2
 ; GFX950-NEXT:    global_store_dword v0, v1, s[0:1]
 ; GFX950-NEXT:    s_endpgm
 ;
@@ -342,25 +334,16 @@ define amdgpu_kernel void @sdiv_i32_i16_fast_path(ptr addrspace(1) %out, i32 %in
 ; GFX90A-NEXT:    s_load_dwordx2 s[0:1], s[4:5], 0x24
 ; GFX90A-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX90A-NEXT:    s_waitcnt lgkmcnt(0)
-; GFX90A-NEXT:    s_sext_i32_i16 s2, s2
+; GFX90A-NEXT:    s_sext_i32_i16 s4, s2
 ; GFX90A-NEXT:    s_mov_b32 s3, 1
-; GFX90A-NEXT:    s_or_b32 s6, s2, s3
-; GFX90A-NEXT:    v_cvt_f32_i32_e64 v3, s6
-; GFX90A-NEXT:    v_rcp_f32_e64 v1, v3
+; GFX90A-NEXT:    s_or_b32 s2, s4, s3
+; GFX90A-NEXT:    v_cvt_f32_i32_e64 v1, s4
+; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s3
 ; GFX90A-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX90A-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX90A-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX90A-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX90A-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX90A-NEXT:    v_mad_f32 v2, -v1, v3, v2
-; GFX90A-NEXT:    v_cmp_ge_f32_e64 s[4:5], |v2|, |v3|
-; GFX90A-NEXT:    s_xor_b32 s2, s2, s6
-; GFX90A-NEXT:    s_mov_b32 s6, 30
-; GFX90A-NEXT:    s_ashr_i32 s2, s2, s6
-; GFX90A-NEXT:    s_or_b32 s2, s2, s3
-; GFX90A-NEXT:    s_mov_b32 s3, 0
-; GFX90A-NEXT:    s_and_b64 s[4:5], s[4:5], exec
-; GFX90A-NEXT:    s_cselect_b32 s2, s2, s3
 ; GFX90A-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s2
 ; GFX90A-NEXT:    global_store_dword v0, v1, s[0:1]
 ; GFX90A-NEXT:    s_endpgm
   %trunc_i16 = trunc i32 %input to i16
@@ -381,31 +364,23 @@ define amdgpu_kernel void @sdiv_i32_i16_i16_fast_path(ptr addrspace(1) %out, i16
 ; GFX950-NEXT:    s_load_dword s0, s[4:5], 0x2c
 ; GFX950-NEXT:    s_waitcnt lgkmcnt(0)
 ; GFX950-NEXT:    s_load_dwordx2 s[0:1], s[4:5], 0x24
-; GFX950-NEXT:    s_load_dword s3, s[4:5], 0x2c
+; GFX950-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX950-NEXT:    s_waitcnt lgkmcnt(0)
-; GFX950-NEXT:    s_mov_b32 s2, s3
+; GFX950-NEXT:    s_mov_b32 s3, s2
 ; GFX950-NEXT:    s_mov_b32 s4, 16
-; GFX950-NEXT:    s_lshr_b32 s3, s3, s4
-; GFX950-NEXT:    s_sext_i32_i16 s2, s2
+; GFX950-NEXT:    s_lshr_b32 s2, s2, s4
 ; GFX950-NEXT:    s_sext_i32_i16 s3, s3
-; GFX950-NEXT:    v_cvt_f32_i32_e64 v3, s3
+; GFX950-NEXT:    s_sext_i32_i16 s2, s2
 ; GFX950-NEXT:    s_waitcnt vmcnt(0)
-; GFX950-NEXT:    v_rcp_f32_e64 v1, v3
+; GFX950-NEXT:    v_cvt_f32_i32_e64 v1, s3
+; GFX950-NEXT:    s_mov_b32 s3, 1
+; GFX950-NEXT:    v_add_u32_e64 v1, v1, s3
 ; GFX950-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX950-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX950-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX950-NEXT:    s_nop 0
+; GFX950-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX950-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX950-NEXT:    v_fma_f32 v2, -v1, v3, v2
-; GFX950-NEXT:    v_cmp_ge_f32_e64 s[4:5], |v2|, |v3|
-; GFX950-NEXT:    s_xor_b32 s2, s2, s3
-; GFX950-NEXT:    s_mov_b32 s3, 30
-; GFX950-NEXT:    s_ashr_i32 s2, s2, s3
-; GFX950-NEXT:    s_mov_b32 s3, 1
-; GFX950-NEXT:    s_or_b32 s2, s2, s3
-; GFX950-NEXT:    s_mov_b32 s3, 0
-; GFX950-NEXT:    s_and_b64 s[4:5], s[4:5], exec
-; GFX950-NEXT:    s_cselect_b32 s2, s2, s3
 ; GFX950-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX950-NEXT:    v_add_u32_e64 v1, v1, s2
 ; GFX950-NEXT:    global_store_dword v0, v1, s[0:1]
 ; GFX950-NEXT:    s_endpgm
 ;
@@ -418,31 +393,22 @@ define amdgpu_kernel void @sdiv_i32_i16_i16_fast_path(ptr addrspace(1) %out, i16
 ; GFX90A-NEXT:    s_load_dword s0, s[4:5], 0x2c
 ; GFX90A-NEXT:    s_waitcnt lgkmcnt(0)
 ; GFX90A-NEXT:    s_load_dwordx2 s[0:1], s[4:5], 0x24
-; GFX90A-NEXT:    s_load_dword s3, s[4:5], 0x2c
+; GFX90A-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX90A-NEXT:    s_waitcnt lgkmcnt(0)
-; GFX90A-NEXT:    s_mov_b32 s2, s3
+; GFX90A-NEXT:    s_mov_b32 s3, s2
 ; GFX90A-NEXT:    s_mov_b32 s4, 16
-; GFX90A-NEXT:    s_lshr_b32 s3, s3, s4
-; GFX90A-NEXT:    s_sext_i32_i16 s2, s2
+; GFX90A-NEXT:    s_lshr_b32 s2, s2, s4
 ; GFX90A-NEXT:    s_sext_i32_i16 s3, s3
-; GFX90A-NEXT:    v_cvt_f32_i32_e64 v3, s3
+; GFX90A-NEXT:    s_sext_i32_i16 s2, s2
 ; GFX90A-NEXT:    s_waitcnt vmcnt(0)
-; GFX90A-NEXT:    v_rcp_f32_e64 v1, v3
+; GFX90A-NEXT:    v_cvt_f32_i32_e64 v1, s3
+; GFX90A-NEXT:    s_mov_b32 s3, 1
+; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s3
 ; GFX90A-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX90A-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX90A-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX90A-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX90A-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX90A-NEXT:    v_mad_f32 v2, -v1, v3, v2
-; GFX90A-NEXT:    v_cmp_ge_f32_e64 s[4:5], |v2|, |v3|
-; GFX90A-NEXT:    s_xor_b32 s2, s2, s3
-; GFX90A-NEXT:    s_mov_b32 s3, 30
-; GFX90A-NEXT:    s_ashr_i32 s2, s2, s3
-; GFX90A-NEXT:    s_mov_b32 s3, 1
-; GFX90A-NEXT:    s_or_b32 s2, s2, s3
-; GFX90A-NEXT:    s_mov_b32 s3, 0
-; GFX90A-NEXT:    s_and_b64 s[4:5], s[4:5], exec
-; GFX90A-NEXT:    s_cselect_b32 s2, s2, s3
 ; GFX90A-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s2
 ; GFX90A-NEXT:    global_store_dword v0, v1, s[0:1]
 ; GFX90A-NEXT:    s_endpgm
   %dividend32 = sext i16 %dividend16 to i32
@@ -637,24 +603,16 @@ define amdgpu_kernel void @srem_i32_i16_fast_path(ptr addrspace(1) %out, i32 %in
 ; GFX950-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX950-NEXT:    s_waitcnt lgkmcnt(0)
 ; GFX950-NEXT:    s_sext_i32_i16 s2, s2
-; GFX950-NEXT:    s_mov_b32 s5, 1
-; GFX950-NEXT:    s_or_b32 s3, s2, s5
-; GFX950-NEXT:    v_cvt_f32_i32_e64 v3, s3
-; GFX950-NEXT:    v_rcp_f32_e64 v1, v3
-; GFX950-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX950-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX950-NEXT:    s_mov_b32 s4, 1
+; GFX950-NEXT:    s_or_b32 s3, s2, s4
+; GFX950-NEXT:    v_cvt_f32_i32_e64 v1, s2
+; GFX950-NEXT:    v_add_u32_e64 v1, v1, s4
+; GFX950-NEXT:    v_cvt_f32_i32_e64 v2, s3
+; GFX950-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX950-NEXT:    s_nop 0
+; GFX950-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX950-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX950-NEXT:    v_fma_f32 v2, -v1, v3, v2
-; GFX950-NEXT:    v_cmp_ge_f32_e64 s[6:7], |v2|, |v3|
-; GFX950-NEXT:    s_xor_b32 s4, s2, s3
-; GFX950-NEXT:    s_mov_b32 s8, 30
-; GFX950-NEXT:    s_ashr_i32 s4, s4, s8
-; GFX950-NEXT:    s_or_b32 s4, s4, s5
-; GFX950-NEXT:    s_mov_b32 s5, 0
-; GFX950-NEXT:    s_and_b64 s[6:7], s[6:7], exec
-; GFX950-NEXT:    s_cselect_b32 s4, s4, s5
 ; GFX950-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX950-NEXT:    v_add_u32_e64 v1, v1, s4
 ; GFX950-NEXT:    v_mul_lo_u32 v1, v1, s3
 ; GFX950-NEXT:    v_sub_u32_e64 v1, s2, v1
 ; GFX950-NEXT:    global_store_dword v0, v1, s[0:1]
@@ -671,24 +629,15 @@ define amdgpu_kernel void @srem_i32_i16_fast_path(ptr addrspace(1) %out, i32 %in
 ; GFX90A-NEXT:    s_load_dword s2, s[4:5], 0x2c
 ; GFX90A-NEXT:    s_waitcnt lgkmcnt(0)
 ; GFX90A-NEXT:    s_sext_i32_i16 s2, s2
-; GFX90A-NEXT:    s_mov_b32 s5, 1
-; GFX90A-NEXT:    s_or_b32 s3, s2, s5
-; GFX90A-NEXT:    v_cvt_f32_i32_e64 v3, s3
-; GFX90A-NEXT:    v_rcp_f32_e64 v1, v3
-; GFX90A-NEXT:    v_cvt_f32_i32_e64 v2, s2
-; GFX90A-NEXT:    v_mul_f32_e64 v1, v2, v1
+; GFX90A-NEXT:    s_mov_b32 s4, 1
+; GFX90A-NEXT:    s_or_b32 s3, s2, s4
+; GFX90A-NEXT:    v_cvt_f32_i32_e64 v1, s2
+; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s4
+; GFX90A-NEXT:    v_cvt_f32_i32_e64 v2, s3
+; GFX90A-NEXT:    v_rcp_f32_e64 v2, v2
+; GFX90A-NEXT:    v_mul_f32_e64 v1, v1, v2
 ; GFX90A-NEXT:    v_trunc_f32_e64 v1, v1
-; GFX90A-NEXT:    v_mad_f32 v2, -v1, v3, v2
-; GFX90A-NEXT:    v_cmp_ge_f32_e64 s[6:7], |v2|, |v3|
-; GFX90A-NEXT:    s_xor_b32 s4, s2, s3
-; GFX90A-NEXT:    s_mov_b32 s8, 30
-; GFX90A-NEXT:    s_ashr_i32 s4, s4, s8
-; GFX90A-NEXT:    s_or_b32 s4, s4, s5
-; GFX90A-NEXT:    s_mov_b32 s5, 0
-; GFX90A-NEXT:    s_and_b64 s[6:7], s[6:7], exec
-; GFX90A-NEXT:    s_cselect_b32 s4, s4, s5
 ; GFX90A-NEXT:    v_cvt_i32_f32_e64 v1, v1
-; GFX90A-NEXT:    v_add_u32_e64 v1, v1, s4
 ; GFX90A-NEXT:    v_mul_lo_u32 v1, v1, s3
 ; GFX90A-NEXT:    v_sub_u32_e64 v1, s2, v1
 ; GFX90A-NEXT:    global_store_dword v0, v1, s[0:1]
diff --git a/llvm/test/CodeGen/AMDGPU/med3-knownbits.ll b/llvm/test/CodeGen/AMDGPU/med3-knownbits.ll
index e799974bd5670..91303680ac49a 100644
--- a/llvm/test/CodeGen/AMDGPU/med3-knownbits.ll
+++ b/llvm/test/CodeGen/AMDGPU/med3-knownbits.ll
@@ -43,22 +43,16 @@ define i32 @v_known_signbits_smed3(i16 %a, i16 %b) {
 ; SI-SDAG-NEXT:    s_movk_i32 s4, 0xffc0
 ; SI-SDAG-NEXT:    v_mov_b32_e32 v2, 0x80
 ; SI-SDAG-NEXT:    v_med3_i32 v1, v1, s4, v2
-; SI-SDAG-NEXT:    v_cvt_f32_i32_e32 v2, v1
+; SI-SDAG-NEXT:    v_cvt_f32_i32_e32 v1, v1
 ; SI-SDAG-NEXT:    v_bfe_i32 v0, v0, 0, 16
 ; SI-SDAG-NEXT:    s_movk_i32 s4, 0xffe0
 ; SI-SDAG-NEXT:    v_med3_i32 v0, v0, s4, 64
-; SI-SDAG-NEXT:    v_cvt_f32_i32_e32 v3, v0
-; SI-SDAG-NEXT:    v_rcp_f32_e32 v4, v2
-; SI-SDAG-NEXT:    v_xor_b32_e32 v0, v0, v1
-; SI-SDAG-NEXT:    v_ashrrev_i32_e32 v0, 30, v0
-; SI-SDAG-NEXT:    v_or_b32_e32 v0, 1, v0
-; SI-SDAG-NEXT:    v_mul_f32_e32 v1, v3, v4
-; SI-SDAG-NEXT:    v_trunc_f32_e32 v1, v1
-; SI-SDAG-NEXT:    v_mad_f32 v3, -v1, v2, v3
-; SI-SDAG-NEXT:    v_cvt_i32_f32_e32 v1, v1
-; SI-SDAG-NEXT:    v_cmp_ge_f32_e64 vcc, |v3|, |v2|
-; SI-SDAG-NEXT:    v_cndmask_b32_e32 v0, 0, v0, vcc
-; SI-SDAG-NEXT:    v_add_i32_e32 v0, vcc, v1, v0
+; SI-SDAG-NEXT:    v_cvt_f32_i32_e32 v0, v0
+; SI-SDAG-NEXT:    v_rcp_f32_e32 v1, v1
+; SI-SDAG-NEXT:    v_add_i32_e32 v0, vcc, 1, v0
+; SI-SDAG-NEXT:    v_mul_f32_e32 v0, v0, v1
+; SI-SDAG-NEXT:    v_trunc_f32_e32 v0, v0
+; SI-SDAG-NEXT:    v_cvt_i32_f32_e32 v0, v0
 ; SI-SDAG-NEXT:    s_setpc_b64 s[30:31]
 ;
 ; SI-GISEL-LABEL: v_known_signbits_smed3:
diff --git a/llvm/test/CodeGen/AMDGPU/sdiv.ll b/llvm/test/CodeGen/AMDGPU/sdiv.ll
index 6eed45c29daf7..ff0fc8972fbb3 100644
--- a/llvm/test/CodeGen/AMDGPU/sdiv.ll
+++ b/llvm/test/CodeGen/AMDGPU/sdiv.ll
@@ -253,30 +253,22 @@ define amdgpu_kernel void @s_test_sdiv22_32(ptr addrspace(1) %out, i32 %x, i32 %
 ;
 ; EG-LABEL: s_test_sdiv22_32:
 ; EG:       ; %bb.0:
-; EG-NEXT:    ALU 20, @4, KC0[CB0:0-32], KC1[]
+; EG-NEXT:    ALU 12, @4, KC0[CB0:0-32], KC1[]
 ; EG-NEXT:    MEM_RAT_CACHELESS STORE_RAW T0.X, T1.X, 1
 ; EG-NEXT:    CF_END
 ; EG-NEXT:    PAD
 ; EG-NEXT:    ALU clause starting at 4:
-; EG-NEXT:     ASHR * T0.W, KC0[2].W, literal.x,
+; EG-NEXT:     ASHR T0.W, KC0[2].W, literal.x,
+; EG-NEXT:     ASHR * T1.W, KC0[2].Z, literal.x,
 ; EG-NEXT:    10(1.401298e-44), 0(0.000000e+00)
 ; EG-NEXT:     INT_TO_FLT * T0.X, PV.W,
-; EG-NEXT:     ASHR T1.W, KC0[2].Z, literal.x,
-; EG-NEXT:     RECIP_IEEE * T0.Y, PS,
-; EG-NEXT:    10(1.401298e-44), 0(0.000000e+00)
-; EG-NEXT:     INT_TO_FLT * T0.Z, PV.W,
-; EG-NEXT:     MUL_IEEE * T2.W, PS, T0.Y,
-; EG-NEXT:     TRUNC T2.W, PV.W,
-; EG-NEXT:     XOR_INT * T0.W, T1.W, T0.W,
-; EG-NEXT:     ASHR T0.W, PS, literal.x,
-; EG-NEXT:     MULADD_IEEE * T1.W, -PV.W, T0.X, T0.Z,
-; EG-NEXT:    30(4.203895e-44), 0(0.000000e+00)
-; EG-NEXT:     TRUNC T0.Z, T2.W,
-; EG-NEXT:     SETGE T1.W, |PS|, |T0.X|,
-; EG-NEXT:     OR_INT * T0.W, PV.W, 1,
-; EG-NEXT:     CNDE T0.W, PV.W, 0.0, PS,
-; EG-NEXT:     FLT_TO_INT * T1.W, PV.Z,
-; EG-NEXT:     ADD_INT T0.X, PS, PV.W,
+; EG-NEXT:     INT_TO_FLT * T0.Y, T1.W,
+; EG-NEXT:     ADD_INT T0.W, PS, 1,
+; EG-NEXT:     RECIP_IEEE * T0.X, T0.X,
+; EG-NEXT:     MUL_IEEE * T0.W, PV.W, PS,
+; EG-NEXT:     TRUNC * T0.W, PV.W,
+; EG-NEXT:     TRUNC * T0.W, PV.W,
+; EG-NEXT:     FLT_TO_INT T0.X, PV.W,
 ; EG-NEXT:     LSHR * T1.X, KC0[2].Y, literal.x,
 ; EG-NEXT:    2(2.802597e-45), 0(0.000000e+00)
   %1 = ashr i32 %x, 10
@@ -1622,7 +1614,7 @@ define amdgpu_kernel void @v_sdiv_i8(ptr addrspace(1) %out, ptr addrspace(1) %in
 ; EG:       ; %bb.0:
 ; EG-NEXT:    ALU 0, @10, KC0[CB0:0-32], KC1[]
 ; EG-NEXT:    TEX 1 @6
-; EG-NEXT:    ALU 21, @11, KC0[CB0:0-32], KC1[]
+; EG-NEXT:    ALU 14, @11, KC0[CB0:0-32], KC1[]
 ; EG-NEXT:    MEM_RAT_CACHELESS STORE_RAW T0.X, T1.X, 1
 ; EG-NEXT:    CF_END
 ; EG-NEXT:    PAD
@@ -1634,23 +1626,16 @@ define amdgpu_kernel void @v_sdiv_i8(ptr addrspace(1) %out, ptr addrspace(1) %in
 ; EG-NEXT:    ALU clause starting at 11:
 ; EG-NEXT:     BFE_INT * T0.W, T1.X, 0.0, literal.x,
 ; EG-NEXT:    8(1.121039e-44), 0(0.000000e+00)
-; EG-NEXT:     INT_TO_FLT * T0.Y, PV.W,
 ; EG-NEXT:     BFE_INT T1.W, T0.X, 0.0, literal.x,
-; EG-NEXT:     RECIP_IEEE * T0.X, PS,
+; EG-NEXT:     INT_TO_FLT * T0.X, PV.W,
 ; EG-NEXT:    8(1.121039e-44), 0(0.000000e+00)
-; EG-NEXT:     INT_TO_FLT * T0.Z, PV.W,
-; EG-NEXT:     MUL_IEEE * T2.W, PS, T0.X,
-; EG-NEXT:     TRUNC T2.W, PV.W,
-; EG-NEXT:     XOR_INT * T0.W, T1.W, T0.W,
-; EG-NEXT:     ASHR T0.W, PS, literal.x,
-; EG-NEXT:     MULADD_IEEE * T1.W, -PV.W, T0.Y, T0.Z,
-; EG-NEXT:    30(4.203895e-44), 0(0.000000e+00)
-; EG-NEXT:     TRUNC T0.Z, T2.W,
-; EG-NEXT:     SETGE T1.W, |PS|, |T0.Y|,
-; EG-NEXT:     OR_INT * T0.W, PV.W, 1,
-; EG-NEXT:     CNDE T0.W, PV.W, 0.0, PS,
-; EG-NEXT:     FLT_TO_INT * T1.W, PV.Z,
-; EG-NEXT:     ADD_INT * T0.W, PS, PV.W,
+; EG-NEXT:     INT_TO_FLT * T0.Y, PV.W,
+; EG-NEXT:     ADD_INT T0.W, PS, 1,
+; EG-NEXT:     RECIP_IEEE * T0.X, T0.X,
+; EG-NEXT:     MUL_IEEE * T0.W, PV.W, PS,
+; EG-NEXT:     TRUNC * T0.W, PV.W,
+; EG-NEXT:     TRUNC * T0.W, PV.W,
+; EG-NEXT:     FLT_TO_INT * T0.W, PV.W,
 ; EG-NEXT:     BFE_INT T0.X, PV.W, 0.0, literal.x,
 ; EG-NEXT:     LSHR * T1.X, KC0[2].Y, literal.y,
 ; EG-NEXT:    8(1.121039e-44), 2(2.802597e-45)
@@ -1779,7 +1764,7 @@ define amdgpu_kernel void @v_sdiv_i23(ptr addrspace(1) %out, ptr addrspace(1) %i
 ; EG:       ; %bb.0:
 ; EG-NEXT:    ALU 0, @14, KC0[CB0:0-32], KC1[]
 ; EG-NEXT:    TEX 3 @6
-; EG-NEXT:    ALU 33, @15, KC0[CB0:0-32], KC1[]
+; EG-NEXT:    ALU 25, @15, KC0[CB0:0-32], KC1[]
 ; EG-NEXT:    MEM_RAT_CACHELESS STORE_RAW T0.X, T1.X, 1
 ; EG-NEXT:    CF_END
 ; EG-NEXT:    PAD
@@ -1796,30 +1781,22 @@ define amdgpu_kernel void @v_sdiv_i23(ptr addrspace(1) %out, ptr addrspace(1) %i
 ; EG-NEXT:     OR_INT T0.W, T0.X, PV.W,
 ; EG-NEXT:     LSHL * T1.W, T3.X, literal.x,
 ; EG-NEXT:    16(2.242078e-44), 0(0.000000e+00)
+; EG-NEXT:     OR_INT T1.W, T2.X, PS,
 ; EG-NEXT:     LSHL * T0.W, PV.W, literal.x,
 ; EG-NEXT:    9(1.261169e-44), 0(0.000000e+00)
-; EG-NEXT:     ASHR T0.W, PV.W, literal.x,
-; EG-NEXT:     OR_INT * T1.W, T2.X, T1.W,
+; EG-NEXT:     ASHR T0.W, PS, literal.x,
+; EG-NEXT:     LSHL * T1.W, PV.W, literal.x,
 ; EG-NEXT:    9(1.261169e-44), 0(0.000000e+00)
-; EG-NEXT:     LSHL T1.W, PS, literal.x,
+; EG-NEXT:     ASHR T1.W, PS, literal.x,
 ; EG-NEXT:     INT_TO_FLT * T0.X, PV.W,
 ; EG-NEXT:    9(1.261169e-44), 0(0.000000e+00)
-; EG-NEXT:     ASHR T1.W, PV.W, literal.x,
-; EG-NEXT:     RECIP_IEEE * T0.Y, PS,
-; EG-NEXT:    9(1.261169e-44), 0(0.000000e+00)
-; EG-NEXT:     INT_TO_FLT * T0.Z, PV.W,
-; EG-NEXT:     MUL_IEEE * T2.W, PS, T0.Y,
-; EG-NEXT:     TRUNC T2.W, PV.W,
-; EG-NEXT:     XOR_INT * T0.W, T1.W, T0.W,
-; EG-NEXT:     ASHR T0.W, PS, literal.x,
-; EG-NEXT:     MULADD_IEEE * T1.W, -PV.W, T0.X, T0.Z,
-; EG-NEXT:    30(4.203895e-44), 0(0.000000e+00)
-; EG-NEXT:     TRUNC T0.Z, T2.W,
-; EG-NEXT:     SETGE T1.W, |PS|, |T0.X|,
-; EG-NEXT:     OR_INT * T0.W, PV.W, 1,
-; EG-NEXT:     CNDE T0.W, PV.W, 0.0, PS,
-; EG-NEXT:     FLT_TO_INT * T1.W, PV.Z,
-; EG-NEXT:     ADD_INT * T0.W, PS, PV.W,
+; EG-NEXT:     INT_TO_FLT * T0.Y, PV.W,
+; EG-NEXT:     ADD_INT T0.W, PS, 1,
+; EG-NEXT:     RECIP_IEEE * T0.X, T0.X,
+; EG-NEXT:     MUL_IEEE * T0.W, PV.W, PS,
+; EG-NEXT:     TRUNC * T0.W, PV.W,
+; EG-NEXT: ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/210684


More information about the llvm-commits mailing list