[clang] [clang] Constexpr for __builtin_shufflevector and __builtin_convertvector (PR #76615)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 15 11:52:42 PST 2024
Pol Marcet =?utf-8?q?Sardà ?= <polmarcetsarda at gmail.com>,
Pol Marcet =?utf-8?q?Sardà ?= <polmarcetsarda at gmail.com>,Pol M
<polmarcetsarda at gmail.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/76615 at github.com>
================
@@ -10895,6 +10899,132 @@ bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+static bool EvaluateVectorOrLValue(APValue &Result, EvalInfo &Info,
+ const Expr *E, const QualType &Type) {
+ 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 &Info, const FPOptions FPO,
+ const Expr *E, QualType SourceTy,
+ QualType DestTy, APValue const &Original,
+ APValue &Result) {
+ 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<VectorType>()->getElementType();
+ QualType SourceTy = SourceVecType->castAs<VectorType>()->getElementType();
+
+ const FPOptions FPO = E->getFPFeaturesInEffect(Info.Ctx.getLangOpts());
+
+ auto SourceLen = Source.getVectorLength();
+ SmallVector<APValue, 4> 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 &Info, const ShuffleVectorExpr *E,
+ QualType ElemType, APValue const &VecVal1,
+ APValue const &VecVal2, unsigned EltNum,
+ APValue &Result) {
+ 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
More information about the cfe-commits
mailing list