zahiraam updated this revision to Diff 382663. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D112094/new/
https://reviews.llvm.org/D112094 Files: clang/docs/LanguageExtensions.rst clang/docs/UsersManual.rst clang/include/clang/Basic/FPOptions.def clang/include/clang/Basic/LangOptions.def clang/include/clang/Basic/LangOptions.h clang/include/clang/Basic/TargetInfo.h clang/include/clang/Driver/Options.td clang/include/clang/Lex/Preprocessor.h clang/include/clang/Parse/Parser.h clang/include/clang/Sema/Sema.h clang/lib/Basic/Targets/OSTargets.h clang/lib/Basic/Targets/X86.h clang/lib/Driver/ToolChains/Clang.cpp clang/lib/Frontend/InitPreprocessor.cpp clang/lib/Parse/ParsePragma.cpp clang/lib/Sema/Sema.cpp clang/lib/Sema/SemaAttr.cpp clang/lib/Sema/SemaExpr.cpp clang/test/CodeGen/fp-floatcontrol-pragma.cpp clang/test/Preprocessor/init-aarch64.c clang/test/Preprocessor/init-arm.c clang/test/Preprocessor/init-mips.c clang/test/Preprocessor/init-ppc.c clang/test/Preprocessor/init-ppc64.c clang/test/Preprocessor/init-s390x.c clang/test/Preprocessor/init-v7k-compat.c clang/test/Preprocessor/init-x86.c clang/test/Preprocessor/init.c
Index: clang/test/Preprocessor/init.c =================================================================== --- clang/test/Preprocessor/init.c +++ clang/test/Preprocessor/init.c @@ -323,7 +323,7 @@ // MSP430:#define __FLT_DENORM_MIN__ 1.40129846e-45F // MSP430:#define __FLT_DIG__ 6 // MSP430:#define __FLT_EPSILON__ 1.19209290e-7F -// MSP430:#define __FLT_EVAL_METHOD__ 0 +// MSP430:#define __FLT_EVAL_METHOD__ -1 // MSP430:#define __FLT_HAS_DENORM__ 1 // MSP430:#define __FLT_HAS_INFINITY__ 1 // MSP430:#define __FLT_HAS_QUIET_NAN__ 1 @@ -511,7 +511,7 @@ // NVPTX32:#define __FLT_DENORM_MIN__ 1.40129846e-45F // NVPTX32:#define __FLT_DIG__ 6 // NVPTX32:#define __FLT_EPSILON__ 1.19209290e-7F -// NVPTX32:#define __FLT_EVAL_METHOD__ 0 +// NVPTX32:#define __FLT_EVAL_METHOD__ -1 // NVPTX32:#define __FLT_HAS_DENORM__ 1 // NVPTX32:#define __FLT_HAS_INFINITY__ 1 // NVPTX32:#define __FLT_HAS_QUIET_NAN__ 1 @@ -700,7 +700,7 @@ // NVPTX64:#define __FLT_DENORM_MIN__ 1.40129846e-45F // NVPTX64:#define __FLT_DIG__ 6 // NVPTX64:#define __FLT_EPSILON__ 1.19209290e-7F -// NVPTX64:#define __FLT_EVAL_METHOD__ 0 +// NVPTX64:#define __FLT_EVAL_METHOD__ -1 // NVPTX64:#define __FLT_HAS_DENORM__ 1 // NVPTX64:#define __FLT_HAS_INFINITY__ 1 // NVPTX64:#define __FLT_HAS_QUIET_NAN__ 1 @@ -904,7 +904,7 @@ // SPARC:#define __FLT_DENORM_MIN__ 1.40129846e-45F // SPARC:#define __FLT_DIG__ 6 // SPARC:#define __FLT_EPSILON__ 1.19209290e-7F -// SPARC:#define __FLT_EVAL_METHOD__ 0 +// SPARC:#define __FLT_EVAL_METHOD__ -1 // SPARC:#define __FLT_HAS_DENORM__ 1 // SPARC:#define __FLT_HAS_INFINITY__ 1 // SPARC:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1105,7 +1105,7 @@ // TCE:#define __FLT_DENORM_MIN__ 1.40129846e-45F // TCE:#define __FLT_DIG__ 6 // TCE:#define __FLT_EPSILON__ 1.19209290e-7F -// TCE:#define __FLT_EVAL_METHOD__ 0 +// TCE:#define __FLT_EVAL_METHOD__ -1 // TCE:#define __FLT_HAS_DENORM__ 1 // TCE:#define __FLT_HAS_INFINITY__ 1 // TCE:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1272,7 +1272,7 @@ // PS4:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PS4:#define __FLT_DIG__ 6 // PS4:#define __FLT_EPSILON__ 1.19209290e-7F -// PS4:#define __FLT_EVAL_METHOD__ 0 +// PS4:#define __FLT_EVAL_METHOD__ -1 // PS4:#define __FLT_HAS_DENORM__ 1 // PS4:#define __FLT_HAS_INFINITY__ 1 // PS4:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1574,7 +1574,7 @@ // WEBASSEMBLY-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F // WEBASSEMBLY-NEXT:#define __FLT_DIG__ 6 // WEBASSEMBLY-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F -// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ 0 +// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ -1 // WEBASSEMBLY-NEXT:#define __FLT_HAS_DENORM__ 1 // WEBASSEMBLY-NEXT:#define __FLT_HAS_INFINITY__ 1 // WEBASSEMBLY-NEXT:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1930,7 +1930,7 @@ // AVR:#define __FLT_DENORM_MIN__ 1.40129846e-45F // AVR:#define __FLT_DIG__ 6 // AVR:#define __FLT_EPSILON__ 1.19209290e-7F -// AVR:#define __FLT_EVAL_METHOD__ 0 +// AVR:#define __FLT_EVAL_METHOD__ -1 // AVR:#define __FLT_HAS_DENORM__ 1 // AVR:#define __FLT_HAS_INFINITY__ 1 // AVR:#define __FLT_HAS_QUIET_NAN__ 1 @@ -2213,7 +2213,7 @@ // RISCV32: #define __FLT_DENORM_MIN__ 1.40129846e-45F // RISCV32: #define __FLT_DIG__ 6 // RISCV32: #define __FLT_EPSILON__ 1.19209290e-7F -// RISCV32: #define __FLT_EVAL_METHOD__ 0 +// RISCV32: #define __FLT_EVAL_METHOD__ -1 // RISCV32: #define __FLT_HAS_DENORM__ 1 // RISCV32: #define __FLT_HAS_INFINITY__ 1 // RISCV32: #define __FLT_HAS_QUIET_NAN__ 1 @@ -2421,7 +2421,7 @@ // RISCV64: #define __FLT_DENORM_MIN__ 1.40129846e-45F // RISCV64: #define __FLT_DIG__ 6 // RISCV64: #define __FLT_EPSILON__ 1.19209290e-7F -// RISCV64: #define __FLT_EVAL_METHOD__ 0 +// RISCV64: #define __FLT_EVAL_METHOD__ -1 // RISCV64: #define __FLT_HAS_DENORM__ 1 // RISCV64: #define __FLT_HAS_INFINITY__ 1 // RISCV64: #define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-x86.c =================================================================== --- clang/test/Preprocessor/init-x86.c +++ clang/test/Preprocessor/init-x86.c @@ -24,7 +24,7 @@ // I386:#define __FLT_DENORM_MIN__ 1.40129846e-45F // I386:#define __FLT_DIG__ 6 // I386:#define __FLT_EPSILON__ 1.19209290e-7F -// I386:#define __FLT_EVAL_METHOD__ 2 +// I386:#define __FLT_EVAL_METHOD__ -1 // I386:#define __FLT_HAS_DENORM__ 1 // I386:#define __FLT_HAS_INFINITY__ 1 // I386:#define __FLT_HAS_QUIET_NAN__ 1 @@ -213,7 +213,7 @@ // I386-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // I386-LINUX:#define __FLT_DIG__ 6 // I386-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F -// I386-LINUX:#define __FLT_EVAL_METHOD__ 0 +// I386-LINUX:#define __FLT_EVAL_METHOD__ -1 // I386-LINUX:#define __FLT_HAS_DENORM__ 1 // I386-LINUX:#define __FLT_HAS_INFINITY__ 1 // I386-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 @@ -416,7 +416,7 @@ // I386-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F // I386-NETBSD:#define __FLT_DIG__ 6 // I386-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// I386-NETBSD:#define __FLT_EVAL_METHOD__ 2 +// I386-NETBSD:#define __FLT_EVAL_METHOD__ -1 // I386-NETBSD:#define __FLT_HAS_DENORM__ 1 // I386-NETBSD:#define __FLT_HAS_INFINITY__ 1 // I386-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 @@ -591,11 +591,11 @@ // I386-NETBSD:#define i386 1 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD-SSE %s -// I386-NETBSD-SSE:#define __FLT_EVAL_METHOD__ 0 +// I386-NETBSD-SSE:#define __FLT_EVAL_METHOD__ -1 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6 %s -// I386-NETBSD6:#define __FLT_EVAL_METHOD__ 1 +// I386-NETBSD6:#define __FLT_EVAL_METHOD__ -1 // RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD6-SSE %s -// I386-NETBSD6-SSE:#define __FLT_EVAL_METHOD__ 1 +// I386-NETBSD6-SSE:#define __FLT_EVAL_METHOD__ -1 // RUN: %clang_cc1 -E -dM -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s // RUN: %clang_cc1 -E -dM -fms-extensions -triple=i686-pc-mingw32 < /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s @@ -631,7 +631,7 @@ // X86_64:#define __FLT_DENORM_MIN__ 1.40129846e-45F // X86_64:#define __FLT_DIG__ 6 // X86_64:#define __FLT_EPSILON__ 1.19209290e-7F -// X86_64:#define __FLT_EVAL_METHOD__ 0 +// X86_64:#define __FLT_EVAL_METHOD__ -1 // X86_64:#define __FLT_HAS_DENORM__ 1 // X86_64:#define __FLT_HAS_INFINITY__ 1 // X86_64:#define __FLT_HAS_QUIET_NAN__ 1 @@ -839,7 +839,7 @@ // X32:#define __FLT_DENORM_MIN__ 1.40129846e-45F // X32:#define __FLT_DIG__ 6 // X32:#define __FLT_EPSILON__ 1.19209290e-7F -// X32:#define __FLT_EVAL_METHOD__ 0 +// X32:#define __FLT_EVAL_METHOD__ -1 // X32:#define __FLT_HAS_DENORM__ 1 // X32:#define __FLT_HAS_INFINITY__ 1 // X32:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1046,7 +1046,7 @@ // X86_64-CLOUDABI:#define __FLT_DENORM_MIN__ 1.40129846e-45F // X86_64-CLOUDABI:#define __FLT_DIG__ 6 // X86_64-CLOUDABI:#define __FLT_EPSILON__ 1.19209290e-7F -// X86_64-CLOUDABI:#define __FLT_EVAL_METHOD__ 0 +// X86_64-CLOUDABI:#define __FLT_EVAL_METHOD__ -1 // X86_64-CLOUDABI:#define __FLT_HAS_DENORM__ 1 // X86_64-CLOUDABI:#define __FLT_HAS_INFINITY__ 1 // X86_64-CLOUDABI:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1341,7 +1341,7 @@ // X86_64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // X86_64-LINUX:#define __FLT_DIG__ 6 // X86_64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F -// X86_64-LINUX:#define __FLT_EVAL_METHOD__ 0 +// X86_64-LINUX:#define __FLT_EVAL_METHOD__ -1 // X86_64-LINUX:#define __FLT_HAS_DENORM__ 1 // X86_64-LINUX:#define __FLT_HAS_INFINITY__ 1 // X86_64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1554,7 +1554,7 @@ // X86_64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F // X86_64-NETBSD:#define __FLT_DIG__ 6 // X86_64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// X86_64-NETBSD:#define __FLT_EVAL_METHOD__ 0 +// X86_64-NETBSD:#define __FLT_EVAL_METHOD__ -1 // X86_64-NETBSD:#define __FLT_HAS_DENORM__ 1 // X86_64-NETBSD:#define __FLT_HAS_INFINITY__ 1 // X86_64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-v7k-compat.c =================================================================== --- clang/test/Preprocessor/init-v7k-compat.c +++ clang/test/Preprocessor/init-v7k-compat.c @@ -28,7 +28,7 @@ // CHECK: #define __FLT_DENORM_MIN__ 1.40129846e-45F // CHECK: #define __FLT_DIG__ 6 // CHECK: #define __FLT_EPSILON__ 1.19209290e-7F -// CHECK: #define __FLT_EVAL_METHOD__ 0 +// CHECK: #define __FLT_EVAL_METHOD__ -1 // CHECK: #define __FLT_HAS_DENORM__ 1 // CHECK: #define __FLT_HAS_INFINITY__ 1 // CHECK: #define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-s390x.c =================================================================== --- clang/test/Preprocessor/init-s390x.c +++ clang/test/Preprocessor/init-s390x.c @@ -23,7 +23,7 @@ // S390X:#define __FLT_DENORM_MIN__ 1.40129846e-45F // S390X:#define __FLT_DIG__ 6 // S390X:#define __FLT_EPSILON__ 1.19209290e-7F -// S390X:#define __FLT_EVAL_METHOD__ 0 +// S390X:#define __FLT_EVAL_METHOD__ -1 // S390X:#define __FLT_HAS_DENORM__ 1 // S390X:#define __FLT_HAS_INFINITY__ 1 // S390X:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-ppc64.c =================================================================== --- clang/test/Preprocessor/init-ppc64.c +++ clang/test/Preprocessor/init-ppc64.c @@ -35,7 +35,7 @@ // PPC64:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC64:#define __FLT_DIG__ 6 // PPC64:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC64:#define __FLT_EVAL_METHOD__ 0 +// PPC64:#define __FLT_EVAL_METHOD__ -1 // PPC64:#define __FLT_HAS_DENORM__ 1 // PPC64:#define __FLT_HAS_INFINITY__ 1 // PPC64:#define __FLT_HAS_QUIET_NAN__ 1 @@ -240,7 +240,7 @@ // PPC64LE:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC64LE:#define __FLT_DIG__ 6 // PPC64LE:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC64LE:#define __FLT_EVAL_METHOD__ 0 +// PPC64LE:#define __FLT_EVAL_METHOD__ -1 // PPC64LE:#define __FLT_HAS_DENORM__ 1 // PPC64LE:#define __FLT_HAS_INFINITY__ 1 // PPC64LE:#define __FLT_HAS_QUIET_NAN__ 1 @@ -703,7 +703,7 @@ // PPC64-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC64-AIX:#define __FLT_DIG__ 6 // PPC64-AIX:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC64-AIX:#define __FLT_EVAL_METHOD__ 1 +// PPC64-AIX:#define __FLT_EVAL_METHOD__ -1 // PPC64-AIX:#define __FLT_HAS_DENORM__ 1 // PPC64-AIX:#define __FLT_HAS_INFINITY__ 1 // PPC64-AIX:#define __FLT_HAS_QUIET_NAN__ 1 @@ -902,7 +902,7 @@ // PPC64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC64-LINUX:#define __FLT_DIG__ 6 // PPC64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC64-LINUX:#define __FLT_EVAL_METHOD__ 0 +// PPC64-LINUX:#define __FLT_EVAL_METHOD__ -1 // PPC64-LINUX:#define __FLT_HAS_DENORM__ 1 // PPC64-LINUX:#define __FLT_HAS_INFINITY__ 1 // PPC64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-ppc.c =================================================================== --- clang/test/Preprocessor/init-ppc.c +++ clang/test/Preprocessor/init-ppc.c @@ -30,7 +30,7 @@ // PPC603E:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC603E:#define __FLT_DIG__ 6 // PPC603E:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC603E:#define __FLT_EVAL_METHOD__ 0 +// PPC603E:#define __FLT_EVAL_METHOD__ -1 // PPC603E:#define __FLT_HAS_DENORM__ 1 // PPC603E:#define __FLT_HAS_INFINITY__ 1 // PPC603E:#define __FLT_HAS_QUIET_NAN__ 1 @@ -224,7 +224,7 @@ // PPC:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC:#define __FLT_DIG__ 6 // PPC:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC:#define __FLT_EVAL_METHOD__ 0 +// PPC:#define __FLT_EVAL_METHOD__ -1 // PPC:#define __FLT_HAS_DENORM__ 1 // PPC:#define __FLT_HAS_INFINITY__ 1 // PPC:#define __FLT_HAS_QUIET_NAN__ 1 @@ -425,7 +425,7 @@ // PPC-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC-AIX:#define __FLT_DIG__ 6 // PPC-AIX:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC-AIX:#define __FLT_EVAL_METHOD__ 1 +// PPC-AIX:#define __FLT_EVAL_METHOD__ -1 // PPC-AIX:#define __FLT_HAS_DENORM__ 1 // PPC-AIX:#define __FLT_HAS_INFINITY__ 1 // PPC-AIX:#define __FLT_HAS_QUIET_NAN__ 1 @@ -798,7 +798,7 @@ // PPC-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC-LINUX:#define __FLT_DIG__ 6 // PPC-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC-LINUX:#define __FLT_EVAL_METHOD__ 0 +// PPC-LINUX:#define __FLT_EVAL_METHOD__ -1 // PPC-LINUX:#define __FLT_HAS_DENORM__ 1 // PPC-LINUX:#define __FLT_HAS_INFINITY__ 1 // PPC-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1006,7 +1006,7 @@ // PPC-DARWIN:#define __FLT_DENORM_MIN__ 1.40129846e-45F // PPC-DARWIN:#define __FLT_DIG__ 6 // PPC-DARWIN:#define __FLT_EPSILON__ 1.19209290e-7F -// PPC-DARWIN:#define __FLT_EVAL_METHOD__ 0 +// PPC-DARWIN:#define __FLT_EVAL_METHOD__ -1 // PPC-DARWIN:#define __FLT_HAS_DENORM__ 1 // PPC-DARWIN:#define __FLT_HAS_INFINITY__ 1 // PPC-DARWIN:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-mips.c =================================================================== --- clang/test/Preprocessor/init-mips.c +++ clang/test/Preprocessor/init-mips.c @@ -37,7 +37,7 @@ // MIPS32BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPS32BE:#define __FLT_DIG__ 6 // MIPS32BE:#define __FLT_EPSILON__ 1.19209290e-7F -// MIPS32BE:#define __FLT_EVAL_METHOD__ 0 +// MIPS32BE:#define __FLT_EVAL_METHOD__ -1 // MIPS32BE:#define __FLT_HAS_DENORM__ 1 // MIPS32BE:#define __FLT_HAS_INFINITY__ 1 // MIPS32BE:#define __FLT_HAS_QUIET_NAN__ 1 @@ -247,7 +247,7 @@ // MIPS32EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPS32EL:#define __FLT_DIG__ 6 // MIPS32EL:#define __FLT_EPSILON__ 1.19209290e-7F -// MIPS32EL:#define __FLT_EVAL_METHOD__ 0 +// MIPS32EL:#define __FLT_EVAL_METHOD__ -1 // MIPS32EL:#define __FLT_HAS_DENORM__ 1 // MIPS32EL:#define __FLT_HAS_INFINITY__ 1 // MIPS32EL:#define __FLT_HAS_QUIET_NAN__ 1 @@ -467,7 +467,7 @@ // MIPSN32BE: #define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPSN32BE: #define __FLT_DIG__ 6 // MIPSN32BE: #define __FLT_EPSILON__ 1.19209290e-7F -// MIPSN32BE: #define __FLT_EVAL_METHOD__ 0 +// MIPSN32BE: #define __FLT_EVAL_METHOD__ -1 // MIPSN32BE: #define __FLT_HAS_DENORM__ 1 // MIPSN32BE: #define __FLT_HAS_INFINITY__ 1 // MIPSN32BE: #define __FLT_HAS_QUIET_NAN__ 1 @@ -774,7 +774,7 @@ // MIPSN32EL: #define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPSN32EL: #define __FLT_DIG__ 6 // MIPSN32EL: #define __FLT_EPSILON__ 1.19209290e-7F -// MIPSN32EL: #define __FLT_EVAL_METHOD__ 0 +// MIPSN32EL: #define __FLT_EVAL_METHOD__ -1 // MIPSN32EL: #define __FLT_HAS_DENORM__ 1 // MIPSN32EL: #define __FLT_HAS_INFINITY__ 1 // MIPSN32EL: #define __FLT_HAS_QUIET_NAN__ 1 @@ -1074,7 +1074,7 @@ // MIPS64BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPS64BE:#define __FLT_DIG__ 6 // MIPS64BE:#define __FLT_EPSILON__ 1.19209290e-7F -// MIPS64BE:#define __FLT_EVAL_METHOD__ 0 +// MIPS64BE:#define __FLT_EVAL_METHOD__ -1 // MIPS64BE:#define __FLT_HAS_DENORM__ 1 // MIPS64BE:#define __FLT_HAS_INFINITY__ 1 // MIPS64BE:#define __FLT_HAS_QUIET_NAN__ 1 @@ -1284,7 +1284,7 @@ // MIPS64EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F // MIPS64EL:#define __FLT_DIG__ 6 // MIPS64EL:#define __FLT_EPSILON__ 1.19209290e-7F -// MIPS64EL:#define __FLT_EVAL_METHOD__ 0 +// MIPS64EL:#define __FLT_EVAL_METHOD__ -1 // MIPS64EL:#define __FLT_HAS_DENORM__ 1 // MIPS64EL:#define __FLT_HAS_INFINITY__ 1 // MIPS64EL:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-arm.c =================================================================== --- clang/test/Preprocessor/init-arm.c +++ clang/test/Preprocessor/init-arm.c @@ -35,7 +35,7 @@ // ARM:#define __FLT_DENORM_MIN__ 1.40129846e-45F // ARM:#define __FLT_DIG__ 6 // ARM:#define __FLT_EPSILON__ 1.19209290e-7F -// ARM:#define __FLT_EVAL_METHOD__ 0 +// ARM:#define __FLT_EVAL_METHOD__ -1 // ARM:#define __FLT_HAS_DENORM__ 1 // ARM:#define __FLT_HAS_INFINITY__ 1 // ARM:#define __FLT_HAS_QUIET_NAN__ 1 @@ -235,7 +235,7 @@ // ARM-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F // ARM-BE:#define __FLT_DIG__ 6 // ARM-BE:#define __FLT_EPSILON__ 1.19209290e-7F -// ARM-BE:#define __FLT_EVAL_METHOD__ 0 +// ARM-BE:#define __FLT_EVAL_METHOD__ -1 // ARM-BE:#define __FLT_HAS_DENORM__ 1 // ARM-BE:#define __FLT_HAS_INFINITY__ 1 // ARM-BE:#define __FLT_HAS_QUIET_NAN__ 1 @@ -428,7 +428,7 @@ // ARMEABISOFTFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F // ARMEABISOFTFP:#define __FLT_DIG__ 6 // ARMEABISOFTFP:#define __FLT_EPSILON__ 1.19209290e-7F -// ARMEABISOFTFP:#define __FLT_EVAL_METHOD__ 0 +// ARMEABISOFTFP:#define __FLT_EVAL_METHOD__ -1 // ARMEABISOFTFP:#define __FLT_HAS_DENORM__ 1 // ARMEABISOFTFP:#define __FLT_HAS_INFINITY__ 1 // ARMEABISOFTFP:#define __FLT_HAS_QUIET_NAN__ 1 @@ -623,7 +623,7 @@ // ARMEABIHARDFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F // ARMEABIHARDFP:#define __FLT_DIG__ 6 // ARMEABIHARDFP:#define __FLT_EPSILON__ 1.19209290e-7F -// ARMEABIHARDFP:#define __FLT_EVAL_METHOD__ 0 +// ARMEABIHARDFP:#define __FLT_EVAL_METHOD__ -1 // ARMEABIHARDFP:#define __FLT_HAS_DENORM__ 1 // ARMEABIHARDFP:#define __FLT_HAS_INFINITY__ 1 // ARMEABIHARDFP:#define __FLT_HAS_QUIET_NAN__ 1 @@ -821,7 +821,7 @@ // ARM-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F // ARM-NETBSD:#define __FLT_DIG__ 6 // ARM-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F -// ARM-NETBSD:#define __FLT_EVAL_METHOD__ 0 +// ARM-NETBSD:#define __FLT_EVAL_METHOD__ -1 // ARM-NETBSD:#define __FLT_HAS_DENORM__ 1 // ARM-NETBSD:#define __FLT_HAS_INFINITY__ 1 // ARM-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/Preprocessor/init-aarch64.c =================================================================== --- clang/test/Preprocessor/init-aarch64.c +++ clang/test/Preprocessor/init-aarch64.c @@ -91,7 +91,7 @@ // AARCH64-NEXT: #define __FLT_DENORM_MIN__ 1.40129846e-45F // AARCH64-NEXT: #define __FLT_DIG__ 6 // AARCH64-NEXT: #define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-NEXT: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-NEXT: #define __FLT_EVAL_METHOD__ -1 // AARCH64-NEXT: #define __FLT_HAS_DENORM__ 1 // AARCH64-NEXT: #define __FLT_HAS_INFINITY__ 1 // AARCH64-NEXT: #define __FLT_HAS_QUIET_NAN__ 1 @@ -109,12 +109,12 @@ // AARCH64-NEXT: #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1 // AARCH64_CXX-NEXT: #define __GLIBCXX_BITSIZE_INT_N_0 128 // AARCH64_CXX-NEXT: #define __GLIBCXX_TYPE_INT_N_0 __int128 -// AARCH64-NEXT: #define __INT16_C_SUFFIX__ +// AARCH64-NEXT: #define __INT16_C_SUFFIX__ // AARCH64-NEXT: #define __INT16_FMTd__ "hd" // AARCH64-NEXT: #define __INT16_FMTi__ "hi" // AARCH64-NEXT: #define __INT16_MAX__ 32767 // AARCH64-NEXT: #define __INT16_TYPE__ short -// AARCH64-NEXT: #define __INT32_C_SUFFIX__ +// AARCH64-NEXT: #define __INT32_C_SUFFIX__ // AARCH64-NEXT: #define __INT32_FMTd__ "d" // AARCH64-NEXT: #define __INT32_FMTi__ "i" // AARCH64-NEXT: #define __INT32_MAX__ 2147483647 @@ -124,7 +124,7 @@ // AARCH64-NEXT: #define __INT64_FMTi__ "li" // AARCH64-NEXT: #define __INT64_MAX__ 9223372036854775807L // AARCH64-NEXT: #define __INT64_TYPE__ long int -// AARCH64-NEXT: #define __INT8_C_SUFFIX__ +// AARCH64-NEXT: #define __INT8_C_SUFFIX__ // AARCH64-NEXT: #define __INT8_FMTd__ "hhd" // AARCH64-NEXT: #define __INT8_FMTi__ "hhi" // AARCH64-NEXT: #define __INT8_MAX__ 127 @@ -239,7 +239,7 @@ // AARCH64-NEXT: #define __STDC_UTF_32__ 1 // AARCH64_C: #define __STDC_VERSION__ 201710L // AARCH64-NEXT: #define __STDC__ 1 -// AARCH64-NEXT: #define __UINT16_C_SUFFIX__ +// AARCH64-NEXT: #define __UINT16_C_SUFFIX__ // AARCH64-NEXT: #define __UINT16_FMTX__ "hX" // AARCH64-NEXT: #define __UINT16_FMTo__ "ho" // AARCH64-NEXT: #define __UINT16_FMTu__ "hu" @@ -260,7 +260,7 @@ // AARCH64-NEXT: #define __UINT64_FMTx__ "lx" // AARCH64-NEXT: #define __UINT64_MAX__ 18446744073709551615UL // AARCH64-NEXT: #define __UINT64_TYPE__ long unsigned int -// AARCH64-NEXT: #define __UINT8_C_SUFFIX__ +// AARCH64-NEXT: #define __UINT8_C_SUFFIX__ // AARCH64-NEXT: #define __UINT8_FMTX__ "hhX" // AARCH64-NEXT: #define __UINT8_FMTo__ "hho" // AARCH64-NEXT: #define __UINT8_FMTu__ "hhu" @@ -330,7 +330,7 @@ // AARCH64-NEXT: #define __UINT_LEAST8_FMTx__ "hhx" // AARCH64-NEXT: #define __UINT_LEAST8_MAX__ 255 // AARCH64-NEXT: #define __UINT_LEAST8_TYPE__ unsigned char -// AARCH64-NEXT: #define __USER_LABEL_PREFIX__ +// AARCH64-NEXT: #define __USER_LABEL_PREFIX__ // AARCH64-NEXT: #define __VERSION__ "{{.*}}" // AARCH64-NEXT: #define __WCHAR_MAX__ 4294967295U // AARCH64-NEXT: #define __WCHAR_TYPE__ unsigned int @@ -373,7 +373,7 @@ // AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F // AARCH64-DARWIN: #define __FLT_DIG__ 6 // AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ -1 // AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1 // AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1 // AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1 @@ -589,7 +589,7 @@ // AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F // AARCH64-MSVC: #define __FLT_DIG__ 6 // AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F -// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0 +// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ -1 // AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1 // AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1 // AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1 Index: clang/test/CodeGen/fp-floatcontrol-pragma.cpp =================================================================== --- clang/test/CodeGen/fp-floatcontrol-pragma.cpp +++ clang/test/CodeGen/fp-floatcontrol-pragma.cpp @@ -1,7 +1,16 @@ +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 -fcxx-exceptions -triple x86_64-apple-darwin -DNF128 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 -fcxx-exceptions -triple arm64-none-linux-gnu -DNF128 -target-feature +neon -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s // RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s -// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-DEFAULT // RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s -// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DNF128 -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source | FileCheck %s -check-prefix=CHECK-SOURCE +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s -check-prefix=CHECK-DOUBLE +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 | FileCheck %s -check-prefix=CHECK-EXTENDED +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source | FileCheck %s -check-prefix=CHECK-FLT-MCR +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s -check-prefix=CHECK-FLT-MCR +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 | FileCheck %s -check-prefix=CHECK-FLT-MCR +// RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK-FLT-MCR // Verify float_control(precise, off) enables fast math flags on fp operations. float fp_precise_1(float a, float b, float c) { @@ -76,11 +85,10 @@ //CHECK: llvm.experimental.constrained.fmul{{.*}} } { -// This pragma has no effect since if there are any fp intrin in the -// function then all the operations need to be fp intrin #pragma float_control(except, off) z = z + x * y; - //CHECK: llvm.experimental.constrained.fmul{{.*}} + // CHECK: llvm.experimental.constrained.fmul.f32{{.*}} + // CHECK: llvm.experimental.constrained.fadd.f32{{.*}} } z = z * z; //CHECK: llvm.experimental.constrained.fmul{{.*}} @@ -229,3 +237,90 @@ result = x + t; return result; } + +float mySub(float x, float y) { + // CHECK: define {{.*}}float {{.*}}mySub{{.*}} + // CHECK-NS: fsub float + // CHECK-SOURCE: fsub float + // CHECK-DOUBLE: fpext float + // CHECK-DOUBLE: fpext float + // CHECK-DOUBLE: fsub double + // CHECK-DOUBLE: fptrunc double {{.*}} to float + // CHECK-EXTENDED: fpext float + // CHECK-EXTENDED: fpext float + // CHECK-EXTENDED: fsub x86_fp80 + // CHECK-EXTENDED: fptrunc x86_fp80 {{.*}} to float + return x - y; +} + +float mySubSource(float x, float y) { +// CHECK: define {{.*}}float {{.*}}mySubSource{{.*}} +#pragma clang fp eval_method(source) + return x - y; + // CHECK: fsub float +} + +float mySubExtended(float x, float y) { +// CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}} +#pragma clang fp eval_method(extended) + return x - y; + // CHECK: fpext float + // CHECK: fpext float + // CHECK: fsub x86_fp80 + // CHECK: fptrunc x86_fp80 {{.*}} to float +} + +float mySubDouble(float x, float y) { +// CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}} +#pragma clang fp eval_method(double) + return x - y; + // CHECK: fpext float + // CHECK: fpext float + // CHECK: fsub double + // CHECK: fptrunc double {{.*}} to float +} + +#ifndef NF128 +__float128 mySub128(__float128 x, __float128 y) { + // CHECK: define {{.*}}mySub128{{.*}} + // Expect no fpext since fp128 is already widest + // CHECK: load fp128 + // CHECK-NEXT: load fp128 + // CHECK-NEXT: fsub fp128 + // CHECK-NEXT: ret fp128 + return x - y; +} +#endif + +void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) { + // CHECK: define {{.*}}mySubfp16{{.*}} + *res = *x - *y; + // CHECK: load half + // CHECK-NEXT: load half + // CHECK-NEXT: fpext half{{.*}} + // CHECK-NEXT: load half + // CHECK-NEXT: load half + // CHECK-NS: fpext half{{.*}} to float + // CHECK-DEFAULT: fpext half{{.*}} to float + // CHECK-DOUBLE: fpext half{{.*}} to double + // CHECK-EXTENDED: fpext half{{.*}} to x86_fp80 + // CHECK-NEXT: fsub + // CHECK-NEXT: fptrunc {{.*}}to half + // CHECK-NS: fptrunc float {{.*}} to half + // CHECK-DOUBLE: fptrunc double {{.*}} to half + // CHECK-EXTENDED: fptrunc x86_fp80 {{.*}} to half +} + +int getFEM() { + // CHECK: define {{.*}}getFEM{{.*}} + return __FLT_EVAL_METHOD__; + // CHECK: ret {{.*}} -1 + // CHECK-FLT-MCR: ret {{.*}} -1 +} + +bool f() { + // CHECK: define {{.*}}f{{.*}} + return __FLT_EVAL_METHOD__ < 0 && + __FLT_EVAL_METHOD__ == -1; + // CHECK: ret {{.*}} true +} Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -774,6 +774,37 @@ QualType Ty = E->getType(); assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); + LangOptions::FPEvalMethodKind EvalMethod = CurFPFeatures.getFPEvalMethod(); + if (EvalMethod != LangOptions::FEM_Source && Ty->isFloatingType()) { + switch (EvalMethod) { + default: + llvm_unreachable("Unrecognized float evaluation method"); + break; + case LangOptions::FEM_UnsetOnCommandLine: + llvm_unreachable("Unset float evaluation method"); + break; + case LangOptions::FEM_Double: + if (Context.getFloatingTypeOrder(Context.DoubleTy, Ty) > 0) + // Widen the expression to double. + return Ty->isComplexType() + ? ImpCastExprToType(E, + Context.getComplexType(Context.DoubleTy), + CK_FloatingComplexCast) + : ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast); + break; + case LangOptions::FEM_Extended: + if (Context.getFloatingTypeOrder(Context.LongDoubleTy, Ty) > 0) + // Widen the expression to long double. + return Ty->isComplexType() + ? ImpCastExprToType( + E, Context.getComplexType(Context.LongDoubleTy), + CK_FloatingComplexCast) + : ImpCastExprToType(E, Context.LongDoubleTy, + CK_FloatingCast); + break; + } + } + // Half FP have to be promoted to float unless it is natively supported if (Ty->isHalfType() && !getLangOpts().NativeHalfType) return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast); Index: clang/lib/Sema/SemaAttr.cpp =================================================================== --- clang/lib/Sema/SemaAttr.cpp +++ clang/lib/Sema/SemaAttr.cpp @@ -470,6 +470,26 @@ Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); } +void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc, + LangOptions::FPEvalMethodKind Value) { + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); + switch (Value) { + default: + llvm_unreachable("invalid pragma eval_method kind"); + case LangOptions::FEM_Source: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source); + break; + case LangOptions::FEM_Double: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double); + break; + case LangOptions::FEM_Extended: + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); + break; + } + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); +} + void Sema::ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, PragmaFloatControlKind Value) { @@ -521,6 +541,7 @@ NewFPFeatures = FpPragmaStack.CurrentValue; break; } + NewFPFeatures.setFPEvalMethodOverride(PP.getCurrentFPEvalMethod()); CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); } Index: clang/lib/Sema/Sema.cpp =================================================================== --- clang/lib/Sema/Sema.cpp +++ clang/lib/Sema/Sema.cpp @@ -234,6 +234,12 @@ SemaPPCallbackHandler = Callbacks.get(); PP.addPPCallbacks(std::move(Callbacks)); SemaPPCallbackHandler->set(*this); + if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine) + // Use setting from TargetInfo. + PP.setCurrentFPEvalMethod(ctxt.getTargetInfo().getFPEvalMethod()); + else + // Set initial value of __FLT_EVAL_METHOD__ from the command line. + PP.setCurrentFPEvalMethod(getLangOpts().getFPEvalMethod()); } // Anchor Sema's type info to this TU. @@ -2567,3 +2573,14 @@ Sema::getMismatchingDeleteExpressions() const { return DeleteExprs; } + +Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S) + : S(S), OldFPFeaturesState(S.CurFPFeatures), + OldOverrides(S.FpPragmaStack.CurrentValue), + OldEvalMethod(S.PP.getCurrentFPEvalMethod()) {} + +Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() { + S.CurFPFeatures = OldFPFeaturesState; + S.FpPragmaStack.CurrentValue = OldOverrides; + S.PP.setCurrentFPEvalMethod(OldEvalMethod); +} Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -3028,12 +3028,13 @@ namespace { /// Used as the annotation value for tok::annot_pragma_fp. struct TokFPAnnotValue { - enum FlagKinds { Contract, Reassociate, Exceptions }; + enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod }; enum FlagValues { On, Off, Fast }; llvm::Optional<LangOptions::FPModeKind> ContractValue; llvm::Optional<LangOptions::FPModeKind> ReassociateValue; llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue; + llvm::Optional<LangOptions::FPEvalMethodKind> EvalMethodValue; }; } // end anonymous namespace @@ -3060,6 +3061,7 @@ .Case("contract", TokFPAnnotValue::Contract) .Case("reassociate", TokFPAnnotValue::Reassociate) .Case("exceptions", TokFPAnnotValue::Exceptions) + .Case("eval_method", TokFPAnnotValue::EvalMethod) .Default(None); if (!FlagKind) { PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) @@ -3074,8 +3076,11 @@ return; } PP.Lex(Tok); + bool isEvalMethodDouble = + Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod; - if (Tok.isNot(tok::identifier)) { + // Don't diagnose if we have an eval_metod pragma with "double" kind. + if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) { PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) << PP.getSpelling(Tok) << OptionInfo->getName() << static_cast<int>(*FlagKind); @@ -3121,6 +3126,19 @@ << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; return; } + } else if (FlagKind == TokFPAnnotValue::EvalMethod) { + AnnotValue->EvalMethodValue = + llvm::StringSwitch<llvm::Optional<LangOptions::FPEvalMethodKind>>( + II->getName()) + .Case("source", LangOptions::FPEvalMethodKind::FEM_Source) + .Case("double", LangOptions::FPEvalMethodKind::FEM_Double) + .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended) + .Default(llvm::None); + if (!AnnotValue->EvalMethodValue) { + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) + << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; + return; + } } PP.Lex(Tok); @@ -3223,6 +3241,9 @@ if (AnnotValue->ExceptionsValue) Actions.ActOnPragmaFPExceptions(Tok.getLocation(), *AnnotValue->ExceptionsValue); + if (AnnotValue->EvalMethodValue) + Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(), + *AnnotValue->EvalMethodValue); ConsumeAnnotationToken(); } Index: clang/lib/Frontend/InitPreprocessor.cpp =================================================================== --- clang/lib/Frontend/InitPreprocessor.cpp +++ clang/lib/Frontend/InitPreprocessor.cpp @@ -1088,7 +1088,7 @@ } // Macros to control C99 numerics and <float.h> - Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod())); + Builder.defineMacro("__FLT_EVAL_METHOD__", "-1"); Builder.defineMacro("__FLT_RADIX__", "2"); Builder.defineMacro("__DECIMAL_DIG__", "__LDBL_DECIMAL_DIG__"); Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -2658,6 +2658,8 @@ StringRef FPModel = ""; // -ffp-exception-behavior options: strict, maytrap, ignore StringRef FPExceptionBehavior = ""; + // -ffp-eval-method options: double, extended, source + StringRef FPEvalMethod = ""; const llvm::DenormalMode DefaultDenormalFPMath = TC.getDefaultDenormalModeForType(Args, JA); const llvm::DenormalMode DefaultDenormalFP32Math = @@ -2851,6 +2853,18 @@ break; } + // Validate and pass through -ffp-eval-method option. + case options::OPT_ffp_eval_method_EQ: { + StringRef Val = A->getValue(); + if (Val.equals("double") || Val.equals("extended") || + Val.equals("source")) + FPEvalMethod = Val; + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + break; + } + case options::OPT_ffinite_math_only: HonorINFs = false; HonorNaNs = false; @@ -2998,6 +3012,9 @@ CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)); + if (!FPEvalMethod.empty()) + CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + FPEvalMethod)); + ParseMRecip(D, Args, CmdArgs); // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the Index: clang/lib/Basic/Targets/X86.h =================================================================== --- clang/lib/Basic/Targets/X86.h +++ clang/lib/Basic/Targets/X86.h @@ -167,9 +167,10 @@ return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e"; } - unsigned getFloatEvalMethod() const override { + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { // X87 evaluates with 80 bits "long double" precision. - return SSELevel == NoSSE ? 2 : 0; + return SSELevel == NoSSE ? LangOptions::FPEvalMethodKind::FEM_Extended + : LangOptions::FPEvalMethodKind::FEM_Source; } ArrayRef<const char *> getGCCRegNames() const override; @@ -470,14 +471,14 @@ NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {} - unsigned getFloatEvalMethod() const override { + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { unsigned Major, Minor, Micro; getTriple().getOSVersion(Major, Minor, Micro); // New NetBSD uses the default rounding mode. if (Major >= 7 || (Major == 6 && Minor == 99 && Micro >= 26) || Major == 0) - return X86_32TargetInfo::getFloatEvalMethod(); + return X86_32TargetInfo::getFPEvalMethod(); // NetBSD before 6.99.26 defaults to "double" rounding. - return 1; + return LangOptions::FPEvalMethodKind::FEM_Double; } }; Index: clang/lib/Basic/Targets/OSTargets.h =================================================================== --- clang/lib/Basic/Targets/OSTargets.h +++ clang/lib/Basic/Targets/OSTargets.h @@ -745,7 +745,9 @@ } // AIX sets FLT_EVAL_METHOD to be 1. - unsigned getFloatEvalMethod() const override { return 1; } + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { + return LangOptions::FPEvalMethodKind::FEM_Double; + } bool defaultsToAIXPowerAlignment() const override { return true; } }; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -1523,19 +1523,15 @@ /// statements. class FPFeaturesStateRAII { public: - FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) { - OldOverrides = S.FpPragmaStack.CurrentValue; - } - ~FPFeaturesStateRAII() { - S.CurFPFeatures = OldFPFeaturesState; - S.FpPragmaStack.CurrentValue = OldOverrides; - } + FPFeaturesStateRAII(Sema &S); + ~FPFeaturesStateRAII(); FPOptionsOverride getOverrides() { return OldOverrides; } private: Sema& S; FPOptions OldFPFeaturesState; FPOptionsOverride OldOverrides; + LangOptions::FPEvalMethodKind OldEvalMethod; }; void addImplicitTypedef(StringRef Name, QualType T); @@ -10070,6 +10066,9 @@ !CurFPFeatures.getAllowApproxFunc(); } + void ActOnPragmaFPEvalMethod(SourceLocation Loc, + LangOptions::FPEvalMethodKind Value); + /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction Action, PragmaFloatControlKind Value); Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -184,6 +184,7 @@ std::unique_ptr<PragmaHandler> PCSectionHandler; std::unique_ptr<PragmaHandler> MSCommentHandler; std::unique_ptr<PragmaHandler> MSDetectMismatchHandler; + std::unique_ptr<PragmaHandler> FPEvalMethodHandler; std::unique_ptr<PragmaHandler> FloatControlHandler; std::unique_ptr<PragmaHandler> MSPointersToMembers; std::unique_ptr<PragmaHandler> MSVtorDisp; Index: clang/include/clang/Lex/Preprocessor.h =================================================================== --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -185,6 +185,12 @@ SourceLocation DATELoc, TIMELoc; + // FEM_UnsetOnCommandLine means that an explicit evaluation method was + // not specified on the command line. The target is queried to set the + // default evaluation method. + LangOptions::FPEvalMethodKind CurrentFPEvalMethod = + LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; + // Next __COUNTER__ value, starts at 0. unsigned CounterValue = 0; @@ -2027,6 +2033,19 @@ unsigned getCounterValue() const { return CounterValue; } void setCounterValue(unsigned V) { CounterValue = V; } + LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const { + assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine && + "FPEvalMethod should be set either from command line or from the " + "target info"); + return CurrentFPEvalMethod; + } + + void setCurrentFPEvalMethod(LangOptions::FPEvalMethodKind Val) { + assert(Val != LangOptions::FEM_UnsetOnCommandLine && + "FPEvalMethod should never be set to FEM_UnsetOnCommandLine"); + CurrentFPEvalMethod = Val; + } + /// Retrieves the module that we're currently building, if any. Module *getCurrentModule(); Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1469,6 +1469,11 @@ def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, Flags<[Unsupported]>; def fhosted : Flag<["-"], "fhosted">, Group<f_Group>; def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, Group<f_Group>, Flags<[CC1Option]>; +def ffp_eval_method_EQ : Joined<["-"], "ffp-eval-method=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Specifies the evaluation method to use for floating-point arithmetic.">, + Values<"source,double,extended">, NormalizedValuesScope<"LangOptions">, + NormalizedValues<["FEM_Source", "FEM_Double", "FEM_Extended"]>, + MarshallingInfoEnum<LangOpts<"FPEvalMethod">, "FEM_UnsetOnCommandLine">; def ffp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, Flags<[NoXarchOption]>, HelpText<"Controls the semantics of floating-point calculations.">; def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, Group<f_Group>, Flags<[CC1Option]>, Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -702,7 +702,9 @@ } /// Return the value for the C99 FLT_EVAL_METHOD macro. - virtual unsigned getFloatEvalMethod() const { return 0; } + virtual LangOptions::FPEvalMethodKind getFPEvalMethod() const { + return LangOptions::FPEvalMethodKind::FEM_Source; + } // getLargeArrayMinWidth/Align - Return the minimum array size that is // 'large' and its alignment. Index: clang/include/clang/Basic/LangOptions.h =================================================================== --- clang/include/clang/Basic/LangOptions.h +++ clang/include/clang/Basic/LangOptions.h @@ -230,6 +230,24 @@ FPE_Strict }; + /// Possible float expression evaluation method choices. + enum FPEvalMethodKind { + /// The evaluation method cannot be determined or is inconsistent for this + /// target. + FEM_Indeterminable = -1, + /// Use the declared type for fp arithmetic. + FEM_Source = 0, + /// Use the type double for fp arithmetic. + FEM_Double = 1, + /// Use extended type for fp arithmetic. + FEM_Extended = 2, + /// Used only for FE option processing; this is only used to indicate that + /// the user did not specify an explicit evaluation method on the command + /// line and so the target should be queried for its default evaluation + /// method instead. + FEM_UnsetOnCommandLine = 3 + }; + /// Possible exception handling behavior. enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -301,6 +301,7 @@ COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict floating point") BENIGN_ENUM_LANGOPT(FPRoundingMode, RoundingMode, 3, RoundingMode::NearestTiesToEven, "FP Rounding Mode type") BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP Exception Behavior Mode type") +BENIGN_ENUM_LANGOPT(FPEvalMethod, FPEvalMethodKind, 2, FEM_UnsetOnCommandLine, "FP type used for floating point arithmetic") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") Index: clang/include/clang/Basic/FPOptions.def =================================================================== --- clang/include/clang/Basic/FPOptions.def +++ clang/include/clang/Basic/FPOptions.def @@ -23,4 +23,5 @@ OPTION(NoSignedZero, bool, 1, NoHonorInfs) OPTION(AllowReciprocal, bool, 1, NoSignedZero) OPTION(AllowApproxFunc, bool, 1, AllowReciprocal) +OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) #undef OPTION Index: clang/docs/UsersManual.rst =================================================================== --- clang/docs/UsersManual.rst +++ clang/docs/UsersManual.rst @@ -1489,6 +1489,18 @@ * ``maytrap`` The compiler avoids transformations that may raise exceptions that would not have been raised by the original code. Constant folding performed by the compiler is exempt from this option. * ``strict`` The compiler ensures that all transformations strictly preserve the floating point exception semantics of the original code. +.. option:: -ffp-eval-method=<value> + + Specify the floating-point evaluation method for intermediate results within + a single expression of the code. + + Valid values are: ``source``, ``double``, and ``extended``. + The default value is target-specific, typically ``source``. Details: + + * ``source`` The compiler uses the floating-point type declared in the source program as the evaluation method. + * ``double`` The compiler uses ``double`` as the floating-point evaluation method for all float expressions of type that is narrower than ``double``. + * ``extended`` The compiler uses ``long double`` as the floating-point evaluation method for all float expressions of type that is narrower than ``long double``. + .. option:: -f[no-]protect-parens: This option pertains to floating-point types, complex types with @@ -1510,6 +1522,14 @@ has no effect because the optimizer is prohibited from making unsafe transformations. +.. _FLT_EVAL_METHOD: + +A note about ``__FLT_EVAL_METHOD__`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The macro ``__FLT_EVAL_METHOD__`` will expand to -1 throughout the translation +unit to represent an indeterminable evaluation method; it is not modified by use +of ``#pragma float_control`` or ``#pragma clang fp eval-method``. + .. _fp-constant-eval: A note about Floating Point Constant Evaluation Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -3678,6 +3678,37 @@ a = b[i] * c[i] + e; } +The ``#pragma clang fp eval_method`` pragma allows precise floating-point +semantics and floating-point exception behavior to be specified for a section +of the source code. This pragma can only appear at file or namespace scope, +within a language linkage specification or at the start of a compound statement +(excluding comments). When used within a compound statement, the pragma is +active within the scope of the compound statement. + +When ``pragma clang fp eval_method(source)`` is enabled, the section of code +governed by the pragma behaves as though the command-line option +``-ffp-eval-method=source`` is enabled. + +When ``pragma clang fp eval_method(double)`` is enabled, the section of code +governed by the pragma behaves as though the command-line option +``-ffp-eval-method=double`` is enabled. + +When ``pragma clang fp eval_method(extended)`` is enabled, the section of code +governed by the pragma behaves as though the command-line option +``-ffp-eval-method=extended`` is enabled. + +The full syntax this pragma supports is +``#pragma clang fp eval_method(source|double|extended)``. + +.. code-block:: c++ + + for(...) { + // The compiler will use long double as the floating-point evaluation + // method. + #pragma clanf fp eval_method(extended) + a = b[i] * c[i] + e; + } + Specifying an attribute for multiple declarations (#pragma clang attribute) ===========================================================================
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits