sepavloff created this revision. sepavloff added reviewers: rjmccall, aaron.ballman, arsenm, kpn, qiucf, efriedma. Herald added a subscriber: hiraditya. Herald added a project: All. sepavloff requested review of this revision. Herald added subscribers: llvm-commits, wdng. Herald added projects: clang, LLVM.
A new builting function __builtin_isfpclass is added. It is called as: __builtin_isfpclass(<test>, <floating point value>) and returns an integer value, which is non-zero if the floating point argument belongs to one of the classes specified by the first argument, and zero otherwise. The set of classes is an integer value, where each value class is represented by a bit. There are ten data classes, as defined by the IEEE-754 standard, they are represented by bits: 0x0001 - Signaling NaN 0x0002 - Quiet NaN 0x0004 - Negative infinity 0x0008 - Negative normal 0x0010 - Negative subnormal 0x0020 - Negative zero 0x0040 - Positive zero 0x0080 - Positive subnormal 0x0100 - Positive normal 0x0200 - Positive infinity The data class encoding is identical to that used in llvm.is.fpclass function. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D152351 Files: clang/include/clang/Basic/Builtins.def clang/lib/CodeGen/CGBuiltin.cpp clang/test/CodeGen/builtins.c clang/test/CodeGen/isfpclass.c llvm/include/llvm/IR/IRBuilder.h llvm/lib/IR/IRBuilder.cpp
Index: llvm/lib/IR/IRBuilder.cpp =================================================================== --- llvm/lib/IR/IRBuilder.cpp +++ llvm/lib/IR/IRBuilder.cpp @@ -1375,6 +1375,14 @@ return Fn; } +Value *IRBuilderBase::createIsFPClass(Value *FPNum, unsigned Test) { + auto TestV = llvm::ConstantInt::get(Type::getInt32Ty(Context), Test); + Module *M = BB->getParent()->getParent(); + Function *FnIsFPClass = + Intrinsic::getDeclaration(M, Intrinsic::is_fpclass, {FPNum->getType()}); + return CreateCall(FnIsFPClass, {FPNum, TestV}); +} + CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper(const DataLayout &DL, Value *PtrValue, Value *AlignValue, Index: llvm/include/llvm/IR/IRBuilder.h =================================================================== --- llvm/include/llvm/IR/IRBuilder.h +++ llvm/include/llvm/IR/IRBuilder.h @@ -2518,6 +2518,8 @@ unsigned Index, unsigned FieldIndex, MDNode *DbgInfo); + Value *createIsFPClass(Value *FPNum, unsigned Test); + private: /// Helper function that creates an assume intrinsic call that /// represents an alignment assumption on the provided pointer \p PtrValue Index: clang/test/CodeGen/isfpclass.c =================================================================== --- /dev/null +++ clang/test/CodeGen/isfpclass.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | FileCheck %s + +_Bool check_isfpclass_finite(float x) { + return __builtin_isfpclass(504 /*Finite*/, x); +} +// CHECK-LABEL: define {{.*}} i1 @check_isfpclass_finite( +// CHECK: call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 504) + +_Bool check_isfpclass_finite_strict(float x) { +#pragma STDC FENV_ACCESS ON + return __builtin_isfpclass(504 /*Finite*/, x); +} +// CHECK-LABEL: define {{.*}} i1 @check_isfpclass_finite_strict( +// CHECK: call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 504) + +_Bool check_isfpclass_nan_f32(float x) { +#pragma STDC FENV_ACCESS ON + return __builtin_isfpclass(3 /*NaN*/, x); +} +// CHECK-LABEL: define {{.*}} i1 @check_isfpclass_nan_f32( +// CHECK: call i1 @llvm.is.fpclass.f32(float {{.*}}, i32 3) + +_Bool check_isfpclass_nan_f64(double x) { +#pragma STDC FENV_ACCESS ON + return __builtin_isfpclass(3 /*NaN*/, x); +} +// CHECK-LABEL: define {{.*}} i1 @check_isfpclass_nan_f64( +// CHECK: call i1 @llvm.is.fpclass.f64(double {{.*}}, i32 3) Index: clang/test/CodeGen/builtins.c =================================================================== --- clang/test/CodeGen/builtins.c +++ clang/test/CodeGen/builtins.c @@ -63,6 +63,7 @@ P(isinf, (1.)); P(isinf_sign, (1.)); P(isnan, (1.)); + P(isfpclass, (1, 1.)); // Bitwise & Numeric Functions Index: clang/lib/CodeGen/CGBuiltin.cpp =================================================================== --- clang/lib/CodeGen/CGBuiltin.cpp +++ clang/lib/CodeGen/CGBuiltin.cpp @@ -3143,6 +3143,17 @@ return RValue::get(V); } + case Builtin::BI__builtin_isfpclass: { + Expr::EvalResult Result; + if (!E->getArg(0)->EvaluateAsInt(Result, CGM.getContext())) + break; + uint64_t Test = Result.Val.getInt().getLimitedValue(); + CodeGenFunction::CGFPOptionsRAII FPOptsRAII(*this, E); + Value *V = EmitScalarExpr(E->getArg(1)); + return RValue::get(Builder.CreateZExt(Builder.createIsFPClass(V, Test), + ConvertType(E->getType()))); + } + case Builtin::BI__builtin_nondeterministic_value: { llvm::Type *Ty = ConvertType(E->getArg(0)->getType()); Index: clang/include/clang/Basic/Builtins.def =================================================================== --- clang/include/clang/Basic/Builtins.def +++ clang/include/clang/Basic/Builtins.def @@ -488,6 +488,7 @@ BUILTIN(__builtin_isinf_sign, "i.", "FnctE") BUILTIN(__builtin_isnan, "i.", "FnctE") BUILTIN(__builtin_isnormal, "i.", "FnctE") +BUILTIN(__builtin_isfpclass, "iCi.", "nctE") // FP signbit builtins BUILTIN(__builtin_signbit, "i.", "Fnct")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits