[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-29 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


sethp wrote:

Well, good news and bad news: I succeeded in trying to save one more cycle by 
asking you to fix the conflict in ReleaseNotes.rst, and these changes are in 
the llvm-project's main branch: 2903df02fb3c057849aaa796a91289b01950a5f0 (sorry 
for mucking up the title, that's one for me to grow on).

The bad news is that github did not consider this an ["indirect 
merge"](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges#indirect-merges)
 as it would have if I'd authored a merge commit resolving the conflict. So we 
have a couple options that I see:

* Mark the PR as "closed" instead of "merged" and celebrate anyway
* @Destroyerrrocket you could try force-pushing your branch to that commit 
(`git push --force-with-lease 
https://github.com/Destroyerrrocket/llvm-project.git 
2903df02fb3c057849aaa796a91289b01950a5f0:refs/heads/Destroyerrrocket-users/destroyerrocket/46593`
 ought to do it), which github will hopefully recognize as associating the two 
properly
* or, some further git shenanigans like 
   ```
  git reset --hard 2903df02fb3c057849aaa796a91289b01950a5f0
  git commit --allow-empty -m 'Mark PR#76615 as integrated'
  git push --force-with-lease
  ```
  and then we hit the "squash and merge" button on _that_.

What do y'all think?


https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-24 Thread Nikolas Klauser via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


philnik777 wrote:

I just wanted to say thanks for working on this. I'd love to enable the 
vectorization branches in libc++ during constant evaluation. It's always a 
great way to have confidence in the correctness of the code, and this brings us 
a step closer to having fewer `__libcpp_is_constant_evaluated()` in the code 
base.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-24 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

It's been a pleasure! Expect to see me again taking the operator[] accessor
(if no one else takes it) by June aprox

El mié, 24 abr 2024, 20:26, sethp ***@***.***> escribió:

> ***@***. approved this pull request.
>
> LGTM!
>
> Barring any objections, I'll plan to hit the squash & merge button on this
> one come Monday (29 April) morning.
>
> Thank you @Destroyerrrocket  for
> your thoroughness and patience! I enjoyed learning my way through the
> details with you 
>
> —
> Reply to this email directly, view it on GitHub
> ,
> or unsubscribe
> 
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>


https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-24 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/sethp approved this pull request.

LGTM!

Barring any objections, I'll plan to hit the squash & merge button on this one 
come Monday (29 April) morning. 

Thank you @Destroyerrrocket for your thoroughness and patience! I enjoyed 
learning my way through the details with you :smile: 

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-20 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

Addressed the comments; I don't really like the expanded macro code, it 
generates 600 lines of really repetitive code, so I left the macros as a source 
of truth that I'd use to generate the cases in the future.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-20 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From c14783de45687c754253c0cbf8a7834c7f986d80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/5] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 204 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 3bead159c8f946..3204e950f92429 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2927,7 +2927,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2981,7 +2981,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c44f238e33846b..071a8f4cff9db9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -203,6 +203,9 @@ Non-comprehensive list of changes in this release
 - ``__typeof_unqual__`` is available in all C modes as an extension, which 
behaves
   like ``typeof_unqual`` from C23, similar to ``__typeof__`` and ``typeof``.
 
+- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
+  now be used within constant expressions.
+
 New Compiler Flags
 --
 - ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 73ae8d8efb23a2..aafea66359d23b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2706,7 +2706,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10709,6 +10710,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10961,6 +10965,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-20 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From 7447038a5006ff5fe5fdeead865287930843d8f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/5] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 204 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 7b23e4d1c2f30c..485e4af69b3e02 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2925,7 +2925,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2979,7 +2979,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 76eaf0bf11c303..a3c96e44eef4dd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -193,6 +193,9 @@ Non-comprehensive list of changes in this release
   with support for any unsigned integer type. Like the previous builtins, these
   new builtins are constexpr and may be used in constant expressions.
 
+- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
+  now be used within constant expressions.
+
 New Compiler Flags
 --
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index dae8f32fc02951..6b43b6a1638fbc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2706,7 +2706,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10709,6 +10710,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10961,6 +10965,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-20 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10961,6 +10968,118 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool handleVectorElementCast(EvalInfo , const FPOptions FPO,
+const Expr *E, QualType SourceTy,
+QualType DestTy, APValue const ,
+APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateAsRValue(Info, E->getSrcExpr(), Source))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorElementCast(Info, FPO, E, SourceTy, DestTy,
+ Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInInputVector = VecVal1.getVectorLength();
+
+  APSInt IndexVal = E->getShuffleMaskIdx(Info.Ctx, EltNum);
+  int64_t index = IndexVal.getExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index == -1) {
+Info.FFDiag(
+E, diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
+<< EltNum;
+return false;
+  }
+
+  if (index < 0 || index >= TotalElementsInInputVector * 2)
+llvm_unreachable("Out of bounds shuffle index");
+
+  if (index >= TotalElementsInInputVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInInputVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateAsRValue(Info, Vec1, VecVal1))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateAsRValue(Info, Vec2, VecVal2))
+return false;
+
+  VectorType const *DestVecTy = E->getType()->castAs();
+  if (!DestVecTy)
+return false;
+
+  QualType DestElTy = DestVecTy->getElementType();

Destroyerrrocket wrote:

That's good to know indeed :)

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-20 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;

Destroyerrrocket wrote:

I agree that adding a diagnostic here, even if unreachable, is more than just 
desired, I'm well convinced on the future-proofing argument. I will not add a 
test because I simply don't have a way to reach this, I believe.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


sethp wrote:

That sounds right to me; the tasks I see are:

- [ ] Expanding the test cases for `__builtin_convertvector`
- [ ] Rewording the diagnostic for -1 in `__builtin_shufflevector`
- [ ] Rewording the comment for -1 in `__builtin_shufflevector`
- [ ] A stylistic change to `__builtin_convertvector`
- [ ] Considering adding a diagnostic for `__builtin_convertvector` in case we 
"fall through" to the bottom (which we think is currently impossible)
- [ ] ReleaseNotes.rst

Of those, I think the only one that isn't pretty much purely mechanical is 
whether or not we add the extra diagnostic. 

Let me know if I missed anything, or if there's anything I can do to help get 
this one over the finish line: thanks so much @Destroyerrrocket for all your 
work already!



https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-15 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

There are some minor comments I believe, I just haven't had any time to
look at them. I'm sorry about that! Hopefully I'll be able to give it the
nudge it needs this month, but looking at the calendar I'm not sure I'd
count on it (no vacations coming)

El lun, 15 abr 2024, 17:14, Simon Pilgrim ***@***.***>
escribió:

> Other than fixing the ReleaseNotes.rst conflict is there anything
> outstanding on this now?
>
> —
> Reply to this email directly, view it on GitHub
> ,
> or unsubscribe
> 
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>


https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-15 Thread Simon Pilgrim via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


RKSimon wrote:

Other than fixing the ReleaseNotes.rst conflict is there anything outstanding 
on this now?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-08 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

erichkeane wrote:

No, i don't think that is worth doing.  I'm still disturbed by how difficult it 
is to figure out exactly what/how we are testing things, but perhaps just some 
detailed comments on the macros are sufficient.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-08 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

sethp wrote:

Well, I got a quick demo of what I was thinking put together. For your 
consideration: 
https://github.com/llvm/llvm-project/commit/17c78a28b4f441bf284bcf6935061938ec908f31

It did & didn't work out quite the way I'd hoped: I'd forgotten just how, uh, 
_peculiar_ the preprocessor is, especially if you're trying to get it to 
generate human-readable output. There might be a way to do it nicely (adding 
`clang-format` into the pipeline?), or it might not be an idea worth pursuing 
at all. I'll leave the final determination up to you & @erichkeane .

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,
Pol Marcet =?utf-8?q?Sard=C3=A0?= 
Message-ID:
In-Reply-To: 


https://github.com/erichkeane commented:

I would love it if @sethp  can do another review, but only 1 nit from me.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10318,6 +10318,8 @@ def err_shufflevector_nonconstant_argument : Error<
 def err_shufflevector_argument_too_large : Error<
   "index for __builtin_shufflevector must be less than the total number "
   "of vector elements">;
+def err_shufflevector_minus_one_is_undefined_behavior_constexpr : Error<
+  "index for __builtin_shufflevector must be within the bounds of the input 
vectors in a constexpr context. An index of -1 at position %0 was found. -1 is 
only allowed at runtime.">;

erichkeane wrote:

```suggestion
  "index for __builtin_shufflevector not within the bounds of the input 
vectors; index of -1 found at position %0 not permitted in a constexpr 
context">;
```

Leave the 'only allowed at runtime' for the documentation (and document it?).

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

Destroyerrrocket wrote:

Great, let's hope operator[] makes it.

The error comes from somewhere in the depths of ExprConst, it intentionally 
tells you that undefined values are indeed illegal in constexpr code. I agree 
with you, a shame it makes sense!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();

Destroyerrrocket wrote:

I see! It seems like Gcc has extra characteristics then. given that at some 
point it could happen that such a thing needs to be supported, let's actually 
rewrite the code to support both sizes. Beware, I won't be able to test it, as 
Sema will prevent it from reaching constexpr. 

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-04-01 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;

Destroyerrrocket wrote:

304 bytes is definitely inside what I'd be slightly worried to allocate without 
thinking into the stack, but having looked at it I think it's going to be fine. 
We're not the only case of smallVectors with APValues, and I'm sure that if it 
ever becomes a problem the default stack size can be modified (or the code can 
be refactored, I'm sure that if that ever happens it's not going to be "just" 
the fault of a smallvector of APValues). I thank you for pointing it out, as I 
simply did not check!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

sethp wrote:

My suggestion was not so much a way to avoid spelling them all out as to trick 
the preprocessor into doing (a lot of) the work. I'll try to put together a toy 
example in the next couple of days, but if you run `clang -E` on the existing 
file and commit the resulting spellings you'll get much of the way to what I 
was thinking. 

Would that address your concern, @erichkeane?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

sethp wrote:

re `Operator[]` there's already a PR for doing that in constant contexts, I 
think: https://github.com/llvm/llvm-project/pull/72607 . Definitely agree it'd 
be helpful for validations! 

re: `APValue::Indeterminate`, I think you're talking about how top-level 
indeterminate values get rejected by clang as not being a constant expression, 
right? Dang, that both makes sense and feels unfortunate: thanks for giving it 
a try, at least!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;

sethp wrote:

Yeah, I don't have much of an idea how to evaluate the tradeoffs here: I was 
hoping you might, and that you'd teach me :)

I agree that it's out of scope for this PR, and that sticking with the 4 for 
consistency's sake is as good a number as any!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;

sethp wrote:

Ah, too bad: thanks for looking into it and reporting back! 

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();

sethp wrote:

I didn't think the vectors had to be the same length: both clang and gcc 
document the extension to require that the vectors have "a compatible element 
type" ([gcc](https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html)) or 
"are vectors that have the same element type" 
([clang](https://clang.llvm.org/docs/LanguageExtensions.html#builtin-shufflevector)).
 

However, while gcc does accept a shuffle of e.g. an 8-element and 4-element 
vector (for a 12-element "input"), clang seems to reject it: 
https://godbolt.org/z/3ooszMKbc

So maybe the thing to do here is add an `assert(VecVal1.getVectorLength() == 
VecVal2.getVectorLength())`? And/or, change the documentation to make it clear 
it's "same element type _and length_"?

An alternative to consider would be to plumb both the `constexpr` and codegen 
pieces to accept a wider range of vectors for arguments 1 and 2, but I'm 
assuming the current lowering is just using LLVM's `shufflevector`, which 
itself only supports homogeneous arguments. To me, that smells like something 
best addressed as its own unit of work and far outside the scope of this PR, 
but I wanted to include it for completeness.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From 7447038a5006ff5fe5fdeead865287930843d8f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/4] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 204 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 7b23e4d1c2f30c..485e4af69b3e02 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2925,7 +2925,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2979,7 +2979,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 76eaf0bf11c303..a3c96e44eef4dd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -193,6 +193,9 @@ Non-comprehensive list of changes in this release
   with support for any unsigned integer type. Like the previous builtins, these
   new builtins are constexpr and may be used in constant expressions.
 
+- Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may
+  now be used within constant expressions.
+
 New Compiler Flags
 --
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index dae8f32fc02951..6b43b6a1638fbc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2706,7 +2706,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10709,6 +10710,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10961,6 +10965,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

I'll rebase when I have more time, around next week (I know that ideally you'd 
prefer to see it already rebased)

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,

Destroyerrrocket wrote:

Went with the EvaluateAsRValue

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

Whenever you have a change, I think this is ready for a second pass. Sorry for 
the delay! ^-^ If I missed something, do let me know

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From cba67a73ea1e59eb8eeb4e702d77f329028f4c22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/5] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   2 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

