Author: Timm Baeder Date: 2024-12-02T14:03:53+01:00 New Revision: c1dcf75a7cf8840ddf20b622148c4ab0c3b16943
URL: https://github.com/llvm/llvm-project/commit/c1dcf75a7cf8840ddf20b622148c4ab0c3b16943 DIFF: https://github.com/llvm/llvm-project/commit/c1dcf75a7cf8840ddf20b622148c4ab0c3b16943.diff LOG: [clang][bytecode] Implement __builtin_reduce_mul (#118287) Added: Modified: clang/lib/AST/ByteCode/Integral.h clang/lib/AST/ByteCode/InterpBuiltin.cpp clang/test/AST/ByteCode/builtin-functions.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h index ca3674263aef4f..cb81b5a6989240 100644 --- a/clang/lib/AST/ByteCode/Integral.h +++ b/clang/lib/AST/ByteCode/Integral.h @@ -123,7 +123,9 @@ template <unsigned Bits, bool Signed> class Integral final { APSInt toAPSInt() const { return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed); } - APSInt toAPSInt(unsigned BitWidth) const { return APSInt(toAPInt(BitWidth)); } + APSInt toAPSInt(unsigned BitWidth) const { + return APSInt(toAPInt(BitWidth), !Signed); + } APInt toAPInt(unsigned BitWidth) const { if constexpr (Signed) return APInt(Bits, static_cast<uint64_t>(V), Signed) diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 8ede6717db0463..b35b90e55e5155 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1695,32 +1695,42 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, assert(Arg.getFieldDesc()->isPrimitiveArray()); unsigned ID = Func->getBuiltinID(); - if (ID == Builtin::BI__builtin_reduce_add) { - QualType ElemType = Arg.getFieldDesc()->getElemQualType(); - assert(Call->getType() == ElemType); - PrimType ElemT = *S.getContext().classify(ElemType); - unsigned NumElems = Arg.getNumElems(); - - INT_TYPE_SWITCH(ElemT, { - T Sum = Arg.atIndex(0).deref<T>(); - unsigned BitWidth = Sum.bitWidth(); - for (unsigned I = 1; I != NumElems; ++I) { - T Elem = Arg.atIndex(I).deref<T>(); - if (T::add(Sum, Elem, BitWidth, &Sum)) { + QualType ElemType = Arg.getFieldDesc()->getElemQualType(); + assert(Call->getType() == ElemType); + PrimType ElemT = *S.getContext().classify(ElemType); + unsigned NumElems = Arg.getNumElems(); + + INT_TYPE_SWITCH(ElemT, { + T Result = Arg.atIndex(0).deref<T>(); + unsigned BitWidth = Result.bitWidth(); + for (unsigned I = 1; I != NumElems; ++I) { + T Elem = Arg.atIndex(I).deref<T>(); + T PrevResult = Result; + + if (ID == Builtin::BI__builtin_reduce_add) { + if (T::add(Result, Elem, BitWidth, &Result)) { unsigned OverflowBits = BitWidth + 1; - (void)handleOverflow( - S, OpPC, - (Sum.toAPSInt(OverflowBits) + Elem.toAPSInt(OverflowBits))); + (void)handleOverflow(S, OpPC, + (PrevResult.toAPSInt(OverflowBits) + + Elem.toAPSInt(OverflowBits))); return false; } + } else if (ID == Builtin::BI__builtin_reduce_mul) { + if (T::mul(Result, Elem, BitWidth, &Result)) { + unsigned OverflowBits = BitWidth * 2; + (void)handleOverflow(S, OpPC, + (PrevResult.toAPSInt(OverflowBits) * + Elem.toAPSInt(OverflowBits))); + return false; + } + } else { + llvm_unreachable("Unhandled vector reduce builtin"); } - pushInteger(S, Sum, Call->getType()); - }); - - return true; - } + } + pushInteger(S, Result, Call->getType()); + }); - llvm_unreachable("Unsupported vector reduce builtin"); + return true; } static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, @@ -2195,6 +2205,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, break; case Builtin::BI__builtin_reduce_add: + case Builtin::BI__builtin_reduce_mul: if (!interp__builtin_vector_reduce(S, OpPC, Frame, F, Call)) return false; break; diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp index 78b692b819a0ab..e59b7616ac5ab9 100644 --- a/clang/test/AST/ByteCode/builtin-functions.cpp +++ b/clang/test/AST/ByteCode/builtin-functions.cpp @@ -1035,6 +1035,35 @@ namespace RecuceAdd { #endif } +namespace ReduceMul { + static_assert(__builtin_reduce_mul((vector4char){}) == 0); + static_assert(__builtin_reduce_mul((vector4char){1, 2, 3, 4}) == 24); + static_assert(__builtin_reduce_mul((vector4short){1, 2, 30, 40}) == 2400); +#ifndef __AVR__ + static_assert(__builtin_reduce_mul((vector4int){10, 20, 300, 400}) == 24'000'000); +#endif + static_assert(__builtin_reduce_mul((vector4long){1000L, 2000L, 3000L, 4000L}) == 24'000'000'000'000L); + constexpr int reduceMulInt1 = __builtin_reduce_mul((vector4int){~(1 << (sizeof(int) * 8 - 1)), 1, 1, 2}); + // both-error@-1 {{must be initialized by a constant expression}} \ + // both-note@-1 {{outside the range of representable values of type 'int'}} + constexpr long long reduceMulLong1 = __builtin_reduce_mul((vector4long){~(1LL << (sizeof(long long) * 8 - 1)), 1, 1, 2}); + // both-error@-1 {{must be initialized by a constant expression}} \ + // both-note@-1 {{outside the range of representable values of type 'long long'}} + constexpr int reduceMulInt2 = __builtin_reduce_mul((vector4int){(1 << (sizeof(int) * 8 - 1)), 1, 1, 2}); + // both-error@-1 {{must be initialized by a constant expression}} \ + // both-note@-1 {{outside the range of representable values of type 'int'}} + constexpr long long reduceMulLong2 = __builtin_reduce_mul((vector4long){(1LL << (sizeof(long long) * 8 - 1)), 1, 1, 2}); + // both-error@-1 {{must be initialized by a constant expression}} \ + // both-note@-1 {{outside the range of representable values of type 'long long'}} + static_assert(__builtin_reduce_mul((vector4uint){~0U, 1, 1, 2}) == +#ifdef __AVR__ + 0); +#else + (~0U - 1)); +#endif + static_assert(__builtin_reduce_mul((vector4ulong){~0ULL, 1, 1, 2}) == ~0ULL - 1); +} + namespace BuiltinMemcpy { constexpr int simple() { int a = 12; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits