Skip to content

Commit 31bde71

Browse files
authored
[clang][bytecode] Support __builtin_reduce_add (#117672)
1 parent 82ed9c0 commit 31bde71

File tree

2 files changed

+91
-2
lines changed

2 files changed

+91
-2
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,14 @@ static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
8989
std::optional<PrimType> T = S.getContext().classify(QT);
9090
assert(T);
9191

92+
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
9293
if (QT->isSignedIntegerOrEnumerationType()) {
9394
int64_t V = Val.getSExtValue();
94-
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
95+
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
9596
} else {
9697
assert(QT->isUnsignedIntegerOrEnumerationType());
9798
uint64_t V = Val.getZExtValue();
98-
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
99+
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
99100
}
100101
}
101102

@@ -137,6 +138,8 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC,
137138
RET_CASE(PT_Uint32);
138139
RET_CASE(PT_Sint64);
139140
RET_CASE(PT_Uint64);
141+
RET_CASE(PT_IntAP);
142+
RET_CASE(PT_IntAPS);
140143
default:
141144
llvm_unreachable("Unsupported return type for builtin function");
142145
}
@@ -1684,6 +1687,42 @@ static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,
16841687
return true;
16851688
}
16861689

1690+
static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1691+
const InterpFrame *Frame,
1692+
const Function *Func,
1693+
const CallExpr *Call) {
1694+
const Pointer &Arg = S.Stk.peek<Pointer>();
1695+
assert(Arg.getFieldDesc()->isPrimitiveArray());
1696+
1697+
unsigned ID = Func->getBuiltinID();
1698+
if (ID == Builtin::BI__builtin_reduce_add) {
1699+
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1700+
assert(Call->getType() == ElemType);
1701+
PrimType ElemT = *S.getContext().classify(ElemType);
1702+
unsigned NumElems = Arg.getNumElems();
1703+
1704+
INT_TYPE_SWITCH(ElemT, {
1705+
T Sum = Arg.atIndex(0).deref<T>();
1706+
unsigned BitWidth = Sum.bitWidth();
1707+
for (unsigned I = 1; I != NumElems; ++I) {
1708+
T Elem = Arg.atIndex(I).deref<T>();
1709+
if (T::add(Sum, Elem, BitWidth, &Sum)) {
1710+
unsigned OverflowBits = BitWidth + 1;
1711+
(void)handleOverflow(
1712+
S, OpPC,
1713+
(Sum.toAPSInt(OverflowBits) + Elem.toAPSInt(OverflowBits)));
1714+
return false;
1715+
}
1716+
}
1717+
pushInteger(S, Sum, Call->getType());
1718+
});
1719+
1720+
return true;
1721+
}
1722+
1723+
llvm_unreachable("Unsupported vector reduce builtin");
1724+
}
1725+
16871726
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
16881727
const CallExpr *Call, uint32_t BuiltinID) {
16891728
const InterpFrame *Frame = S.Current;
@@ -2129,6 +2168,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
21292168
return false;
21302169
break;
21312170

2171+
case Builtin::BI__builtin_reduce_add:
2172+
if (!interp__builtin_vector_reduce(S, OpPC, Frame, F, Call))
2173+
return false;
2174+
break;
2175+
21322176
default:
21332177
S.FFDiag(S.Current->getLocation(OpPC),
21342178
diag::note_invalid_subexpr_in_const_expr)

clang/test/AST/ByteCode/builtin-functions.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,3 +990,48 @@ namespace BuiltinInImplicitCtor {
990990
} Foo;
991991
static_assert(Foo.a == 0, "");
992992
}
993+
994+
995+
typedef double vector4double __attribute__((__vector_size__(32)));
996+
typedef float vector4float __attribute__((__vector_size__(16)));
997+
typedef long long vector4long __attribute__((__vector_size__(32)));
998+
typedef int vector4int __attribute__((__vector_size__(16)));
999+
typedef unsigned long long vector4ulong __attribute__((__vector_size__(32)));
1000+
typedef unsigned int vector4uint __attribute__((__vector_size__(16)));
1001+
typedef short vector4short __attribute__((__vector_size__(8)));
1002+
typedef char vector4char __attribute__((__vector_size__(4)));
1003+
typedef double vector8double __attribute__((__vector_size__(64)));
1004+
typedef float vector8float __attribute__((__vector_size__(32)));
1005+
typedef long long vector8long __attribute__((__vector_size__(64)));
1006+
typedef int vector8int __attribute__((__vector_size__(32)));
1007+
typedef short vector8short __attribute__((__vector_size__(16)));
1008+
typedef char vector8char __attribute__((__vector_size__(8)));
1009+
1010+
namespace RecuceAdd {
1011+
static_assert(__builtin_reduce_add((vector4char){}) == 0);
1012+
static_assert(__builtin_reduce_add((vector4char){1, 2, 3, 4}) == 10);
1013+
static_assert(__builtin_reduce_add((vector4short){10, 20, 30, 40}) == 100);
1014+
static_assert(__builtin_reduce_add((vector4int){100, 200, 300, 400}) == 1000);
1015+
static_assert(__builtin_reduce_add((vector4long){1000, 2000, 3000, 4000}) == 10000);
1016+
constexpr int reduceAddInt1 = __builtin_reduce_add((vector4int){~(1 << (sizeof(int) * 8 - 1)), 0, 0, 1});
1017+
// both-error@-1 {{must be initialized by a constant expression}} \
1018+
// both-note@-1 {{outside the range of representable values of type 'int'}}
1019+
constexpr long long reduceAddLong1 = __builtin_reduce_add((vector4long){~(1LL << (sizeof(long long) * 8 - 1)), 0, 0, 1});
1020+
// both-error@-1 {{must be initialized by a constant expression}} \
1021+
// both-note@-1 {{outside the range of representable values of type 'long long'}}
1022+
constexpr int reduceAddInt2 = __builtin_reduce_add((vector4int){(1 << (sizeof(int) * 8 - 1)), 0, 0, -1});
1023+
// both-error@-1 {{must be initialized by a constant expression}} \
1024+
// both-note@-1 {{outside the range of representable values of type 'int'}}
1025+
constexpr long long reduceAddLong2 = __builtin_reduce_add((vector4long){(1LL << (sizeof(long long) * 8 - 1)), 0, 0, -1});
1026+
// both-error@-1 {{must be initialized by a constant expression}} \
1027+
// both-note@-1 {{outside the range of representable values of type 'long long'}}
1028+
static_assert(__builtin_reduce_add((vector4uint){~0U, 0, 0, 1}) == 0);
1029+
static_assert(__builtin_reduce_add((vector4ulong){~0ULL, 0, 0, 1}) == 0);
1030+
1031+
1032+
#ifdef __SIZEOF_INT128__
1033+
typedef __int128 v4i128 __attribute__((__vector_size__(128 * 2)));
1034+
constexpr __int128 reduceAddInt3 = __builtin_reduce_add((v4i128){});
1035+
static_assert(reduceAddInt3 == 0);
1036+
#endif
1037+
}

0 commit comments

Comments
 (0)