Destroyerrrocket wrote:

Bad news... seems like APValue::Indeterminate and None are both intentionally 
disallowed. I'll go with the second option then, make the user choose what 
element they want to use as a source in constexpr. They can always `if 
consteval`

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;

Destroyerrrocket wrote:

I could not find a way that would not require copying (the move operator is 
just a copy in this case) about 600 bytes of data. I think I'll just leave it 
as is, as just making a new APValue to insert values to does not seem to solve 
much

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;

Destroyerrrocket wrote:

it seems like the only one missing is _BitInt(8) or bigger. I'll just add 
support for that

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;

Destroyerrrocket wrote:

Looking at how other code does it, it seems like I also based my decision on 
the fact that all other vector code uses a size of 4. I think that just for 
consistency, it is ok to leave it as it is.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,

Destroyerrrocket wrote:

I think that these errors should be covered by convertvector.c, I'll add one of 
the missing diagnostics you pointed out. One already exists

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

Destroyerrrocket wrote:

Operator[] needs lvalue support for vectors, I think I commented with @RKSimon 
that it would be a really useful thing for validations. For now, I'm static 
casting to get arround this

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

Destroyerrrocket wrote:

APValue::Indeterminate seems to be exactly what I was looking for! I'll read up 
on this, thank you. I assumed that such a thing did not exist, but I'm glad to 
be proven wrong

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

