Timm =?utf-8?q?Bäder?= <tbae...@redhat.com>, Timm =?utf-8?q?Bäder?= <tbae...@redhat.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/158...@github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/158589 >From 1ee924c160f8b369b82fe4baf05a7428c8a10586 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 15 Sep 2025 11:25:28 +0200 Subject: [PATCH 1/3] [clang][ExprConst] Reject unary vector shuffles This is not implemented at compile time and asserts later in codegen, so reject it here. --- clang/lib/AST/ByteCode/Compiler.cpp | 4 ++ clang/lib/AST/ExprConstant.cpp | 3 ++ clang/lib/Sema/SemaChecking.cpp | 43 ++++++++++---------- clang/test/Sema/constant-builtins-vector.cpp | 13 ++++++ 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 78b74acc3789d..99f4bfbea973d 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -3986,6 +3986,10 @@ bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) { template <class Emitter> bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) { + // FIXME: Unary shuffle with mask not currently supported. + if (E->getNumSubExprs() == 2) + return this->emitInvalid(E); + assert(Initializing); assert(E->getNumSubExprs() > 2); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 820b053057067..f80691f57e602 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12160,6 +12160,9 @@ static bool handleVectorShuffle(EvalInfo &Info, const ShuffleVectorExpr *E, } bool VectorExprEvaluator::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) { + // FIXME: Unary shuffle with mask not currently supported. + if (E->getNumSubExprs() == 2) + return Error(E); APValue VecVal1; const Expr *Vec1 = E->getExpr(0); if (!EvaluateAsRValue(Info, Vec1, VecVal1)) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 077f4311ed729..446d3ceb1b45e 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5558,7 +5558,8 @@ bool Sema::BuiltinComplex(CallExpr *TheCall) { /// BuiltinShuffleVector - Handle __builtin_shufflevector. // This is declared to take (...), so we have to check everything. ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { - if (TheCall->getNumArgs() < 2) + unsigned NumArgs = TheCall->getNumArgs(); + if (NumArgs < 2) return ExprError(Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) << 0 /*function call*/ << 2 << TheCall->getNumArgs() @@ -5567,8 +5568,8 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { // Determine which of the following types of shufflevector we're checking: // 1) unary, vector mask: (lhs, mask) // 2) binary, scalar mask: (lhs, rhs, index, ..., index) - QualType resType = TheCall->getArg(0)->getType(); - unsigned numElements = 0; + QualType ResType = TheCall->getArg(0)->getType(); + unsigned NumElements = 0; if (!TheCall->getArg(0)->isTypeDependent() && !TheCall->getArg(1)->isTypeDependent()) { @@ -5582,39 +5583,39 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { << SourceRange(TheCall->getArg(0)->getBeginLoc(), TheCall->getArg(1)->getEndLoc())); - numElements = LHSType->castAs<VectorType>()->getNumElements(); - unsigned numResElements = TheCall->getNumArgs() - 2; + NumElements = LHSType->castAs<VectorType>()->getNumElements(); + unsigned NumResElements = TheCall->getNumArgs() - 2; // Check to see if we have a call with 2 vector arguments, the unary shuffle // with mask. If so, verify that RHS is an integer vector type with the // same number of elts as lhs. if (TheCall->getNumArgs() == 2) { if (!RHSType->hasIntegerRepresentation() || - RHSType->castAs<VectorType>()->getNumElements() != numElements) + RHSType->castAs<VectorType>()->getNumElements() != NumElements) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector) << TheCall->getDirectCallee() - << /*isMorethantwoArgs*/ false + << /*isMoreThanTwoArgs*/ false << SourceRange(TheCall->getArg(1)->getBeginLoc(), TheCall->getArg(1)->getEndLoc())); } else if (!Context.hasSameUnqualifiedType(LHSType, RHSType)) { return ExprError(Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_incompatible_vector) << TheCall->getDirectCallee() - << /*isMorethantwoArgs*/ false + << /*isMoreThanTwoArgs*/ false << SourceRange(TheCall->getArg(0)->getBeginLoc(), TheCall->getArg(1)->getEndLoc())); - } else if (numElements != numResElements) { + } else if (NumElements != NumResElements) { QualType eltType = LHSType->castAs<VectorType>()->getElementType(); - resType = resType->isExtVectorType() - ? Context.getExtVectorType(eltType, numResElements) - : Context.getVectorType(eltType, numResElements, + ResType = ResType->isExtVectorType() + ? Context.getExtVectorType(eltType, NumResElements) + : Context.getVectorType(eltType, NumResElements, VectorKind::Generic); } } - for (unsigned i = 2; i < TheCall->getNumArgs(); i++) { - Expr *Arg = TheCall->getArg(i); + for (unsigned I = 2; I != NumArgs; ++I) { + Expr *Arg = TheCall->getArg(I); if (Arg->isTypeDependent() || Arg->isValueDependent()) continue; @@ -5628,21 +5629,21 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { if (Result->isSigned() && Result->isAllOnes()) ; else if (Result->getActiveBits() > 64 || - Result->getZExtValue() >= numElements * 2) + Result->getZExtValue() >= NumElements * 2) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_argument_too_large) << Arg->getSourceRange()); - TheCall->setArg(i, ConstantExpr::Create(Context, Arg, APValue(*Result))); + TheCall->setArg(I, ConstantExpr::Create(Context, Arg, APValue(*Result))); } - SmallVector<Expr *> exprs; - for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; i++) { - exprs.push_back(TheCall->getArg(i)); - TheCall->setArg(i, nullptr); + SmallVector<Expr *> Exprs; + for (unsigned I = 0; I != NumArgs; I++) { + Exprs.push_back(TheCall->getArg(I)); + TheCall->setArg(I, nullptr); } - return new (Context) ShuffleVectorExpr(Context, exprs, resType, + return new (Context) ShuffleVectorExpr(Context, Exprs, ResType, TheCall->getCallee()->getBeginLoc(), TheCall->getRParenLoc()); } diff --git a/clang/test/Sema/constant-builtins-vector.cpp b/clang/test/Sema/constant-builtins-vector.cpp index 714a7fb753214..455284ef65e9b 100644 --- a/clang/test/Sema/constant-builtins-vector.cpp +++ b/clang/test/Sema/constant-builtins-vector.cpp @@ -731,6 +731,19 @@ permitted in a constexpr context}} vector4charConst1, vector4charConst2, -1, -1, -1, -1); +namespace UnaryShuffleUnsupported { + typedef int vi6 __attribute__((ext_vector_type(2))); + constexpr int foo() { // expected-error {{never produces a constant expression}} + vi6 a = {1,2}; + vi6 b = {3,4}; + vi6 r = __builtin_shufflevector(a, b); // expected-note 2{{subexpression not valid in a constant expression}} + + return r[0] + r[1]; + } + static_assert(foo() == 0); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} +} + static_assert(__builtin_reduce_add((vector4char){}) == 0); static_assert(__builtin_reduce_add((vector4char){1, 2, 3, 4}) == 10); static_assert(__builtin_reduce_add((vector4short){10, 20, 30, 40}) == 100); >From cef3544a5b8dba143e17d1e9b8b089e8337dae80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 15 Sep 2025 12:40:16 +0200 Subject: [PATCH 2/3] A few more things --- clang/lib/Sema/SemaChecking.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 446d3ceb1b45e..923d8b0d0832c 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5562,7 +5562,7 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { if (NumArgs < 2) return ExprError(Diag(TheCall->getEndLoc(), diag::err_typecheck_call_too_few_args_at_least) - << 0 /*function call*/ << 2 << TheCall->getNumArgs() + << 0 /*function call*/ << 2 << NumArgs << /*is non object*/ 0 << TheCall->getSourceRange()); // Determine which of the following types of shufflevector we're checking: @@ -5579,17 +5579,17 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { if (!LHSType->isVectorType() || !RHSType->isVectorType()) return ExprError( Diag(TheCall->getBeginLoc(), diag::err_vec_builtin_non_vector) - << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ false + << TheCall->getDirectCallee() << /*isMoreThanTwoArgs*/ false << SourceRange(TheCall->getArg(0)->getBeginLoc(), TheCall->getArg(1)->getEndLoc())); NumElements = LHSType->castAs<VectorType>()->getNumElements(); - unsigned NumResElements = TheCall->getNumArgs() - 2; + unsigned NumResElements = NumArgs - 2; // Check to see if we have a call with 2 vector arguments, the unary shuffle // with mask. If so, verify that RHS is an integer vector type with the // same number of elts as lhs. - if (TheCall->getNumArgs() == 2) { + if (NumArgs == 2) { if (!RHSType->hasIntegerRepresentation() || RHSType->castAs<VectorType>()->getNumElements() != NumElements) return ExprError(Diag(TheCall->getBeginLoc(), @@ -5606,10 +5606,10 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { << SourceRange(TheCall->getArg(0)->getBeginLoc(), TheCall->getArg(1)->getEndLoc())); } else if (NumElements != NumResElements) { - QualType eltType = LHSType->castAs<VectorType>()->getElementType(); + QualType EltType = LHSType->castAs<VectorType>()->getElementType(); ResType = ResType->isExtVectorType() - ? Context.getExtVectorType(eltType, NumResElements) - : Context.getVectorType(eltType, NumResElements, + ? Context.getExtVectorType(EltType, NumResElements) + : Context.getVectorType(EltType, NumResElements, VectorKind::Generic); } } >From 6066f474467fbc4bdf20f1946535022fd9c002dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Mon, 15 Sep 2025 13:30:33 +0200 Subject: [PATCH 3/3] Spare the last SmallVector --- clang/lib/Sema/SemaChecking.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 923d8b0d0832c..f62c82e3d214f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5637,15 +5637,13 @@ ExprResult Sema::BuiltinShuffleVector(CallExpr *TheCall) { TheCall->setArg(I, ConstantExpr::Create(Context, Arg, APValue(*Result))); } - SmallVector<Expr *> Exprs; - for (unsigned I = 0; I != NumArgs; I++) { - Exprs.push_back(TheCall->getArg(I)); - TheCall->setArg(I, nullptr); - } + auto *Result = new (Context) ShuffleVectorExpr( + Context, ArrayRef(TheCall->getArgs(), NumArgs), ResType, + TheCall->getCallee()->getBeginLoc(), TheCall->getRParenLoc()); - return new (Context) ShuffleVectorExpr(Context, Exprs, ResType, - TheCall->getCallee()->getBeginLoc(), - TheCall->getRParenLoc()); + // All moved to Result. + TheCall->shrinkNumArgs(0); + return Result; } ExprResult Sema::ConvertVectorExpr(Expr *E, TypeSourceInfo *TInfo, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits