[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-18 Thread Serge Pavlov via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7dd387d2971d: [clang] Add __builtin_isfpclass (authored by 
sepavloff).

Changed prior to commit:
  https://reviews.llvm.org/D152351?vs=530772=532477#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Frontend/InitPreprocessor.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGen/isfpclass.c
  clang/test/Preprocessor/init-aarch64.c
  clang/test/Preprocessor/init.c
  clang/test/Sema/builtins.c
  clang/test/Sema/constant-builtins-2.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
@@ -1383,6 +1383,14 @@
   return Fn;
 }
 
+Value *IRBuilderBase::createIsFPClass(Value *FPNum, unsigned Test) {
+  ConstantInt *TestV = getInt32(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 ,
  Value *PtrValue,
  Value *AlignValue,
Index: llvm/include/llvm/IR/IRBuilder.h
===
--- llvm/include/llvm/IR/IRBuilder.h
+++ llvm/include/llvm/IR/IRBuilder.h
@@ -2528,6 +2528,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/Sema/constant-builtins-2.c
===
--- clang/test/Sema/constant-builtins-2.c
+++ clang/test/Sema/constant-builtins-2.c
@@ -124,6 +124,47 @@
 char isnormal_nan[!__builtin_isnormal(__builtin_nan("")) ? 1 : -1];
 char isnormal_snan   [!__builtin_isnormal(__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
+char isfpclass_inf_pos_3[!__builtin_isfpclass(__builtin_inf(), 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_0[__builtin_isfpclass(1.0, 0x0100) ? 1 : -1]; // fcPosNormal
+char isfpclass_pos_1[!__builtin_isfpclass(1.0f, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_pos_2[__builtin_isfpclass(1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_3[!__builtin_isfpclass(1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan
+char isfpclass_pdenorm_0[__builtin_isfpclass(1.0e-40f, 0x0080) ? 1 : -1]; // fcPosSubnormal
+char isfpclass_pdenorm_1[__builtin_isfpclass(1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pdenorm_2[!__builtin_isfpclass(1.0e-40f, 0x003C) ? 1 : -1]; // fcNegative
+char isfpclass_pdenorm_3[!__builtin_isfpclass(1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_pzero_0  [__builtin_isfpclass(0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_pzero_1  [__builtin_isfpclass(0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pzero_2  [!__builtin_isfpclass(0.0L, 0x0020) ? 1 : -1]; // fcNegZero
+char isfpclass_pzero_3  [!__builtin_isfpclass(0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_nzero_0  [__builtin_isfpclass(-0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_nzero_1  [__builtin_isfpclass(-0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_nzero_2  [!__builtin_isfpclass(-0.0L, 0x0040) ? 1 : -1]; // fcPosZero
+char isfpclass_nzero_3  [!__builtin_isfpclass(-0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_ndenorm_0[__builtin_isfpclass(-1.0e-40f, 0x0010) ? 1 : -1]; // fcNegSubnormal
+char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive
+char isfpclass_ndenorm_3[!__builtin_isfpclass(-1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_neg_0[__builtin_isfpclass(-1.0, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_neg_1[!__builtin_isfpclass(-1.0f, 0x00100) ? 1 : -1]; // fcPosNormal
+char isfpclass_neg_2[__builtin_isfpclass(-1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char 

[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-18 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff added a comment.

Thanks!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-15 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

Clang bits LGTM, thank you!


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-12 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff marked 2 inline comments as done.
sepavloff added inline comments.



Comment at: clang/test/CodeGen/isfpclass.c:2
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | 
FileCheck %s
+
+_Bool check_isfpclass_finite(float x) {

arsenm wrote:
> sepavloff wrote:
> > arsenm wrote:
> > >  Can you also add a half test, also vectors
> > Half is added. But vectors cannot, because in this case result is also a 
> > vector.
> Could copy what __builtin_elementwise does. Should that be in this builtin, 
> or should there be a separate __builtin_elementwise_isfpclass?
Other math functions have separate elementwise functions. It looks natural to 
have separate elementwise function for this function as well.



Comment at: clang/test/Sema/builtins.c:384
+  int x1 = __builtin_isfpclass(x, 1024); // expected-error {{argument value 
1024 is outside the valid range [0, 1023]}}
+  int x2 = __builtin_isfpclass(3, 3); // expected-error{{floating point 
classification requires argument of floating point type (passed in 'int')}}
+  int x3 = __builtin_isfpclass(x, 3, x); // expected-error{{too many arguments 
to function call, expected 2, have 3}}

arsenm wrote:
> For any other float argument, 3 would accept implicit conversion. Do we just 
> not do that for these type inferring intrinsics?
As any other classification function, this one is evaluated with semantic type. 
The test `CodeGen/isfpclass.c` demonstrates that type promotion is absent for 
_Float16.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-12 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff updated this revision to Diff 530772.
sepavloff added a comment.
Herald added subscribers: aheejin, dschuff.

Updated patch

- Added named constants for data classes,
- Fixed documentation,
- Changed test for generated IR.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Frontend/InitPreprocessor.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGen/isfpclass.c
  clang/test/Preprocessor/init-aarch64.c
  clang/test/Preprocessor/init.c
  clang/test/Sema/builtins.c
  clang/test/Sema/constant-builtins-2.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) {
+  ConstantInt *TestV = getInt32(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 ,
  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/Sema/constant-builtins-2.c
===
--- clang/test/Sema/constant-builtins-2.c
+++ clang/test/Sema/constant-builtins-2.c
@@ -124,6 +124,47 @@
 char isnormal_nan[!__builtin_isnormal(__builtin_nan("")) ? 1 : -1];
 char isnormal_snan   [!__builtin_isnormal(__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
+char isfpclass_inf_pos_3[!__builtin_isfpclass(__builtin_inf(), 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_0[__builtin_isfpclass(1.0, 0x0100) ? 1 : -1]; // fcPosNormal
+char isfpclass_pos_1[!__builtin_isfpclass(1.0f, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_pos_2[__builtin_isfpclass(1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_3[!__builtin_isfpclass(1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan
+char isfpclass_pdenorm_0[__builtin_isfpclass(1.0e-40f, 0x0080) ? 1 : -1]; // fcPosSubnormal
+char isfpclass_pdenorm_1[__builtin_isfpclass(1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pdenorm_2[!__builtin_isfpclass(1.0e-40f, 0x003C) ? 1 : -1]; // fcNegative
+char isfpclass_pdenorm_3[!__builtin_isfpclass(1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_pzero_0  [__builtin_isfpclass(0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_pzero_1  [__builtin_isfpclass(0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pzero_2  [!__builtin_isfpclass(0.0L, 0x0020) ? 1 : -1]; // fcNegZero
+char isfpclass_pzero_3  [!__builtin_isfpclass(0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_nzero_0  [__builtin_isfpclass(-0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_nzero_1  [__builtin_isfpclass(-0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_nzero_2  [!__builtin_isfpclass(-0.0L, 0x0040) ? 1 : -1]; // fcPosZero
+char isfpclass_nzero_3  [!__builtin_isfpclass(-0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_ndenorm_0[__builtin_isfpclass(-1.0e-40f, 0x0010) ? 1 : -1]; // fcNegSubnormal
+char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive
+char isfpclass_ndenorm_3[!__builtin_isfpclass(-1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_neg_0[__builtin_isfpclass(-1.0, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_neg_1[!__builtin_isfpclass(-1.0f, 0x00100) ? 1 : -1]; // fcPosNormal
+char isfpclass_neg_2[__builtin_isfpclass(-1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_neg_3

[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Thorsten via Phabricator via cfe-commits
tschuett added a comment.

Could Clang offer a builtin.h file? It is always included. You place named 
constants and enums inside.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Matt Arsenault via Phabricator via cfe-commits
arsenm added inline comments.



Comment at: clang/test/CodeGen/isfpclass.c:2
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | 
FileCheck %s
+
+_Bool check_isfpclass_finite(float x) {

sepavloff wrote:
> arsenm wrote:
> >  Can you also add a half test, also vectors
> Half is added. But vectors cannot, because in this case result is also a 
> vector.
Could copy what __builtin_elementwise does. Should that be in this builtin, or 
should there be a separate __builtin_elementwise_isfpclass?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

In D152351#4409725 , @sepavloff wrote:

> In D152351#4403904 , @aaron.ballman 
> wrote:
>
>> In D152351#4402785 , @arsenm wrote:
>>
>>> Also should get mentioned in the builtin docs and release notes
>>
>> +1, also, should there be named constants for the mask values?
>
> I don't know where these constants could be placed.

The preprocessor predefines a bunch of macros, so I was thinking along those 
same lines. e.g., 
https://github.com/llvm/llvm-project/blob/main/clang/lib/Frontend/InitPreprocessor.cpp#L737


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff marked 8 inline comments as done.
sepavloff added a comment.

In D152351#4403904 , @aaron.ballman 
wrote:

> In D152351#4402785 , @arsenm wrote:
>
>> Also should get mentioned in the builtin docs and release notes
>
> +1, also, should there be named constants for the mask values?

I don't know where these constants could be placed.




Comment at: clang/test/CodeGen/isfpclass.c:2
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | 
FileCheck %s
+
+_Bool check_isfpclass_finite(float x) {

arsenm wrote:
>  Can you also add a half test, also vectors
Half is added. But vectors cannot, because in this case result is also a vector.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Matt Arsenault via Phabricator via cfe-commits
arsenm added a comment.

Typo builting in commit message




Comment at: clang/docs/LanguageExtensions.rst:3418
+
+This function never raises floating-point exceptions.
+

Maybe also mention it doesn't canonicalize its input



Comment at: clang/test/CodeGen/isfpclass.c:54
+_Bool check_isfpclass_nan_f16(_Float16 x) {
+#pragma STDC FENV_ACCESS ON
+  return __builtin_isfpclass(x, 3 /*NaN*/);

Also tests without fenv access



Comment at: clang/test/CodeGen/isfpclass.c:56
+  return __builtin_isfpclass(x, 3 /*NaN*/);
+}

Test some vectors?



Comment at: clang/test/Sema/builtins.c:384
+  int x1 = __builtin_isfpclass(x, 1024); // expected-error {{argument value 
1024 is outside the valid range [0, 1023]}}
+  int x2 = __builtin_isfpclass(3, 3); // expected-error{{floating point 
classification requires argument of floating point type (passed in 'int')}}
+  int x3 = __builtin_isfpclass(x, 3, x); // expected-error{{too many arguments 
to function call, expected 2, have 3}}

For any other float argument, 3 would accept implicit conversion. Do we just 
not do that for these type inferring intrinsics?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-09 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff updated this revision to Diff 530041.
sepavloff added a comment.

Updated patch


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGen/isfpclass.c
  clang/test/Sema/builtins.c
  clang/test/Sema/constant-builtins-2.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) {
+  ConstantInt *TestV = getInt32(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 ,
  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/Sema/constant-builtins-2.c
===
--- clang/test/Sema/constant-builtins-2.c
+++ clang/test/Sema/constant-builtins-2.c
@@ -124,6 +124,47 @@
 char isnormal_nan[!__builtin_isnormal(__builtin_nan("")) ? 1 : -1];
 char isnormal_snan   [!__builtin_isnormal(__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
+char isfpclass_inf_pos_3[!__builtin_isfpclass(__builtin_inf(), 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_0[__builtin_isfpclass(1.0, 0x0100) ? 1 : -1]; // fcPosNormal
+char isfpclass_pos_1[!__builtin_isfpclass(1.0f, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_pos_2[__builtin_isfpclass(1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pos_3[!__builtin_isfpclass(1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan
+char isfpclass_pdenorm_0[__builtin_isfpclass(1.0e-40f, 0x0080) ? 1 : -1]; // fcPosSubnormal
+char isfpclass_pdenorm_1[__builtin_isfpclass(1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pdenorm_2[!__builtin_isfpclass(1.0e-40f, 0x003C) ? 1 : -1]; // fcNegative
+char isfpclass_pdenorm_3[!__builtin_isfpclass(1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_pzero_0  [__builtin_isfpclass(0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_pzero_1  [__builtin_isfpclass(0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_pzero_2  [!__builtin_isfpclass(0.0L, 0x0020) ? 1 : -1]; // fcNegZero
+char isfpclass_pzero_3  [!__builtin_isfpclass(0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_nzero_0  [__builtin_isfpclass(-0.0f, 0x0060) ? 1 : -1]; // fcZero
+char isfpclass_nzero_1  [__builtin_isfpclass(-0.0, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_nzero_2  [!__builtin_isfpclass(-0.0L, 0x0040) ? 1 : -1]; // fcPosZero
+char isfpclass_nzero_3  [!__builtin_isfpclass(-0.0, 0x0003) ? 1 : -1]; // fcNan
+char isfpclass_ndenorm_0[__builtin_isfpclass(-1.0e-40f, 0x0010) ? 1 : -1]; // fcNegSubnormal
+char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive
+char isfpclass_ndenorm_3[!__builtin_isfpclass(-1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
+char isfpclass_neg_0[__builtin_isfpclass(-1.0, 0x0008) ? 1 : -1]; // fcNegNormal
+char isfpclass_neg_1[!__builtin_isfpclass(-1.0f, 0x00100) ? 1 : -1]; // fcPosNormal
+char isfpclass_neg_2[__builtin_isfpclass(-1.0L, 0x01F8) ? 1 : -1]; // fcFinite
+char isfpclass_neg_3[!__builtin_isfpclass(-1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan
+char isfpclass_inf_neg_0[__builtin_isfpclass(-__builtin_inf(), 0x0004) ? 1 : -1]; // fcNegInf
+char isfpclass_inf_neg_1[!__builtin_isfpclass(-__builtin_inff(), 0x0200) ? 1 : -1]; // fcPosInf
+char 

[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

In D152351#4402785 , @arsenm wrote:

> Also should get mentioned in the builtin docs and release notes

+1, also, should there be named constants for the mask values?




Comment at: clang/include/clang/Basic/Builtins.def:491
 BUILTIN(__builtin_isnormal,   "i.", "FnctE")
+BUILTIN(__builtin_isfpclass,  "iCi.", "nctE")
 

`E` in the third arguments means it can be constant evaluated in the frontend, 
but I don't see any code or tests for that.



Comment at: clang/lib/Sema/SemaChecking.cpp:2776-2778
+  case Builtin::BI__builtin_isfpclass:
+if (SemaBuiltinConstantArgRange(TheCall, 0, 0, llvm::fcAllFlags))
+  return ExprError();

Do we diagnose if the second argument to the call isn't a floating-point value? 
e.g., `__builtin_isfpclass(0x1, some_struct)`



Comment at: clang/test/Sema/builtins.c:384
+  return __builtin_isfpclass(1024, x); // expected-error {{argument value 1024 
is outside the valid range [0, 1023]}}
+}

arsenm wrote:
> What happens if you pass complex?
What happens if you pass a non-float second argument, or a bit mask that 
doesn't match any of the valid values, or a bit mask that matches multiple 
valid values?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Matt Arsenault via Phabricator via cfe-commits
arsenm added a comment.

Also should get mentioned in the builtin docs and release notes


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Matt Arsenault via Phabricator via cfe-commits
arsenm added inline comments.



Comment at: clang/test/CodeGen/isfpclass.c:1
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | 
FileCheck %s
+

Use generated checks?



Comment at: clang/test/CodeGen/isfpclass.c:2
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -O1 -emit-llvm %s -o - | 
FileCheck %s
+
+_Bool check_isfpclass_finite(float x) {

 Can you also add a half test, also vectors



Comment at: clang/test/CodeGen/isfpclass.c:11
+#pragma STDC FENV_ACCESS ON
+  return __builtin_isfpclass(504 /*Finite*/, x);
+}

These operands are backwards, the test should be second 



Comment at: clang/test/Sema/builtins.c:383
+int test_is_fpclass(float x) {
+  return __builtin_isfpclass(1024, x); // expected-error {{argument value 1024 
is outside the valid range [0, 1023]}}
+}

Need a test for non-immediate class mask. Also a negative value 



Comment at: clang/test/Sema/builtins.c:384
+  return __builtin_isfpclass(1024, x); // expected-error {{argument value 1024 
is outside the valid range [0, 1023]}}
+}

What happens if you pass complex?



Comment at: llvm/lib/IR/IRBuilder.cpp:1379
+Value *IRBuilderBase::createIsFPClass(Value *FPNum, unsigned Test) {
+  auto TestV = llvm::ConstantInt::get(Type::getInt32Ty(Context), Test);
+  Module *M = BB->getParent()->getParent();

Use IRBuilder::getInt32


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff added a comment.

In D152351#4402615 , @qiucf wrote:

> It's necessary to check range of first argument in `SemaChecking.cpp` using 
> `SemaBuiltinConstantArgRange`.
>
>   _Bool check_isfpclass_1(float x) { return __builtin_isfpclass(123456, x); } 
> // ICE
>   
>   int g;
>   // error: cannot compile this builtin function yet
>   // there's better diagnostics when 1st argument is not constant
>   _Bool check_isfpclass_2(float x) { return __builtin_isfpclass(g, x); }

Added the check and a test for it. Thanks!




Comment at: clang/include/clang/Basic/Builtins.def:491
 BUILTIN(__builtin_isnormal,   "i.", "FnctE")
+BUILTIN(__builtin_isfpclass,  "iCi.", "nctE")
 

qiucf wrote:
> Why these intrinsics' type spec end with dot? I thought they are for vaargs.
It is a hack to have polymorphic builtin function. The argument `.` represents 
one argument but it can be of any type. So no need to have separate functions 
for every type.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Serge Pavlov via Phabricator via cfe-commits
sepavloff updated this revision to Diff 529243.
sepavloff added a comment.

Add check for test bit mask value


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

Files:
  clang/include/clang/Basic/Builtins.def
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/builtins.c
  clang/test/CodeGen/isfpclass.c
  clang/test/Sema/builtins.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 ,
  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/Sema/builtins.c
===
--- clang/test/Sema/builtins.c
+++ clang/test/Sema/builtins.c
@@ -378,3 +378,7 @@
 }
 
 _Complex double builtin_complex_static_init = __builtin_complex(1.0, 2.0);
+
+int test_is_fpclass(float x) {
+  return __builtin_isfpclass(1024, x); // expected-error {{argument value 1024 is outside the valid range [0, 1023]}}
+}
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/Sema/SemaChecking.cpp
===
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2770,7 +2770,13 @@
diag::err_hip_invalid_args_builtin_mangled_name);
   return ExprError();
 }
+break;
   }
+
+  case Builtin::BI__builtin_isfpclass:
+if (SemaBuiltinConstantArgRange(TheCall, 0, 0, llvm::fcAllFlags))
+  return ExprError();
+break;
   }
 
   // Since the target specific builtins for each arch overlap, only check those
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 

[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Qiu Chaofan via Phabricator via cfe-commits
qiucf added a comment.

It's necessary to check range of first argument in `SemaChecking.cpp` using 
`SemaBuiltinConstantArgRange`.

  _Bool check_isfpclass_1(float x) { return __builtin_isfpclass(123456, x); } 
// ICE
  
  int g;
  // error: cannot compile this builtin function yet
  // there's better diagnostics when 1st argument is not constant
  _Bool check_isfpclass_2(float x) { return __builtin_isfpclass(g, x); }




Comment at: clang/include/clang/Basic/Builtins.def:491
 BUILTIN(__builtin_isnormal,   "i.", "FnctE")
+BUILTIN(__builtin_isfpclass,  "iCi.", "nctE")
 

Why these intrinsics' type spec end with dot? I thought they are for vaargs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D152351/new/

https://reviews.llvm.org/D152351

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D152351: [clang] Add __builtin_isfpclass

2023-06-07 Thread Serge Pavlov via Phabricator via cfe-commits
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(, )

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 ,
  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),
+