Destroyerrrocket wrote:

:6:12: error: first two arguments to '__builtin_shufflevector' must 
have the same type
6 | return __builtin_shufflevector((vector4char){}, (vector8char){}, 
10)[0];
  |^   
1 error generated.

Latest trunk seems to also think that both input vectors should match in size. 
I'll add an llvm_unreachable for the case where it is out of bounds

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;
+
+  VectorType const *DestVecTy = E->getType()->castAs();
+  if (!DestVecTy)
+return false;
+
+  QualType DestElTy = DestVecTy->getElementType();
+
+  auto TotalElementsInOutputVector = DestVecTy->getNumElements();
+
+  SmallVector ResultElements;
+  ResultElements.reserve(TotalElementsInOutputVector);
+  for (unsigned EltNum = 0; EltNum < TotalElementsInOutputVector; ++EltNum) {

Destroyerrrocket wrote:

getShuffleMaskIdx is exactly what I should be using! Thanks for pointing that 
out

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;

Destroyerrrocket wrote:

I 100% Agree! I'll look if concatenating the vectors can be done in an 
efficient manner!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());

Destroyerrrocket wrote:

I think that beyond some differences in memory layout, I'd expect the 
performance to be about the same for the normal case. The bad case might be 
able to save a bit of performance by avoiding a copy (happening inside the 
APValue) (that probably will get optimized anyway). Without measuring, I think 
this is performant enough, and I value code being short and easy enough to read 
(not that the proposed code is bad in any way; If I saw it in a PR I wouldn't 
even blink)

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

Destroyerrrocket wrote:

If you could provide a toy example, I can do that for this test

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

Destroyerrrocket wrote:

I'm sorry @sethp, I don't follow your explanation, I'm not familiar enough with 
the testing infrastructure in Clang. If you think that will make the code look 
cleaner while still not having to spell out all convinations, I'm all for it!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-31 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();

Destroyerrrocket wrote:

Aren't both vectors the same size? This code assumes that based on the spec. If 
They are not the same size, I need to revisit this, but otherwise I think the 
name is just fine. Maybe I'll rename it to `TotalElementsInInputVector` so it 
is a bit more descriptive

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-23 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;

Destroyerrrocket wrote:

I certainly don't know about any such case...

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-23 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;

Destroyerrrocket wrote:

I chose 4 as plenty of times I've had to deal with SIMD code it has been either 
SSE code dealing with floats and doubles and AVX code mainly dealing with 
doubles, but this certainly is a biased worldview; not all applications deal 
with doubles and certainly from time to time I've had to code for avx512.

In any case, I think that doubling the smallvector would not be ideal 
stacksize-wise, and a normal vector with a reserve call would be more than 
enough to cover all cases. We always know the size and a normal allocation 
should be fine.

APValue is indeed expensive, but it is also convenient; I think I'm going to 
stick with it for this PR, and if very long vectors ever get supported this 
might need to be improved upon. Should I leave a comment explaining that to the 
reader?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-21 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

@RKSimon Hi, Sorry I have not reached out! Yes, I plan to do some work on this 
in the next two weeks; on a normal work week I end up way too tired to work 
more in the weekend, if you need this and want to take over just let me know, I 
don't want to stall anyone!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-03-21 Thread Simon Pilgrim via cfe-commits
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,Pol M
 
Message-ID:
In-Reply-To: 


RKSimon wrote:

@Destroyerrrocket reverse-ping - are you still working on this?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

@sethp This is an amazing review! I won't be able to work on this for 2 weeks, 
but thank you a lot for your work!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;

sethp wrote:

I don't think this quite implements `__builtin_shufflevector`; consider:

```c++
typedef char vector4char __attribute__((__vector_size__(4)));
typedef char vector8char __attribute__((__vector_size__(8)));

__builtin_shufflevector((vector4char){}, (vector8char){}, 10);
```

That should produce a single-element `char` vector whose element has value `0`: 
https://godbolt.org/z/9655x1oc6 (though it looks like there's another issue 
elsewhere in Sema that's not currently accepting that).

Also, the `>=` suggests to me that it'll also produce values for out-of-bounds 
indexes. Happily, this already aborts (with a useful diagnostic):

```c++
__builtin_shufflevector((vector8char){}, (vector8char){}, 20);
```

So, for that part it's probably enough here to clarify with an `assert` that 
`index` is less the sum of the vectors' lengths (or the -1 sentinel).

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,

sethp wrote:

I've dealt with lvalues in the interpreter, but maybe only a little more than 
you have. I've found it more than a little confusing, especially because 
interpreter seemingly uses "RValue" as a synonym for "actual value" (as you're 
using it here), and "LValue" as "opaque blob of bytes" (with metadata, and 
accessors, but enough wrinkles that it's just easier to convert to an RValue to 
work with the actual data).

That said, I think there's two ways to go here to meet the need instead of this 
function:

