[compiler-rt] [compiler-rt][nsan] Add support for nan detection (PR #101531)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 7 00:06:23 PDT 2024
https://github.com/cseslowpoke updated https://github.com/llvm/llvm-project/pull/101531
>From 3a70ccbc4a07edc7659aba4ccbdfec06182a3801 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Wed, 31 Jul 2024 19:52:05 +0800
Subject: [PATCH 1/7] [compiler-rt][nsan] Add support for NaN detection
---
compiler-rt/lib/nsan/nsan.cpp | 8 ++++++++
compiler-rt/lib/nsan/nsan_flags.inc | 1 +
2 files changed, 9 insertions(+)
diff --git a/compiler-rt/lib/nsan/nsan.cpp b/compiler-rt/lib/nsan/nsan.cpp
index 568a1b3a65575..9c505193daa00 100644
--- a/compiler-rt/lib/nsan/nsan.cpp
+++ b/compiler-rt/lib/nsan/nsan.cpp
@@ -444,6 +444,14 @@ int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType,
const InternalFT check_value = value;
const InternalFT check_shadow = Shadow;
+ // We only check for NaNs in the value, not the shadow.
+ if (flags().check_nan && isnan(check_value)) {
+ Decorator D;
+ Printf("%s", D.Warning());
+ Printf("WARNING: NumericalStabilitySanitizer: NaN detected\n");
+ Printf("%s", D.Default());
+ }
+
// See this article for an interesting discussion of how to compare floats:
// https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
static constexpr const FT Eps = FTInfo<FT>::kEpsilon;
diff --git a/compiler-rt/lib/nsan/nsan_flags.inc b/compiler-rt/lib/nsan/nsan_flags.inc
index 63c15475f6754..321305d386dbd 100644
--- a/compiler-rt/lib/nsan/nsan_flags.inc
+++ b/compiler-rt/lib/nsan/nsan_flags.inc
@@ -47,3 +47,4 @@ NSAN_FLAG(bool, enable_loadtracking_stats, false,
"memory, the number of times nsan resumed from the original value "
"due to invalid or unknown types.")
NSAN_FLAG(bool, print_stats_on_exit, false, "If true, print stats on exit.")
+NSAN_FLAG(bool, check_nan, false, "If true, check the floating-point number is nan")
\ No newline at end of file
>From a43e25ed97b8dc80d86f092e3fc46510d6a76538 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Thu, 1 Aug 2024 19:54:30 +0800
Subject: [PATCH 2/7] [compiler-rt][nsan] Add test for NaN dectection
---
compiler-rt/test/nsan/nan.cpp | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 compiler-rt/test/nsan/nan.cpp
diff --git a/compiler-rt/test/nsan/nan.cpp b/compiler-rt/test/nsan/nan.cpp
new file mode 100644
index 0000000000000..ce38c1abd9f44
--- /dev/null
+++ b/compiler-rt/test/nsan/nan.cpp
@@ -0,0 +1,22 @@
+// RUN: %clangxx_nsan -O0 -g %s -o %t
+// RUN: NSAN_OPTIONS=check_nan=true %run %t 2>&1 | FileCheck %s
+
+
+#include<cmath>
+#include<cstdio>
+
+// This function returns a NaN value for triggering the NaN detection.
+__attribute__((noinline))
+float ReturnNaN() {
+ float ret = 0.0 / 0.0;
+ return ret;
+ // CHECK: WARNING: NumericalStabilitySanitizer: NaN detected
+}
+
+
+int main() {
+ float val = ReturnNaN();
+ printf("val: %f\n", val);
+ // CHECK: WARNING: NumericalStabilitySanitizer: NaN detected
+ return 0;
+}
>From e6017b53bf27fbbd9ca55a60ff50af78c8986eae Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Fri, 2 Aug 2024 01:40:49 +0800
Subject: [PATCH 3/7] update formatting
---
compiler-rt/lib/nsan/nsan_flags.inc | 3 ++-
compiler-rt/test/nsan/nan.cpp | 9 +++------
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/compiler-rt/lib/nsan/nsan_flags.inc b/compiler-rt/lib/nsan/nsan_flags.inc
index 321305d386dbd..2c67c4bb7f779 100644
--- a/compiler-rt/lib/nsan/nsan_flags.inc
+++ b/compiler-rt/lib/nsan/nsan_flags.inc
@@ -47,4 +47,5 @@ NSAN_FLAG(bool, enable_loadtracking_stats, false,
"memory, the number of times nsan resumed from the original value "
"due to invalid or unknown types.")
NSAN_FLAG(bool, print_stats_on_exit, false, "If true, print stats on exit.")
-NSAN_FLAG(bool, check_nan, false, "If true, check the floating-point number is nan")
\ No newline at end of file
+NSAN_FLAG(bool, check_nan, false,
+ "If true, check the floating-point number is nan")
\ No newline at end of file
diff --git a/compiler-rt/test/nsan/nan.cpp b/compiler-rt/test/nsan/nan.cpp
index ce38c1abd9f44..a84b51859aaed 100644
--- a/compiler-rt/test/nsan/nan.cpp
+++ b/compiler-rt/test/nsan/nan.cpp
@@ -1,19 +1,16 @@
// RUN: %clangxx_nsan -O0 -g %s -o %t
// RUN: NSAN_OPTIONS=check_nan=true %run %t 2>&1 | FileCheck %s
-
-#include<cmath>
-#include<cstdio>
+#include <cmath>
+#include <cstdio>
// This function returns a NaN value for triggering the NaN detection.
-__attribute__((noinline))
-float ReturnNaN() {
+__attribute__((noinline)) float ReturnNaN() {
float ret = 0.0 / 0.0;
return ret;
// CHECK: WARNING: NumericalStabilitySanitizer: NaN detected
}
-
int main() {
float val = ReturnNaN();
printf("val: %f\n", val);
>From acfd2c85b8806d378e27f5e6f9b382cccedf4d01 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Sat, 3 Aug 2024 10:38:43 +0800
Subject: [PATCH 4/7] Change flag default and Return early when NaN is found.
---
compiler-rt/lib/nsan/nsan.cpp | 3 +++
compiler-rt/lib/nsan/nsan_flags.inc | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/nsan/nsan.cpp b/compiler-rt/lib/nsan/nsan.cpp
index 9c505193daa00..fa99c05f4f590 100644
--- a/compiler-rt/lib/nsan/nsan.cpp
+++ b/compiler-rt/lib/nsan/nsan.cpp
@@ -450,6 +450,9 @@ int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType,
Printf("%s", D.Warning());
Printf("WARNING: NumericalStabilitySanitizer: NaN detected\n");
Printf("%s", D.Default());
+ stack.Print();
+ // Checking for NaN values is meaningless when dealing with numbers.
+ return kResumeFromValue;
}
// See this article for an interesting discussion of how to compare floats:
diff --git a/compiler-rt/lib/nsan/nsan_flags.inc b/compiler-rt/lib/nsan/nsan_flags.inc
index 2c67c4bb7f779..52ca95a084dc4 100644
--- a/compiler-rt/lib/nsan/nsan_flags.inc
+++ b/compiler-rt/lib/nsan/nsan_flags.inc
@@ -47,5 +47,5 @@ NSAN_FLAG(bool, enable_loadtracking_stats, false,
"memory, the number of times nsan resumed from the original value "
"due to invalid or unknown types.")
NSAN_FLAG(bool, print_stats_on_exit, false, "If true, print stats on exit.")
-NSAN_FLAG(bool, check_nan, false,
+NSAN_FLAG(bool, check_nan, true,
"If true, check the floating-point number is nan")
\ No newline at end of file
>From f15bec8fbac68627b1bcf321b38417f472e555f9 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Mon, 5 Aug 2024 09:24:27 +0000
Subject: [PATCH 5/7] Show stack info for NaN check and add softmax test
---
compiler-rt/lib/nsan/nsan.cpp | 10 ++++++-
compiler-rt/test/nsan/softmax.cpp | 45 +++++++++++++++++++++++++++++++
2 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 compiler-rt/test/nsan/softmax.cpp
diff --git a/compiler-rt/lib/nsan/nsan.cpp b/compiler-rt/lib/nsan/nsan.cpp
index fa99c05f4f590..d5bdcac5da981 100644
--- a/compiler-rt/lib/nsan/nsan.cpp
+++ b/compiler-rt/lib/nsan/nsan.cpp
@@ -446,12 +446,20 @@ int32_t checkFT(const FT value, ShadowFT Shadow, CheckTypeT CheckType,
// We only check for NaNs in the value, not the shadow.
if (flags().check_nan && isnan(check_value)) {
+ GET_CALLER_PC_BP;
+ BufferedStackTrace stack;
+ stack.Unwind(pc, bp, nullptr, false);
+ if (GetSuppressionForStack(&stack, CheckKind::Consistency)) {
+ // FIXME: optionally print.
+ return flags().resume_after_suppression ? kResumeFromValue
+ : kContinueWithShadow;
+ }
Decorator D;
Printf("%s", D.Warning());
Printf("WARNING: NumericalStabilitySanitizer: NaN detected\n");
Printf("%s", D.Default());
stack.Print();
- // Checking for NaN values is meaningless when dealing with numbers.
+ // Performing other tests for NaN values is meaningless when dealing with numbers.
return kResumeFromValue;
}
diff --git a/compiler-rt/test/nsan/softmax.cpp b/compiler-rt/test/nsan/softmax.cpp
new file mode 100644
index 0000000000000..fe4a2d960020a
--- /dev/null
+++ b/compiler-rt/test/nsan/softmax.cpp
@@ -0,0 +1,45 @@
+// RUN: %clangxx_nsan -O0 -g %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
+#include<iostream>
+#include<vector>
+#include<algorithm>
+#include<cmath>
+
+__attribute__((noinline)) void softmax(std::vector<double> &values) {
+ double sum_exp = 0.0;
+ for (auto &i: values) {
+ i = std::exp(i);
+ sum_exp += i;
+ }
+ for (auto &i: values) {
+ i /= sum_exp;
+ }
+}
+
+__attribute__((noinline)) void stable_softmax(std::vector<double> values) {
+ double sum_exp = 0.0;
+ double max_values = *std::max_element(values.begin(), values.end());
+ for (auto &i: values) {
+ i = std::exp(i - max_values);
+ sum_exp += i;
+ }
+ for (auto &i:values) {
+ i /= sum_exp;
+ }
+}
+
+int main() {
+ std::vector<double> data = {1000, 1001, 1002};
+ stable_softmax(data);
+ for (auto i:data) {
+ printf("%f ", i);
+ }
+ printf("\n");
+ data = {1000, 1001, 1002};
+ softmax(data);
+ for (auto i:data) {
+ printf("%f", i);
+ // CHECK: WARNING: NumericalStabilitySanitizer: NaN detected
+ }
+ printf("\n");
+}
\ No newline at end of file
>From 22231fec75180a82219c2ff82c6b92fe177a2f37 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Tue, 6 Aug 2024 12:32:29 +0000
Subject: [PATCH 6/7] change nsan test
---
compiler-rt/test/nsan/softmax.cpp | 36 +++++++++++++++++--------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/compiler-rt/test/nsan/softmax.cpp b/compiler-rt/test/nsan/softmax.cpp
index fe4a2d960020a..36dabcdc07bab 100644
--- a/compiler-rt/test/nsan/softmax.cpp
+++ b/compiler-rt/test/nsan/softmax.cpp
@@ -1,12 +1,20 @@
-// RUN: %clangxx_nsan -O0 -g %s -o %t
+// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=softmax %s -o %t
// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=softmax %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=stable_softmax %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1
+// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=stable_softmax %s -o %t
+// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1
+
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
-
-__attribute__((noinline)) void softmax(std::vector<double> &values) {
- double sum_exp = 0.0;
+// unstable softmax
+template <typename T>
+__attribute__((noinline)) void softmax(std::vector<T> &values) {
+ T sum_exp = 0.0;
for (auto &i: values) {
i = std::exp(i);
sum_exp += i;
@@ -16,9 +24,12 @@ __attribute__((noinline)) void softmax(std::vector<double> &values) {
}
}
-__attribute__((noinline)) void stable_softmax(std::vector<double> values) {
- double sum_exp = 0.0;
- double max_values = *std::max_element(values.begin(), values.end());
+// use max value to avoid overflow
+// \sigma_i exp(x_i) / \sum_j exp(x_j) = \sigma_i exp(x_i - max(x)) / \sum_j exp(x_j - max(x))
+template <typename T>
+__attribute__((noinline)) void stable_softmax(std::vector<T> values) {
+ T sum_exp = 0.0;
+ T max_values = *std::max_element(values.begin(), values.end());
for (auto &i: values) {
i = std::exp(i - max_values);
sum_exp += i;
@@ -30,16 +41,9 @@ __attribute__((noinline)) void stable_softmax(std::vector<double> values) {
int main() {
std::vector<double> data = {1000, 1001, 1002};
- stable_softmax(data);
- for (auto i:data) {
- printf("%f ", i);
- }
- printf("\n");
- data = {1000, 1001, 1002};
- softmax(data);
- for (auto i:data) {
+ SOFTMAX(data);
+ for (auto i: data) {
printf("%f", i);
// CHECK: WARNING: NumericalStabilitySanitizer: NaN detected
}
- printf("\n");
}
\ No newline at end of file
>From 9215016daae4a095628869a495c0e77027f3b5a0 Mon Sep 17 00:00:00 2001
From: cseslowpoke <cseslowpoke at gmail.com>
Date: Wed, 7 Aug 2024 15:04:37 +0800
Subject: [PATCH 7/7] Change default mode for check-nan and update some test
defaults
---
compiler-rt/lib/nsan/nsan_flags.inc | 2 +-
compiler-rt/test/nsan/nan.cpp | 2 +-
compiler-rt/test/nsan/softmax.cpp | 8 ++++----
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/compiler-rt/lib/nsan/nsan_flags.inc b/compiler-rt/lib/nsan/nsan_flags.inc
index 52ca95a084dc4..2c67c4bb7f779 100644
--- a/compiler-rt/lib/nsan/nsan_flags.inc
+++ b/compiler-rt/lib/nsan/nsan_flags.inc
@@ -47,5 +47,5 @@ NSAN_FLAG(bool, enable_loadtracking_stats, false,
"memory, the number of times nsan resumed from the original value "
"due to invalid or unknown types.")
NSAN_FLAG(bool, print_stats_on_exit, false, "If true, print stats on exit.")
-NSAN_FLAG(bool, check_nan, true,
+NSAN_FLAG(bool, check_nan, false,
"If true, check the floating-point number is nan")
\ No newline at end of file
diff --git a/compiler-rt/test/nsan/nan.cpp b/compiler-rt/test/nsan/nan.cpp
index a84b51859aaed..db94c6e887bbf 100644
--- a/compiler-rt/test/nsan/nan.cpp
+++ b/compiler-rt/test/nsan/nan.cpp
@@ -1,5 +1,5 @@
// RUN: %clangxx_nsan -O0 -g %s -o %t
-// RUN: NSAN_OPTIONS=check_nan=true %run %t 2>&1 | FileCheck %s
+// RUN: NSAN_OPTIONS=check_nan=true,halt_on_error=0 %run %t 2>&1 | FileCheck %s
#include <cmath>
#include <cstdio>
diff --git a/compiler-rt/test/nsan/softmax.cpp b/compiler-rt/test/nsan/softmax.cpp
index 36dabcdc07bab..bcc3e3a964103 100644
--- a/compiler-rt/test/nsan/softmax.cpp
+++ b/compiler-rt/test/nsan/softmax.cpp
@@ -1,11 +1,11 @@
// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=softmax %s -o %t
-// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
+// RUN: NSAN_OPTIONS=check_nan=true,halt_on_error=0,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=softmax %s -o %t
-// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
+// RUN: NSAN_OPTIONS=check_nan=true,halt_on_error=0,log2_max_relative_error=19 %run %t 2>&1 | FileCheck %s
// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=stable_softmax %s -o %t
-// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1
+// RUN: NSAN_OPTIONS=check_nan=true,halt_on_error=0,log2_max_relative_error=19 %run %t 2>&1
// RUN: %clangxx_nsan -O0 -g -DSOFTMAX=stable_softmax %s -o %t
-// RUN: NSAN_OPTIONS=halt_on_error=1,log2_max_relative_error=19 %run %t 2>&1
+// RUN: NSAN_OPTIONS=check_nan=true,halt_on_error=0,log2_max_relative_error=19 %run %t 2>&1
#include<iostream>
#include<vector>
More information about the llvm-commits
mailing list