OpenCL loses fast math information by going through libcall wrappers around intrinsics. Do this to preserve call site flags which are lost when inlining. It's not safe in general to propagate flags during inline, so avoid dealing with this by just special casing some of the useful calls.
562 lines
20 KiB
LLVM
562 lines
20 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
|
|
; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=amdgpu-simplifylib %s | FileCheck %s
|
|
|
|
target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8"
|
|
|
|
declare float @_Z3expf(float)
|
|
declare <2 x float> @_Z3expDv2_f(<2 x float>)
|
|
declare <3 x float> @_Z3expDv3_f(<3 x float>)
|
|
declare <4 x float> @_Z3expDv4_f(<4 x float>)
|
|
declare <8 x float> @_Z3expDv8_f(<8 x float>)
|
|
declare <16 x float> @_Z3expDv16_f(<16 x float>)
|
|
|
|
declare double @_Z3expd(double)
|
|
declare <2 x double> @_Z3expDv2_d(<2 x double>)
|
|
declare <3 x double> @_Z3expDv3_d(<3 x double>)
|
|
declare <4 x double> @_Z3expDv4_d(<4 x double>)
|
|
declare <8 x double> @_Z3expDv8_d(<8 x double>)
|
|
declare <16 x double> @_Z3expDv16_d(<16 x double>)
|
|
|
|
declare half @_Z3expDh(half)
|
|
declare <2 x half> @_Z3expDv2_Dh(<2 x half>)
|
|
declare <3 x half> @_Z3expDv3_Dh(<3 x half>)
|
|
declare <4 x half> @_Z3expDv4_Dh(<4 x half>)
|
|
declare <8 x half> @_Z3expDv8_Dh(<8 x half>)
|
|
declare <16 x half> @_Z3expDv16_Dh(<16 x half>)
|
|
|
|
define float @test_exp_f32(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_f32
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_v2f32(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_v2f32
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg), !fpmath !0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define <3 x float> @test_exp_v3f32(<3 x float> %arg) {
|
|
; CHECK-LABEL: define <3 x float> @test_exp_v3f32
|
|
; CHECK-SAME: (<3 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <3 x float> @_Z3expDv3_f(<3 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <3 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <3 x float> @_Z3expDv3_f(<3 x float> %arg), !fpmath !0
|
|
ret <3 x float> %exp
|
|
}
|
|
|
|
define <4 x float> @test_exp_v4f32(<4 x float> %arg) {
|
|
; CHECK-LABEL: define <4 x float> @test_exp_v4f32
|
|
; CHECK-SAME: (<4 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <4 x float> @_Z3expDv4_f(<4 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <4 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <4 x float> @_Z3expDv4_f(<4 x float> %arg), !fpmath !0
|
|
ret <4 x float> %exp
|
|
}
|
|
|
|
define <8 x float> @test_exp_v8f32(<8 x float> %arg) {
|
|
; CHECK-LABEL: define <8 x float> @test_exp_v8f32
|
|
; CHECK-SAME: (<8 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <8 x float> @_Z3expDv8_f(<8 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <8 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <8 x float> @_Z3expDv8_f(<8 x float> %arg), !fpmath !0
|
|
ret <8 x float> %exp
|
|
}
|
|
|
|
define <16 x float> @test_exp_v16f32(<16 x float> %arg) {
|
|
; CHECK-LABEL: define <16 x float> @test_exp_v16f32
|
|
; CHECK-SAME: (<16 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <16 x float> @_Z3expDv16_f(<16 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <16 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <16 x float> @_Z3expDv16_f(<16 x float> %arg), !fpmath !0
|
|
ret <16 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_cr_f32(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_cr_f32
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg)
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_cr_v2f32(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_cr_v2f32
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg)
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define <3 x float> @test_exp_cr_v3f32(<3 x float> %arg) {
|
|
; CHECK-LABEL: define <3 x float> @test_exp_cr_v3f32
|
|
; CHECK-SAME: (<3 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <3 x float> @_Z3expDv3_f(<3 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <3 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <3 x float> @_Z3expDv3_f(<3 x float> %arg)
|
|
ret <3 x float> %exp
|
|
}
|
|
|
|
define <4 x float> @test_exp_cr_v4f32(<4 x float> %arg) {
|
|
; CHECK-LABEL: define <4 x float> @test_exp_cr_v4f32
|
|
; CHECK-SAME: (<4 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <4 x float> @_Z3expDv4_f(<4 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <4 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <4 x float> @_Z3expDv4_f(<4 x float> %arg)
|
|
ret <4 x float> %exp
|
|
}
|
|
|
|
define <8 x float> @test_exp_cr_v8f32(<8 x float> %arg) {
|
|
; CHECK-LABEL: define <8 x float> @test_exp_cr_v8f32
|
|
; CHECK-SAME: (<8 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <8 x float> @_Z3expDv8_f(<8 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <8 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <8 x float> @_Z3expDv8_f(<8 x float> %arg)
|
|
ret <8 x float> %exp
|
|
}
|
|
|
|
define <16 x float> @test_exp_cr_v16f32(<16 x float> %arg) {
|
|
; CHECK-LABEL: define <16 x float> @test_exp_cr_v16f32
|
|
; CHECK-SAME: (<16 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <16 x float> @_Z3expDv16_f(<16 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <16 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <16 x float> @_Z3expDv16_f(<16 x float> %arg)
|
|
ret <16 x float> %exp
|
|
}
|
|
|
|
define double @test_exp_f64(double %arg) {
|
|
; CHECK-LABEL: define double @test_exp_f64
|
|
; CHECK-SAME: (double [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call double @_Z3expd(double [[ARG]])
|
|
; CHECK-NEXT: ret double [[EXP]]
|
|
;
|
|
%exp = tail call double @_Z3expd(double %arg)
|
|
ret double %exp
|
|
}
|
|
|
|
define <2 x double> @test_exp_v2f64(<2 x double> %arg) {
|
|
; CHECK-LABEL: define <2 x double> @test_exp_v2f64
|
|
; CHECK-SAME: (<2 x double> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x double> @_Z3expDv2_d(<2 x double> [[ARG]])
|
|
; CHECK-NEXT: ret <2 x double> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x double> @_Z3expDv2_d(<2 x double> %arg)
|
|
ret <2 x double> %exp
|
|
}
|
|
|
|
define <3 x double> @test_exp_v3f64(<3 x double> %arg) {
|
|
; CHECK-LABEL: define <3 x double> @test_exp_v3f64
|
|
; CHECK-SAME: (<3 x double> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <3 x double> @_Z3expDv3_d(<3 x double> [[ARG]])
|
|
; CHECK-NEXT: ret <3 x double> [[EXP]]
|
|
;
|
|
%exp = tail call <3 x double> @_Z3expDv3_d(<3 x double> %arg)
|
|
ret <3 x double> %exp
|
|
}
|
|
|
|
define <4 x double> @test_exp_v4f64(<4 x double> %arg) {
|
|
; CHECK-LABEL: define <4 x double> @test_exp_v4f64
|
|
; CHECK-SAME: (<4 x double> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <4 x double> @_Z3expDv4_d(<4 x double> [[ARG]])
|
|
; CHECK-NEXT: ret <4 x double> [[EXP]]
|
|
;
|
|
%exp = tail call <4 x double> @_Z3expDv4_d(<4 x double> %arg)
|
|
ret <4 x double> %exp
|
|
}
|
|
|
|
define <8 x double> @test_exp_v8f64(<8 x double> %arg) {
|
|
; CHECK-LABEL: define <8 x double> @test_exp_v8f64
|
|
; CHECK-SAME: (<8 x double> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <8 x double> @_Z3expDv8_d(<8 x double> [[ARG]])
|
|
; CHECK-NEXT: ret <8 x double> [[EXP]]
|
|
;
|
|
%exp = tail call <8 x double> @_Z3expDv8_d(<8 x double> %arg)
|
|
ret <8 x double> %exp
|
|
}
|
|
|
|
define <16 x double> @test_exp_v16f64(<16 x double> %arg) {
|
|
; CHECK-LABEL: define <16 x double> @test_exp_v16f64
|
|
; CHECK-SAME: (<16 x double> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <16 x double> @_Z3expDv16_d(<16 x double> [[ARG]])
|
|
; CHECK-NEXT: ret <16 x double> [[EXP]]
|
|
;
|
|
%exp = tail call <16 x double> @_Z3expDv16_d(<16 x double> %arg)
|
|
ret <16 x double> %exp
|
|
}
|
|
|
|
define half @test_exp_f16(half %arg) {
|
|
; CHECK-LABEL: define half @test_exp_f16
|
|
; CHECK-SAME: (half [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call half @_Z3expDh(half [[ARG]])
|
|
; CHECK-NEXT: ret half [[EXP]]
|
|
;
|
|
%exp = tail call half @_Z3expDh(half %arg)
|
|
ret half %exp
|
|
}
|
|
|
|
define half @test_exp_f16_fast(half %arg) {
|
|
; CHECK-LABEL: define half @test_exp_f16_fast
|
|
; CHECK-SAME: (half [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast half @llvm.exp.f16(half [[ARG]])
|
|
; CHECK-NEXT: ret half [[EXP]]
|
|
;
|
|
%exp = tail call fast half @_Z3expDh(half %arg)
|
|
ret half %exp
|
|
}
|
|
|
|
define <2 x half> @test_exp_v2f16(<2 x half> %arg) {
|
|
; CHECK-LABEL: define <2 x half> @test_exp_v2f16
|
|
; CHECK-SAME: (<2 x half> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x half> @_Z3expDv2_Dh(<2 x half> [[ARG]])
|
|
; CHECK-NEXT: ret <2 x half> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x half> @_Z3expDv2_Dh(<2 x half> %arg)
|
|
ret <2 x half> %exp
|
|
}
|
|
|
|
define <3 x half> @test_exp_v3f16(<3 x half> %arg) {
|
|
; CHECK-LABEL: define <3 x half> @test_exp_v3f16
|
|
; CHECK-SAME: (<3 x half> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <3 x half> @_Z3expDv3_Dh(<3 x half> [[ARG]])
|
|
; CHECK-NEXT: ret <3 x half> [[EXP]]
|
|
;
|
|
%exp = tail call <3 x half> @_Z3expDv3_Dh(<3 x half> %arg)
|
|
ret <3 x half> %exp
|
|
}
|
|
|
|
define <4 x half> @test_exp_v4f16(<4 x half> %arg) {
|
|
; CHECK-LABEL: define <4 x half> @test_exp_v4f16
|
|
; CHECK-SAME: (<4 x half> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <4 x half> @_Z3expDv4_Dh(<4 x half> [[ARG]])
|
|
; CHECK-NEXT: ret <4 x half> [[EXP]]
|
|
;
|
|
%exp = tail call <4 x half> @_Z3expDv4_Dh(<4 x half> %arg)
|
|
ret <4 x half> %exp
|
|
}
|
|
|
|
define <8 x half> @test_exp_v8f16(<8 x half> %arg) {
|
|
; CHECK-LABEL: define <8 x half> @test_exp_v8f16
|
|
; CHECK-SAME: (<8 x half> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <8 x half> @_Z3expDv8_Dh(<8 x half> [[ARG]])
|
|
; CHECK-NEXT: ret <8 x half> [[EXP]]
|
|
;
|
|
%exp = tail call <8 x half> @_Z3expDv8_Dh(<8 x half> %arg)
|
|
ret <8 x half> %exp
|
|
}
|
|
|
|
define <16 x half> @test_exp_v16f16(<16 x half> %arg) {
|
|
; CHECK-LABEL: define <16 x half> @test_exp_v16f16
|
|
; CHECK-SAME: (<16 x half> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <16 x half> @_Z3expDv16_Dh(<16 x half> [[ARG]])
|
|
; CHECK-NEXT: ret <16 x half> [[EXP]]
|
|
;
|
|
%exp = tail call <16 x half> @_Z3expDv16_Dh(<16 x half> %arg)
|
|
ret <16 x half> %exp
|
|
}
|
|
|
|
define float @test_exp_f32_nobuiltin_callsite(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_f32_nobuiltin_callsite
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]]) #[[ATTR6:[0-9]+]], !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg) #0, !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_v2f32_nobuiltin_callsite(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_v2f32_nobuiltin_callsite
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]]) #[[ATTR6]], !fpmath !0
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg) #0, !fpmath !0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_cr_f32_nobuiltin_callsite(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_cr_f32_nobuiltin_callsite
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]]) #[[ATTR6]]
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg) #0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_cr_v2f32_nobuiltin_callsite(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_cr_v2f32_nobuiltin_callsite
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]]) #[[ATTR6]]
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg) #0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
; "no-builtins" should be ignored
|
|
define float @test_exp_f32_nobuiltins(float %arg) #1 {
|
|
; CHECK-LABEL: define float @test_exp_f32_nobuiltins
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR0:[0-9]+]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]]) #[[ATTR6]], !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg) #0, !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_v2f32_nobuiltins(<2 x float> %arg) #1 {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_v2f32_nobuiltins
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]]) #[[ATTR6]], !fpmath !0
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg) #0, !fpmath !0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_cr_f32_nobuiltins(float %arg) #1 {
|
|
; CHECK-LABEL: define float @test_exp_cr_f32_nobuiltins
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @_Z3expf(float [[ARG]]) #[[ATTR6]]
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @_Z3expf(float %arg) #0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_cr_v2f32_nobuiltins(<2 x float> %arg) #1 {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_cr_v2f32_nobuiltins
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) #[[ATTR0]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call <2 x float> @_Z3expDv2_f(<2 x float> [[ARG]]) #[[ATTR6]]
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call <2 x float> @_Z3expDv2_f(<2 x float> %arg) #0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_f32_preserve_flags(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_f32_preserve_flags
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nnan ninf float @llvm.exp.f32(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call nnan ninf float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_v2f32_preserve_flags(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_v2f32_preserve_flags
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nnan nsz contract <2 x float> @llvm.exp.v2f32(<2 x float> [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call contract nsz nnan <2 x float> @_Z3expDv2_f(<2 x float> %arg), !fpmath !0
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_f32_preserve_flags_md(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_f32_preserve_flags_md
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nnan ninf float @llvm.exp.f32(float [[ARG]]), !fpmath !0, !foo !1
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call nnan ninf float @_Z3expf(float %arg), !fpmath !0, !foo !1
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_v2f32_preserve_flags_md(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_v2f32_preserve_flags_md
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nnan nsz contract <2 x float> @llvm.exp.v2f32(<2 x float> [[ARG]]), !fpmath !0, !foo !1
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call contract nsz nnan <2 x float> @_Z3expDv2_f(<2 x float> %arg), !fpmath !0, !foo !1
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
define float @test_exp_cr_f32_preserve_flags(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_cr_f32_preserve_flags
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call ninf contract float @llvm.exp.f32(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call ninf contract float @_Z3expf(float %arg)
|
|
ret float %exp
|
|
}
|
|
|
|
define <2 x float> @test_exp_cr_v2f32_preserve_flags(<2 x float> %arg) {
|
|
; CHECK-LABEL: define <2 x float> @test_exp_cr_v2f32_preserve_flags
|
|
; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nnan nsz <2 x float> @llvm.exp.v2f32(<2 x float> [[ARG]])
|
|
; CHECK-NEXT: ret <2 x float> [[EXP]]
|
|
;
|
|
%exp = tail call nnan nsz <2 x float> @_Z3expDv2_f(<2 x float> %arg)
|
|
ret <2 x float> %exp
|
|
}
|
|
|
|
; Test the libm name, not a recognized opencl builtin.
|
|
declare float @expf(float) #2
|
|
declare double @exp(double) #2
|
|
|
|
define float @test_libm_exp_f32(float %arg) {
|
|
; CHECK-LABEL: define float @test_libm_exp_f32
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @expf(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @expf(float %arg)
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_libm_exp_f32_fast(float %arg) {
|
|
; CHECK-LABEL: define float @test_libm_exp_f32_fast
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast float @expf(float [[ARG]])
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call fast float @expf(float %arg)
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_libm_exp_f32_fpmath(float %arg) {
|
|
; CHECK-LABEL: define float @test_libm_exp_f32_fpmath
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call float @expf(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call float @expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define double @test_libm_exp_f64(double %arg) {
|
|
; CHECK-LABEL: define double @test_libm_exp_f64
|
|
; CHECK-SAME: (double [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call double @exp(double [[ARG]])
|
|
; CHECK-NEXT: ret double [[EXP]]
|
|
;
|
|
%exp = tail call double @exp(double %arg)
|
|
ret double %exp
|
|
}
|
|
|
|
define double @test_libm_exp_f64_fast(double %arg) {
|
|
; CHECK-LABEL: define double @test_libm_exp_f64_fast
|
|
; CHECK-SAME: (double [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast double @exp(double [[ARG]])
|
|
; CHECK-NEXT: ret double [[EXP]]
|
|
;
|
|
%exp = tail call fast double @exp(double %arg)
|
|
ret double %exp
|
|
}
|
|
|
|
define double @test_libm_exp_f64_fpmath(double %arg) {
|
|
; CHECK-LABEL: define double @test_libm_exp_f64_fpmath
|
|
; CHECK-SAME: (double [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call double @exp(double [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret double [[EXP]]
|
|
;
|
|
%exp = tail call double @exp(double %arg), !fpmath !0
|
|
ret double %exp
|
|
}
|
|
|
|
define float @test_exp_f32_fast_noinline(float %arg) {
|
|
; CHECK-LABEL: define float @test_exp_f32_fast_noinline
|
|
; CHECK-SAME: (float [[ARG:%.*]]) {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast float @_Z3expf(float [[ARG]]) #[[ATTR7:[0-9]+]], !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call fast float @_Z3expf(float %arg) #3, !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_exp_f32_fast_optsize(float %arg) #4 {
|
|
; CHECK-LABEL: define float @test_exp_f32_fast_optsize
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR2:[0-9]+]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast float @llvm.exp.f32(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call fast float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_exp_f32_fast_minsize(float %arg) #5 {
|
|
; CHECK-LABEL: define float @test_exp_f32_fast_minsize
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR3:[0-9]+]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call fast float @llvm.exp.f32(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call fast float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_exp_f32_nsz_contract_optsize(float %arg) #4 {
|
|
; CHECK-LABEL: define float @test_exp_f32_nsz_contract_optsize
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR2]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nsz contract float @llvm.exp.f32(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call nsz contract float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define float @test_exp_f32_nsz_contract_minsize(float %arg) #5 {
|
|
; CHECK-LABEL: define float @test_exp_f32_nsz_contract_minsize
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nsz contract float @_Z3expf(float [[ARG]]), !fpmath !0
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call nsz contract float @_Z3expf(float %arg), !fpmath !0
|
|
ret float %exp
|
|
}
|
|
|
|
define half @test_exp_f16_fast_minsize(half %arg) #5 {
|
|
; CHECK-LABEL: define half @test_exp_f16_fast_minsize
|
|
; CHECK-SAME: (half [[ARG:%.*]]) #[[ATTR3]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call half @_Z3expDh(half [[ARG]])
|
|
; CHECK-NEXT: ret half [[EXP]]
|
|
;
|
|
%exp = tail call half @_Z3expDh(half %arg)
|
|
ret half %exp
|
|
}
|
|
|
|
define float @test_exp_f32_strictfp(float %arg) #6 {
|
|
; CHECK-LABEL: define float @test_exp_f32_strictfp
|
|
; CHECK-SAME: (float [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
|
|
; CHECK-NEXT: [[EXP:%.*]] = tail call nsz float @_Z3expf(float [[ARG]]) #[[ATTR4]]
|
|
; CHECK-NEXT: ret float [[EXP]]
|
|
;
|
|
%exp = tail call nsz float @_Z3expf(float %arg) #6
|
|
ret float %exp
|
|
}
|
|
|
|
attributes #0 = { nobuiltin }
|
|
attributes #1 = { "no-builtins" }
|
|
attributes #2 = { nounwind memory(none) }
|
|
attributes #3 = { noinline }
|
|
attributes #4 = { optsize }
|
|
attributes #5 = { minsize }
|
|
attributes #6 = { strictfp }
|
|
|
|
!0 = !{float 3.000000e+00}
|
|
!1 = !{i32 1234}
|