1. Teach the parser that these builtins ought to take their arguments as 
rvalues, so that it will insert a `LValueToRValue` cast in the expression tree 
wrapping the src value, and so you can use `EvaluateVector` (probably loosening 
its assertion to allow `xvalue`s too). This probably would have downstream 
consequences, though, and I lack the expertise to know whether they'd be good 
or bad. But it might be interesting!
2. Use, as much of the interpreter seems to, `EvaluateAsRValue` as shorthand 
for "do an in-place 'dereference' of the lvalue": the main difference I see 
from `EvaluateVectorOrLValue` here is that the latter checks for an impossible 
condition (SemaChecking.cpp already prevents construction of any  
[ConvertVectorExpr](https://github.com/llvm/llvm-project/blob/2e08e821b7ea5bf7c0fe0775feb94a7fdb5204c7/clang/lib/Sema/SemaChecking.cpp#L9428-L9435)
 or 
[ShuffleVectorExpr](https://github.com/llvm/llvm-project/blob/2e08e821b7ea5bf7c0fe0775feb94a7fdb5204c7/clang/lib/Sema/SemaChecking.cpp#L9351-L9356)
 that doesn't have vector-typed arguments in the appropriate slots).

For the latter path, it might be wise to add a test case to exercise the 
checker, too; perhaps something like this for `__builtin_convertvector`?

```c++
static_assert([]{
__builtin_convertvector(0, vector8char); // expected-error {{must be a 
vector}}
__builtin_convertvector((vector8char){}, int); // expected-error {{must be 
of vector type}}
return 1;
}());
```

(and similar for `__builtin_shufflevector`)

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr

sethp wrote:

```suggestion
// FIXME: Missing: conditional operator (for GNU
// conditional select), ExtVectorElementExpr
```

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;

sethp wrote:

I think it would be nice to include a diagnostic here: maybe something to the 
effect of `constexpr vector conversion involving type %s not yet supported`?

That said, I'm not sure what types exist that would be valid vector elements 
but fall through to this case (fixed point? complex?).

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


https://github.com/sethp commented:

Hi @Destroyerrrocket, thanks for your work getting vectors into constexpr-land! 
I'm also curious about that, so I did my best to give you a helpful review. 

The only part I'd be uncomfortable about merging is the handling of `-1` 
sentinels / indeterminate values: everything else I expect you to take as no 
more than a gentle suggestion.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,

sethp wrote:

This is more or less the same thing as an cast expression for a single element, 
right? Maybe it would be better named `handleVectorElementCast` or 
`handleScalarConversion`?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;
+
+  VectorType const *DestVecTy = E->getType()->castAs();
+  if (!DestVecTy)
+return false;
+
+  QualType DestElTy = DestVecTy->getElementType();
+
+  auto TotalElementsInOutputVector = DestVecTy->getNumElements();
+
+  SmallVector ResultElements;
+  ResultElements.reserve(TotalElementsInOutputVector);
+  for (unsigned EltNum = 0; EltNum < TotalElementsInOutputVector; ++EltNum) {

sethp wrote:

Hmm, this looks suspicious to me; it should be OK, but it's not clear on first 
read the link between the number of subexpressions and the output vector 
elements, so it looks like it might be an OOB access.

I think either asserting that `TotalElementsInOutputVector == 
E->getNumSubExprs() - 2`, or using `E->getShuffleMaskIdx(EltNum)` instead of 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());

sethp wrote:

This is probably my own inadequate understanding of C++, but I feel like the 
pattern I see elsewhere in the evaluator would look more like this here:

```c++
  APFloat Float;
  if (!HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
DestTy, Float);
  return false;
  Result = APValue(Float);
  return true;  
```

Is the difference meaningful, do you think?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();

sethp wrote:

It's a bit of a nit, but this seems odd to me; should it be called 
`TotalElementsInFirstArg`?



https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;
+  ResultElements.reserve(SourceLen);
+  for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info))
+return false;
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2)
+index = 0;
+
+  if (index >= TotalElementsInAVector)
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  else
+Result = VecVal1.getVectorElt(index);
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;

sethp wrote:

Not quite sure how to do it, it seems like it'd be handy if we could finesse 
the evaluator here into producing a single APValue that's the concatenation of 
the vectors produced by the first two sub-expressions.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result))
+  return false;
+  }
+
+  return Result.isVector();
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  auto SourceLen = Source.getVectorLength();
+  SmallVector ResultElements;

sethp wrote:

I'm not super familiar with the tradeoffs here, but I'm a bit curious how you 
selected `4`? From what I can see, that occupies ~304 bytes of stack space, 
which feels like it might be already be a lot, but I'd expect some fairly 
commonly used vectors to have 8 elements. 

Not really a topic for this PR, but maybe what this is suggesting is that 
storing an APValue per vector element slot is kind of an expensive 
representation?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

sethp wrote:

There might be a "best of both worlds" situation here to check in the generated 
result. Maybe something like an `#ifdef GEN_TESTS` wrapping the macros, and a 
second `RUN` pipeline wrapping `clang -DGEN_TESTS -E` and `FileCheck` to 
validate that the output and contents of this file are in sync?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-15 Thread via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


https://github.com/sethp edited https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-09 Thread Simon Pilgrim via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 



@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));

RKSimon wrote:

(style) assertion message

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-05 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= ,Pol M
 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From cba67a73ea1e59eb8eeb4e702d77f329028f4c22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/4] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   2 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,

Destroyerrrocket wrote:

> is the name inaccurate, or is this using 'false' to mean 'failure' AND 'not a 
> vector'?
Indeed, false is being treated as a failure and not a vector.
> It seems to me that this needs to be something like "EvaluateLValueVector" or 
> something?
I'm not entirely sure if the way I implemented the handling of an lvalue as a 
parameter is even the correct way to go with, so it might very well be that the 
reason it sticks out is because I'm doing something wrong. I guess I'll have to 
wait for someone who has dealt with lvalues in constexpr to tell me where I 
went wrong

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

Destroyerrrocket wrote:

I just really didn't want to type out all the combinations. I can expand the 
macros out, np!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,99 @@
+// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only %s
+// expected-no-diagnostics
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

erichkeane wrote:

Can we clean up this test?  All of the macros doing the 'check' generation make 
this pretty unreadable.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 



@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,

erichkeane wrote:

This interface to this function seems really odd for the name?  Is the name 
inaccurate, or is this using 'false' to mean 'failure' AND 'not a vector'?  

It seems to me that this needs to be something like "EvaluateLValueVector" or 
something?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/erichkeane commented:

Hopefully someone with more knowledge of the const evaluator (@shafik and 
@tbaederr have experience lately!) can poke their head in, but a few things 
from my look over.

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Erich Keane via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sard=C3=A0?= ,
Pol Marcet =?utf-8?q?Sard=C3=A0?= 
Message-ID:
In-Reply-To: 


Destroyerrrocket wrote:

(sorry about the typo!)

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= ,
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From cba67a73ea1e59eb8eeb4e702d77f329028f4c22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/3] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   2 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Simon Pilgrim via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


RKSimon wrote:

