Skip to content

Commit e11a197

Browse files
committed
PR feedback.
1 parent 5dd9690 commit e11a197

File tree

11 files changed

+153
-79
lines changed

11 files changed

+153
-79
lines changed

clang/include/clang/AST/ASTContext.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,13 +3014,13 @@ class ASTContext : public RefCountedBase<ASTContext> {
30143014
/// of \p LHS is less than \p RHS, return FRCR_Equal_Lesser_Subrank. Subrank
30153015
/// and Unordered comparison were introduced in C++23.
30163016
FloatConvRankCompareResult getFloatingTypeOrder(QualType LHS,
3017-
QualType RHS) const;
3017+
QualType RHS) const;
30183018

30193019
/// Compare the rank of two floating point types as above, but compare equal
30203020
/// if both types have the same floating-point semantics on the target (i.e.
30213021
/// long double and double on AArch64 will return FRCR_Equal).
30223022
FloatConvRankCompareResult getFloatingTypeSemanticOrder(QualType LHS,
3023-
QualType RHS) const;
3023+
QualType RHS) const;
30243024

30253025
/// C++23 6.8.2p12 [basic.fundamental]
30263026
/// Checks if extended floating point rules apply to a pair of types.

clang/lib/AST/ASTContext.cpp

Lines changed: 47 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
#include "clang/Basic/TargetInfo.h"
6666
#include "clang/Basic/XRayLists.h"
6767
#include "llvm/ADT/APFixedPoint.h"
68+
#include "llvm/ADT/APFloat.h"
6869
#include "llvm/ADT/APInt.h"
6970
#include "llvm/ADT/APSInt.h"
7071
#include "llvm/ADT/ArrayRef.h"
@@ -152,64 +153,50 @@ constexpr unsigned CXX23FloatRankToIndex(clang::BuiltinType::Kind Kind) {
152153
}
153154

