Skip to content

Commit 45cc6bd

Browse files
committed
[clang][Interp] Implement __builtin_shufflevector
1 parent 6706aeb commit 45cc6bd

File tree

4 files changed

+96
-18
lines changed

4 files changed

+96
-18
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ clang/test/AST/Interp/ @tbaederr
132132
/bolt/ @aaupov @maksfb @rafaelauler @ayermolo @dcci
133133

134134
# Bazel build system.
135-
/utils/bazel/ @rupprecht @keith
135+
/utils/bazel/ @rupprecht
136136

137137
# InstallAPI and TextAPI
138138
/llvm/**/TextAPI/ @cyndyishida

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2531,6 +2531,51 @@ bool ByteCodeExprGen<Emitter>::VisitConvertVectorExpr(
25312531
return true;
25322532
}
25332533

2534+
template <class Emitter>
2535+
bool ByteCodeExprGen<Emitter>::VisitShuffleVectorExpr(
2536+
const ShuffleVectorExpr *E) {
2537+
assert(Initializing);
2538+
assert(E->getNumSubExprs() > 2);
2539+
2540+
const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)};
2541+
assert(Vecs[0]->getType() == Vecs[1]->getType());
2542+
2543+
const VectorType *VT = Vecs[0]->getType()->castAs<VectorType>();
2544+
PrimType ElemT = classifyPrim(VT->getElementType());
2545+
unsigned NumInputElems = VT->getNumElements();
2546+
unsigned NumOutputElems = E->getNumSubExprs() - 2;
2547+
assert(NumOutputElems > 0);
2548+
2549+
// Save both input vectors to a local variable.
2550+
unsigned VectorOffsets[2];
2551+
for (unsigned I = 0; I != 2; ++I) {
2552+
VectorOffsets[I] = this->allocateLocalPrimitive(
2553+
Vecs[I], PT_Ptr, /*IsConst=*/true, /*IsExtended=*/false);
2554+
if (!this->visit(Vecs[I]))
2555+
return false;
2556+
if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))
2557+
return false;
2558+
}
2559+
for (unsigned I = 0; I != NumOutputElems; ++I) {
2560+
APSInt ShuffleIndex = E->getShuffleMaskIdx(Ctx.getASTContext(), I);
2561+
if (ShuffleIndex == -1)
2562+
return this->emitInvalid(E); // FIXME: Better diagnostic.
2563+
2564+
assert(ShuffleIndex < (NumInputElems * 2));
2565+
if (!this->emitGetLocal(PT_Ptr,
2566+
VectorOffsets[ShuffleIndex >= NumInputElems], E))
2567+
return false;
2568+
unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;
2569+
if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))
2570+
return false;
2571+
2572+
if (!this->emitInitElem(ElemT, I, E))
2573+
return false;
2574+
}
2575+
2576+
return true;
2577+
}
2578+
25342579
template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
25352580
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
25362581
/*NewInitializing=*/false);

clang/lib/AST/Interp/ByteCodeExprGen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
124124
bool VisitRecoveryExpr(const RecoveryExpr *E);
125125
bool VisitAddrLabelExpr(const AddrLabelExpr *E);
126126
bool VisitConvertVectorExpr(const ConvertVectorExpr *E);
127+
bool VisitShuffleVectorExpr(const ShuffleVectorExpr *E);
127128