Please can you rename constat_builtins_vector.cpp -> 
constant_builtins_vector.cpp

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-04 Thread Pol M via cfe-commits
Pol Marcet =?utf-8?q?Sardà?= 
Message-ID:
In-Reply-To: 


https://github.com/Destroyerrrocket updated 
https://github.com/llvm/llvm-project/pull/76615

>From cba67a73ea1e59eb8eeb4e702d77f329028f4c22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH 1/2] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   2 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Pol M via cfe-commits


@@ -302,3 +302,64 @@ extern __typeof__(__builtin_expect(0, 0)) bi0;
 // Strings
 int array1[__builtin_strlen("ab\0cd")];
 int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef long long vector4long __attribute__((__vector_size__(32)));
+typedef int vector4int __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+typedef char vector4char __attribute__((__vector_size__(4)));
+typedef double vector8double __attribute__((__vector_size__(64)));
+typedef float vector8float __attribute__((__vector_size__(32)));
+typedef long long vector8long __attribute__((__vector_size__(64)));
+typedef int vector8int __attribute__((__vector_size__(32)));
+typedef short vector8short __attribute__((__vector_size__(16)));
+typedef char vector8char __attribute__((__vector_size__(8)));
+
+// Convert vector
+#define CHECK_NUM(__size, __typeFrom, __typeTo, ...)   
 \
+  vector##__size##__typeTo 
 \
+  from_##vector##__size##__typeFrom##_to_##vector##__size##__typeTo##_var 
= \
+  __builtin_convertvector((vector##__size##__typeFrom){__VA_ARGS__},   
 \
+  vector##__size##__typeTo);
+#define CHECK_TO_ALL_TYPES(__size, __typeFrom, ...)
\
+  CHECK_NUM(__size, __typeFrom, double, __VA_ARGS__)   
\
+  CHECK_NUM(__size, __typeFrom, float, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, long, __VA_ARGS__) 
\
+  CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__)  
\
+  CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__)
+
+#define CHECK_ALL_COMBINATIONS(__size, ...)
\
+  CHECK_TO_ALL_TYPES(__size, double, __VA_ARGS__)  
\
+  CHECK_TO_ALL_TYPES(__size, float, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__)
\
+  CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) 
\
+  CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
+
+CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
+CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
+#undef CHECK_ALL_COMBINATIONS
+#undef CHECK_TO_ALL_TYPES
+#undef CHECK_NUM
+
+// Shuffle vector
+vector4int const vector4intConst1 = {0, 1, 2, 3};
+vector4int const vector4intConst2 = {4, 5, 6, 7};
+vector8int const vector8intConst = {};
+
+vector4int vectorShuffle1 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 1, 2, 3);
+vector4int vectorShuffle2 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 4, 5, 6, 7);
+vector4int vectorShuffle3 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, -1, -1, -1, 
-1);
+vector4int vectorShuffle4 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6);
+vector8int vectorShuffle5 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
+vector4int vectorShuffle6 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6);
+vector8int vectorShuffle7 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6, 1, 
3, 5, 7);

Destroyerrrocket wrote:

But just for this validation, I'd definitiely take the bitcast approach

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Pol M via cfe-commits


@@ -302,3 +302,64 @@ extern __typeof__(__builtin_expect(0, 0)) bi0;
 // Strings
 int array1[__builtin_strlen("ab\0cd")];
 int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef long long vector4long __attribute__((__vector_size__(32)));
+typedef int vector4int __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+typedef char vector4char __attribute__((__vector_size__(4)));
+typedef double vector8double __attribute__((__vector_size__(64)));
+typedef float vector8float __attribute__((__vector_size__(32)));
+typedef long long vector8long __attribute__((__vector_size__(64)));
+typedef int vector8int __attribute__((__vector_size__(32)));
+typedef short vector8short __attribute__((__vector_size__(16)));
+typedef char vector8char __attribute__((__vector_size__(8)));
+
+// Convert vector
+#define CHECK_NUM(__size, __typeFrom, __typeTo, ...)   
 \
+  vector##__size##__typeTo 
 \
+  from_##vector##__size##__typeFrom##_to_##vector##__size##__typeTo##_var 
= \
+  __builtin_convertvector((vector##__size##__typeFrom){__VA_ARGS__},   
 \
+  vector##__size##__typeTo);
+#define CHECK_TO_ALL_TYPES(__size, __typeFrom, ...)
\
+  CHECK_NUM(__size, __typeFrom, double, __VA_ARGS__)   
\
+  CHECK_NUM(__size, __typeFrom, float, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, long, __VA_ARGS__) 
\
+  CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__)  
\
+  CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__)
+
+#define CHECK_ALL_COMBINATIONS(__size, ...)
\
+  CHECK_TO_ALL_TYPES(__size, double, __VA_ARGS__)  
\
+  CHECK_TO_ALL_TYPES(__size, float, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__)
\
+  CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) 
\
+  CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
+
+CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
+CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
+#undef CHECK_ALL_COMBINATIONS
+#undef CHECK_TO_ALL_TYPES
+#undef CHECK_NUM
+
+// Shuffle vector
+vector4int const vector4intConst1 = {0, 1, 2, 3};
+vector4int const vector4intConst2 = {4, 5, 6, 7};
+vector8int const vector8intConst = {};
+
+vector4int vectorShuffle1 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 1, 2, 3);
+vector4int vectorShuffle2 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 4, 5, 6, 7);
+vector4int vectorShuffle3 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, -1, -1, -1, 
-1);
+vector4int vectorShuffle4 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6);
+vector8int vectorShuffle5 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
+vector4int vectorShuffle6 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6);
+vector8int vectorShuffle7 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6, 1, 
3, 5, 7);

Destroyerrrocket wrote:

Yep, I'll copy that over.

