From 65bf05a494c9a2fec7128e0c7b59aadcfb9f774c Mon Sep 17 00:00:00 2001 From: Lewis Crawford Date: Tue, 17 Mar 2026 15:01:45 +0000 Subject: [PATCH] [Instrumentation][nsan] Intrinsic tests + bugfixes (#186803) Add comprehensive lit-test coverage to the NumericalStabilitySanitizer's intrinsic and libfunc handling. Also, several minor bugfixes: - Fix typo in llvm.nearbyint.f80's name. - Remove lround and llround intrinsics, since they return ints (and are not instrumented by nsan as a result). - Fix fmuladd.f64 intrinsic to map to fmuladd instead of fma. - Add missing fmuladd.f80 variant. --- .../NumericalStabilitySanitizer.cpp | 23 +- .../NumericalStabilitySanitizer/basic.ll | 74 - .../NumericalStabilitySanitizer/intrinsics.ll | 1809 +++++++++++++++++ .../NumericalStabilitySanitizer/libfuncs.ll | 1432 +++++++++++++ 4 files changed, 3245 insertions(+), 93 deletions(-) create mode 100644 llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll create mode 100644 llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll diff --git a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp index 1581ae4f3ce7..5f895ad33d06 100644 --- a/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/NumericalStabilitySanitizer.cpp @@ -1398,14 +1398,11 @@ const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = { {"llvm.log2.f64", Intrinsic::log2, makeX86FP80X86FP80}, {"llvm.log2.f80", Intrinsic::log2, makeX86FP80X86FP80}, {"llvm.fma.f32", Intrinsic::fma, makeDoubleDoubleDoubleDouble}, - - {"llvm.fmuladd.f32", Intrinsic::fmuladd, makeDoubleDoubleDoubleDouble}, - {"llvm.fma.f64", Intrinsic::fma, makeX86FP80X86FP80X86FP80X86FP80}, - - {"llvm.fmuladd.f64", Intrinsic::fma, makeX86FP80X86FP80X86FP80X86FP80}, - {"llvm.fma.f80", Intrinsic::fma, makeX86FP80X86FP80X86FP80X86FP80}, + {"llvm.fmuladd.f32", Intrinsic::fmuladd, makeDoubleDoubleDoubleDouble}, + {"llvm.fmuladd.f64", Intrinsic::fmuladd, makeX86FP80X86FP80X86FP80X86FP80}, + {"llvm.fmuladd.f80", Intrinsic::fmuladd, makeX86FP80X86FP80X86FP80X86FP80}, {"llvm.fabs.f32", Intrinsic::fabs, makeDoubleDouble}, {"llvm.fabs.f64", Intrinsic::fabs, makeX86FP80X86FP80}, {"llvm.fabs.f80", Intrinsic::fabs, makeX86FP80X86FP80}, @@ -1438,22 +1435,10 @@ const KnownIntrinsic::WidenedIntrinsic KnownIntrinsic::kWidenedIntrinsics[] = { {"llvm.rint.f80", Intrinsic::rint, makeX86FP80X86FP80}, {"llvm.nearbyint.f32", Intrinsic::nearbyint, makeDoubleDouble}, {"llvm.nearbyint.f64", Intrinsic::nearbyint, makeX86FP80X86FP80}, - {"llvm.nearbyin80f64", Intrinsic::nearbyint, makeX86FP80X86FP80}, + {"llvm.nearbyint.f80", Intrinsic::nearbyint, makeX86FP80X86FP80}, {"llvm.round.f32", Intrinsic::round, makeDoubleDouble}, {"llvm.round.f64", Intrinsic::round, makeX86FP80X86FP80}, {"llvm.round.f80", Intrinsic::round, makeX86FP80X86FP80}, - {"llvm.lround.f32", Intrinsic::lround, makeDoubleDouble}, - {"llvm.lround.f64", Intrinsic::lround, makeX86FP80X86FP80}, - {"llvm.lround.f80", Intrinsic::lround, makeX86FP80X86FP80}, - {"llvm.llround.f32", Intrinsic::llround, makeDoubleDouble}, - {"llvm.llround.f64", Intrinsic::llround, makeX86FP80X86FP80}, - {"llvm.llround.f80", Intrinsic::llround, makeX86FP80X86FP80}, - {"llvm.lrint.f32", Intrinsic::lrint, makeDoubleDouble}, - {"llvm.lrint.f64", Intrinsic::lrint, makeX86FP80X86FP80}, - {"llvm.lrint.f80", Intrinsic::lrint, makeX86FP80X86FP80}, - {"llvm.llrint.f32", Intrinsic::llrint, makeDoubleDouble}, - {"llvm.llrint.f64", Intrinsic::llrint, makeX86FP80X86FP80}, - {"llvm.llrint.f80", Intrinsic::llrint, makeX86FP80X86FP80}, }; const KnownIntrinsic::LFEntry KnownIntrinsic::kLibfuncIntrinsics[] = { diff --git a/llvm/test/Instrumentation/NumericalStabilitySanitizer/basic.ll b/llvm/test/Instrumentation/NumericalStabilitySanitizer/basic.ll index 304508d9f86c..a27e3318c59e 100644 --- a/llvm/test/Instrumentation/NumericalStabilitySanitizer/basic.ll +++ b/llvm/test/Instrumentation/NumericalStabilitySanitizer/basic.ll @@ -503,80 +503,6 @@ entry: ret void } -declare float @llvm.sin.f32(float) readnone - -define float @call_sin_intrinsic() sanitize_numerical_stability { -; CHECK-LABEL: @call_sin_intrinsic( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float 1.000000e+00) -; 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_sin_intrinsic 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 @llvm.sin.f32(float 1.0) - ret float %r -} - -declare float @sinf(float) - -define float @call_sinf_libfunc() sanitize_numerical_stability { -; CHECK-LABEL: @call_sinf_libfunc( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[R:%.*]] = call float @sinf(float 1.000000e+00) #[[ATTR3:[0-9]+]] -; 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_libfunc 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 -} - -declare double @sin(double) - -; FIXME: nsan uses `sin(double)` for fp128. -define double @call_sin_libfunc() sanitize_numerical_stability { -; DQQ-LABEL: @call_sin_libfunc( -; 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 0xK3FFF8000000000000000) -; 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_libfunc 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_libfunc( -; 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 0xK3FFF8000000000000000) -; 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_libfunc 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 -} - declare double @frexp(double, i32*) define double @call_frexp_libfunc_nointrinsic(double %0, i32* nocapture %1) sanitize_numerical_stability { diff --git a/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll b/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll new file mode 100644 index 000000000000..b2d67bc9816d --- /dev/null +++ b/llvm/test/Instrumentation/NumericalStabilitySanitizer/intrinsics.ll @@ -0,0 +1,1809 @@ +; 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 @llvm.sqrt.f32(float) readnone +declare double @llvm.sqrt.f64(double) readnone +declare x86_fp80 @llvm.sqrt.f80(x86_fp80) readnone + +define float @call_sqrt_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_sqrt_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.sqrt.f32(float 4.000000e+00) +; 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_sqrt_f32 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 @llvm.sqrt.f32(float 4.0) + ret float %r +} + +define double @call_sqrt_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_sqrt_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.sqrt.f64(double 4.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.sqrt.f64(double 4.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) +; 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_f64 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 @llvm.sqrt.f64(double 4.0) + ret double %r +} + +define x86_fp80 @call_sqrt_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_sqrt_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) +; 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_sqrt_f80 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 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# powi # +;############################################################### +declare float @llvm.powi.f32(float, i32) readnone +declare double @llvm.powi.f64(double, i32) readnone +declare x86_fp80 @llvm.powi.f80(x86_fp80, i32) readnone + +define float @call_powi_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_powi_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.powi.f32.i32(float 2.000000e+00, i32 3) +; CHECK-NEXT: [[TMP0:%.*]] = call float @llvm.powi.f32.i32(float 2.000000e+00, i32 3) +; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[TMP0]] to double +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_float_d(float [[R]], double [[TMP1]], i32 1, i64 0) +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = fpext float [[R]] to double +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], double [[TMP4]], double [[TMP1]] +; CHECK-NEXT: store i64 ptrtoint (ptr @call_powi_f32 to i64), ptr @__nsan_shadow_ret_tag, align 8 +; CHECK-NEXT: store double [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 8 +; CHECK-NEXT: ret float [[R]] +; +entry: + %r = call float @llvm.powi.f32(float 2.0, i32 3) + ret float %r +} + +define double @call_powi_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_powi_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.powi.f64.i32(double 2.000000e+00, i32 3) +; DQQ-NEXT: [[TMP0:%.*]] = call double @llvm.powi.f64.i32(double 2.000000e+00, i32 3) +; DQQ-NEXT: [[TMP1:%.*]] = fpext double [[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_powi_f64 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_powi_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.powi.f64.i32(double 2.000000e+00, i32 3) +; DLQ-NEXT: [[TMP0:%.*]] = call double @llvm.powi.f64.i32(double 2.000000e+00, i32 3) +; DLQ-NEXT: [[TMP1:%.*]] = fpext double [[TMP0]] to x86_fp80 +; DLQ-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_double_l(double [[R]], x86_fp80 [[TMP1]], i32 1, i64 0) +; DLQ-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 +; DLQ-NEXT: [[TMP4:%.*]] = fpext double [[R]] to x86_fp80 +; DLQ-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], x86_fp80 [[TMP4]], x86_fp80 [[TMP1]] +; DLQ-NEXT: store i64 ptrtoint (ptr @call_powi_f64 to i64), ptr @__nsan_shadow_ret_tag, align 8 +; DLQ-NEXT: store x86_fp80 [[TMP5]], ptr @__nsan_shadow_ret_ptr, align 16 +; DLQ-NEXT: ret double [[R]] +; +entry: + %r = call double @llvm.powi.f64(double 2.0, i32 3) + ret double %r +} + +define x86_fp80 @call_powi_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_powi_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.powi.f80.i32(x86_fp80 0xK40008000000000000000, i32 3) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.powi.f80.i32(x86_fp80 0xK40008000000000000000, i32 3) +; 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_powi_f80 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 @llvm.powi.f80(x86_fp80 0xK40008000000000000000, i32 3) + ret x86_fp80 %r +} + +;############################################################### +;# sin # +;############################################################### +declare float @llvm.sin.f32(float) readnone +declare double @llvm.sin.f64(double) readnone +declare x86_fp80 @llvm.sin.f80(x86_fp80) readnone + +define float @call_sin_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_sin_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.sin.f32(float 1.000000e+00) +; 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_sin_f32 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 @llvm.sin.f32(float 1.0) + ret float %r +} + +define double @call_sin_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_sin_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.sin.f64(double 1.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.sin.f64(double 1.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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 @llvm.sin.f64(double 1.0) + ret double %r +} + +define x86_fp80 @call_sin_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_sin_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_sin_f80 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 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# cos # +;############################################################### +declare float @llvm.cos.f32(float) readnone +declare double @llvm.cos.f64(double) readnone +declare x86_fp80 @llvm.cos.f80(x86_fp80) readnone + +define float @call_cos_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_cos_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.cos.f32(float 1.000000e+00) +; 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_cos_f32 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 @llvm.cos.f32(float 1.0) + ret float %r +} + +define double @call_cos_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_cos_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.cos.f64(double 1.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.cos.f64(double 1.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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 @llvm.cos.f64(double 1.0) + ret double %r +} + +define x86_fp80 @call_cos_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_cos_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_cos_f80 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 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# pow # +;############################################################### +declare float @llvm.pow.f32(float, float) readnone +declare double @llvm.pow.f64(double, double) readnone +declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) readnone + +define float @call_pow_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_pow_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.pow.f32(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_pow_f32 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 @llvm.pow.f32(float 2.0, float 3.0) + ret float %r +} + +define double @call_pow_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_pow_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.pow.f64(double 2.000000e+00, double 3.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.pow.f64(double 2.000000e+00, double 3.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_f64 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 @llvm.pow.f64(double 2.0, double 3.0) + ret double %r +} + +define x86_fp80 @call_pow_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_pow_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; 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_pow_f80 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 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# exp # +;############################################################### +declare float @llvm.exp.f32(float) readnone +declare double @llvm.exp.f64(double) readnone +declare x86_fp80 @llvm.exp.f80(x86_fp80) readnone + +define float @call_exp_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_exp_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.exp.f32(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_exp_f32 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 @llvm.exp.f32(float 1.0) + ret float %r +} + +define double @call_exp_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_exp_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.exp.f64(double 1.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.exp.f64(double 1.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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 @llvm.exp.f64(double 1.0) + ret double %r +} + +define x86_fp80 @call_exp_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_exp_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_exp_f80 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 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# exp2 # +;############################################################### +declare float @llvm.exp2.f32(float) readnone +declare double @llvm.exp2.f64(double) readnone +declare x86_fp80 @llvm.exp2.f80(x86_fp80) readnone + +define float @call_exp2_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_exp2_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.exp2.f32(float 1.000000e+00) +; 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_exp2_f32 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 @llvm.exp2.f32(float 1.0) + ret float %r +} + +define double @call_exp2_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_exp2_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.exp2.f64(double 1.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.exp2.f64(double 1.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_f64 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 @llvm.exp2.f64(double 1.0) + ret double %r +} + +define x86_fp80 @call_exp2_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_exp2_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) +; 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_exp2_f80 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 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# log # +;############################################################### +declare float @llvm.log.f32(float) readnone +declare double @llvm.log.f64(double) readnone +declare x86_fp80 @llvm.log.f80(x86_fp80) readnone + +define float @call_log_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_log_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.log.f32(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_log_f32 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 @llvm.log.f32(float 2.0) + ret float %r +} + +define double @call_log_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_log_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.log.f64(double 2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 0xK40008000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.log.f64(double 2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 0xK40008000000000000000) +; 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_f64 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 @llvm.log.f64(double 2.0) + ret double %r +} + +define x86_fp80 @call_log_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_log_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 0xK40008000000000000000) +; 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_log_f80 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 @llvm.log.f80(x86_fp80 0xK40008000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# log10 # +;############################################################### +declare float @llvm.log10.f32(float) readnone +declare double @llvm.log10.f64(double) readnone +declare x86_fp80 @llvm.log10.f80(x86_fp80) readnone + +define float @call_log10_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_log10_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.log10.f32(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_log10_f32 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 @llvm.log10.f32(float 100.0) + ret float %r +} + +define double @call_log10_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_log10_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.log10.f64(double 1.000000e+02) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 0xK4005C800000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.log10.f64(double 1.000000e+02) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 0xK4005C800000000000000) +; 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_f64 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 @llvm.log10.f64(double 100.0) + ret double %r +} + +define x86_fp80 @call_log10_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_log10_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 0xK7FFF0000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 0xK7FFF0000000000000000) +; 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_log10_f80 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 @llvm.log10.f80(x86_fp80 0xK40590000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# log2 # +;############################################################### +declare float @llvm.log2.f32(float) readnone +declare double @llvm.log2.f64(double) readnone +declare x86_fp80 @llvm.log2.f80(x86_fp80) readnone + +define float @call_log2_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_log2_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.log2.f32(float 8.000000e+00) +; 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_log2_f32 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 @llvm.log2.f32(float 8.0) + ret float %r +} + +define double @call_log2_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_log2_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.log2.f64(double 8.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 0xK40028000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.log2.f64(double 8.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 0xK40028000000000000000) +; 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_f64 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 @llvm.log2.f64(double 8.0) + ret double %r +} + +define x86_fp80 @call_log2_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_log2_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 0xK40018000000000000000) +; 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_log2_f80 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 @llvm.log2.f80(x86_fp80 0xK40018000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# fma # +;############################################################### +declare float @llvm.fma.f32(float, float, float) readnone +declare double @llvm.fma.f64(double, double, double) readnone +declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) readnone + +define float @call_fma_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_fma_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.fma.f32(float 1.000000e+00, float 2.000000e+00, float 3.000000e+00) +; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.fma.f64(double 1.000000e+00, 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_fma_f32 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 @llvm.fma.f32(float 1.0, float 2.0, float 3.0) + ret float %r +} + +define double @call_fma_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_fma_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 1.000000e+00, double 2.000000e+00, double 3.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fma.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_fma_f64 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_fma_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.fma.f64(double 1.000000e+00, double 2.000000e+00, double 3.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fma.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_fma_f64 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 @llvm.fma.f64(double 1.0, double 2.0, double 3.0) + ret double %r +} + +define x86_fp80 @call_fma_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_fma_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.fma.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fma.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; 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_fma_f80 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 @llvm.fma.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# fmuladd # +;############################################################### +declare float @llvm.fmuladd.f32(float, float, float) readnone +declare double @llvm.fmuladd.f64(double, double, double) readnone +declare x86_fp80 @llvm.fmuladd.f80(x86_fp80, x86_fp80, x86_fp80) readnone + +define float @call_fmuladd_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_fmuladd_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.fmuladd.f32(float 1.000000e+00, float 2.000000e+00, float 3.000000e+00) +; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.fmuladd.f64(double 1.000000e+00, 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_fmuladd_f32 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 @llvm.fmuladd.f32(float 1.0, float 2.0, float 3.0) + ret float %r +} + +define double @call_fmuladd_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_fmuladd_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 1.000000e+00, double 2.000000e+00, double 3.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_fmuladd_f64 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_fmuladd_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.fmuladd.f64(double 1.000000e+00, double 2.000000e+00, double 3.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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_fmuladd_f64 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 @llvm.fmuladd.f64(double 1.0, double 2.0, double 3.0) + ret double %r +} + +define x86_fp80 @call_fmuladd_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_fmuladd_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP6:%.*]] = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP1:%.*]] = fpext x86_fp80 [[TMP6]] to fp128 +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @__nsan_internal_check_longdouble_q(x86_fp80 [[TMP0]], fp128 [[TMP1]], i32 1, i64 0) +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 1 +; CHECK-NEXT: [[TMP4:%.*]] = fpext x86_fp80 [[TMP0]] to fp128 +; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], fp128 [[TMP4]], fp128 [[TMP1]] +; CHECK-NEXT: store i64 ptrtoint (ptr @call_fmuladd_f80 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 [[TMP0]] +; +entry: + %r = call x86_fp80 @llvm.fmuladd.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# fabs # +;############################################################### +declare float @llvm.fabs.f32(float) readnone +declare double @llvm.fabs.f64(double) readnone +declare x86_fp80 @llvm.fabs.f80(x86_fp80) readnone + +define float @call_fabs_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_fabs_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.fabs.f32(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_fabs_f32 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 @llvm.fabs.f32(float -1.0) + ret float %r +} + +define double @call_fabs_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_fabs_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.fabs.f64(double -1.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.fabs.f64(double -1.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) +; 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_f64 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 @llvm.fabs.f64(double -1.0) + ret double %r +} + +define x86_fp80 @call_fabs_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_fabs_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) +; 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_fabs_f80 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 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# minnum # +;############################################################### +declare float @llvm.minnum.f32(float, float) readnone +declare double @llvm.minnum.f64(double, double) readnone +declare x86_fp80 @llvm.minnum.f80(x86_fp80, x86_fp80) readnone + +define float @call_minnum_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_minnum_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.minnum.f32(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_minnum_f32 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 @llvm.minnum.f32(float 1.0, float 2.0) + ret float %r +} + +define double @call_minnum_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_minnum_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double 1.000000e+00, double 2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minnum_f64 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_minnum_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.minnum.f64(double 1.000000e+00, double 2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minnum_f64 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 @llvm.minnum.f64(double 1.0, double 2.0) + ret double %r +} + +define x86_fp80 @call_minnum_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_minnum_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minnum_f80 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 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# maxnum # +;############################################################### +declare float @llvm.maxnum.f32(float, float) readnone +declare double @llvm.maxnum.f64(double, double) readnone +declare x86_fp80 @llvm.maxnum.f80(x86_fp80, x86_fp80) readnone + +define float @call_maxnum_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_maxnum_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.maxnum.f32(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_maxnum_f32 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 @llvm.maxnum.f32(float 1.0, float 2.0) + ret float %r +} + +define double @call_maxnum_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_maxnum_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.maxnum.f64(double 1.000000e+00, double 2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maxnum_f64 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_maxnum_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.maxnum.f64(double 1.000000e+00, double 2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maxnum_f64 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 @llvm.maxnum.f64(double 1.0, double 2.0) + ret double %r +} + +define x86_fp80 @call_maxnum_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_maxnum_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maxnum_f80 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 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# minimum # +;############################################################### +declare float @llvm.minimum.f32(float, float) readnone +declare double @llvm.minimum.f64(double, double) readnone +declare x86_fp80 @llvm.minimum.f80(x86_fp80, x86_fp80) readnone + +define float @call_minimum_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_minimum_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.minimum.f32(float 1.000000e+00, float 2.000000e+00) +; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.minimum.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_minimum_f32 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 @llvm.minimum.f32(float 1.0, float 2.0) + ret float %r +} + +define double @call_minimum_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_minimum_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.minimum.f64(double 1.000000e+00, double 2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minimum_f64 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_minimum_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.minimum.f64(double 1.000000e+00, double 2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minimum_f64 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 @llvm.minimum.f64(double 1.0, double 2.0) + ret double %r +} + +define x86_fp80 @call_minimum_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_minimum_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.minimum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minimum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_minimum_f80 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 @llvm.minimum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# maximum # +;############################################################### +declare float @llvm.maximum.f32(float, float) readnone +declare double @llvm.maximum.f64(double, double) readnone +declare x86_fp80 @llvm.maximum.f80(x86_fp80, x86_fp80) readnone + +define float @call_maximum_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_maximum_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.maximum.f32(float 1.000000e+00, float 2.000000e+00) +; CHECK-NEXT: [[TMP0:%.*]] = call double @llvm.maximum.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_maximum_f32 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 @llvm.maximum.f32(float 1.0, float 2.0) + ret float %r +} + +define double @call_maximum_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_maximum_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.maximum.f64(double 1.000000e+00, double 2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maximum_f64 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_maximum_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.maximum.f64(double 1.000000e+00, double 2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maximum_f64 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 @llvm.maximum.f64(double 1.0, double 2.0) + ret double %r +} + +define x86_fp80 @call_maximum_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_maximum_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.maximum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maximum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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_maximum_f80 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 @llvm.maximum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# copysign # +;############################################################### +declare float @llvm.copysign.f32(float, float) readnone +declare double @llvm.copysign.f64(double, double) readnone +declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) readnone + +define float @call_copysign_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_copysign_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.copysign.f32(float 1.000000e+00, float -2.000000e+00) +; 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_copysign_f32 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 @llvm.copysign.f32(float 1.0, float -2.0) + ret float %r +} + +define double @call_copysign_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_copysign_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double -2.000000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKC0008000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double -2.000000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKC0008000000000000000) +; 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_f64 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 @llvm.copysign.f64(double 1.0, double -2.0) + ret double %r +} + +define x86_fp80 @call_copysign_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_copysign_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) +; 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_copysign_f80 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 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# floor # +;############################################################### +declare float @llvm.floor.f32(float) readnone +declare double @llvm.floor.f64(double) readnone +declare x86_fp80 @llvm.floor.f80(x86_fp80) readnone + +define float @call_floor_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_floor_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.floor.f32(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_floor_f32 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 @llvm.floor.f32(float 1.5) + ret float %r +} + +define double @call_floor_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_floor_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.floor.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.floor.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.floor.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_floor_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_floor_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_floor_f80 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 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# ceil # +;############################################################### +declare float @llvm.ceil.f32(float) readnone +declare double @llvm.ceil.f64(double) readnone +declare x86_fp80 @llvm.ceil.f80(x86_fp80) readnone + +define float @call_ceil_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_ceil_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.ceil.f32(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_ceil_f32 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 @llvm.ceil.f32(float 1.5) + ret float %r +} + +define double @call_ceil_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_ceil_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.ceil.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.ceil.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.ceil.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_ceil_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_ceil_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_ceil_f80 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 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# trunc # +;############################################################### +declare float @llvm.trunc.f32(float) readnone +declare double @llvm.trunc.f64(double) readnone +declare x86_fp80 @llvm.trunc.f80(x86_fp80) readnone + +define float @call_trunc_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_trunc_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.trunc.f32(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_trunc_f32 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 @llvm.trunc.f32(float 1.5) + ret float %r +} + +define double @call_trunc_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_trunc_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.trunc.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.trunc.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.trunc.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_trunc_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_trunc_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_trunc_f80 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 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# rint # +;############################################################### +declare float @llvm.rint.f32(float) readnone +declare double @llvm.rint.f64(double) readnone +declare x86_fp80 @llvm.rint.f80(x86_fp80) readnone + +define float @call_rint_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_rint_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.rint.f32(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_rint_f32 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 @llvm.rint.f32(float 1.5) + ret float %r +} + +define double @call_rint_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_rint_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.rint.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.rint.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.rint.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_rint_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_rint_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_rint_f80 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 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# nearbyint # +;############################################################### +declare float @llvm.nearbyint.f32(float) readnone +declare double @llvm.nearbyint.f64(double) readnone +declare x86_fp80 @llvm.nearbyint.f80(x86_fp80) readnone + +define float @call_nearbyint_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_nearbyint_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.nearbyint.f32(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_nearbyint_f32 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 @llvm.nearbyint.f32(float 1.5) + ret float %r +} + +define double @call_nearbyint_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_nearbyint_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.nearbyint.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.nearbyint.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.nearbyint.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_nearbyint_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_nearbyint_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_nearbyint_f80 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 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} + +;############################################################### +;# round # +;############################################################### +declare float @llvm.round.f32(float) readnone +declare double @llvm.round.f64(double) readnone +declare x86_fp80 @llvm.round.f80(x86_fp80) readnone + +define float @call_round_f32() sanitize_numerical_stability { +; CHECK-LABEL: @call_round_f32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call float @llvm.round.f32(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_round_f32 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 @llvm.round.f32(float 1.5) + ret float %r +} + +define double @call_round_f64() sanitize_numerical_stability { +; DQQ-LABEL: @call_round_f64( +; DQQ-NEXT: entry: +; DQQ-NEXT: [[R:%.*]] = call double @llvm.round.f64(double 1.500000e+00) +; DQQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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_f64( +; DLQ-NEXT: entry: +; DLQ-NEXT: [[R:%.*]] = call double @llvm.round.f64(double 1.500000e+00) +; DLQ-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_f64 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 @llvm.round.f64(double 1.5) + ret double %r +} + +define x86_fp80 @call_round_f80() sanitize_numerical_stability { +; CHECK-LABEL: @call_round_f80( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[R:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) +; 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_round_f80 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 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) + ret x86_fp80 %r +} diff --git a/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll b/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll new file mode 100644 index 000000000000..e9ef2104fd37 --- /dev/null +++ b/llvm/test/Instrumentation/NumericalStabilitySanitizer/libfuncs.ll @@ -0,0 +1,1432 @@ +; 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 0xK40018000000000000000) +; 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 0xK40018000000000000000) +; 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 0xK40018000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sqrt.f80(x86_fp80 0xK40018000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.sin.f80(x86_fp80 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.cos.f80(x86_fp80 0xK3FFF8000000000000000) +; 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 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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 0xK40008000000000000000, x86_fp80 0xK4000C000000000000000) +; 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 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.pow.f80(x86_fp80 0xK40008000000000000000, x86_fp80 0xK40018000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp.f80(x86_fp80 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) +; 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 0xK3FFF8000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.exp2.f80(x86_fp80 0xK3FFF8000000000000000) +; 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 0xK40008000000000000000) +; 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 0xK40008000000000000000) +; 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 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log.f80(x86_fp80 0xK40008000000000000000) +; 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 0xK4005C800000000000000) +; 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 0xK4005C800000000000000) +; 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 0xK7FFF0000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log10.f80(x86_fp80 0xK7FFF0000000000000000) +; 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 0xK40028000000000000000) +; 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 0xK40028000000000000000) +; 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 0xK40018000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.log2.f80(x86_fp80 0xK40018000000000000000) +; 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 0xKBFFF8000000000000000) +; 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 0xKBFFF8000000000000000) +; 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 0xKBFFF8000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.fabs.f80(x86_fp80 0xKBFFF8000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xKC0008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xKC0008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) #[[ATTR3]] +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.copysign.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xKBFFF8000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.floor.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.maxnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.minnum.f80(x86_fp80 0xK3FFF8000000000000000, x86_fp80 0xK40008000000000000000) +; 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 +} + +;############################################################### +;# 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.ceil.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.trunc.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.rint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.nearbyint.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; 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 0xK3FFFC000000000000000) +; CHECK-NEXT: [[TMP0:%.*]] = call x86_fp80 @llvm.round.f80(x86_fp80 0xK3FFFC000000000000000) +; 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 +}