128129
protected:
129130
bool visitExpr(const Expr *E) override;

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

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -644,24 +644,23 @@ static_assert(__builtin_os_log_format_buffer_size("%{mask.xyz}s", "abc") != 0, "
644644
/// Some tests are missing since we run this for multiple targets,
645645
/// some of which do not support _BitInt.
646646
#ifndef __AVR__
647-
namespace convertvector {
648-
typedef _BitInt(128) BitInt128;
649-
650-
typedef double vector4double __attribute__((__vector_size__(32)));
651-
typedef float vector4float __attribute__((__vector_size__(16)));
652-
typedef long long vector4long __attribute__((__vector_size__(32)));
653-
typedef int vector4int __attribute__((__vector_size__(16)));
654-
typedef short vector4short __attribute__((__vector_size__(8)));
655-
typedef char vector4char __attribute__((__vector_size__(4)));
656-
typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64)));
657-
typedef double vector8double __attribute__((__vector_size__(64)));
658-
typedef float vector8float __attribute__((__vector_size__(32)));
659-
typedef long long vector8long __attribute__((__vector_size__(64)));
660-
typedef int vector8int __attribute__((__vector_size__(32)));
661-
typedef short vector8short __attribute__((__vector_size__(16)));
662-
typedef char vector8char __attribute__((__vector_size__(8)));
663-
typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128)));
647+
typedef _BitInt(128) BitInt128;
648+
typedef double vector4double __attribute__((__vector_size__(32)));
649+
typedef float vector4float __attribute__((__vector_size__(16)));
650+
typedef long long vector4long __attribute__((__vector_size__(32)));
651+
typedef int vector4int __attribute__((__vector_size__(16)));
652+
typedef short vector4short __attribute__((__vector_size__(8)));
653+
typedef char vector4char __attribute__((__vector_size__(4)));
654+
typedef BitInt128 vector4BitInt128 __attribute__((__vector_size__(64)));
655+
typedef double vector8double __attribute__((__vector_size__(64)));
656+
typedef float vector8float __attribute__((__vector_size__(32)));
657+
typedef long long vector8long __attribute__((__vector_size__(64)));
658+
typedef int vector8int __attribute__((__vector_size__(32)));
659+
typedef short vector8short __attribute__((__vector_size__(16)));
660+
typedef char vector8char __attribute__((__vector_size__(8)));
661+
typedef BitInt128 vector8BitInt128 __attribute__((__vector_size__(128)));
664662

663+
namespace convertvector {
665664
constexpr vector4double from_vector4double_to_vector4double_var =
666665
__builtin_convertvector((vector4double){0, 1, 2, 3}, vector4double);
667666
constexpr vector4float from_vector4double_to_vector4float_var =
@@ -873,4 +872,37 @@ namespace convertvector {
873872
static_assert(from_vector8BitInt128_to_vector8BitInt128_var[3] == 3, ""); // ref-error {{not an integral constant expression}}
874873
static_assert(from_vector8BitInt128_to_vector8BitInt128_var[4] == 4, ""); // ref-error {{not an integral constant expression}}
875874
}
875+
876+
namespace shufflevector {
877+
constexpr vector4char vector4charConst1 = {0, 1, 2, 3};
878+
constexpr vector4char vector4charConst2 = {4, 5, 6, 7};
879+
constexpr vector8char vector8intConst = {8, 9, 10, 11, 12, 13, 14, 15};
880+
constexpr vector4char vectorShuffle1 =
881+
__builtin_shufflevector(vector4charConst1, vector4charConst2, 0, 1, 2, 3);
882+
constexpr vector4char vectorShuffle2 =
883+
__builtin_shufflevector(vector4charConst1, vector4charConst2, 4, 5, 6, 7);
884+
constexpr vector4char vectorShuffle3 =
885+
__builtin_shufflevector(vector4charConst1, vector4charConst2, 0, 2, 4, 6);
886+
constexpr vector8char vectorShuffle4 = __builtin_shufflevector(
887+
vector8intConst, vector8intConst, 0, 2, 4, 6, 8, 10, 12, 14);
888+
constexpr vector4char vectorShuffle5 =
889+
__builtin_shufflevector(vector8intConst, vector8intConst, 0, 2, 4, 6);
890+
constexpr vector8char vectorShuffle6 = __builtin_shufflevector(
891+
vector4charConst1, vector4charConst2, 0, 2, 4, 6, 1, 3, 5, 7);
892+
893+
static_assert(vectorShuffle6[0] == 0, "");// ref-error {{not an integral constant expression}}
894+
static_assert(vectorShuffle6[1] == 2, "");// ref-error {{not an integral constant expression}}
895+
static_assert(vectorShuffle6[2] == 4, "");// ref-error {{not an integral constant expression}}
896+
static_assert(vectorShuffle6[3] == 6, "");// ref-error {{not an integral constant expression}}
897+
static_assert(vectorShuffle6[4] == 1, "");// ref-error {{not an integral constant expression}}
898+
static_assert(vectorShuffle6[5] == 3, "");// ref-error {{not an integral constant expression}}
899+
static_assert(vectorShuffle6[6] == 5, "");// ref-error {{not an integral constant expression}}
900+
static_assert(vectorShuffle6[7] == 7, "");// ref-error {{not an integral constant expression}}
901+
902+
constexpr vector4char vectorShuffleFail1 = __builtin_shufflevector( // both-error {{must be initialized by a constant expression}}\
903+
// ref-error {{index for __builtin_shufflevector not within the bounds of the input vectors; index of -1 found at position 0 not permitted in a constexpr context.}}
904+
vector4charConst1,
905+
vector4charConst2, -1, -1, -1, -1);
906+
}
907+
876908
#endif

0 commit comments

Comments
 (0)