result by default, and the old expansion with the afn flag. The old result was good enough for OpenCL conformance, so consider the fpmath metadata and use the fast path. This is done in AMDGPUCodeGenPrepare for the same reason that sqrt is handled here, which is the DAG does not have a way to access fpmath metadata from the original instruction. This is not yet of practical use, because the log calls sourced from OpenCL are not actually marked with this metadata and there isn't a method to produce it from the source languages.
187 lines
6.8 KiB
LLVM
187 lines
6.8 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
|
|
; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx700 -passes=amdgpu-codegenprepare %s | FileCheck -check-prefixes=CHECK,GFX7 %s
|
|
; RUN: opt -S -mtriple=amdgcn-- -mcpu=gfx803 -passes=amdgpu-codegenprepare %s | FileCheck -check-prefixes=CHECK,GFX8 %s
|
|
|
|
; Ignore correct case
|
|
define half @log_f16(half %x) {
|
|
; CHECK-LABEL: define half @log_f16(
|
|
; CHECK-SAME: half [[X:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call half @llvm.log.f16(half [[X]])
|
|
; CHECK-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log.f16(half %x)
|
|
ret half %result
|
|
}
|
|
|
|
; afn case should be handled by codegen
|
|
define half @log_afn_f16(half %x) {
|
|
; CHECK-LABEL: define half @log_afn_f16(
|
|
; CHECK-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[RESULT:%.*]] = call afn half @llvm.log.f16(half [[X]])
|
|
; CHECK-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call afn half @llvm.log.f16(half %x)
|
|
ret half %result
|
|
}
|
|
|
|
; exact ulp threshold
|
|
define half @log_f16_ulp180(half %x) {
|
|
; GFX7-LABEL: define half @log_f16_ulp180(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call half @llvm.log.f16(half [[X]]), !fpmath [[META0:![0-9]+]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log_f16_ulp180(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[TMP1:%.*]] = call half @llvm.log2.f16(half [[X]])
|
|
; GFX8-NEXT: [[RESULT:%.*]] = fmul half [[TMP1]], 0xH398C
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log.f16(half %x), !fpmath !{float 0x3FFCCCCCC0000000}
|
|
ret half %result
|
|
}
|
|
|
|
; off by one, ignore
|
|
define half @log_f16_ulp180_nextdown(half %x) {
|
|
; GFX7-LABEL: define half @log_f16_ulp180_nextdown(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call half @llvm.log.f16(half [[X]]), !fpmath [[META1:![0-9]+]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log_f16_ulp180_nextdown(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[RESULT:%.*]] = call half @llvm.log.f16(half [[X]]), !fpmath [[META0:![0-9]+]]
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log.f16(half %x), !fpmath !{float 0x3FFCCCCCA0000000}
|
|
ret half %result
|
|
}
|
|
|
|
; OpenCL limit
|
|
define half @log_f16_ulp2(half %x) {
|
|
; GFX7-LABEL: define half @log_f16_ulp2(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call half @llvm.log.f16(half [[X]]), !fpmath [[META2:![0-9]+]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log_f16_ulp2(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[TMP1:%.*]] = call half @llvm.log2.f16(half [[X]])
|
|
; GFX8-NEXT: [[RESULT:%.*]] = fmul half [[TMP1]], 0xH398C
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log.f16(half %x), !fpmath !0
|
|
ret half %result
|
|
}
|
|
|
|
; OpenCL limit
|
|
define half @log10_f16_ulp2(half %x) {
|
|
; GFX7-LABEL: define half @log10_f16_ulp2(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call half @llvm.log10.f16(half [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log10_f16_ulp2(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[TMP1:%.*]] = call half @llvm.log2.f16(half [[X]])
|
|
; GFX8-NEXT: [[RESULT:%.*]] = fmul half [[TMP1]], 0xH34D1
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log10.f16(half %x), !fpmath !0
|
|
ret half %result
|
|
}
|
|
|
|
; Ignore log2
|
|
define half @log2_f16_ulp2(half %x) {
|
|
; GFX7-LABEL: define half @log2_f16_ulp2(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call half @llvm.log2.f16(half [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log2_f16_ulp2(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[RESULT:%.*]] = call half @llvm.log2.f16(half [[X]]), !fpmath [[META1:![0-9]+]]
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call half @llvm.log2.f16(half %x), !fpmath !0
|
|
ret half %result
|
|
}
|
|
|
|
; afn case should be handled by codegen
|
|
define half @log_afn_f16_ulp2(half %x) {
|
|
; GFX7-LABEL: define half @log_afn_f16_ulp2(
|
|
; GFX7-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call afn half @llvm.log.f16(half [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret half [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define half @log_afn_f16_ulp2(
|
|
; GFX8-SAME: half [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[RESULT:%.*]] = call afn half @llvm.log.f16(half [[X]]), !fpmath [[META1]]
|
|
; GFX8-NEXT: ret half [[RESULT]]
|
|
;
|
|
%result = call afn half @llvm.log.f16(half %x), !fpmath !0
|
|
ret half %result
|
|
}
|
|
|
|
; Handle vector with scalarization
|
|
define <2 x half> @log_v2f16_ulp2(<2 x half> %x) {
|
|
; GFX7-LABEL: define <2 x half> @log_v2f16_ulp2(
|
|
; GFX7-SAME: <2 x half> [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call <2 x half> @llvm.log.v2f16(<2 x half> [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret <2 x half> [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define <2 x half> @log_v2f16_ulp2(
|
|
; GFX8-SAME: <2 x half> [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.log2.v2f16(<2 x half> [[X]])
|
|
; GFX8-NEXT: [[RESULT:%.*]] = fmul <2 x half> [[TMP1]], splat (half 0xH398C)
|
|
; GFX8-NEXT: ret <2 x half> [[RESULT]]
|
|
;
|
|
%result = call <2 x half> @llvm.log.v2f16(<2 x half> %x), !fpmath !0
|
|
ret <2 x half> %result
|
|
}
|
|
|
|
; Handle vector with scalarization
|
|
define <3 x half> @log_v3f16_ulp2(<3 x half> %x) {
|
|
; GFX7-LABEL: define <3 x half> @log_v3f16_ulp2(
|
|
; GFX7-SAME: <3 x half> [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call <3 x half> @llvm.log.v3f16(<3 x half> [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret <3 x half> [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define <3 x half> @log_v3f16_ulp2(
|
|
; GFX8-SAME: <3 x half> [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[TMP1:%.*]] = call <3 x half> @llvm.log2.v3f16(<3 x half> [[X]])
|
|
; GFX8-NEXT: [[RESULT:%.*]] = fmul <3 x half> [[TMP1]], splat (half 0xH398C)
|
|
; GFX8-NEXT: ret <3 x half> [[RESULT]]
|
|
;
|
|
%result = call <3 x half> @llvm.log.v3f16(<3 x half> %x), !fpmath !0
|
|
ret <3 x half> %result
|
|
}
|
|
|
|
; bfloat not handled
|
|
define bfloat @log_bf16_ulp2(bfloat %x) {
|
|
; GFX7-LABEL: define bfloat @log_bf16_ulp2(
|
|
; GFX7-SAME: bfloat [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX7-NEXT: [[RESULT:%.*]] = call bfloat @llvm.log.bf16(bfloat [[X]]), !fpmath [[META2]]
|
|
; GFX7-NEXT: ret bfloat [[RESULT]]
|
|
;
|
|
; GFX8-LABEL: define bfloat @log_bf16_ulp2(
|
|
; GFX8-SAME: bfloat [[X:%.*]]) #[[ATTR0]] {
|
|
; GFX8-NEXT: [[RESULT:%.*]] = call bfloat @llvm.log.bf16(bfloat [[X]]), !fpmath [[META1]]
|
|
; GFX8-NEXT: ret bfloat [[RESULT]]
|
|
;
|
|
%result = call bfloat @llvm.log.bf16(bfloat %x), !fpmath !0
|
|
ret bfloat %result
|
|
}
|
|
|
|
!0 = !{float 2.0}
|
|
|
|
|
|
;.
|
|
; GFX7: [[META0]] = !{float 0x3FFCCCCCC0000000}
|
|
; GFX7: [[META1]] = !{float 0x3FFCCCCCA0000000}
|
|
; GFX7: [[META2]] = !{float 2.000000e+00}
|
|
;.
|
|
; GFX8: [[META0]] = !{float 0x3FFCCCCCA0000000}
|
|
; GFX8: [[META1]] = !{float 2.000000e+00}
|
|
;.
|