Fix shuffling of vectors with a different size mask LLVM specifies that for the `shufflevector` instruction "The result of the instruction is a vector whose length is the same as the shuffle mask": https://llvm.org/docs/LangRef.html#shufflevector-instruction. Reactor's Nucleus::createShuffleVector() function however takes a raw pointer to integers as the selection mask, and assumes the size of this array to be the same as the number of components in the source vectors. This was also how lowerShuffleVector() worked previously, which was fine for all uses we had in the x86 specific code. For other architectures the lowerPack() function was assuming the LLVM behavior. To reconcile this, the lowerShuffleVector() now takes an llvm::ArrayRef<int> and behaves like LLVM, and createShuffleVector() explicitly creates an llvm::SmallVector<int> of the desired size. Bug: b/218700092 Bug: b/165000222 Change-Id: I70ff9f1d9c1f085ccc548a4ec706e7d515b638d5 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/62708 Tested-by: Nicolas Capens <nicolascapens@google.com> Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp index d38f1a1..8f564c5 100644 --- a/src/Reactor/LLVMReactor.cpp +++ b/src/Reactor/LLVMReactor.cpp
@@ -217,9 +217,9 @@ return jit->builder->CreateLShr(x, y); } -llvm::Value *lowerShuffleVector(llvm::Value *v1, llvm::Value *v2, const int *select) +llvm::Value *lowerShuffleVector(llvm::Value *v1, llvm::Value *v2, llvm::ArrayRef<int> select) { - int size = llvm::cast<llvm::FixedVectorType>(v1->getType())->getNumElements(); + int size = select.size(); const int maxSize = 16; llvm::Constant *swizzle[maxSize]; ASSERT(size <= maxSize); @@ -253,8 +253,8 @@ oddIdx.push_back(i + 1); } - llvm::Value *lhs = lowerShuffleVector(mult, undef, evenIdx.data()); - llvm::Value *rhs = lowerShuffleVector(mult, undef, oddIdx.data()); + llvm::Value *lhs = lowerShuffleVector(mult, undef, evenIdx); + llvm::Value *rhs = lowerShuffleVector(mult, undef, oddIdx); return jit->builder->CreateAdd(lhs, rhs); } @@ -291,7 +291,7 @@ llvm::SmallVector<int, 16> index(srcTy->getNumElements() * 2); std::iota(index.begin(), index.end(), 0); - return lowerShuffleVector(x, y, index.data()); + return lowerShuffleVector(x, y, index); } [[maybe_unused]] llvm::Value *lowerSignMask(llvm::Value *x, llvm::Type *retTy) @@ -1660,7 +1660,15 @@ Value *Nucleus::createShuffleVector(Value *v1, Value *v2, const int *select) { RR_DEBUG_INFO_UPDATE_LOC(); - return V(lowerShuffleVector(V(v1), V(v2), select)); + + int size = llvm::cast<llvm::FixedVectorType>(V(v1)->getType())->getNumElements(); + llvm::SmallVector<int, 16> mask; + for(int i = 0; i < size; i++) + { + mask.push_back(select[i]); + } + + return V(lowerShuffleVector(V(v1), V(v2), mask)); } Value *Nucleus::createSelect(Value *c, Value *ifTrue, Value *ifFalse)