Well, in that case I would have to care about lvalues (in my code I just needed 
the values to return a new copy, so I could ignore all that machinery for now). 
I'd have to learn how these work more in depth. I don't think they'd be 
necessarily super complicated, and that would make for an ideal follow-up for 
me! (looks like this would be part of: 
https://github.com/llvm/llvm-project/issues/41806, and also this also looks 
interesting: https://github.com/llvm/llvm-project/issues/30794)

I think this is a pretty interesting set of tasks to work on!

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -302,3 +302,64 @@ extern __typeof__(__builtin_expect(0, 0)) bi0;
 // Strings
 int array1[__builtin_strlen("ab\0cd")];
 int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef long long vector4long __attribute__((__vector_size__(32)));
+typedef int vector4int __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+typedef char vector4char __attribute__((__vector_size__(4)));
+typedef double vector8double __attribute__((__vector_size__(64)));
+typedef float vector8float __attribute__((__vector_size__(32)));
+typedef long long vector8long __attribute__((__vector_size__(64)));
+typedef int vector8int __attribute__((__vector_size__(32)));
+typedef short vector8short __attribute__((__vector_size__(16)));
+typedef char vector8char __attribute__((__vector_size__(8)));
+
+// Convert vector
+#define CHECK_NUM(__size, __typeFrom, __typeTo, ...)   
 \
+  vector##__size##__typeTo 
 \
+  from_##vector##__size##__typeFrom##_to_##vector##__size##__typeTo##_var 
= \
+  __builtin_convertvector((vector##__size##__typeFrom){__VA_ARGS__},   
 \
+  vector##__size##__typeTo);
+#define CHECK_TO_ALL_TYPES(__size, __typeFrom, ...)
\
+  CHECK_NUM(__size, __typeFrom, double, __VA_ARGS__)   
\
+  CHECK_NUM(__size, __typeFrom, float, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, long, __VA_ARGS__) 
\
+  CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__)  
\
+  CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__)
+
+#define CHECK_ALL_COMBINATIONS(__size, ...)
\
+  CHECK_TO_ALL_TYPES(__size, double, __VA_ARGS__)  
\
+  CHECK_TO_ALL_TYPES(__size, float, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__)
\
+  CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) 
\
+  CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
+
+CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
+CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
+#undef CHECK_ALL_COMBINATIONS
+#undef CHECK_TO_ALL_TYPES
+#undef CHECK_NUM
+
+// Shuffle vector
+vector4int const vector4intConst1 = {0, 1, 2, 3};
+vector4int const vector4intConst2 = {4, 5, 6, 7};
+vector8int const vector8intConst = {};
+
+vector4int vectorShuffle1 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 1, 2, 3);
+vector4int vectorShuffle2 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 4, 5, 6, 7);
+vector4int vectorShuffle3 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, -1, -1, -1, 
-1);
+vector4int vectorShuffle4 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6);
+vector8int vectorShuffle5 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
+vector4int vectorShuffle6 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6);
+vector8int vectorShuffle7 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6, 1, 
3, 5, 7);

RKSimon wrote:

Maybe use the same 'LITTLE_END' define approach used in 
clang\test\SemaCXX\constexpr-builtin-bit-cast.cpp?

How much work will it to be to eventually implement the vector operator[] as a 
constexpr as well do you think?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Pol M via cfe-commits


@@ -302,3 +302,64 @@ extern __typeof__(__builtin_expect(0, 0)) bi0;
 // Strings
 int array1[__builtin_strlen("ab\0cd")];
 int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef long long vector4long __attribute__((__vector_size__(32)));
+typedef int vector4int __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+typedef char vector4char __attribute__((__vector_size__(4)));
+typedef double vector8double __attribute__((__vector_size__(64)));
+typedef float vector8float __attribute__((__vector_size__(32)));
+typedef long long vector8long __attribute__((__vector_size__(64)));
+typedef int vector8int __attribute__((__vector_size__(32)));
+typedef short vector8short __attribute__((__vector_size__(16)));
+typedef char vector8char __attribute__((__vector_size__(8)));
+
+// Convert vector
+#define CHECK_NUM(__size, __typeFrom, __typeTo, ...)   
 \
+  vector##__size##__typeTo 
 \
+  from_##vector##__size##__typeFrom##_to_##vector##__size##__typeTo##_var 
= \
+  __builtin_convertvector((vector##__size##__typeFrom){__VA_ARGS__},   
 \
+  vector##__size##__typeTo);
+#define CHECK_TO_ALL_TYPES(__size, __typeFrom, ...)
\
+  CHECK_NUM(__size, __typeFrom, double, __VA_ARGS__)   
\
+  CHECK_NUM(__size, __typeFrom, float, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, long, __VA_ARGS__) 
\
+  CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__)  
\
+  CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__)
+
+#define CHECK_ALL_COMBINATIONS(__size, ...)
\
+  CHECK_TO_ALL_TYPES(__size, double, __VA_ARGS__)  
\
+  CHECK_TO_ALL_TYPES(__size, float, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__)
\
+  CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) 
\
+  CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
+
+CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
+CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
+#undef CHECK_ALL_COMBINATIONS
+#undef CHECK_TO_ALL_TYPES
+#undef CHECK_NUM
+
+// Shuffle vector
+vector4int const vector4intConst1 = {0, 1, 2, 3};
+vector4int const vector4intConst2 = {4, 5, 6, 7};
+vector8int const vector8intConst = {};
+
+vector4int vectorShuffle1 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 1, 2, 3);
+vector4int vectorShuffle2 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 4, 5, 6, 7);
+vector4int vectorShuffle3 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, -1, -1, -1, 
-1);
+vector4int vectorShuffle4 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6);
+vector8int vectorShuffle5 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
+vector4int vectorShuffle6 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6);
+vector8int vectorShuffle7 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6, 1, 
3, 5, 7);

Destroyerrrocket wrote:

You're right! we can indeed make something like:
constexpr vector4char v = {1,2,3,4};
static_assert(std::bit_cast(v) == 0x4030201, "equal");
I had initially dismissed this as the operator[] is not implemented for 
vectors. This is endian dependent, is there a particular way I should handle 
this?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Pol M via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  SmallVector ResultElements;
+  ResultElements.reserve(Source.getVectorLength());
+  for (unsigned EltNum = 0; EltNum < Source.getVectorLength(); ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info)) {
+return false;
+  }
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2) {
+index = 0;
+  }

Destroyerrrocket wrote:

