Files
llvm-project/llvm/test/CodeGen/AMDGPU/amdgpu-codegenprepare-log.ll
Matt Arsenault d72bc0903f AMDGPU: Use fpmath metadata on f16 log/log10 intrinsics (#180489)
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.
2026-02-17 09:58:43 +01:00

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}
;.