https://github.com/spavloff updated https://github.com/llvm/llvm-project/pull/90877
>From 5d906b537636ca0d8706a8a888dd78edfbec684f Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Thu, 2 May 2024 22:28:05 +0700 Subject: [PATCH 1/8] [clang] Use constant rounding mode for floating literals Conversion of floating-point literal to binary representation must be made using constant rounding mode, which can be changed using pragma FENV_ROUND. For example, the literal "0.1F" should be representes by either 0.099999994 or 0.100000001 depending on the rounding direction. --- clang/include/clang/Lex/LiteralSupport.h | 10 ++++------ clang/lib/Lex/LiteralSupport.cpp | 6 +++--- clang/lib/Sema/SemaExpr.cpp | 3 ++- clang/test/AST/const-fpfeatures.c | 6 ++++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 2ed42d1c5f9aae..705021fcfa5b11 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -118,12 +118,10 @@ class NumericLiteralParser { /// bits of the result and return true. Otherwise, return false. bool GetIntegerValue(llvm::APInt &Val); - /// GetFloatValue - Convert this numeric literal to a floating value, using - /// the specified APFloat fltSemantics (specifying float, double, etc). - /// The optional bool isExact (passed-by-reference) has its value - /// set to true if the returned APFloat can represent the number in the - /// literal exactly, and false otherwise. - llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + /// Convert this numeric literal to a floating value, using the specified + /// APFloat fltSemantics (specifying float, double, etc) and rounding mode. + llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM); /// GetFixedPointValue - Convert this numeric literal value into a /// scaled integer that represents this value. Returns true if an overflow diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 9c0cbea5052cb2..3df0391bdda772 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1520,7 +1520,8 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) { } llvm::APFloat::opStatus -NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { +NumericLiteralParser::GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM) { using llvm::APFloat; unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin); @@ -1534,8 +1535,7 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { Str = Buffer; } - auto StatusOrErr = - Result.convertFromString(Str, APFloat::rmNearestTiesToEven); + auto StatusOrErr = Result.convertFromString(Str, RM); assert(StatusOrErr && "Invalid floating point representation"); return !errorToBool(StatusOrErr.takeError()) ? *StatusOrErr : APFloat::opInvalidOp; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0cca02c338954a..db96c8692f2516 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3858,7 +3858,8 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, using llvm::APFloat; APFloat Val(Format); - APFloat::opStatus result = Literal.GetFloatValue(Val); + APFloat::opStatus result = + Literal.GetFloatValue(Val, S.CurFPFeatures.getRoundingMode()); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). diff --git a/clang/test/AST/const-fpfeatures.c b/clang/test/AST/const-fpfeatures.c index 6600ea27405d9c..247245c776fed1 100644 --- a/clang/test/AST/const-fpfeatures.c +++ b/clang/test/AST/const-fpfeatures.c @@ -19,6 +19,9 @@ float FI1u = 0xFFFFFFFFU; float _Complex C1u = C0; // CHECK: @C1u = {{.*}} { float, float } { float 0x3FF0000020000000, float 0x3FF0000020000000 } +float FLu = 0.1F; +// CHECK: @FLu = {{.*}} float 0x3FB9999980000000 + #pragma STDC FENV_ROUND FE_DOWNWARD @@ -35,3 +38,6 @@ float FI1d = 0xFFFFFFFFU; float _Complex C1d = C0; // CHECK: @C1d = {{.*}} { float, float } { float 1.000000e+00, float 1.000000e+00 } + +float FLd = 0.1F; +// CHECK: @FLd = {{.*}} float 0x3FB99999A0000000 >From a6fad25517b283c4b282324595d1e84f99717e16 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Fri, 3 May 2024 13:45:36 +0700 Subject: [PATCH 2/8] Fix typo --- clang/test/AST/const-fpfeatures.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/AST/const-fpfeatures.c b/clang/test/AST/const-fpfeatures.c index 247245c776fed1..276d46b70c21d9 100644 --- a/clang/test/AST/const-fpfeatures.c +++ b/clang/test/AST/const-fpfeatures.c @@ -20,7 +20,7 @@ float _Complex C1u = C0; // CHECK: @C1u = {{.*}} { float, float } { float 0x3FF0000020000000, float 0x3FF0000020000000 } float FLu = 0.1F; -// CHECK: @FLu = {{.*}} float 0x3FB9999980000000 +// CHECK: @FLu = {{.*}} float 0x3FB99999A0000000 #pragma STDC FENV_ROUND FE_DOWNWARD @@ -40,4 +40,4 @@ float _Complex C1d = C0; // CHECK: @C1d = {{.*}} { float, float } { float 1.000000e+00, float 1.000000e+00 } float FLd = 0.1F; -// CHECK: @FLd = {{.*}} float 0x3FB99999A0000000 +// CHECK: @FLd = {{.*}} float 0x3FB9999980000000 >From f2e04141fc76b2ddf7e4481ebecd5392f1653843 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Fri, 3 May 2024 19:08:49 +0700 Subject: [PATCH 3/8] Add test for NTTP --- clang/test/AST/const-fpfeatures.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/clang/test/AST/const-fpfeatures.cpp b/clang/test/AST/const-fpfeatures.cpp index 9c807b34625f3a..c5739359b10e0a 100644 --- a/clang/test/AST/const-fpfeatures.cpp +++ b/clang/test/AST/const-fpfeatures.cpp @@ -79,3 +79,16 @@ float V7 = []() -> float { 0x0.000001p0F); }(); // CHECK: @V7 = {{.*}} float 1.000000e+00 + +template<float V> struct L { + constexpr L() : value(V) {} + float value; +}; + +#pragma STDC FENV_ROUND FE_DOWNWARD +L<0.1F> val_d; +// CHECK: @val_d = {{.*}} { float 0x3FB9999980000000 } + +#pragma STDC FENV_ROUND FE_UPWARD +L<0.1F> val_u; +// CHECK: @val_u = {{.*}} { float 0x3FB99999A0000000 } >From cf6ff55ad4a45875a821b3ac82c22bb7917b4d67 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Fri, 3 May 2024 20:04:13 +0700 Subject: [PATCH 4/8] Replace dynamic rounding mode with NearestTiesToEven --- clang/lib/Sema/SemaExpr.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index db96c8692f2516..da107a684446c9 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3858,8 +3858,11 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, using llvm::APFloat; APFloat Val(Format); + llvm::RoundingMode RM = S.CurFPFeatures.getRoundingMode(); + if (RM == llvm::RoundingMode::Dynamic) + RM = llvm::RoundingMode::NearestTiesToEven; APFloat::opStatus result = - Literal.GetFloatValue(Val, S.CurFPFeatures.getRoundingMode()); + Literal.GetFloatValue(Val, RM); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). >From aeb6074444513587924106081213335f73ba6eb0 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Fri, 3 May 2024 22:16:54 +0700 Subject: [PATCH 5/8] Add additional test for float literal as NTTP --- clang/test/AST/const-fpfeatures.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/clang/test/AST/const-fpfeatures.cpp b/clang/test/AST/const-fpfeatures.cpp index c5739359b10e0a..df8856de3f1ec3 100644 --- a/clang/test/AST/const-fpfeatures.cpp +++ b/clang/test/AST/const-fpfeatures.cpp @@ -92,3 +92,16 @@ L<0.1F> val_d; #pragma STDC FENV_ROUND FE_UPWARD L<0.1F> val_u; // CHECK: @val_u = {{.*}} { float 0x3FB99999A0000000 } + +template<typename T, T C> +constexpr T foo() { + return C; +} + +#pragma STDC FENV_ROUND FE_DOWNWARD +float var_d = foo<float, 0.1F>(); +// CHECK: @var_d = {{.*}} float 0x3FB9999980000000 + +#pragma STDC FENV_ROUND FE_UPWARD +float var_u = foo<float, 0.1F>(); +// CHECK: @var_u = {{.*}} float 0x3FB99999A0000000 >From ed25d8a3df2d27b63481cf9468f6a2a807defbf0 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Fri, 3 May 2024 22:50:25 +0700 Subject: [PATCH 6/8] Fix clang-format error --- clang/lib/Sema/SemaExpr.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index da107a684446c9..a344d1281e60af 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3861,8 +3861,7 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, llvm::RoundingMode RM = S.CurFPFeatures.getRoundingMode(); if (RM == llvm::RoundingMode::Dynamic) RM = llvm::RoundingMode::NearestTiesToEven; - APFloat::opStatus result = - Literal.GetFloatValue(Val, RM); + APFloat::opStatus result = Literal.GetFloatValue(Val, RM); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). >From da2795c2a84a96f4942e3464f30de8ae0d1ddd26 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Sat, 4 May 2024 00:49:59 +0700 Subject: [PATCH 7/8] Add test for template instatiations --- clang/test/AST/const-fpfeatures.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/clang/test/AST/const-fpfeatures.cpp b/clang/test/AST/const-fpfeatures.cpp index df8856de3f1ec3..4065452306668b 100644 --- a/clang/test/AST/const-fpfeatures.cpp +++ b/clang/test/AST/const-fpfeatures.cpp @@ -80,6 +80,8 @@ float V7 = []() -> float { }(); // CHECK: @V7 = {{.*}} float 1.000000e+00 +#pragma STDC FENV_ROUND FE_DYNAMIC + template<float V> struct L { constexpr L() : value(V) {} float value; @@ -93,6 +95,8 @@ L<0.1F> val_d; L<0.1F> val_u; // CHECK: @val_u = {{.*}} { float 0x3FB99999A0000000 } +#pragma STDC FENV_ROUND FE_DYNAMIC + template<typename T, T C> constexpr T foo() { return C; @@ -105,3 +109,25 @@ float var_d = foo<float, 0.1F>(); #pragma STDC FENV_ROUND FE_UPWARD float var_u = foo<float, 0.1F>(); // CHECK: @var_u = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DYNAMIC + +template<typename T, T f> void foo2() { + T Val = f; +} + +void func_01() { + #pragma STDC FENV_ROUND FE_DOWNWARD + foo2<float, 0.1f>(); +} + +void func_02() { + #pragma STDC FENV_ROUND FE_UPWARD + foo2<float, 0.1f>(); +} + +// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dccccccEEvv() +// CHECK: store float 0x3FB9999980000000, ptr + +// CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dcccccdEEvv() +// CHECK: store float 0x3FB99999A0000000, ptr >From 58cbc15b154a16eba475b215a0b1b11b0d72aee4 Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Sun, 5 May 2024 00:43:42 +0700 Subject: [PATCH 8/8] Add test for literal in macro --- clang/test/AST/const-fpfeatures.cpp | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/clang/test/AST/const-fpfeatures.cpp b/clang/test/AST/const-fpfeatures.cpp index 4065452306668b..8438ae56106135 100644 --- a/clang/test/AST/const-fpfeatures.cpp +++ b/clang/test/AST/const-fpfeatures.cpp @@ -131,3 +131,33 @@ void func_02() { // CHECK-LABEL: define {{.*}} void @_Z4foo2IfTnT_Lf3dcccccdEEvv() // CHECK: store float 0x3FB99999A0000000, ptr + + +// Check literals in macros. + +#pragma STDC FENV_ROUND FE_DOWNWARD +#define CONSTANT_0_1 0.1F + +#pragma STDC FENV_ROUND FE_UPWARD +float C1_ru = CONSTANT_0_1; +// CHECK: @C1_ru = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +float C1_rd = CONSTANT_0_1; +// CHECK: @C1_rd = {{.*}} float 0x3FB9999980000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +#define PRAGMA(x) _Pragma(#x) +#define CONSTANT_0_1_RM(v, rm) ([](){ PRAGMA(STDC FENV_ROUND rm); return v; }()) + +#pragma STDC FENV_ROUND FE_UPWARD +float C2_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD); +float C2_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD); +// CHECK: @C2_rd = {{.*}} float 0x3FB9999980000000 +// CHECK: @C2_ru = {{.*}} float 0x3FB99999A0000000 + +#pragma STDC FENV_ROUND FE_DOWNWARD +float C3_rd = CONSTANT_0_1_RM(0.1F, FE_DOWNWARD); +float C3_ru = CONSTANT_0_1_RM(0.1F, FE_UPWARD); +// CHECK: @C3_rd = {{.*}} float 0x3FB9999980000000 +// CHECK: @C3_ru = {{.*}} float 0x3FB99999A0000000 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits