[llvm] AMDGPU: Teach lowering that sqrt never returns subnormal (PR #174838)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 7 11:07:40 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-amdgpu

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>



---
Full diff: https://github.com/llvm/llvm-project/pull/174838.diff


1 Files Affected:

- (modified) llvm/test/CodeGen/AMDGPU/fsqrt.f32.ll (+230) 


``````````diff
diff --git a/llvm/test/CodeGen/AMDGPU/fsqrt.f32.ll b/llvm/test/CodeGen/AMDGPU/fsqrt.f32.ll
index ae499a9db98e4..68baf186fe2c2 100644
--- a/llvm/test/CodeGen/AMDGPU/fsqrt.f32.ll
+++ b/llvm/test/CodeGen/AMDGPU/fsqrt.f32.ll
@@ -4852,6 +4852,236 @@ define float @v_sqrt_f32__amdgcn_log_known_not_denorm(float %x) {
   ret float %result
 }
 
+define float @v_sqrt_f32__sqrt_known_not_denorm(float %x) {
+; SDAG-IEEE-LABEL: v_sqrt_f32__sqrt_known_not_denorm:
+; SDAG-IEEE:       ; %bb.0:
+; SDAG-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SDAG-IEEE-NEXT:    s_mov_b32 s6, 0xf800000
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v1, 0x4f800000, v0
+; SDAG-IEEE-NEXT:    v_cmp_gt_f32_e32 vcc, s6, v0
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v0, v0, v1, vcc
+; SDAG-IEEE-NEXT:    v_sqrt_f32_e32 v1, v0
+; SDAG-IEEE-NEXT:    v_add_i32_e64 v2, s[4:5], -1, v1
+; SDAG-IEEE-NEXT:    v_fma_f32 v3, -v2, v1, v0
+; SDAG-IEEE-NEXT:    v_cmp_ge_f32_e64 s[4:5], 0, v3
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e64 v2, v1, v2, s[4:5]
+; SDAG-IEEE-NEXT:    v_add_i32_e64 v3, s[4:5], 1, v1
+; SDAG-IEEE-NEXT:    v_fma_f32 v1, -v3, v1, v0
+; SDAG-IEEE-NEXT:    v_cmp_lt_f32_e64 s[4:5], 0, v1
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e64 v1, v2, v3, s[4:5]
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v2, 0x37800000, v1
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v1, v1, v2, vcc
+; SDAG-IEEE-NEXT:    v_mov_b32_e32 v2, 0x260
+; SDAG-IEEE-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v1, 0x4f800000, v0
+; SDAG-IEEE-NEXT:    v_cmp_gt_f32_e32 vcc, s6, v0
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v0, v0, v1, vcc
+; SDAG-IEEE-NEXT:    v_rsq_f32_e32 v1, v0
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v3, v0, v1
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; SDAG-IEEE-NEXT:    v_fma_f32 v4, -v1, v3, 0.5
+; SDAG-IEEE-NEXT:    v_fma_f32 v3, v3, v4, v3
+; SDAG-IEEE-NEXT:    v_fma_f32 v5, -v3, v3, v0
+; SDAG-IEEE-NEXT:    v_fma_f32 v1, v1, v4, v1
+; SDAG-IEEE-NEXT:    v_fma_f32 v1, v5, v1, v3
+; SDAG-IEEE-NEXT:    v_mul_f32_e32 v3, 0x37800000, v1
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v1, v1, v3, vcc
+; SDAG-IEEE-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; SDAG-IEEE-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; SDAG-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-IEEE-LABEL: v_sqrt_f32__sqrt_known_not_denorm:
+; GISEL-IEEE:       ; %bb.0:
+; GISEL-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-IEEE-NEXT:    v_mov_b32_e32 v1, 0xf800000
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-IEEE-NEXT:    v_sqrt_f32_e32 v2, v0
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v3, s[4:5], -1, v2
+; GISEL-IEEE-NEXT:    v_fma_f32 v4, -v3, v2, v0
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v5, s[4:5], 1, v2
+; GISEL-IEEE-NEXT:    v_fma_f32 v6, -v5, v2, v0
+; GISEL-IEEE-NEXT:    v_cmp_ge_f32_e64 s[4:5], 0, v4
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v2, v2, v3, s[4:5]
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e64 s[4:5], 0, v6
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v2, v2, v5, s[4:5]
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v3, 0x37800000, v2
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v2, v2, v3, vcc
+; GISEL-IEEE-NEXT:    v_mov_b32_e32 v3, 0x260
+; GISEL-IEEE-NEXT:    v_cmp_class_f32_e32 vcc, v0, v3
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v2, v0, vcc
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-IEEE-NEXT:    v_sqrt_f32_e32 v1, v0
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v2, s[4:5], -1, v1
+; GISEL-IEEE-NEXT:    v_fma_f32 v4, -v2, v1, v0
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v5, s[4:5], 1, v1
+; GISEL-IEEE-NEXT:    v_fma_f32 v6, -v5, v1, v0
+; GISEL-IEEE-NEXT:    v_cmp_ge_f32_e64 s[4:5], 0, v4
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v1, v1, v2, s[4:5]
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e64 s[4:5], 0, v6
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v1, v1, v5, s[4:5]
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v2, 0x37800000, v1
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v1, v1, v2, vcc
+; GISEL-IEEE-NEXT:    v_cmp_class_f32_e32 vcc, v0, v3
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; GISEL-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; SDAG-DAZ-LABEL: v_sqrt_f32__sqrt_known_not_denorm:
+; SDAG-DAZ:       ; %bb.0:
+; SDAG-DAZ-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SDAG-DAZ-NEXT:    s_mov_b32 s4, 0xf800000
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v1, 0x4f800000, v0
+; SDAG-DAZ-NEXT:    v_cmp_gt_f32_e32 vcc, s4, v0
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v0, v0, v1, vcc
+; SDAG-DAZ-NEXT:    v_rsq_f32_e32 v1, v0
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v2, v0, v1
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; SDAG-DAZ-NEXT:    v_fma_f32 v3, -v1, v2, 0.5
+; SDAG-DAZ-NEXT:    v_fma_f32 v2, v2, v3, v2
+; SDAG-DAZ-NEXT:    v_fma_f32 v4, -v2, v2, v0
+; SDAG-DAZ-NEXT:    v_fma_f32 v1, v1, v3, v1
+; SDAG-DAZ-NEXT:    v_fma_f32 v1, v4, v1, v2
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v2, 0x37800000, v1
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v1, v1, v2, vcc
+; SDAG-DAZ-NEXT:    v_mov_b32_e32 v2, 0x260
+; SDAG-DAZ-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v1, 0x4f800000, v0
+; SDAG-DAZ-NEXT:    v_cmp_gt_f32_e32 vcc, s4, v0
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v0, v0, v1, vcc
+; SDAG-DAZ-NEXT:    v_rsq_f32_e32 v1, v0
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v3, v0, v1
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; SDAG-DAZ-NEXT:    v_fma_f32 v4, -v1, v3, 0.5
+; SDAG-DAZ-NEXT:    v_fma_f32 v3, v3, v4, v3
+; SDAG-DAZ-NEXT:    v_fma_f32 v5, -v3, v3, v0
+; SDAG-DAZ-NEXT:    v_fma_f32 v1, v1, v4, v1
+; SDAG-DAZ-NEXT:    v_fma_f32 v1, v5, v1, v3
+; SDAG-DAZ-NEXT:    v_mul_f32_e32 v3, 0x37800000, v1
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v1, v1, v3, vcc
+; SDAG-DAZ-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; SDAG-DAZ-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; SDAG-DAZ-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-DAZ-LABEL: v_sqrt_f32__sqrt_known_not_denorm:
+; GISEL-DAZ:       ; %bb.0:
+; GISEL-DAZ-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-DAZ-NEXT:    v_mov_b32_e32 v1, 0xf800000
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-DAZ-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-DAZ-NEXT:    v_rsq_f32_e32 v2, v0
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v3, v0, v2
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, 0.5, v2
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v2, v3, 0.5
+; GISEL-DAZ-NEXT:    v_fma_f32 v3, v3, v4, v3
+; GISEL-DAZ-NEXT:    v_fma_f32 v2, v2, v4, v2
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v3, v3, v0
+; GISEL-DAZ-NEXT:    v_fma_f32 v2, v4, v2, v3
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v3, 0x37800000, v2
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v2, v2, v3, vcc
+; GISEL-DAZ-NEXT:    v_mov_b32_e32 v3, 0x260
+; GISEL-DAZ-NEXT:    v_cmp_class_f32_e32 vcc, v0, v3
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v2, v0, vcc
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-DAZ-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-DAZ-NEXT:    v_rsq_f32_e32 v1, v0
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, v0, v1
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v1, v2, 0.5
+; GISEL-DAZ-NEXT:    v_fma_f32 v2, v2, v4, v2
+; GISEL-DAZ-NEXT:    v_fma_f32 v1, v1, v4, v1
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v2, v2, v0
+; GISEL-DAZ-NEXT:    v_fma_f32 v1, v4, v1, v2
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, 0x37800000, v1
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v1, v1, v2, vcc
+; GISEL-DAZ-NEXT:    v_cmp_class_f32_e32 vcc, v0, v3
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; GISEL-DAZ-NEXT:    s_setpc_b64 s[30:31]
+  %sqrt0 = call float @llvm.sqrt.f32(float %x)
+  %result = call float @llvm.sqrt.f32(float %sqrt0)
+  ret float %result
+}
+
+define float @v_sqrt_f32__amdgcn_sqrt_known_not_denorm(float %x) {
+; SDAG-LABEL: v_sqrt_f32__amdgcn_sqrt_known_not_denorm:
+; SDAG:       ; %bb.0:
+; SDAG-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SDAG-NEXT:    v_sqrt_f32_e32 v0, v0
+; SDAG-NEXT:    s_mov_b32 s4, 0xf800000
+; SDAG-NEXT:    v_mov_b32_e32 v2, 0x260
+; SDAG-NEXT:    v_mul_f32_e32 v1, 0x4f800000, v0
+; SDAG-NEXT:    v_cmp_gt_f32_e32 vcc, s4, v0
+; SDAG-NEXT:    v_cndmask_b32_e32 v0, v0, v1, vcc
+; SDAG-NEXT:    v_rsq_f32_e32 v1, v0
+; SDAG-NEXT:    v_mul_f32_e32 v3, v0, v1
+; SDAG-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; SDAG-NEXT:    v_fma_f32 v4, -v1, v3, 0.5
+; SDAG-NEXT:    v_fma_f32 v3, v3, v4, v3
+; SDAG-NEXT:    v_fma_f32 v1, v1, v4, v1
+; SDAG-NEXT:    v_fma_f32 v4, -v3, v3, v0
+; SDAG-NEXT:    v_fma_f32 v1, v4, v1, v3
+; SDAG-NEXT:    v_mul_f32_e32 v3, 0x37800000, v1
+; SDAG-NEXT:    v_cndmask_b32_e32 v1, v1, v3, vcc
+; SDAG-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; SDAG-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; SDAG-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-IEEE-LABEL: v_sqrt_f32__amdgcn_sqrt_known_not_denorm:
+; GISEL-IEEE:       ; %bb.0:
+; GISEL-IEEE-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-IEEE-NEXT:    v_sqrt_f32_e32 v0, v0
+; GISEL-IEEE-NEXT:    v_mov_b32_e32 v1, 0xf800000
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-IEEE-NEXT:    v_sqrt_f32_e32 v1, v0
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v2, s[4:5], -1, v1
+; GISEL-IEEE-NEXT:    v_add_i32_e64 v3, s[4:5], 1, v1
+; GISEL-IEEE-NEXT:    v_fma_f32 v4, -v2, v1, v0
+; GISEL-IEEE-NEXT:    v_fma_f32 v5, -v3, v1, v0
+; GISEL-IEEE-NEXT:    v_cmp_ge_f32_e64 s[4:5], 0, v4
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v1, v1, v2, s[4:5]
+; GISEL-IEEE-NEXT:    v_cmp_lt_f32_e64 s[4:5], 0, v5
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e64 v1, v1, v3, s[4:5]
+; GISEL-IEEE-NEXT:    v_mul_f32_e32 v2, 0x37800000, v1
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v1, v1, v2, vcc
+; GISEL-IEEE-NEXT:    v_mov_b32_e32 v2, 0x260
+; GISEL-IEEE-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; GISEL-IEEE-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; GISEL-IEEE-NEXT:    s_setpc_b64 s[30:31]
+;
+; GISEL-DAZ-LABEL: v_sqrt_f32__amdgcn_sqrt_known_not_denorm:
+; GISEL-DAZ:       ; %bb.0:
+; GISEL-DAZ-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-DAZ-NEXT:    v_sqrt_f32_e32 v0, v0
+; GISEL-DAZ-NEXT:    v_mov_b32_e32 v1, 0xf800000
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v2, 0x4f800000, v0
+; GISEL-DAZ-NEXT:    v_cmp_lt_f32_e32 vcc, v0, v1
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v0, v2, vcc
+; GISEL-DAZ-NEXT:    v_rsq_f32_e32 v1, v0
+; GISEL-DAZ-NEXT:    v_mov_b32_e32 v2, 0x260
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v3, v0, v1
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v1, 0.5, v1
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v1, v3, 0.5
+; GISEL-DAZ-NEXT:    v_fma_f32 v3, v3, v4, v3
+; GISEL-DAZ-NEXT:    v_fma_f32 v1, v1, v4, v1
+; GISEL-DAZ-NEXT:    v_fma_f32 v4, -v3, v3, v0
+; GISEL-DAZ-NEXT:    v_fma_f32 v1, v4, v1, v3
+; GISEL-DAZ-NEXT:    v_mul_f32_e32 v3, 0x37800000, v1
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v1, v1, v3, vcc
+; GISEL-DAZ-NEXT:    v_cmp_class_f32_e32 vcc, v0, v2
+; GISEL-DAZ-NEXT:    v_cndmask_b32_e32 v0, v1, v0, vcc
+; GISEL-DAZ-NEXT:    s_setpc_b64 s[30:31]
+  %sqrt0 = call float @llvm.amdgcn.sqrt.f32(float %x)
+  %result = call float @llvm.sqrt.f32(float %sqrt0)
+  ret float %result
+}
 
 declare float @llvm.fabs.f32(float) #0
 declare float @llvm.sqrt.f32(float) #0

``````````

</details>


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


More information about the llvm-commits mailing list