154155
// C++23 6.8.6p2 [conv.rank]
155-
// Grid to determine the rank of a floating point type when compared with
156-
// another floating point type.
157-
constexpr std::array<std::array<FloatConvRankCompareResult, 5>, 5>
158-
CXX23FloatingPointConversionRankMap = {
159-
{// Float16 x Float16
160-
// Float16 x BFloat16
161-
// Float16 x Float
162-
// Float16 x Double
163-
// Float16 x LongDouble
164-
{{FloatConvRankCompareResult::FRCR_Equal,
165-
FloatConvRankCompareResult::FRCR_Unordered,
166-
FloatConvRankCompareResult::FRCR_Lesser,
167-
FloatConvRankCompareResult::FRCR_Lesser,
168-
FloatConvRankCompareResult::FRCR_Lesser}},
169-
170-
// BFloat16 x Float16
171-
// BFloat16 x BFloat16
172-
// BFloat16 x Float
173-
// BFloat16 x Double
174-
// BFloat16 x LongDouble
175-
{{FloatConvRankCompareResult::FRCR_Unordered,
176-
FloatConvRankCompareResult::FRCR_Equal,
177-
FloatConvRankCompareResult::FRCR_Lesser,
178-
FloatConvRankCompareResult::FRCR_Lesser,
179-
FloatConvRankCompareResult::FRCR_Lesser}},
180-
181-
// Float x Float16
182-
// Float x BFloat16
183-
// Float x Float
184-
// Float x Double
185-
// Float x LongDouble
186-
{{FloatConvRankCompareResult::FRCR_Greater,
187-
FloatConvRankCompareResult::FRCR_Greater,
188-
FloatConvRankCompareResult::FRCR_Equal,
189-
FloatConvRankCompareResult::FRCR_Lesser,
190-
FloatConvRankCompareResult::FRCR_Lesser}},
191-
192-
// Double x Float16
193-
// Double x BFloat16
194-
// Double x Float
195-
// Double x Double
196-
// Double x LongDouble
197-
{{FloatConvRankCompareResult::FRCR_Greater,
198-
FloatConvRankCompareResult::FRCR_Greater,
199-
FloatConvRankCompareResult::FRCR_Greater,
200-
FloatConvRankCompareResult::FRCR_Equal,
201-
FloatConvRankCompareResult::FRCR_Lesser}},
202-
203-
// LongDouble x Float16
204-
// LongDouble x BFloat16
205-
// LongDouble x Float
206-
// LongDouble x Double
207-
// LongDouble x LongDouble
208-
{{FloatConvRankCompareResult::FRCR_Greater,
209-
FloatConvRankCompareResult::FRCR_Greater,
210-
FloatConvRankCompareResult::FRCR_Greater,
211-
FloatConvRankCompareResult::FRCR_Greater,
212-
FloatConvRankCompareResult::FRCR_Equal}}}};
156+
FloatConvRankCompareResult
157+
CXX23CompareFpConversionRanks(BuiltinType::Kind LHSKind,
158+
BuiltinType::Kind RHSKind, QualType LHS,
159+
QualType RHS, const ASTContext &Ctx) {
160+
161+
// Same types.
162+
if (LHSKind == RHSKind)
163+
return FloatConvRankCompareResult::FRCR_Equal;
164+
165+
// Special case comparision between float, double and long double.
166+
if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::Double)
167+
return FloatConvRankCompareResult::FRCR_Lesser;
168+
if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::Float)
169+
return FloatConvRankCompareResult::FRCR_Greater;
170+
if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::LongDouble)
171+
return FloatConvRankCompareResult::FRCR_Lesser;
172+
if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Float)
173+
return FloatConvRankCompareResult::FRCR_Greater;
174+
if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::LongDouble)
175+
return FloatConvRankCompareResult::FRCR_Lesser;
176+
if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Double)
177+
return FloatConvRankCompareResult::FRCR_Greater;
178+
179+
const llvm::fltSemantics &LHSSemantics = Ctx.getFloatTypeSemantics(LHS);
180+
const llvm::fltSemantics &RHSSemantics = Ctx.getFloatTypeSemantics(RHS);
181+
182+
bool LHSRepresentableByRHS =
183+
llvm::APFloat::isRepresentableBy(LHSSemantics, RHSSemantics);
184+
bool RHSRepresentableByLHS =
185+
llvm::APFloat::isRepresentableBy(RHSSemantics, LHSSemantics);
186+
187+
if (LHSRepresentableByRHS && !RHSRepresentableByLHS)
188+
return FloatConvRankCompareResult::FRCR_Lesser;
189+
if (!LHSRepresentableByRHS && RHSRepresentableByLHS)
190+
return FloatConvRankCompareResult::FRCR_Greater;
191+
192+
if (!LHSRepresentableByRHS && !RHSRepresentableByLHS)
193+
return FloatConvRankCompareResult::FRCR_Unordered;
194+
195+
// Both types are representable by each other, compare sub-ranks, however, as
196+
// of today this scenario doesn't exist.
197+
llvm_unreachable(
198+
"Both types are representable by each other, compare sub-ranks");
199+
}
213200

214201
/// \returns The locations that are relevant when searching for Doc comments
215202
/// related to \p D.
@@ -7757,7 +7744,7 @@ static FloatingRank getFloatingRank(QualType T) {
77577744
/// point types, ignoring the domain of the type (i.e. 'double' ==
77587745
/// '_Complex double').
77597746
/// If LHS > RHS, return FRCR_Greater. If LHS == RHS, return FRCR_Equal. If
7760-
/// LHS < RHS, return FRCR_Lesser. If the values representedable by the two
7747+
/// LHS < RHS, return FRCR_Lesser. If the values representable by the two
77617748
/// are not subset of each other, return FRCR_Unordered. If LHS == RHS but
77627749
/// LHS has a higher subrank than RHS return FRCR_Equal_Greater_Subrank else
77637750
/// return FRCR_Equal_Lesser_Subrank.
@@ -7775,8 +7762,7 @@ ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
77757762
RHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind();
77767763
else
77777764
RHSKind = RHS->castAs<BuiltinType>()->getKind();
7778-
return CXX23FloatingPointConversionRankMap[CXX23FloatRankToIndex(LHSKind)]
7779-
[CXX23FloatRankToIndex(RHSKind)];
7765+
return CXX23CompareFpConversionRanks(LHSKind, RHSKind, LHS, RHS, *this);
77807766
}
77817767

