; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -passes=nsan -nsan-shadow-type-mapping=dqq -nsan-truncate-fcmp-eq=false -S %s | FileCheck %s --check-prefixes=CHECK,DQQ ; RUN: opt -passes=nsan -nsan-shadow-type-mapping=dlq -nsan-truncate-fcmp-eq=false -S %s | FileCheck %s --check-prefixes=CHECK,DLQ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ; FIXME: nsan is currently using long double (e.g. sin.f80) instead of quad (sin.f128). ;############################################################### ;# sqrt # ;############################################################### declare float @sqrtf(float) declare double @sqrt(double) declare x86_fp80 @sqrtl(x86_fp80) define float @call_sqrtf() sanitize_numerical_stability { ; CHECK-LABEL: @call_sqrtf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @sqrtf(float 4.000000e+00) #[[ATTR3:[0-9]+]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.sqrt.f64(double 4.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sqrtf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @sqrtf(float 4.0) ret float %r } define double @call_sqrt() sanitize_numerical_stability { ; DQQ-LABEL: @call_sqrt( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @sqrt(double 4.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 4.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_sqrt to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_sqrt( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @sqrt(double 4.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 4.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_sqrt to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @sqrt(double 4.0) ret double %r } define x86_fp80 @call_sqrtl() sanitize_numerical_stability { ; CHECK-LABEL: @call_sqrtl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @sqrtl(x86_fp80 4.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 4.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sqrtl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @sqrtl(x86_fp80 0xK40018000000000000000) ret x86_fp80 %r } ;############################################################### ;# sin # ;############################################################### declare float @sinf(float) declare double @sin(double) declare x86_fp80 @sinl(x86_fp80) define float @call_sinf() sanitize_numerical_stability { ; CHECK-LABEL: @call_sinf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @sinf(float 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.sin.f64(double 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sinf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @sinf(float 1.0) ret float %r } define double @call_sin() sanitize_numerical_stability { ; DQQ-LABEL: @call_sin( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @sin(double 1.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 1.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_sin to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_sin( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @sin(double 1.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 1.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_sin to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @sin(double 1.0) ret double %r } define x86_fp80 @call_sinl() sanitize_numerical_stability { ; CHECK-LABEL: @call_sinl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @sinl(x86_fp80 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_sinl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @sinl(x86_fp80 0xK3FFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# cos # ;############################################################### declare float @cosf(float) declare double @cos(double) declare x86_fp80 @cosl(x86_fp80) define float @call_cosf() sanitize_numerical_stability { ; CHECK-LABEL: @call_cosf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @cosf(float 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.cos.f64(double 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_cosf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @cosf(float 1.0) ret float %r } define double @call_cos() sanitize_numerical_stability { ; DQQ-LABEL: @call_cos( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @cos(double 1.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 1.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_cos to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_cos( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @cos(double 1.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 1.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_cos to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @cos(double 1.0) ret double %r } define x86_fp80 @call_cosl() sanitize_numerical_stability { ; CHECK-LABEL: @call_cosl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @cosl(x86_fp80 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_cosl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @cosl(x86_fp80 0xK3FFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# pow # ;############################################################### declare float @powf(float, float) declare double @pow(double, double) declare x86_fp80 @powl(x86_fp80, x86_fp80) define float @call_powf() sanitize_numerical_stability { ; CHECK-LABEL: @call_powf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @powf(float 2.000000e+00, float 3.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.pow.f64(double 2.000000e+00, double 3.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_powf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @powf(float 2.0, float 3.0) ret float %r } define double @call_pow() sanitize_numerical_stability { ; DQQ-LABEL: @call_pow( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @pow(double 2.000000e+00, double 3.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 2.000000e+00, x86_fp80 3.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_pow to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_pow( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @pow(double 2.000000e+00, double 3.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 2.000000e+00, x86_fp80 3.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_pow to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @pow(double 2.0, double 3.0) ret double %r } define x86_fp80 @call_powl() sanitize_numerical_stability { ; CHECK-LABEL: @call_powl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @powl(x86_fp80 2.000000e+00, x86_fp80 4.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 2.000000e+00, x86_fp80 4.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_powl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @powl(x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) ret x86_fp80 %r } ;############################################################### ;# exp # ;############################################################### declare float @expf(float) declare double @exp(double) declare x86_fp80 @expl(x86_fp80) define float @call_expf() sanitize_numerical_stability { ; CHECK-LABEL: @call_expf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @expf(float 1.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.exp.f64(double 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_expf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @expf(float 1.0) ret float %r } define double @call_exp() sanitize_numerical_stability { ; DQQ-LABEL: @call_exp( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @exp(double 1.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 1.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_exp to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_exp( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @exp(double 1.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 1.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_exp to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @exp(double 1.0) ret double %r } define x86_fp80 @call_expl() sanitize_numerical_stability { ; CHECK-LABEL: @call_expl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @expl(x86_fp80 1.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_expl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @expl(x86_fp80 0xK3FFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# exp2 # ;############################################################### declare float @exp2f(float) declare double @exp2(double) declare x86_fp80 @exp2l(x86_fp80) define float @call_exp2f() sanitize_numerical_stability { ; CHECK-LABEL: @call_exp2f( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @exp2f(float 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.exp2.f64(double 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_exp2f to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @exp2f(float 1.0) ret float %r } define double @call_exp2() sanitize_numerical_stability { ; DQQ-LABEL: @call_exp2( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @exp2(double 1.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 1.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_exp2 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_exp2( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @exp2(double 1.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 1.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_exp2 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @exp2(double 1.0) ret double %r } define x86_fp80 @call_exp2l() sanitize_numerical_stability { ; CHECK-LABEL: @call_exp2l( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @exp2l(x86_fp80 1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_exp2l to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @exp2l(x86_fp80 0xK3FFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# log # ;############################################################### declare float @logf(float) declare double @log(double) declare x86_fp80 @logl(x86_fp80) define float @call_logf() sanitize_numerical_stability { ; CHECK-LABEL: @call_logf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @logf(float 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.log.f64(double 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_logf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @logf(float 2.0) ret float %r } define double @call_log() sanitize_numerical_stability { ; DQQ-LABEL: @call_log( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @log(double 2.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_log to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_log( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @log(double 2.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_log to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @log(double 2.0) ret double %r } define x86_fp80 @call_logl() sanitize_numerical_stability { ; CHECK-LABEL: @call_logl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @logl(x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_logl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @logl(x86_fp80 0xK40008000000000000000) ret x86_fp80 %r } ;############################################################### ;# log10 # ;############################################################### declare float @log10f(float) declare double @log10(double) declare x86_fp80 @log10l(x86_fp80) define float @call_log10f() sanitize_numerical_stability { ; CHECK-LABEL: @call_log10f( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @log10f(float 1.000000e+02) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.log10.f64(double 1.000000e+02) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_log10f to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @log10f(float 100.0) ret float %r } define double @call_log10() sanitize_numerical_stability { ; DQQ-LABEL: @call_log10( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @log10(double 1.000000e+02) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 1.000000e+02) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_log10 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_log10( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @log10(double 1.000000e+02) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 1.000000e+02) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_log10 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @log10(double 100.0) ret double %r } define x86_fp80 @call_log10l() sanitize_numerical_stability { ; CHECK-LABEL: @call_log10l( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @log10l(x86_fp80 +snan(0x0)) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 +snan(0x0)) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_log10l to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @log10l(x86_fp80 0xK40590000000000000000) ret x86_fp80 %r } ;############################################################### ;# log2 # ;############################################################### declare float @log2f(float) declare double @log2(double) declare x86_fp80 @log2l(x86_fp80) define float @call_log2f() sanitize_numerical_stability { ; CHECK-LABEL: @call_log2f( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @log2f(float 8.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.log2.f64(double 8.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_log2f to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @log2f(float 8.0) ret float %r } define double @call_log2() sanitize_numerical_stability { ; DQQ-LABEL: @call_log2( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @log2(double 8.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 8.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_log2 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_log2( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @log2(double 8.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 8.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_log2 to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @log2(double 8.0) ret double %r } define x86_fp80 @call_log2l() sanitize_numerical_stability { ; CHECK-LABEL: @call_log2l( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @log2l(x86_fp80 4.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 4.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_log2l to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @log2l(x86_fp80 0xK40018000000000000000) ret x86_fp80 %r } ;############################################################### ;# fabs # ;############################################################### declare float @fabsf(float) declare double @fabs(double) declare x86_fp80 @fabsl(x86_fp80) define float @call_fabsf() sanitize_numerical_stability { ; CHECK-LABEL: @call_fabsf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @fabsf(float -1.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.fabs.f64(double -1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fabsf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @fabsf(float -1.0) ret float %r } define double @call_fabs() sanitize_numerical_stability { ; DQQ-LABEL: @call_fabs( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @fabs(double -1.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 -1.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_fabs to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_fabs( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @fabs(double -1.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 -1.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_fabs to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @fabs(double -1.0) ret double %r } define x86_fp80 @call_fabsl() sanitize_numerical_stability { ; CHECK-LABEL: @call_fabsl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fabsl(x86_fp80 -1.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 -1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fabsl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @fabsl(x86_fp80 0xKBFFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# copysign # ;############################################################### declare float @copysignf(float, float) declare double @copysign(double, double) declare x86_fp80 @copysignl(x86_fp80, x86_fp80) define float @call_copysignf() sanitize_numerical_stability { ; CHECK-LABEL: @call_copysignf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @copysignf(float 1.000000e+00, float -2.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double -2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_copysignf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @copysignf(float 1.0, float -2.0) ret float %r } define double @call_copysign() sanitize_numerical_stability { ; DQQ-LABEL: @call_copysign( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @copysign(double 1.000000e+00, double -2.000000e+00) #[[ATTR3]] ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 1.000000e+00, x86_fp80 -2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_copysign to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_copysign( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @copysign(double 1.000000e+00, double -2.000000e+00) #[[ATTR3]] ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 1.000000e+00, x86_fp80 -2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_copysign to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @copysign(double 1.0, double -2.0) ret double %r } define x86_fp80 @call_copysignl() sanitize_numerical_stability { ; CHECK-LABEL: @call_copysignl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @copysignl(x86_fp80 1.000000e+00, x86_fp80 -1.000000e+00) #[[ATTR3]] ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 1.000000e+00, x86_fp80 -1.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_copysignl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @copysignl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) ret x86_fp80 %r } ;############################################################### ;# floor # ;############################################################### declare float @floorf(float) declare double @floor(double) declare x86_fp80 @floorl(x86_fp80) define float @call_floorf() sanitize_numerical_stability { ; CHECK-LABEL: @call_floorf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @floorf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.floor.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_floorf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @floorf(float 1.5) ret float %r } define double @call_floor() sanitize_numerical_stability { ; DQQ-LABEL: @call_floor( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @floor(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_floor to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_floor( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @floor(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_floor to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @floor(double 1.5) ret double %r } define x86_fp80 @call_floorl() sanitize_numerical_stability { ; CHECK-LABEL: @call_floorl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @floorl(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_floorl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @floorl(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r } ;############################################################### ;# fmax # ;############################################################### declare float @fmaxf(float, float) declare double @fmax(double, double) declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) define float @call_fmaxf() sanitize_numerical_stability { ; CHECK-LABEL: @call_fmaxf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @fmaxf(float 1.000000e+00, float 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.maxnum.f64(double 1.000000e+00, double 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaxf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @fmaxf(float 1.0, float 2.0) ret float %r } define double @call_fmax() sanitize_numerical_stability { ; DQQ-LABEL: @call_fmax( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @fmax(double 1.000000e+00, double 2.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_fmax to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_fmax( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @fmax(double 1.000000e+00, double 2.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_fmax to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @fmax(double 1.0, double 2.0) ret double %r } define x86_fp80 @call_fmaxl() sanitize_numerical_stability { ; CHECK-LABEL: @call_fmaxl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fmaxl(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaxl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @fmaxl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) ret x86_fp80 %r } ;############################################################### ;# fmin # ;############################################################### declare float @fminf(float, float) declare double @fmin(double, double) declare x86_fp80 @fminl(x86_fp80, x86_fp80) define float @call_fminf() sanitize_numerical_stability { ; CHECK-LABEL: @call_fminf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @fminf(float 1.000000e+00, float 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.minnum.f64(double 1.000000e+00, double 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @fminf(float 1.0, float 2.0) ret float %r } define double @call_fmin() sanitize_numerical_stability { ; DQQ-LABEL: @call_fmin( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @fmin(double 1.000000e+00, double 2.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_fmin to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_fmin( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @fmin(double 1.000000e+00, double 2.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_fmin to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @fmin(double 1.0, double 2.0) ret double %r } define x86_fp80 @call_fminl() sanitize_numerical_stability { ; CHECK-LABEL: @call_fminl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fminl(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @fminl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) ret x86_fp80 %r } ;############################################################### ;# fminimum_num # ;############################################################### declare float @fminimum_numf(float, float) declare double @fminimum_num(double, double) declare x86_fp80 @fminimum_numl(x86_fp80, x86_fp80) define float @call_fminimum_numf() sanitize_numerical_stability { ; CHECK-LABEL: @call_fminimum_numf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @fminimum_numf(float 1.000000e+00, float 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.minimumnum.f64(double 1.000000e+00, double 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminimum_numf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @fminimum_numf(float 1.0, float 2.0) ret float %r } define double @call_fminimum_num() sanitize_numerical_stability { ; DQQ-LABEL: @call_fminimum_num( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @fminimum_num(double 1.000000e+00, double 2.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_fminimum_num to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_fminimum_num( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @fminimum_num(double 1.000000e+00, double 2.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_fminimum_num to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @fminimum_num(double 1.0, double 2.0) ret double %r } define x86_fp80 @call_fminimum_numl() sanitize_numerical_stability { ; CHECK-LABEL: @call_fminimum_numl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fminimum_numl(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fminimum_numl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @fminimum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) ret x86_fp80 %r } ;############################################################### ;# fmaximum_num # ;############################################################### declare float @fmaximum_numf(float, float) declare double @fmaximum_num(double, double) declare x86_fp80 @fmaximum_numl(x86_fp80, x86_fp80) define float @call_fmaximum_numf() sanitize_numerical_stability { ; CHECK-LABEL: @call_fmaximum_numf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @fmaximum_numf(float 1.000000e+00, float 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.maximumnum.f64(double 1.000000e+00, double 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaximum_numf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @fmaximum_numf(float 1.0, float 2.0) ret float %r } define double @call_fmaximum_num() sanitize_numerical_stability { ; DQQ-LABEL: @call_fmaximum_num( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @fmaximum_num(double 1.000000e+00, double 2.000000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_fmaximum_num to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_fmaximum_num( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @fmaximum_num(double 1.000000e+00, double 2.000000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_fmaximum_num to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @fmaximum_num(double 1.0, double 2.0) ret double %r } define x86_fp80 @call_fmaximum_numl() sanitize_numerical_stability { ; CHECK-LABEL: @call_fmaximum_numl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @fmaximum_numl(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximumnum.f80(x86_fp80 1.000000e+00, x86_fp80 2.000000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmaximum_numl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @fmaximum_numl(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) ret x86_fp80 %r } ;############################################################### ;# ceil # ;############################################################### declare float @ceilf(float) declare double @ceil(double) declare x86_fp80 @ceill(x86_fp80) define float @call_ceilf() sanitize_numerical_stability { ; CHECK-LABEL: @call_ceilf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @ceilf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.ceil.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_ceilf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @ceilf(float 1.5) ret float %r } define double @call_ceil() sanitize_numerical_stability { ; DQQ-LABEL: @call_ceil( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @ceil(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_ceil to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_ceil( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @ceil(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_ceil to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @ceil(double 1.5) ret double %r } define x86_fp80 @call_ceill() sanitize_numerical_stability { ; CHECK-LABEL: @call_ceill( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @ceill(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_ceill to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @ceill(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r } ;############################################################### ;# trunc # ;############################################################### declare float @truncf(float) declare double @trunc(double) declare x86_fp80 @truncl(x86_fp80) define float @call_truncf() sanitize_numerical_stability { ; CHECK-LABEL: @call_truncf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @truncf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.trunc.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_truncf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @truncf(float 1.5) ret float %r } define double @call_trunc() sanitize_numerical_stability { ; DQQ-LABEL: @call_trunc( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @trunc(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_trunc to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_trunc( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @trunc(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_trunc to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @trunc(double 1.5) ret double %r } define x86_fp80 @call_truncl() sanitize_numerical_stability { ; CHECK-LABEL: @call_truncl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @truncl(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_truncl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @truncl(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r } ;############################################################### ;# rint # ;############################################################### declare float @rintf(float) declare double @rint(double) declare x86_fp80 @rintl(x86_fp80) define float @call_rintf() sanitize_numerical_stability { ; CHECK-LABEL: @call_rintf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @rintf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.rint.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_rintf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @rintf(float 1.5) ret float %r } define double @call_rint() sanitize_numerical_stability { ; DQQ-LABEL: @call_rint( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @rint(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_rint to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_rint( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @rint(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_rint to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @rint(double 1.5) ret double %r } define x86_fp80 @call_rintl() sanitize_numerical_stability { ; CHECK-LABEL: @call_rintl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @rintl(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_rintl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @rintl(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r } ;############################################################### ;# nearbyint # ;############################################################### declare float @nearbyintf(float) declare double @nearbyint(double) declare x86_fp80 @nearbyintl(x86_fp80) define float @call_nearbyintf() sanitize_numerical_stability { ; CHECK-LABEL: @call_nearbyintf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @nearbyintf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.nearbyint.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_nearbyintf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @nearbyintf(float 1.5) ret float %r } define double @call_nearbyint() sanitize_numerical_stability { ; DQQ-LABEL: @call_nearbyint( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @nearbyint(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_nearbyint to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_nearbyint( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @nearbyint(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_nearbyint to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @nearbyint(double 1.5) ret double %r } define x86_fp80 @call_nearbyintl() sanitize_numerical_stability { ; CHECK-LABEL: @call_nearbyintl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @nearbyintl(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_nearbyintl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @nearbyintl(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r } ;############################################################### ;# round # ;############################################################### declare float @roundf(float) declare double @round(double) declare x86_fp80 @roundl(x86_fp80) define float @call_roundf() sanitize_numerical_stability { ; CHECK-LABEL: @call_roundf( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call float @roundf(float 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.round.f64(double 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP0]], i32 1, i64 0) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; CHECK-NEXT: [[TMP3:%.*]] = fpext float [[R]] to double ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], double [[TMP3]], double [[TMP0]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_roundf to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store double [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 8 ; CHECK-NEXT: ret float [[R]] ; entry: %r = call float @roundf(float 1.5) ret float %r } define double @call_round() sanitize_numerical_stability { ; DQQ-LABEL: @call_round( ; DQQ-NEXT: entry: ; DQQ-NEXT: [[R:%.*]] = call double @round(double 1.500000e+00) ; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 1.500000e+00) ; DQQ-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; DQQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_q(double [[R]], fp128 [[TMP1]], i32 1, i64 0) ; DQQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; DQQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to fp128 ; DQQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; DQQ-NEXT: store i64 ptrtoint (ptr @call_round to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DQQ-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; DQQ-NEXT: ret double [[R]] ; ; DLQ-LABEL: @call_round( ; DLQ-NEXT: entry: ; DLQ-NEXT: [[R:%.*]] = call double @round(double 1.500000e+00) ; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 1.500000e+00) ; DLQ-NEXT: [[TMP1:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP0]], i32 1, i64 0) ; DLQ-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 ; DLQ-NEXT: [[TMP3:%.*]] = fpext double [[R]] to x86_fp80 ; DLQ-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], x86_fp80 [[TMP3]], x86_fp80 [[TMP0]] ; DLQ-NEXT: store i64 ptrtoint (ptr @call_round to i64), ptr @__nsan_shadow_ret_tag, align 8 ; DLQ-NEXT: store x86_fp80 [[TMP4]], ptr @__nsan_shadow_ret_ptr, align 16 ; DLQ-NEXT: ret double [[R]] ; entry: %r = call double @round(double 1.5) ret double %r } define x86_fp80 @call_roundl() sanitize_numerical_stability { ; CHECK-LABEL: @call_roundl( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @roundl(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 1.500000e+00) ; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 ; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[R]], fp128 [[TMP1]], i32 1, i64 0) ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 ; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[R]] to fp128 ; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] ; CHECK-NEXT: store i64 ptrtoint (ptr @call_roundl to i64), ptr @__nsan_shadow_ret_tag, align 8 ; CHECK-NEXT: store fp128 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 ; CHECK-NEXT: ret x86_fp80 [[R]] ; entry: %r = call x86_fp80 @roundl(x86_fp80 0xK3FFFC000000000000000) ret x86_fp80 %r }