If there is, I unfortunately don't know how...

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  SmallVector ResultElements;
+  ResultElements.reserve(Source.getVectorLength());
+  for (unsigned EltNum = 0; EltNum < Source.getVectorLength(); ++EltNum) {

RKSimon wrote:

Pull out repeated Source.getVectorLength() calls?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -302,3 +302,64 @@ extern __typeof__(__builtin_expect(0, 0)) bi0;
 // Strings
 int array1[__builtin_strlen("ab\0cd")];
 int array2[(sizeof(array1)/sizeof(int)) == 2? 1 : -1];
+
+typedef double vector4double __attribute__((__vector_size__(32)));
+typedef float vector4float __attribute__((__vector_size__(16)));
+typedef long long vector4long __attribute__((__vector_size__(32)));
+typedef int vector4int __attribute__((__vector_size__(16)));
+typedef short vector4short __attribute__((__vector_size__(8)));
+typedef char vector4char __attribute__((__vector_size__(4)));
+typedef double vector8double __attribute__((__vector_size__(64)));
+typedef float vector8float __attribute__((__vector_size__(32)));
+typedef long long vector8long __attribute__((__vector_size__(64)));
+typedef int vector8int __attribute__((__vector_size__(32)));
+typedef short vector8short __attribute__((__vector_size__(16)));
+typedef char vector8char __attribute__((__vector_size__(8)));
+
+// Convert vector
+#define CHECK_NUM(__size, __typeFrom, __typeTo, ...)   
 \
+  vector##__size##__typeTo 
 \
+  from_##vector##__size##__typeFrom##_to_##vector##__size##__typeTo##_var 
= \
+  __builtin_convertvector((vector##__size##__typeFrom){__VA_ARGS__},   
 \
+  vector##__size##__typeTo);
+#define CHECK_TO_ALL_TYPES(__size, __typeFrom, ...)
\
+  CHECK_NUM(__size, __typeFrom, double, __VA_ARGS__)   
\
+  CHECK_NUM(__size, __typeFrom, float, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, long, __VA_ARGS__) 
\
+  CHECK_NUM(__size, __typeFrom, int, __VA_ARGS__)  
\
+  CHECK_NUM(__size, __typeFrom, short, __VA_ARGS__)
\
+  CHECK_NUM(__size, __typeFrom, char, __VA_ARGS__)
+
+#define CHECK_ALL_COMBINATIONS(__size, ...)
\
+  CHECK_TO_ALL_TYPES(__size, double, __VA_ARGS__)  
\
+  CHECK_TO_ALL_TYPES(__size, float, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, long, __VA_ARGS__)
\
+  CHECK_TO_ALL_TYPES(__size, int, __VA_ARGS__) 
\
+  CHECK_TO_ALL_TYPES(__size, short, __VA_ARGS__)   
\
+  CHECK_TO_ALL_TYPES(__size, char, __VA_ARGS__)
+
+CHECK_ALL_COMBINATIONS(4, 0, 1, 2, 3);
+CHECK_ALL_COMBINATIONS(8, 0, 1, 2, 3, 4, 5, 6, 7);
+#undef CHECK_ALL_COMBINATIONS
+#undef CHECK_TO_ALL_TYPES
+#undef CHECK_NUM
+
+// Shuffle vector
+vector4int const vector4intConst1 = {0, 1, 2, 3};
+vector4int const vector4intConst2 = {4, 5, 6, 7};
+vector8int const vector8intConst = {};
+
+vector4int vectorShuffle1 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 1, 2, 3);
+vector4int vectorShuffle2 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 4, 5, 6, 7);
+vector4int vectorShuffle3 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, -1, -1, -1, 
-1);
+vector4int vectorShuffle4 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6);
+vector8int vectorShuffle5 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
+vector4int vectorShuffle6 = __builtin_shufflevector(
+vector8intConst, vector8intConst, 0, 2, 4, 6);
+vector8int vectorShuffle7 =
+__builtin_shufflevector(vector4intConst1, vector4intConst2, 0, 2, 4, 6, 1, 
3, 5, 7);

RKSimon wrote:

What could we do to check the result values of the constant expression? Could 
we bitcast a char4 to a uint value and static assert the result for instance?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits

https://github.com/RKSimon commented:

A few minors but a frontend specialist really needs to review this

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  SmallVector ResultElements;
+  ResultElements.reserve(Source.getVectorLength());
+  for (unsigned EltNum = 0; EltNum < Source.getVectorLength(); ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info)) {
+return false;
+  }
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2) {
+index = 0;
+  }
+
+  if (index >= TotalElementsInAVector) {
+Result = VecVal2.getVectorElt(index - TotalElementsInAVector);
+  } else {
+Result = VecVal1.getVectorElt(index);
+  }
+  return true;
+}
+
+bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
+  APValue VecVal1;
+  const Expr *Vec1 = E->getExpr(0);
+  if (!EvaluateVectorOrLValue(VecVal1, Info, Vec1, Vec1->getType()))
+return false;
+  APValue VecVal2;
+  const Expr *Vec2 = E->getExpr(1);
+  if (!EvaluateVectorOrLValue(VecVal2, Info, Vec2, Vec2->getType()))
+return false;
+
+  VectorType const *DestVecTy = E->getType()->castAs();
+  if (!DestVecTy) {
+return false;
+  }

RKSimon wrote:

(style) unnecessary braces

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  SmallVector ResultElements;
+  ResultElements.reserve(Source.getVectorLength());
+  for (unsigned EltNum = 0; EltNum < Source.getVectorLength(); ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info)) {
+return false;
+  }
+
+  uint32_t index = IndexVal.getZExtValue();
+  // The spec says that -1 should be treated as undef for optimizations,
+  // but in constexpr we need to choose a value. We'll choose 0.
+  if (index >= TotalElementsInAVector * 2) {
+index = 0;
+  }

RKSimon wrote:

Is there any chance we can retain the undef? Could we insert an undef element?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;

RKSimon wrote:

Just use `return Result.isVector()` ?

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits

https://github.com/RKSimon edited 
https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2024-01-01 Thread Simon Pilgrim via cfe-commits