77827768
FloatingRank LHSR = getFloatingRank(LHS);

clang/lib/AST/Type.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,8 +2304,10 @@ bool Type::isCXX23ExtendedFloatingPointType(const ASTContext &Ctx) const {
23042304
if (!Ctx.getLangOpts().CPlusPlus23)
23052305
return false;
23062306
if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType))
2307-
return BT->getKind() == BuiltinType::Float16 ||
2308-
BT->getKind() == BuiltinType::BFloat16;
2307+
return (BT->getKind() == BuiltinType::Float16 &&
2308+
Ctx.getTargetInfo().hasFloat16Type()) ||
2309+
(BT->getKind() == BuiltinType::BFloat16 &&
2310+
Ctx.getTargetInfo().hasFullBFloat16Type());
23092311
if (const auto *CT = dyn_cast<ComplexType>(CanonicalType))
23102312
return CT->getElementType()->isCXX23ExtendedFloatingPointType(Ctx);
23112313
return false;

clang/lib/Frontend/InitPreprocessor.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,12 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI,
473473
else if (LangOpts.CPlusPlus23) {
474474
Builder.defineMacro("__cplusplus", "202302L");
475475
// [C++23] 15.11p2 [cpp.predefined]
476-
Builder.defineMacro("__STDCPP_FLOAT16_T__", "1");
477-
Builder.defineMacro("__STDCPP_BFLOAT16_T__", "1");
476+
if (TI.hasFloat16Type()) {
477+
Builder.defineMacro("__STDCPP_FLOAT16_T__", "1");
478+
}
479+
if (TI.hasFullBFloat16Type()) {
480+
Builder.defineMacro("__STDCPP_BFLOAT16_T__", "1");
481+
}
478482
}
479483
// [C++20] The integer literal 202002L.
480484
else if (LangOpts.CPlusPlus20)

