[llvm] f19ee76 - AMDGPU: Add baseline tests for rcp to rsq fold

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 16 07:12:31 PDT 2023


Author: Matt Arsenault
Date: 2023-08-16T10:03:49-04:00
New Revision: f19ee76f35b47e2b4548fa35d0ec7192db16f73c

URL: https://github.com/llvm/llvm-project/commit/f19ee76f35b47e2b4548fa35d0ec7192db16f73c
DIFF: https://github.com/llvm/llvm-project/commit/f19ee76f35b47e2b4548fa35d0ec7192db16f73c.diff

LOG: AMDGPU: Add baseline tests for rcp to rsq fold

Added: 
    llvm/test/Transforms/InstCombine/AMDGPU/rcp-contract-rsq.ll

Modified: 
    

Removed: 
    


################################################################################
diff  --git a/llvm/test/Transforms/InstCombine/AMDGPU/rcp-contract-rsq.ll b/llvm/test/Transforms/InstCombine/AMDGPU/rcp-contract-rsq.ll
new file mode 100644
index 00000000000000..e695433e586c5c
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/rcp-contract-rsq.ll
@@ -0,0 +1,337 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
+; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=instcombine -S < %s | FileCheck %s
+
+declare half @llvm.amdgcn.sqrt.f16(half)
+declare float @llvm.amdgcn.sqrt.f32(float)
+declare double @llvm.amdgcn.sqrt.f64(double)
+
+declare half @llvm.amdgcn.rcp.f16(half)
+declare float @llvm.amdgcn.rcp.f32(float)
+declare double @llvm.amdgcn.rcp.f64(double)
+
+declare half @llvm.amdgcn.rsq.f16(half)
+declare float @llvm.amdgcn.rsq.f32(float)
+declare double @llvm.amdgcn.rsq.f64(double)
+
+
+declare half @llvm.sqrt.f16(half)
+declare float @llvm.sqrt.f32(float)
+declare double @llvm.sqrt.f64(double)
+
+; Should allow precision increasing contraction to rsq call
+define float @amdgcn_rcp_amdgcn_sqrt_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; contract required on both calls
+define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.amdgcn.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call float @llvm.amdgcn.sqrt.f32(float %x)
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; contract required on both calls
+define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
+  %rsq = call float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; Reject from multiple uses of sqrt
+define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use(float %x, ptr %ptr) {
+; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use
+; CHECK-SAME: (float [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]])
+; CHECK-NEXT:    store float [[SQRT]], ptr [[PTR]], align 4
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x)
+  store float %sqrt, ptr %ptr
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; Test flags are or'd together
+define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan contract float @llvm.amdgcn.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call ninf contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call nnan contract float @llvm.amdgcn.sqrt.f32(float %x)
+  %rsq = call ninf contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; Should allow precision increasing contraction to rsq call
+define half @amdgcn_rcp_amdgcn_sqrt_f16_contract(half %x) {
+; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract
+; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.amdgcn.sqrt.f16(half [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
+  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; contract required on both calls
+define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0(half %x) {
+; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0
+; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call half @llvm.amdgcn.sqrt.f16(half [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call half @llvm.amdgcn.sqrt.f16(half %x)
+  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; contract required on both calls
+define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1(half %x) {
+; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1
+; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.amdgcn.sqrt.f16(half [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
+  %rsq = call half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; Reject from multiple uses of sqrt
+define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use(half %x, ptr %ptr) {
+; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use
+; CHECK-SAME: (half [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.amdgcn.sqrt.f16(half [[X]])
+; CHECK-NEXT:    store half [[SQRT]], ptr [[PTR]], align 2
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x)
+  store half %sqrt, ptr %ptr
+  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; Test flags are or'd together
+define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract(half %x) {
+; CHECK-LABEL: define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract
+; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan contract half @llvm.amdgcn.sqrt.f16(half [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call ninf contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call nnan contract half @llvm.amdgcn.sqrt.f16(half %x)
+  %rsq = call ninf contract half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; Should allow precision increasing contraction to rsq call
+define double @amdgcn_rcp_amdgcn_sqrt_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; contract required on both calls
+define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.amdgcn.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call double @llvm.amdgcn.sqrt.f64(double %x)
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; contract required on both calls
+define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
+  %rsq = call double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; Reject from multiple uses of sqrt
+define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use(double %x, ptr %ptr) {
+; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use
+; CHECK-SAME: (double [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]])
+; CHECK-NEXT:    store double [[SQRT]], ptr [[PTR]], align 8
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x)
+  store double %sqrt, ptr %ptr
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; Test flags are or'd together
+define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call nnan contract double @llvm.amdgcn.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call ninf contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call nnan contract double @llvm.amdgcn.sqrt.f64(double %x)
+  %rsq = call ninf contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; Do not contract with regular sqrt
+define float @amdgcn_rcp_sqrt_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_sqrt_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.sqrt.f32(float %x)
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; Do contract with regular sqrt for f16
+define half @amdgcn_rcp_sqrt_f16_contract(half %x) {
+; CHECK-LABEL: define half @amdgcn_rcp_sqrt_f16_contract
+; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract half @llvm.sqrt.f16(half [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]])
+; CHECK-NEXT:    ret half [[RSQ]]
+;
+  %sqrt = call contract half @llvm.sqrt.f16(half %x)
+  %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)
+  ret half %rsq
+}
+
+; Do not contract with regular sqrt
+define double @amdgcn_rcp_sqrt_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_sqrt_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.sqrt.f64(double %x)
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+define float @amdgcn_rcp_afn_sqrt_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_afn_sqrt_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract afn float @llvm.sqrt.f32(float [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call afn contract float @llvm.sqrt.f32(float %x)
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+define float @amdgcn_rcp_fpmath3_sqrt_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_fpmath3_sqrt_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]), !fpmath !0
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !0
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+define float @amdgcn_rcp_fpmath1_sqrt_f32_contract(float %x) {
+; CHECK-LABEL: define float @amdgcn_rcp_fpmath1_sqrt_f32_contract
+; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]), !fpmath !1
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]])
+; CHECK-NEXT:    ret float [[RSQ]]
+;
+  %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !1
+  %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)
+  ret float %rsq
+}
+
+; Ignore f64 sqrt
+define double @amdgcn_rcp_afn_sqrt_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_afn_sqrt_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract afn double @llvm.sqrt.f64(double [[X]])
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call afn contract double @llvm.sqrt.f64(double %x)
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; Ignore f64 sqrt
+define double @amdgcn_rcp_fpmath3_sqrt_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_fpmath3_sqrt_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !0
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !0
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+; Ignore f64 sqrt
+define double @amdgcn_rcp_fpmath1_sqrt_f64_contract(double %x) {
+; CHECK-LABEL: define double @amdgcn_rcp_fpmath1_sqrt_f64_contract
+; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {
+; CHECK-NEXT:    [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !1
+; CHECK-NEXT:    [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]])
+; CHECK-NEXT:    ret double [[RSQ]]
+;
+  %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !1
+  %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)
+  ret double %rsq
+}
+
+!0 = !{float 3.0}
+!1 = !{float 1.0}


        


More information about the llvm-commits mailing list