@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = Original;
+  return HandleFloatToFloatCast(Info, E, SourceTy, DestTy,
+Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(APSInt());
+  return HandleFloatToIntCast(Info, E, SourceTy, Original.getFloat(),
+  DestTy, Result.getInt());
+}
+  }
+  return false;
+}
+
+bool VectorExprEvaluator::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
+  APValue Source;
+  QualType SourceVecType = E->getSrcExpr()->getType();
+  if (!EvaluateVectorOrLValue(Source, Info, E->getSrcExpr(), SourceVecType))
+return false;
+
+  QualType DestTy = E->getType()->castAs()->getElementType();
+  QualType SourceTy = SourceVecType->castAs()->getElementType();
+
+  const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+  SmallVector ResultElements;
+  ResultElements.reserve(Source.getVectorLength());
+  for (unsigned EltNum = 0; EltNum < Source.getVectorLength(); ++EltNum) {
+APValue Elt;
+if (!handleVectorConversion(Info, FPO, E, SourceTy, DestTy,
+Source.getVectorElt(EltNum), Elt))
+  return false;
+ResultElements.push_back(std::move(Elt));
+  }
+
+  return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+}
+
+static bool handleVectorShuffle(EvalInfo , const ShuffleVectorExpr *E,
+QualType ElemType, APValue const ,
+APValue const , unsigned EltNum,
+APValue ) {
+  unsigned const TotalElementsInAVector = VecVal1.getVectorLength();
+
+  Expr const *IndexExpr = E->getExpr(2 + EltNum);
+  APSInt IndexVal;
+  if (!EvaluateInteger(IndexExpr, IndexVal, Info)) {
+return false;
+  }

RKSimon wrote:

(style) unnecessary braces

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2023-12-30 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Pol M (Destroyerrrocket)


Changes

Summary:

This patch adds constexpr support for __builtin_shufflevector and 
__builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an lvalue 
without any sort of implicit cast of any kind. I solved this through the 
EvaluateVectorOrLValue function, which treats the lvalue as if it was in an 
rvalue cast, which gets me the desired vector.

---
Full diff: https://github.com/llvm/llvm-project/pull/76615.diff


4 Files Affected:

- (modified) clang/docs/LanguageExtensions.rst (+3-2) 
- (modified) clang/docs/ReleaseNotes.rst (+2) 
- (modified) clang/lib/AST/ExprConstant.cpp (+137-1) 
- (modified) clang/test/Sema/constant-builtins-2.c (+61) 


``diff
diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+   QualType DestTy, APValue const ,
+   APValue ) {
+  if (SourceTy->isIntegerType()) {
+if (DestTy->isRealFloatingType()) {
+  Result = APValue(APFloat(0.0));
+  return HandleIntToFloatCast(Info, E, FPO, SourceTy, Original.getInt(),
+  DestTy, Result.getFloat());
+}
+if (DestTy->isIntegerType()) {
+  Result = APValue(
+  HandleIntToIntCast(Info, E, DestTy, SourceTy, Original.getInt()));
+  return true;
+}
+  } else if (SourceTy->isRealFloatingType()) {
+if 

[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2023-12-30 Thread via cfe-commits

github-actions[bot] wrote:

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be
notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write
permissions for the repository. In which case you can instead tag reviewers by
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review
by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate
is once a week. Please remember that you are asking for valuable time from 
other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/76615
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)

2023-12-30 Thread Pol M via cfe-commits

https://github.com/Destroyerrrocket created 
https://github.com/llvm/llvm-project/pull/76615

Summary:

This patch adds constexpr support for __builtin_shufflevector and 
__builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an lvalue 
without any sort of implicit cast of any kind. I solved this through the 
EvaluateVectorOrLValue function, which treats the lvalue as if it was in an 
rvalue cast, which gets me the desired vector.

>From cba67a73ea1e59eb8eeb4e702d77f329028f4c22 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pol=20Marcet=20Sard=C3=A0?= 
Date: Sat, 30 Dec 2023 13:59:00 +0100
Subject: [PATCH] [clang] Constexpr for __builtin_shufflevector and
 __builtin_convertvector

Summary:

This patch adds constexpr support for __builtin_shufflevector
and __builtin_convertvector.

A small oddity encountered was that the arg to the intrinsics may be an
lvalue without any sort of implicit cast of any kind. I solved this
through the EvaluateVectorOrLValue function, which treats the lvalue as
if it was in an rvalue cast, which gets me the desired vector.
---
 clang/docs/LanguageExtensions.rst |   5 +-
 clang/docs/ReleaseNotes.rst   |   2 +
 clang/lib/AST/ExprConstant.cpp| 138 +-
 clang/test/Sema/constant-builtins-2.c |  61 
 4 files changed, 203 insertions(+), 3 deletions(-)

diff --git a/clang/docs/LanguageExtensions.rst 
b/clang/docs/LanguageExtensions.rst
index 23a7f4f5d5b926..5f06c3d4b86f94 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2853,7 +2853,7 @@ Query for this feature with 
``__has_builtin(__builtin_dump_struct)``
 ``__builtin_shufflevector`` is used to express generic vector
 permutation/shuffle/swizzle operations.  This builtin is also very important
 for the implementation of various target-specific header files like
-.
+. This builtin can be used within constant expressions.
 
 **Syntax**:
 
@@ -2907,7 +2907,8 @@ Query for this feature with 
``__has_builtin(__builtin_shufflevector)``.
 
 ``__builtin_convertvector`` is used to express generic vector
 type-conversion operations. The input vector and the output vector
-type must have the same number of elements.
+type must have the same number of elements. This builtin can be used within
+constant expressions.
 
 **Syntax**:
 
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0c8fec691bf3c9..b6f1407436ed4f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -237,6 +237,8 @@ Non-comprehensive list of changes in this release
 * Since MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``, this 
release adds the attribute as well.
 
 * Added ``#pragma clang fp reciprocal``.
+* Builtins ``__builtin_shufflevector()`` and ``__builtin_convertvector()`` may 
now be used within constant
+ expressions.
 
 New Compiler Flags
 --
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index f6aeee1a4e935d..e8afa10fe7aaac 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2702,7 +2702,8 @@ static bool checkFloatingPointResult(EvalInfo , 
const Expr *E,
 static bool HandleFloatToFloatCast(EvalInfo , const Expr *E,
QualType SrcType, QualType DestType,
APFloat ) {
-  assert(isa(E) || isa(E));
+  assert(isa(E) || isa(E) ||
+ isa(E));
   llvm::RoundingMode RM = getActiveRoundingMode(Info, E);
   APFloat::opStatus St;
   APFloat Value = Result;
@@ -10643,6 +10644,9 @@ namespace {
 bool VisitUnaryImag(const UnaryOperator *E);
 bool VisitBinaryOperator(const BinaryOperator *E);
 bool VisitUnaryOperator(const UnaryOperator *E);
+bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
+bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
+
 // FIXME: Missing: conditional operator (for GNU
 // conditional select), shufflevector, ExtVectorElementExpr
   };
@@ -10895,6 +10899,138 @@ bool VectorExprEvaluator::VisitUnaryOperator(const 
UnaryOperator *E) {
   return Success(APValue(ResultElements.data(), ResultElements.size()), E);
 }
 
+static bool EvaluateVectorOrLValue(APValue , EvalInfo ,
+   const Expr *E, const QualType ) {
+  if (!Evaluate(Result, Info, E))
+return false;
+
+  if (Result.isLValue()) {
+// Source of the data is an lvalue; Manually handle the lvalue as if
+// it was an rvalue to get the current APValue.
+LValue LValueFound;
+LValueFound.setFrom(Info.Ctx, Result);
+if (!handleLValueToRValueConversion(Info, E, Type, LValueFound, Result)) {
+  return false;
+}
+  }
+
+  if (!Result.isVector()) {
+return false;
+  }
+  return true;
+}
+
+static bool handleVectorConversion(EvalInfo , const FPOptions FPO,
+   const Expr *E, QualType SourceTy,
+