clang/lib/Lex/LiteralSupport.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/ADT/APInt.h"
2424
#include "llvm/ADT/SmallVector.h"
2525
#include "llvm/ADT/StringExtras.h"
26+
#include "llvm/ADT/StringRef.h"
2627
#include "llvm/ADT/StringSwitch.h"
2728
#include "llvm/Support/ConvertUTF.h"
2829
#include "llvm/Support/Error.h"
@@ -1038,14 +1039,17 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
10381039
case 'B':
10391040
if (!isFPConstant)
10401041
break; // Error for integer constant.
1041-
if (s + 3 < ThisTokEnd && (s[1] == 'f' || s[1] == 'F') && s[2] == '1' &&
1042-
s[3] == '6') {
1043-
if (HasSize)
1044-
break;
1045-
HasSize = true;
1046-
s += 3;
1047-
isBFloat16 = true;
1048-
continue;
1042+
if (HasSize)
1043+
break;
1044+
HasSize = true;
1045+
1046+
if ((s + 3 < ThisTokEnd) && Target.hasFullBFloat16Type()) {
1047+
StringRef suffix(s, 4);
1048+
if (suffix == "bf16" || suffix == "BF16") {
1049+
s += 3;
1050+
isBFloat16 = true;
1051+
continue;
1052+
}
10491053
}
10501054
break;
10511055
case 'q': // FP Suffix for "__float128"

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7445,7 +7445,8 @@ isArithmeticArgumentPromotion(Sema &S, const ImplicitCastExpr *ICE) {
74457445
if (const auto *VecTy = To->getAs<ExtVectorType>())
74467446
To = VecTy->getElementType();
74477447
// It's a floating promotion if the source type is float.
7448-
// [7.3.8p1][conv.fpprom] https://eel.is/c++draft/conv.fpprom
7448+
// [7.3.8p1][conv.fpprom] A prvalue of type float can be converted to a
7449+
// prvalue of type double. The value is unchanged.
74497450
return (ICE->getCastKind() == CK_FloatingCast &&
74507451
S.Context.isPromotableFloatingType(From) &&
74517452
S.Context.getPromotedFloatingType(From) == To);

clang/lib/Sema/SemaOverload.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4455,7 +4455,7 @@ CompareStandardConversionSequences(Sema &S, SourceLocation Loc,
44554455
? ImplicitConversionSequence::Better
44564456
: ImplicitConversionSequence::Worse;
44574457

4458-
// C++23 12.2.4.3p4:
4458+
// C++23 [over.ics.rank]p4b3:
44594459
// A conversion in either direction between floating-point type FP1 and
44604460
// floating-point type FP2 is better than a conversion in the same direction
44614461
// between FP1 and arithmetic type T3 if:

clang/test/CodeGenCXX/cxx23-fp-ext-std-names-p1467r9.cpp

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
2-
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-linux-gnu -target-feature +fullbf16 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
2+
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown -target-feature +fullbf16 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK
33

44
// CHECK-LABEL: define {{[^@]+}}@_Z1fDF16b
55
// CHECK-SAME: (bfloat noundef [[V:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -497,3 +497,67 @@ void test9_7() {
497497
// User-defined overload cases
498498
decltype(0.BF16) bfloat16_val_2(user_defined_val_2); // calls operator int()
499499
}
500+
501+
template <typename T>
502+
T passThrough(T x) { return x; }
503+
504+
template <typename T>
505+
void acceptSameType(T, T) {}
506+
507+
// CHECK-LABEL: define {{[^@]+}}@_Z8test10_1v
508+
// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
509+
// CHECK-NEXT: entry:
510+
// CHECK-NEXT: [[HF:%.*]] = alloca half, align 2
511+
// CHECK-NEXT: [[BF:%.*]] = alloca bfloat, align 2
512+
// CHECK-NEXT: [[RES1:%.*]] = alloca half, align 2
513+
// CHECK-NEXT: [[RES2:%.*]] = alloca bfloat, align 2
514+
// CHECK-NEXT: [[F:%.*]] = alloca float, align 4
515+
// CHECK-NEXT: [[D:%.*]] = alloca double, align 8
516+
// CHECK-NEXT: [[LD:%.*]] = alloca x86_fp80, align 16
517+
// CHECK-NEXT: [[R3:%.*]] = alloca float, align 4
518+
// CHECK-NEXT: [[R4:%.*]] = alloca double, align 8
519+
// CHECK-NEXT: [[R5:%.*]] = alloca x86_fp80, align 16
520+
// CHECK-NEXT: store half 0xH3C00, ptr [[HF]], align 2
521+
// CHECK-NEXT: store bfloat 0xR4000, ptr [[BF]], align 2
522+
// CHECK-NEXT: [[TMP0:%.*]] = load half, ptr [[HF]], align 2
523+
// CHECK-NEXT: [[CALL:%.*]] = call noundef half @_Z11passThroughIDF16_ET_S0_(half noundef [[TMP0]])
524+
// CHECK-NEXT: store half [[CALL]], ptr [[RES1]], align 2
525+
// CHECK-NEXT: [[TMP1:%.*]] = load bfloat, ptr [[BF]], align 2
526+
// CHECK-NEXT: [[CALL1:%.*]] = call noundef bfloat @_Z11passThroughIDF16bET_S0_(bfloat noundef [[TMP1]])
527+
// CHECK-NEXT: store bfloat [[CALL1]], ptr [[RES2]], align 2
528+
// CHECK-NEXT: store float 3.000000e+00, ptr [[F]], align 4
529+
// CHECK-NEXT: store double 4.000000e+00, ptr [[D]], align 8
530+
// CHECK-NEXT: store x86_fp80 0xK4001A000000000000000, ptr [[LD]], align 16
531+
// CHECK-NEXT: [[TMP2:%.*]] = load half, ptr [[HF]], align 2
532+
// CHECK-NEXT: call void @_Z14acceptSameTypeIDF16_EvT_S0_(half noundef [[TMP2]], half noundef 0xH4600)
533+
// CHECK-NEXT: [[TMP3:%.*]] = load bfloat, ptr [[BF]], align 2
534+
// CHECK-NEXT: call void @_Z14acceptSameTypeIDF16bEvT_S0_(bfloat noundef [[TMP3]], bfloat noundef 0xR40E0)
535+
// CHECK-NEXT: [[TMP4:%.*]] = load float, ptr [[F]], align 4
536+
// CHECK-NEXT: [[CALL2:%.*]] = call noundef float @_Z11passThroughIfET_S0_(float noundef [[TMP4]])
537+
// CHECK-NEXT: store float [[CALL2]], ptr [[R3]], align 4
538+
// CHECK-NEXT: [[TMP5:%.*]] = load double, ptr [[D]], align 8
539+
// CHECK-NEXT: [[CALL3:%.*]] = call noundef double @_Z11passThroughIdET_S0_(double noundef [[TMP5]])
540+
// CHECK-NEXT: store double [[CALL3]], ptr [[R4]], align 8
541+
// CHECK-NEXT: [[TMP6:%.*]] = load x86_fp80, ptr [[LD]], align 16
542+
// CHECK-NEXT: [[CALL4:%.*]] = call noundef x86_fp80 @_Z11passThroughIeET_S0_(x86_fp80 noundef [[TMP6]])
543+
// CHECK-NEXT: store x86_fp80 [[CALL4]], ptr [[R5]], align 16
544+
// CHECK-NEXT: ret void
545+
//
546+
void test10_1() {
547+
_Float16 hf = 1.0f16;
548+
decltype(0.BF16) bf = 2.0bf16;
549+
550+
auto res1 = passThrough(hf);
551+
auto res2 = passThrough(bf);
552+
553+
float f = 3.0f;
554+
double d = 4.0;
555+
long double ld = 5.0L;
556+
557+
acceptSameType(hf, _Float16(6.0f16));
558+
acceptSameType(bf, decltype(0.BF16)(7.0bf16));
559+
560+
auto r3 = passThrough(f);
561+
auto r4 = passThrough(d);
562+
auto r5 = passThrough(ld);
563+
}

clang/test/Sema/cxx23-fp-ext-std-names-p1467r9.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -fsyntax-only -std=c++23 -target-feature +fullbf16 -verify -ast-dump %s | FileCheck %s
1+
// RUN: %clang_cc1 -fsyntax-only -std=c++23 -triple x86_64-unknown-unknown -target-feature +fullbf16 -verify -ast-dump %s | FileCheck %s
22
#include <stdarg.h>
33
_Float16 f16_val_1 = 1.0bf16; // expected-error {{cannot initialize a variable of type '_Float16' with an rvalue of type '__bf16'}}
44
_Float16 f16_val_2 = 1.0f; // expected-error {{cannot initialize a variable of type '_Float16' with an rvalue of type 'float'}}

llvm/include/llvm/ADT/APFloat.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,9 @@ class APFloat : public APFloatBase {
13701370
/// shorter semantics, like IEEEhalf.
13711371
float convertToFloat() const;
13721372

1373+
static bool isRepresentableBy(const fltSemantics &Sem,
1374+
const fltSemantics &Other);
1375+
13731376
bool operator==(const APFloat &RHS) const { return compare(RHS) == cmpEqual; }
13741377

13751378
bool operator!=(const APFloat &RHS) const { return compare(RHS) != cmpEqual; }

0 commit comments

Comments
 (0)