aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-06-13 17:54:52 +0000
committerSanjay Patel <spatel@rotateright.com>2018-06-13 17:54:52 +0000
commit1d7ed944398913c7c282ba086965b101bf0b0d54 (patch)
treef06c55d8bf3e0cd29a5dd418c46d859b93237690
parent4d1c85488418e1b0516e22d8856d263cfadf7ad8 (diff)
downloadllvm-1d7ed944398913c7c282ba086965b101bf0b0d54.zip
llvm-1d7ed944398913c7c282ba086965b101bf0b0d54.tar.gz
llvm-1d7ed944398913c7c282ba086965b101bf0b0d54.tar.bz2
[CodeGen] make nan builtins pure rather than const (PR37778)
https://bugs.llvm.org/show_bug.cgi?id=37778 ...shows a miscompile resulting from marking nan builtins as 'const'. The nan libcalls/builtins take a pointer argument: http://www.cplusplus.com/reference/cmath/nan-function/ ...and the chars dereferenced by that arg are used to fill in the NaN constant payload bits. "const" means that the pointer argument isn't dereferenced. That's translated to "readnone" in LLVM. "pure" means that the pointer argument may be dereferenced. That's translated to "readonly" in LLVM. This change prevents the IR optimizer from killing the lead-up to the nan call here: double a() { char buf[4]; buf[0] = buf[1] = buf[2] = '9'; buf[3] = '\0'; return __builtin_nan(buf); } ...the optimizer isn't currently able to simplify this to a constant as we might hope, but this patch should solve the miscompile. Differential Revision: https://reviews.llvm.org/D48134 llvm-svn: 334628
-rw-r--r--clang/include/clang/Basic/Builtins.def16
-rw-r--r--clang/test/CodeGen/math-builtins.c36
2 files changed, 27 insertions, 25 deletions
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 6f39c16..dd0730f 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -137,14 +137,14 @@ BUILTIN(__builtin_ldexpl, "LdLdi", "Fne")
BUILTIN(__builtin_modf , "ddd*" , "Fn")
BUILTIN(__builtin_modff, "fff*" , "Fn")
BUILTIN(__builtin_modfl, "LdLdLd*", "Fn")
-BUILTIN(__builtin_nan, "dcC*" , "ncF")
-BUILTIN(__builtin_nanf, "fcC*" , "ncF")
-BUILTIN(__builtin_nanl, "LdcC*", "ncF")
-BUILTIN(__builtin_nanf128, "LLdcC*", "ncF")
-BUILTIN(__builtin_nans, "dcC*" , "ncF")
-BUILTIN(__builtin_nansf, "fcC*" , "ncF")
-BUILTIN(__builtin_nansl, "LdcC*", "ncF")
-BUILTIN(__builtin_nansf128, "LLdcC*", "ncF")
+BUILTIN(__builtin_nan, "dcC*" , "FnU")
+BUILTIN(__builtin_nanf, "fcC*" , "FnU")
+BUILTIN(__builtin_nanl, "LdcC*", "FnU")
+BUILTIN(__builtin_nanf128, "LLdcC*", "FnU")
+BUILTIN(__builtin_nans, "dcC*" , "FnU")
+BUILTIN(__builtin_nansf, "fcC*" , "FnU")
+BUILTIN(__builtin_nansl, "LdcC*", "FnU")
+BUILTIN(__builtin_nansf128, "LLdcC*", "FnU")
BUILTIN(__builtin_powi , "ddi" , "Fnc")
BUILTIN(__builtin_powif, "ffi" , "Fnc")
BUILTIN(__builtin_powil, "LdLdi", "Fnc")
diff --git a/clang/test/CodeGen/math-builtins.c b/clang/test/CodeGen/math-builtins.c
index 4be8981..82f049b 100644
--- a/clang/test/CodeGen/math-builtins.c
+++ b/clang/test/CodeGen/math-builtins.c
@@ -90,25 +90,25 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
__builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); __builtin_nanf128(c);
-// NO__ERRNO: declare double @nan(i8*) [[READNONE]]
-// NO__ERRNO: declare float @nanf(i8*) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]]
-// NO__ERRNO: declare fp128 @nanf128(i8*) [[READNONE]]
-// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]]
-// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]]
-// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]]
-// HAS_ERRNO: declare fp128 @nanf128(i8*) [[READNONE]]
+// NO__ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]]
+// NO__ERRNO: declare float @nanf(i8*) [[PURE]]
+// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]]
+// NO__ERRNO: declare fp128 @nanf128(i8*) [[PURE]]
+// HAS_ERRNO: declare double @nan(i8*) [[PURE:#[0-9]+]]
+// HAS_ERRNO: declare float @nanf(i8*) [[PURE]]
+// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[PURE]]
+// HAS_ERRNO: declare fp128 @nanf128(i8*) [[PURE]]
__builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); __builtin_nansf128(c);
-// NO__ERRNO: declare double @nans(i8*) [[READNONE]]
-// NO__ERRNO: declare float @nansf(i8*) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]]
-// NO__ERRNO: declare fp128 @nansf128(i8*) [[READNONE]]
-// HAS_ERRNO: declare double @nans(i8*) [[READNONE]]
-// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]]
-// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]]
-// HAS_ERRNO: declare fp128 @nansf128(i8*) [[READNONE]]
+// NO__ERRNO: declare double @nans(i8*) [[PURE]]
+// NO__ERRNO: declare float @nansf(i8*) [[PURE]]
+// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]]
+// NO__ERRNO: declare fp128 @nansf128(i8*) [[PURE]]
+// HAS_ERRNO: declare double @nans(i8*) [[PURE]]
+// HAS_ERRNO: declare float @nansf(i8*) [[PURE]]
+// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[PURE]]
+// HAS_ERRNO: declare fp128 @nansf128(i8*) [[PURE]]
__builtin_pow(f,f); __builtin_powf(f,f); __builtin_powl(f,f);
@@ -188,7 +188,7 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO: declare double @cbrt(double) [[READNONE]]
// NO__ERRNO: declare float @cbrtf(float) [[READNONE]]
// NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]]
-// HAS_ERRNO: declare double @cbrt(double) [[READNONE]]
+// HAS_ERRNO: declare double @cbrt(double) [[READNONE:#[0-9]+]]
// HAS_ERRNO: declare float @cbrtf(float) [[READNONE]]
// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]]
@@ -581,9 +581,11 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} }
// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} }
+// NO__ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} }
// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} }
// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }
+// HAS_ERRNO: attributes [[PURE]] = { {{.*}}readonly{{.*}} }
// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} }
// HAS_ERRNO_GNU: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} }