[clang] 1125934 - [Clang] `constexpr` builtin floating point classification / comparison functions (#94118)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 18 02:50:46 PDT 2024
Author: Mital Ashok
Date: 2024-08-18T13:50:42+04:00
New Revision: 11259343593043c77678b59d420159fcd147a858
URL: https://github.com/llvm/llvm-project/commit/11259343593043c77678b59d420159fcd147a858
DIFF: https://github.com/llvm/llvm-project/commit/11259343593043c77678b59d420159fcd147a858.diff
LOG: [Clang] `constexpr` builtin floating point classification / comparison functions (#94118)
As per [P0533R9](https://wg21.link/P0533R9), the corresponding C++
`[c.math.fpclass]` standard library functions for the C macros are now
`constexpr`.
The only classification function that wasn't already `constexpr` was
`__builtin_signbit`.
The floating point comparison functions `__builtin_isgreater`,
`__builtin_isgreaterequal`, `__builtin_isless`, `__builtin_islessequal`,
`__builtin_islessgreater` and `__builtin_isunordered` are now
`constexpr`.
The C23 macro `iseqsig` is not currently supported because
`__bulitin_iseqsig` doesn't exist yet (and C++26 is still currently
based on C18).
This also allows them to be constant folded in C, matching the behaviour
of GCC.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/Builtins.td
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/lib/AST/ExprConstant.cpp
clang/test/Analysis/builtin_signbit.cpp
clang/test/Sema/constant-builtins-2.c
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ffdd063ec99037..12a3707db8a39f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -161,6 +161,10 @@ C23 Feature Support
Non-comprehensive list of changes in this release
-------------------------------------------------
+- The floating point comparison builtins (``__builtin_isgreater``,
+ ``__builtin_isgreaterequal``, ``__builtin_isless``, etc.) and
+ ``__builtin_signbit`` can now be used in constant expressions.
+
New Compiler Flags
------------------
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 0a874d8638df43..036366cdadf4aa 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -533,42 +533,42 @@ def BuiltinComplex : Builtin {
def IsGreater : Builtin {
let Spellings = ["__builtin_isgreater"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def IsGreaterEqual : Builtin {
let Spellings = ["__builtin_isgreaterequal"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def IsLess : Builtin {
let Spellings = ["__builtin_isless"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def IsLessEqual : Builtin {
let Spellings = ["__builtin_islessequal"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def IsLessGreater : Builtin {
let Spellings = ["__builtin_islessgreater"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def IsUnordered : Builtin {
let Spellings = ["__builtin_isunordered"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
@@ -646,19 +646,21 @@ def IsFPClass : Builtin {
def Signbit : Builtin {
let Spellings = ["__builtin_signbit"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
- CustomTypeChecking];
+ CustomTypeChecking, Constexpr];
let Prototype = "int(...)";
}
def SignbitF : Builtin {
let Spellings = ["__builtin_signbitf"];
- let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const];
+ let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
+ Constexpr];
let Prototype = "int(float)";
}
def SignbitL : Builtin {
let Spellings = ["__builtin_signbitl"];
- let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const];
+ let Attributes = [FunctionWithBuiltinPrefix, NoThrow, Const,
+ Constexpr];
let Prototype = "int(long double)";
}
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index c3370e2e5286e0..26abf582051067 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -433,6 +433,51 @@ static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame, const Function *F,
+ const CallExpr *Call) {
+ const Floating &Arg = S.Stk.peek<Floating>();
+
+ pushInteger(S, Arg.isNegative(), Call->getType());
+ return true;
+}
+
+static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const Function *F,
+ const CallExpr *Call) {
+ const Floating &RHS = S.Stk.peek<Floating>();
+ const Floating &LHS = S.Stk.peek<Floating>(align(2u * primSize(PT_Float)));
+ unsigned ID = F->getBuiltinID();
+
+ pushInteger(
+ S,
+ [&] {
+ switch (ID) {
+ case Builtin::BI__builtin_isgreater:
+ return LHS > RHS;
+ case Builtin::BI__builtin_isgreaterequal:
+ return LHS >= RHS;
+ case Builtin::BI__builtin_isless:
+ return LHS < RHS;
+ case Builtin::BI__builtin_islessequal:
+ return LHS <= RHS;
+ case Builtin::BI__builtin_islessgreater: {
+ ComparisonCategoryResult cmp = LHS.compare(RHS);
+ return cmp == ComparisonCategoryResult::Less ||
+ cmp == ComparisonCategoryResult::Greater;
+ }
+ case Builtin::BI__builtin_isunordered:
+ return LHS.compare(RHS) == ComparisonCategoryResult::Unordered;
+ default:
+ llvm_unreachable("Unexpected builtin ID: Should be a floating point "
+ "comparison function");
+ }
+ }(),
+ Call->getType());
+ return true;
+}
+
/// First parameter to __builtin_isfpclass is the floating value, the
/// second one is an integral value.
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
@@ -1313,6 +1358,21 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
if (!interp__builtin_iszero(S, OpPC, Frame, F, Call))
return false;
break;
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl:
+ if (!interp__builtin_signbit(S, OpPC, Frame, F, Call))
+ return false;
+ break;
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered:
+ if (!interp_floating_comparison(S, OpPC, Frame, F, Call))
+ return false;
+ break;
case Builtin::BI__builtin_isfpclass:
if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
return false;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7bfc63ffd81e28..31b65ff4bcc135 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12833,6 +12833,54 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Success(Val.isZero() ? 1 : 0, E);
}
+ case Builtin::BI__builtin_signbit:
+ case Builtin::BI__builtin_signbitf:
+ case Builtin::BI__builtin_signbitl: {
+ APFloat Val(0.0);
+ return EvaluateFloat(E->getArg(0), Val, Info) &&
+ Success(Val.isNegative() ? 1 : 0, E);
+ }
+
+ case Builtin::BI__builtin_isgreater:
+ case Builtin::BI__builtin_isgreaterequal:
+ case Builtin::BI__builtin_isless:
+ case Builtin::BI__builtin_islessequal:
+ case Builtin::BI__builtin_islessgreater:
+ case Builtin::BI__builtin_isunordered: {
+ APFloat LHS(0.0);
+ APFloat RHS(0.0);
+ if (!EvaluateFloat(E->getArg(0), LHS, Info) ||
+ !EvaluateFloat(E->getArg(1), RHS, Info))
+ return false;
+
+ return Success(
+ [&] {
+ switch (BuiltinOp) {
+ case Builtin::BI__builtin_isgreater:
+ return LHS > RHS;
+ case Builtin::BI__builtin_isgreaterequal:
+ return LHS >= RHS;
+ case Builtin::BI__builtin_isless:
+ return LHS < RHS;
+ case Builtin::BI__builtin_islessequal:
+ return LHS <= RHS;
+ case Builtin::BI__builtin_islessgreater: {
+ APFloat::cmpResult cmp = LHS.compare(RHS);
+ return cmp == APFloat::cmpResult::cmpLessThan ||
+ cmp == APFloat::cmpResult::cmpGreaterThan;
+ }
+ case Builtin::BI__builtin_isunordered:
+ return LHS.compare(RHS) == APFloat::cmpResult::cmpUnordered;
+ default:
+ llvm_unreachable("Unexpected builtin ID: Should be a floating "
+ "point comparison function");
+ }
+ }()
+ ? 1
+ : 0,
+ E);
+ }
+
case Builtin::BI__builtin_issignaling: {
APFloat Val(0.0);
return EvaluateFloat(E->getArg(0), Val, Info) &&
diff --git a/clang/test/Analysis/builtin_signbit.cpp b/clang/test/Analysis/builtin_signbit.cpp
index be10f0950f69b7..ad185d855cfff3 100644
--- a/clang/test/Analysis/builtin_signbit.cpp
+++ b/clang/test/Analysis/builtin_signbit.cpp
@@ -12,103 +12,83 @@ long double ld = -1.0L;
// CHECK-BE32-LABEL: define dso_local void @_Z12test_signbitv(
// CHECK-BE32-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-BE32-NEXT: entry:
-// CHECK-BE32-NEXT: [[TMP0:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64
-// CHECK-BE32-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i64
-// CHECK-BE32-NEXT: [[TMP2:%.*]] = icmp slt i64 [[TMP1]], 0
-// CHECK-BE32-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8
+// CHECK-BE32-NEXT: store i8 0, ptr @b, align 1
+// CHECK-BE32-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-BE32-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128
+// CHECK-BE32-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64
+// CHECK-BE32-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64
+// CHECK-BE32-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0
+// CHECK-BE32-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP4]] to i8
// CHECK-BE32-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1
-// CHECK-BE32-NEXT: [[TMP3:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-BE32-NEXT: [[TMP4:%.*]] = bitcast ppc_fp128 [[TMP3]] to i128
-// CHECK-BE32-NEXT: [[TMP5:%.*]] = lshr i128 [[TMP4]], 64
-// CHECK-BE32-NEXT: [[TMP6:%.*]] = trunc i128 [[TMP5]] to i64
-// CHECK-BE32-NEXT: [[TMP7:%.*]] = icmp slt i64 [[TMP6]], 0
+// CHECK-BE32-NEXT: store i8 0, ptr @b, align 1
+// CHECK-BE32-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8
+// CHECK-BE32-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float
+// CHECK-BE32-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32
+// CHECK-BE32-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0
// CHECK-BE32-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP7]] to i8
// CHECK-BE32-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1
// CHECK-BE32-NEXT: store i8 0, ptr @b, align 1
-// CHECK-BE32-NEXT: [[TMP8:%.*]] = load double, ptr @d, align 8
-// CHECK-BE32-NEXT: [[CONV:%.*]] = fptrunc double [[TMP8]] to float
-// CHECK-BE32-NEXT: [[TMP9:%.*]] = bitcast float [[CONV]] to i32
-// CHECK-BE32-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0
-// CHECK-BE32-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8
+// CHECK-BE32-NEXT: [[TMP8:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-BE32-NEXT: [[TMP9:%.*]] = bitcast ppc_fp128 [[TMP8]] to i128
+// CHECK-BE32-NEXT: [[TMP10:%.*]] = lshr i128 [[TMP9]], 64
+// CHECK-BE32-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64
+// CHECK-BE32-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0
+// CHECK-BE32-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP12]] to i8
// CHECK-BE32-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1
-// CHECK-BE32-NEXT: [[TMP11:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64
-// CHECK-BE32-NEXT: [[TMP12:%.*]] = trunc i128 [[TMP11]] to i64
-// CHECK-BE32-NEXT: [[TMP13:%.*]] = icmp slt i64 [[TMP12]], 0
-// CHECK-BE32-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP13]] to i8
-// CHECK-BE32-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1
-// CHECK-BE32-NEXT: [[TMP14:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-BE32-NEXT: [[TMP15:%.*]] = bitcast ppc_fp128 [[TMP14]] to i128
-// CHECK-BE32-NEXT: [[TMP16:%.*]] = lshr i128 [[TMP15]], 64
-// CHECK-BE32-NEXT: [[TMP17:%.*]] = trunc i128 [[TMP16]] to i64
-// CHECK-BE32-NEXT: [[TMP18:%.*]] = icmp slt i64 [[TMP17]], 0
-// CHECK-BE32-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP18]] to i8
-// CHECK-BE32-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1
// CHECK-BE32-NEXT: ret void
//
// CHECK-BE64-LABEL: define dso_local void @_Z12test_signbitv(
// CHECK-BE64-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-BE64-NEXT: entry:
-// CHECK-BE64-NEXT: [[TMP0:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64
-// CHECK-BE64-NEXT: [[TMP1:%.*]] = trunc i128 [[TMP0]] to i64
-// CHECK-BE64-NEXT: [[TMP2:%.*]] = icmp slt i64 [[TMP1]], 0
-// CHECK-BE64-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP2]] to i8
+// CHECK-BE64-NEXT: store i8 0, ptr @b, align 1
+// CHECK-BE64-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-BE64-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128
+// CHECK-BE64-NEXT: [[TMP2:%.*]] = lshr i128 [[TMP1]], 64
+// CHECK-BE64-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64
+// CHECK-BE64-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0
+// CHECK-BE64-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP4]] to i8
// CHECK-BE64-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1
-// CHECK-BE64-NEXT: [[TMP3:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-BE64-NEXT: [[TMP4:%.*]] = bitcast ppc_fp128 [[TMP3]] to i128
-// CHECK-BE64-NEXT: [[TMP5:%.*]] = lshr i128 [[TMP4]], 64
-// CHECK-BE64-NEXT: [[TMP6:%.*]] = trunc i128 [[TMP5]] to i64
-// CHECK-BE64-NEXT: [[TMP7:%.*]] = icmp slt i64 [[TMP6]], 0
+// CHECK-BE64-NEXT: store i8 0, ptr @b, align 1
+// CHECK-BE64-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8
+// CHECK-BE64-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float
+// CHECK-BE64-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32
+// CHECK-BE64-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0
// CHECK-BE64-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP7]] to i8
// CHECK-BE64-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1
// CHECK-BE64-NEXT: store i8 0, ptr @b, align 1
-// CHECK-BE64-NEXT: [[TMP8:%.*]] = load double, ptr @d, align 8
-// CHECK-BE64-NEXT: [[CONV:%.*]] = fptrunc double [[TMP8]] to float
-// CHECK-BE64-NEXT: [[TMP9:%.*]] = bitcast float [[CONV]] to i32
-// CHECK-BE64-NEXT: [[TMP10:%.*]] = icmp slt i32 [[TMP9]], 0
-// CHECK-BE64-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8
+// CHECK-BE64-NEXT: [[TMP8:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-BE64-NEXT: [[TMP9:%.*]] = bitcast ppc_fp128 [[TMP8]] to i128
+// CHECK-BE64-NEXT: [[TMP10:%.*]] = lshr i128 [[TMP9]], 64
+// CHECK-BE64-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64
+// CHECK-BE64-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0
+// CHECK-BE64-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP12]] to i8
// CHECK-BE64-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1
-// CHECK-BE64-NEXT: [[TMP11:%.*]] = lshr i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128), 64
-// CHECK-BE64-NEXT: [[TMP12:%.*]] = trunc i128 [[TMP11]] to i64
-// CHECK-BE64-NEXT: [[TMP13:%.*]] = icmp slt i64 [[TMP12]], 0
-// CHECK-BE64-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP13]] to i8
-// CHECK-BE64-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1
-// CHECK-BE64-NEXT: [[TMP14:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-BE64-NEXT: [[TMP15:%.*]] = bitcast ppc_fp128 [[TMP14]] to i128
-// CHECK-BE64-NEXT: [[TMP16:%.*]] = lshr i128 [[TMP15]], 64
-// CHECK-BE64-NEXT: [[TMP17:%.*]] = trunc i128 [[TMP16]] to i64
-// CHECK-BE64-NEXT: [[TMP18:%.*]] = icmp slt i64 [[TMP17]], 0
-// CHECK-BE64-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP18]] to i8
-// CHECK-BE64-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1
// CHECK-BE64-NEXT: ret void
//
// CHECK-LE-LABEL: define dso_local void @_Z12test_signbitv(
// CHECK-LE-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-LE-NEXT: entry:
-// CHECK-LE-NEXT: [[TMP0:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0
-// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP0]] to i8
+// CHECK-LE-NEXT: store i8 0, ptr @b, align 1
+// CHECK-LE-NEXT: [[TMP0:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-LE-NEXT: [[TMP1:%.*]] = bitcast ppc_fp128 [[TMP0]] to i128
+// CHECK-LE-NEXT: [[TMP2:%.*]] = trunc i128 [[TMP1]] to i64
+// CHECK-LE-NEXT: [[TMP3:%.*]] = icmp slt i64 [[TMP2]], 0
+// CHECK-LE-NEXT: [[FROMBOOL:%.*]] = zext i1 [[TMP3]] to i8
// CHECK-LE-NEXT: store i8 [[FROMBOOL]], ptr @b, align 1
-// CHECK-LE-NEXT: [[TMP1:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-LE-NEXT: [[TMP2:%.*]] = bitcast ppc_fp128 [[TMP1]] to i128
-// CHECK-LE-NEXT: [[TMP3:%.*]] = trunc i128 [[TMP2]] to i64
-// CHECK-LE-NEXT: [[TMP4:%.*]] = icmp slt i64 [[TMP3]], 0
-// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP4]] to i8
+// CHECK-LE-NEXT: store i8 0, ptr @b, align 1
+// CHECK-LE-NEXT: [[TMP4:%.*]] = load double, ptr @d, align 8
+// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP4]] to float
+// CHECK-LE-NEXT: [[TMP5:%.*]] = bitcast float [[CONV]] to i32
+// CHECK-LE-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP5]], 0
+// CHECK-LE-NEXT: [[FROMBOOL1:%.*]] = zext i1 [[TMP6]] to i8
// CHECK-LE-NEXT: store i8 [[FROMBOOL1]], ptr @b, align 1
// CHECK-LE-NEXT: store i8 0, ptr @b, align 1
-// CHECK-LE-NEXT: [[TMP5:%.*]] = load double, ptr @d, align 8
-// CHECK-LE-NEXT: [[CONV:%.*]] = fptrunc double [[TMP5]] to float
-// CHECK-LE-NEXT: [[TMP6:%.*]] = bitcast float [[CONV]] to i32
-// CHECK-LE-NEXT: [[TMP7:%.*]] = icmp slt i32 [[TMP6]], 0
-// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP7]] to i8
+// CHECK-LE-NEXT: [[TMP7:%.*]] = load ppc_fp128, ptr @ld, align 16
+// CHECK-LE-NEXT: [[TMP8:%.*]] = bitcast ppc_fp128 [[TMP7]] to i128
+// CHECK-LE-NEXT: [[TMP9:%.*]] = trunc i128 [[TMP8]] to i64
+// CHECK-LE-NEXT: [[TMP10:%.*]] = icmp slt i64 [[TMP9]], 0
+// CHECK-LE-NEXT: [[FROMBOOL2:%.*]] = zext i1 [[TMP10]] to i8
// CHECK-LE-NEXT: store i8 [[FROMBOOL2]], ptr @b, align 1
-// CHECK-LE-NEXT: [[TMP8:%.*]] = icmp slt i64 trunc (i128 bitcast (ppc_fp128 0xM3FF00000000000000000000000000000 to i128) to i64), 0
-// CHECK-LE-NEXT: [[FROMBOOL3:%.*]] = zext i1 [[TMP8]] to i8
-// CHECK-LE-NEXT: store i8 [[FROMBOOL3]], ptr @b, align 1
-// CHECK-LE-NEXT: [[TMP9:%.*]] = load ppc_fp128, ptr @ld, align 16
-// CHECK-LE-NEXT: [[TMP10:%.*]] = bitcast ppc_fp128 [[TMP9]] to i128
-// CHECK-LE-NEXT: [[TMP11:%.*]] = trunc i128 [[TMP10]] to i64
-// CHECK-LE-NEXT: [[TMP12:%.*]] = icmp slt i64 [[TMP11]], 0
-// CHECK-LE-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP12]] to i8
-// CHECK-LE-NEXT: store i8 [[FROMBOOL4]], ptr @b, align 1
// CHECK-LE-NEXT: ret void
//
void test_signbit()
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index 37b63cf4f6b328..c359eba4e3d16c 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fexperimental-new-constant-interpreter -verify %s
// Math stuff
@@ -204,6 +205,53 @@ char isfpclass_snan_1 [!__builtin_isfpclass(__builtin_nans(""), 0x0002) ? 1 :
char isfpclass_snan_2 [__builtin_isfpclass(__builtin_nansl(""), 0x0207) ? 1 : -1]; // ~fcFinite
char isfpclass_snan_3 [!__builtin_isfpclass(__builtin_nans(""), 0x01F8) ? 1 : -1]; // fcFinite
+__extension__ _Static_assert(
+ !__builtin_signbit(1.0) && __builtin_signbit(-1.0) && !__builtin_signbit(0.0) && __builtin_signbit(-0.0) &&
+ !__builtin_signbitf(1.0f) && __builtin_signbitf(-1.0f) && !__builtin_signbitf(0.0f) && __builtin_signbitf(-0.0f) &&
+ !__builtin_signbitl(1.0L) && __builtin_signbitf(-1.0L) && !__builtin_signbitf(0.0L) && __builtin_signbitf(-0.0L) &&
+ !__builtin_signbit(1.0f) && __builtin_signbit(-1.0f) && !__builtin_signbit(0.0f) && __builtin_signbit(-0.0f) &&
+ !__builtin_signbit(1.0L) && __builtin_signbit(-1.0L) && !__builtin_signbit(0.0L) && __builtin_signbit(-0.0L) &&
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+ !__builtin_signbit(1.0q) && __builtin_signbit(-1.0q) && !__builtin_signbit(0.0q) && __builtin_signbit(-0.0q) &&
+#endif
+ 1, ""
+);
+
+#define LESS(X, Y) \
+ !__builtin_isgreater(X, Y) && __builtin_isgreater(Y, X) && \
+ !__builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \
+ __builtin_isless(X, Y) && !__builtin_isless(Y, X) && \
+ __builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \
+ __builtin_islessgreater(X, Y) && __builtin_islessgreater(Y, X) && \
+ !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X)
+#define EQUAL(X, Y) \
+ !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \
+ __builtin_isgreaterequal(X, Y) && __builtin_isgreaterequal(Y, X) && \
+ !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \
+ __builtin_islessequal(X, Y) && __builtin_islessequal(Y, X) && \
+ !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \
+ !__builtin_isunordered(X, Y) && !__builtin_isunordered(Y, X)
+#define UNORDERED(X, Y) \
+ !__builtin_isgreater(X, Y) && !__builtin_isgreater(Y, X) && \
+ !__builtin_isgreaterequal(X, Y) && !__builtin_isgreaterequal(Y, X) && \
+ !__builtin_isless(X, Y) && !__builtin_isless(Y, X) && \
+ !__builtin_islessequal(X, Y) && !__builtin_islessequal(Y, X) && \
+ !__builtin_islessgreater(X, Y) && !__builtin_islessgreater(Y, X) && \
+ __builtin_isunordered(X, Y) && __builtin_isunordered(Y, X)
+
+__extension__ _Static_assert(
+ LESS(0.0, 1.0) && EQUAL(1.0, 1.0) && EQUAL(0.0, -0.0) &&
+ UNORDERED(__builtin_nan(""), 1.0) && UNORDERED(__builtin_nan(""), __builtin_inf()) && LESS(0.0, __builtin_inf()) &&
+ LESS(0.0f, 1.0f) && EQUAL(1.0f, 1.0f) && EQUAL(0.0f, -0.0f) &&
+ UNORDERED(__builtin_nanf(""), 1.0f) && UNORDERED(__builtin_nanf(""), __builtin_inff()) && LESS(0.0f, __builtin_inff()) &&
+ LESS(0.0L, 1.0L) && EQUAL(1.0L, 1.0L) && EQUAL(0.0L, -0.0L) &&
+ UNORDERED(__builtin_nanl(""), 1.0L) && UNORDERED(__builtin_nanl(""), __builtin_infl()) && LESS(0.0L, __builtin_infl()) &&
+#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__)
+ LESS(0.0q, 1.0q) && EQUAL(1.0q, 1.0q) && EQUAL(0.0q, -0.0q) &&
+#endif
+ 1, ""
+);
+
//double g19 = __builtin_powi(2.0, 4);
//float g20 = __builtin_powif(2.0f, 4);
//long double g21 = __builtin_powil(2.0L, 4);
More information about the cfe-commits
mailing list