[clang] [clang] Additional FP classification functions (PR #69041)
Serge Pavlov via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 15 07:54:24 PDT 2023
https://github.com/spavloff updated https://github.com/llvm/llvm-project/pull/69041
>From 1374e323198d7188e688845eb951df4148a1dfd8 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Wed, 11 Oct 2023 14:27:26 +0700
Subject: [PATCH 1/2] [clang] Additional FP classification functions
C language standard defined library functions `iszero`, `issignaling`
and `issubnormal`, which did not have counterparts among clang
builtin functions. This change adds new functions:
__builtin_iszero
__builtin_issubnormal
__builtin_issignaling
They provide builtin implementation for the missing standard functions.
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/include/clang/Basic/Builtins.def | 3 +++
clang/lib/CodeGen/CGBuiltin.cpp | 24 ++++++++++++++++++++++++
clang/test/CodeGen/builtins.c | 15 +++++++++++++++
4 files changed, 44 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2d918967e7f0b02..2453804cd7735be 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -621,6 +621,8 @@ Floating Point Support in Clang
- Add ``__builtin_exp10``, ``__builtin_exp10f``,
``__builtin_exp10f16``, ``__builtin_exp10l`` and
``__builtin_exp10f128`` builtins.
+- Add ``__builtin_iszero``, ``__builtin_issignaling`` and
+ ``__builtin_issubnormal``.
AST Matchers
------------
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 6ea8484606cfd5d..ebcb5b45e5bdc23 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -494,6 +494,9 @@ BUILTIN(__builtin_isinf, "i.", "FnctE")
BUILTIN(__builtin_isinf_sign, "i.", "FnctE")
BUILTIN(__builtin_isnan, "i.", "FnctE")
BUILTIN(__builtin_isnormal, "i.", "FnctE")
+BUILTIN(__builtin_issubnormal,"i.", "FnctE")
+BUILTIN(__builtin_iszero, "i.", "FnctE")
+BUILTIN(__builtin_issignaling,"i.", "FnctE")
BUILTIN(__builtin_isfpclass, "i.", "nctE")
// FP signbit builtins
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 8cb7943df9a7822..5d3946a84b6c34a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3287,6 +3287,14 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ConvertType(E->getType())));
}
+ case Builtin::BI__builtin_issignaling: {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ Value *V = EmitScalarExpr(E->getArg(0));
+ return RValue::get(
+ Builder.CreateZExt(Builder.createIsFPClass(V, FPClassTest::fcSNan),
+ ConvertType(E->getType())));
+ }
+
case Builtin::BI__builtin_isinf: {
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
Value *V = EmitScalarExpr(E->getArg(0));
@@ -3321,6 +3329,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
ConvertType(E->getType())));
}
+ case Builtin::BI__builtin_issubnormal: {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ Value *V = EmitScalarExpr(E->getArg(0));
+ return RValue::get(
+ Builder.CreateZExt(Builder.createIsFPClass(V, FPClassTest::fcSubnormal),
+ ConvertType(E->getType())));
+ }
+
+ case Builtin::BI__builtin_iszero: {
+ CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E);
+ Value *V = EmitScalarExpr(E->getArg(0));
+ return RValue::get(
+ Builder.CreateZExt(Builder.createIsFPClass(V, FPClassTest::fcZero),
+ ConvertType(E->getType())));
+ }
+
case Builtin::BI__builtin_isfpclass: {
Expr::EvalResult Result;
if (!E->getArg(1)->EvaluateAsInt(Result, CGM.getContext()))
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 1b1b2cd6413a344..ce1182b724dcc21 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -64,6 +64,9 @@ int main(void) {
P(isinf_sign, (1.));
P(isnan, (1.));
P(isfinite, (1.));
+ P(iszero, (1.));
+ P(issubnormal, (1.));
+ P(issignaling, (1.));
P(isfpclass, (1., 1));
// Bitwise & Numeric Functions
@@ -270,6 +273,18 @@ void test_float_builtins(__fp16 *H, float F, double D, long double LD) {
// CHECK: [[TMP:%.*]] = call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 264)
// CHECK: zext i1 [[TMP]] to i32
+ res = __builtin_issubnormal(F);
+ // CHECK: [[TMP:%.*]] = call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 144)
+ // CHECK: zext i1 [[TMP]] to i32
+
+ res = __builtin_iszero(F);
+ // CHECK: [[TMP:%.*]] = call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 96)
+ // CHECK: zext i1 [[TMP]] to i32
+
+ res = __builtin_issignaling(F);
+ // CHECK: [[TMP:%.*]] = call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 1)
+ // CHECK: zext i1 [[TMP]] to i32
+
res = __builtin_flt_rounds();
// CHECK: call i32 @llvm.get.rounding(
}
>From ec574ef66538047d58bc0b1bf93c7231adc19856 Mon Sep 17 00:00:00 2001
From: Serge Pavlov <sepavloff at gmail.com>
Date: Sun, 15 Oct 2023 21:39:56 +0700
Subject: [PATCH 2/2] Add handling in constant evaluator
---
clang/lib/AST/ExprConstant.cpp | 18 +++++++++++++
clang/test/Sema/constant-builtins-2.c | 39 +++++++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index e5539dedec02a4b..b4da8f336b0bebf 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12303,6 +12303,24 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
Success(Val.isNormal() ? 1 : 0, E);
}
+ case Builtin::BI__builtin_issubnormal: {
+ APFloat Val(0.0);
+ return EvaluateFloat(E->getArg(0), Val, Info) &&
+ Success(Val.isDenormal() ? 1 : 0, E);
+ }
+
+ case Builtin::BI__builtin_iszero: {
+ APFloat Val(0.0);
+ return EvaluateFloat(E->getArg(0), Val, Info) &&
+ Success(Val.isZero() ? 1 : 0, E);
+ }
+
+ case Builtin::BI__builtin_issignaling: {
+ APFloat Val(0.0);
+ return EvaluateFloat(E->getArg(0), Val, Info) &&
+ Success(Val.isSignaling() ? 1 : 0, E);
+ }
+
case Builtin::BI__builtin_isfpclass: {
APSInt MaskVal;
if (!EvaluateInteger(E->getArg(1), MaskVal, Info))
diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c
index 93948201c451b49..2bdd7b06daabfea 100644
--- a/clang/test/Sema/constant-builtins-2.c
+++ b/clang/test/Sema/constant-builtins-2.c
@@ -124,6 +124,45 @@ char isnormal_inf_neg[!__builtin_isnormal(-__builtin_inf()) ? 1 : -1];
char isnormal_nan [!__builtin_isnormal(__builtin_nan("")) ? 1 : -1];
char isnormal_snan [!__builtin_isnormal(__builtin_nans("")) ? 1 : -1];
+char iszero_inf_pos[!__builtin_iszero(__builtin_inf()) ? 1 : -1];
+char iszero_pos [!__builtin_iszero(1.0) ? 1 : -1];
+char iszero_normf [!__builtin_iszero(1e-37f) ? 1 : -1];
+char iszero_denormf[!__builtin_iszero(1e-38f) ? 1 : -1];
+char iszero_norm [!__builtin_iszero(1e-307) ? 1 : -1];
+char iszero_denorm [!__builtin_iszero(1e-308) ? 1 : -1];
+char iszero_zero [__builtin_iszero(0.0) ? 1 : -1];
+char iszero_negzero[__builtin_iszero(-0.0) ? 1 : -1];
+char iszero_neg [!__builtin_iszero(-1.0) ? 1 : -1];
+char iszero_inf_neg[!__builtin_iszero(-__builtin_inf()) ? 1 : -1];
+char iszero_nan [!__builtin_iszero(__builtin_nan("")) ? 1 : -1];
+char iszero_snan [!__builtin_iszero(__builtin_nans("")) ? 1 : -1];
+
+char issubnormal_inf_pos[!__builtin_issubnormal(__builtin_inf()) ? 1 : -1];
+char issubnormal_pos [!__builtin_issubnormal(1.0) ? 1 : -1];
+char issubnormal_normf [!__builtin_issubnormal(1e-37f) ? 1 : -1];
+char issubnormal_denormf[__builtin_issubnormal(1e-38f) ? 1 : -1];
+char issubnormal_norm [!__builtin_issubnormal(1e-307) ? 1 : -1];
+char issubnormal_denorm [__builtin_issubnormal(1e-308) ? 1 : -1];
+char issubnormal_zero [!__builtin_issubnormal(0.0) ? 1 : -1];
+char issubnormal_negzero[!__builtin_issubnormal(-0.0) ? 1 : -1];
+char issubnormal_neg [!__builtin_issubnormal(-1.0) ? 1 : -1];
+char issubnormal_inf_neg[!__builtin_issubnormal(-__builtin_inf()) ? 1 : -1];
+char issubnormal_nan [!__builtin_issubnormal(__builtin_nan("")) ? 1 : -1];
+char issubnormal_snan [!__builtin_issubnormal(__builtin_nans("")) ? 1 : -1];
+
+char issignaling_inf_pos[!__builtin_issignaling(__builtin_inf()) ? 1 : -1];
+char issignaling_pos [!__builtin_issignaling(1.0) ? 1 : -1];
+char issignaling_normf [!__builtin_issignaling(1e-37f) ? 1 : -1];
+char issignaling_denormf[!__builtin_issignaling(1e-38f) ? 1 : -1];
+char issignaling_norm [!__builtin_issignaling(1e-307) ? 1 : -1];
+char issignaling_denorm [!__builtin_issignaling(1e-308) ? 1 : -1];
+char issignaling_zero [!__builtin_issignaling(0.0) ? 1 : -1];
+char issignaling_negzero[!__builtin_issignaling(-0.0) ? 1 : -1];
+char issignaling_neg [!__builtin_issignaling(-1.0) ? 1 : -1];
+char issignaling_inf_neg[!__builtin_issignaling(-__builtin_inf()) ? 1 : -1];
+char issignaling_nan [!__builtin_issignaling(__builtin_nan("")) ? 1 : -1];
+char issignaling_snan [__builtin_issignaling(__builtin_nans("")) ? 1 : -1];
+
char isfpclass_inf_pos_0[__builtin_isfpclass(__builtin_inf(), 0x0200) ? 1 : -1]; // fcPosInf
char isfpclass_inf_pos_1[!__builtin_isfpclass(__builtin_inff(), 0x0004) ? 1 : -1]; // fcNegInf
char isfpclass_inf_pos_2[__builtin_isfpclass(__builtin_infl(), 0x0207) ? 1 : -1]; // fcSNan|fcQNan|fcNegInf|fcPosInf
More information about the cfe-commits
mailing list