[clang] [clang][bytecode] Implement __builtin_reduce_mul (PR #118287)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 2 04:12:43 PST 2024
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/118287
None
>From 4c5d7a068871216dfa57f03412c2e47b4e58f865 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Mon, 2 Dec 2024 13:11:04 +0100
Subject: [PATCH] [clang][bytecode] Implement __builtin_reduce_mul
---
clang/lib/AST/ByteCode/Integral.h | 4 +-
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 53 +++++++++++--------
clang/test/AST/ByteCode/builtin-functions.cpp | 29 ++++++++++
3 files changed, 64 insertions(+), 22 deletions(-)
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 at -1 {{must be initialized by a constant expression}} \
+ // both-note at -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 at -1 {{must be initialized by a constant expression}} \
+ // both-note at -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 at -1 {{must be initialized by a constant expression}} \
+ // both-note at -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 at -1 {{must be initialized by a constant expression}} \
+ // both-note at -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;
More information about the cfe-commits
mailing list