Timm =?utf-8?q?Bäder?= <tbae...@redhat.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/147...@github.com>
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/147892 >From 8cfa60433b285accc0fb58531ad9ee5c74fe46d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 10 Jul 2025 07:25:15 +0200 Subject: [PATCH 1/2] [clang][bytecode] Implement missing elementwise builtins --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 108 ++++++++++++++++++- clang/test/Sema/constant_builtins_vector.cpp | 4 + 2 files changed, 107 insertions(+), 5 deletions(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 1fe6d146b511d..a7f88ac01f300 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SipHash.h" namespace clang { @@ -1673,6 +1674,12 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, (void)T::bitOr(Result, Elem, BitWidth, &Result); } else if (ID == Builtin::BI__builtin_reduce_xor) { (void)T::bitXor(Result, Elem, BitWidth, &Result); + } else if (ID == Builtin::BI__builtin_reduce_min) { + if (Elem < Result) + Result = Elem; + } else if (ID == Builtin::BI__builtin_reduce_max) { + if (Elem > Result) + Result = Elem; } else { llvm_unreachable("Unhandled vector reduce builtin"); } @@ -1686,12 +1693,18 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, /// Can be called with an integer or vector as the first and only parameter. static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, - const CallExpr *Call) { + const CallExpr *Call, + unsigned BuiltinID) { assert(Call->getNumArgs() == 1); if (Call->getArg(0)->getType()->isIntegerType()) { PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); APSInt Val = popToAPSInt(S.Stk, ArgT); - pushInteger(S, Val.popcount(), Call->getType()); + + if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) { + pushInteger(S, Val.popcount(), Call->getType()); + } else { + pushInteger(S, Val.reverseBits(), Call->getType()); + } return true; } // Otherwise, the argument must be a vector. @@ -1710,8 +1723,13 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, // FIXME: Reading from uninitialized vector elements? for (unsigned I = 0; I != NumElems; ++I) { INT_TYPE_SWITCH_NO_BOOL(ElemT, { - Dst.atIndex(I).deref<T>() = - T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); + if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) { + Dst.atIndex(I).deref<T>() = + T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); + } else { + Dst.atIndex(I).deref<T>() = T::from( + Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue()); + } Dst.atIndex(I).initialize(); }); } @@ -2234,6 +2252,78 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, + const CallExpr *Call, + unsigned BuiltinID) { + Call->dumpColor(); + assert(Call->getNumArgs() == 2); + + // Single integer case. + if (!Call->getArg(0)->getType()->isVectorType()) { + assert(!Call->getArg(1)->getType()->isVectorType()); + APSInt RHS = popToAPSInt( + S.Stk, *S.getContext().classify(Call->getArg(1)->getType())); + APSInt LHS = popToAPSInt( + S.Stk, *S.getContext().classify(Call->getArg(0)->getType())); + APInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) { + Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS); + } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) { + Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS); + } else { + llvm_unreachable("Wrong builtin ID"); + } + + pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType()); + return true; + } + + // Vector case. + assert(Call->getArg(0)->getType()->isVectorType() && + Call->getArg(1)->getType()->isVectorType()); + const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>(); + assert(VT->getElementType() == + Call->getArg(1)->getType()->castAs<VectorType>()->getElementType()); + assert(VT->getNumElements() == + Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements()); + assert(VT->getElementType()->isIntegralOrEnumerationType()); + + const Pointer &RHS = S.Stk.pop<Pointer>(); + const Pointer &LHS = S.Stk.pop<Pointer>(); + const Pointer &Dst = S.Stk.peek<Pointer>(); + PrimType ElemT = *S.getContext().classify(VT->getElementType()); + unsigned NumElems = VT->getNumElements(); + for (unsigned I = 0; I != NumElems; ++I) { + APSInt Elem1; + APSInt Elem2; + INT_TYPE_SWITCH_NO_BOOL(ElemT, { + Elem1 = LHS.atIndex(I).deref<T>().toAPSInt(); + Elem2 = RHS.atIndex(I).deref<T>().toAPSInt(); + }); + + APSInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) { + Result = APSInt(Elem1.isSigned() ? Elem1.sadd_sat(Elem2) + : Elem2.uadd_sat(Elem2), + Call->getType()->isUnsignedIntegerOrEnumerationType()); + } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) { + Result = APSInt(Elem1.isSigned() ? Elem1.ssub_sat(Elem2) + : Elem2.usub_sat(Elem2), + Call->getType()->isUnsignedIntegerOrEnumerationType()); + } else { + llvm_unreachable("Wrong builtin ID"); + } + + INT_TYPE_SWITCH_NO_BOOL(ElemT, { + const Pointer &E = Dst.atIndex(I); + E.deref<T>() = static_cast<T>(Result); + E.initialize(); + }); + } + + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID) { if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID)) @@ -2592,10 +2682,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case Builtin::BI__builtin_reduce_and: case Builtin::BI__builtin_reduce_or: case Builtin::BI__builtin_reduce_xor: + case Builtin::BI__builtin_reduce_min: + case Builtin::BI__builtin_reduce_max: return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID); case Builtin::BI__builtin_elementwise_popcount: - return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call); + case Builtin::BI__builtin_elementwise_bitreverse: + return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call, + BuiltinID); case Builtin::BI__builtin_memcpy: case Builtin::BImemcpy: @@ -2633,6 +2727,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case Builtin::BI__builtin_is_within_lifetime: return interp__builtin_is_within_lifetime(S, OpPC, Call); + case Builtin::BI__builtin_elementwise_add_sat: + case Builtin::BI__builtin_elementwise_sub_sat: + return interp__builtin_elementwise_sat(S, OpPC, Call, BuiltinID); + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp index 8659fa9e46612..f26dfb25d49b9 100644 --- a/clang/test/Sema/constant_builtins_vector.cpp +++ b/clang/test/Sema/constant_builtins_vector.cpp @@ -2,6 +2,10 @@ // RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64-unknown-linux %s // RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64le-unknown-linux %s +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64-unknown-linux %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -verify -std=c++2a -fsyntax-only -Wno-bit-int-extension -triple ppc64le-unknown-linux %s -fexperimental-new-constant-interpreter + #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ #define LITTLE_END 1 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ >From e23839533f3eb15b8f53a4d67ff0a809d2c260f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Thu, 10 Jul 2025 07:29:18 +0200 Subject: [PATCH 2/2] Tentatively fix #147891 --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index a7f88ac01f300..de0b97fd93c76 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2304,11 +2304,11 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, APSInt Result; if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) { Result = APSInt(Elem1.isSigned() ? Elem1.sadd_sat(Elem2) - : Elem2.uadd_sat(Elem2), + : Elem1.uadd_sat(Elem2), Call->getType()->isUnsignedIntegerOrEnumerationType()); } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) { Result = APSInt(Elem1.isSigned() ? Elem1.ssub_sat(Elem2) - : Elem2.usub_sat(Elem2), + : Elem1.usub_sat(Elem2), Call->getType()->isUnsignedIntegerOrEnumerationType()); } else { llvm_unreachable("Wrong builtin ID"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits