328 lines
14 KiB
LLVM
328 lines
14 KiB
LLVM
|
; 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: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call nnan ninf contract float @llvm.amdgcn.rsq.f32(float [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]])
|
||
|
; 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.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.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.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: [[RSQ:%.*]] = call nnan ninf contract half @llvm.amdgcn.rsq.f16(half [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rsq.f64(double [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call nnan ninf contract double @llvm.amdgcn.rsq.f64(double [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract afn float @llvm.amdgcn.rsq.f32(float [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
|
||
|
; 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: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]])
|
||
|
; 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}
|