[clang] c1dcf75 - [clang][bytecode] Implement __builtin_reduce_mul (#118287)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 2 05:03:57 PST 2024


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 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