Fix constant vector construction for emulated types. Emulated vectors have fewer elements than their underlying type, e.g. v4i16 is stored in the lower half of a v8i16 vector, but for constant vector construction we need to provide values for all the elements of the underlying vector. Bug b/65124545 Change-Id: Iaf942c4d517b1d4d464894ec501f7d339ae86438 Reviewed-on: https://swiftshader-review.googlesource.com/11908 Reviewed-by: Nicolas Capens <nicolascapens@google.com> Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp index b299f6d..8abb17a 100644 --- a/src/Reactor/LLVMReactor.cpp +++ b/src/Reactor/LLVMReactor.cpp
@@ -159,6 +159,26 @@ return T(type)->getPrimitiveSizeInBits() / 8; } + static unsigned int elementCount(Type *type) + { + uintptr_t t = reinterpret_cast<uintptr_t>(type); + if(t < EmulatedTypeCount) + { + switch(t) + { + case Type_v2i32: return 2; + case Type_v4i16: return 4; + case Type_v2i16: return 2; + case Type_v8i8: return 8; + case Type_v4i8: return 4; + case Type_v2f32: return 2; + default: assert(false); + } + } + + return llvm::cast<llvm::VectorType>(T(type))->getNumElements(); + } + Nucleus::Nucleus() { ::codegenMutex.lock(); // Reactor and LLVM are currently not thread safe @@ -905,31 +925,33 @@ Value *Nucleus::createConstantVector(const int64_t *constants, Type *type) { assert(llvm::isa<llvm::VectorType>(T(type))); - const int numConstants = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); - assert(numConstants <= 16); + const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. + const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type. + assert(numElements <= 16 && numConstants <= numElements); llvm::Constant *constantVector[16]; - for(int i = 0; i < numConstants; i++) + for(int i = 0; i < numElements; i++) { - constantVector[i] = llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i]); + constantVector[i] = llvm::ConstantInt::get(T(type)->getContainedType(0), constants[i % numConstants]); } - return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numConstants))); + return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numElements))); } Value *Nucleus::createConstantVector(const double *constants, Type *type) { assert(llvm::isa<llvm::VectorType>(T(type))); - const int numConstants = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); - assert(numConstants <= 8); + const int numConstants = elementCount(type); // Number of provided constants for the (emulated) type. + const int numElements = llvm::cast<llvm::VectorType>(T(type))->getNumElements(); // Number of elements of the underlying vector type. + assert(numElements <= 8 && numConstants <= numElements); llvm::Constant *constantVector[8]; - for(int i = 0; i < numConstants; i++) + for(int i = 0; i < numElements; i++) { - constantVector[i] = llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i]); + constantVector[i] = llvm::ConstantFP::get(T(type)->getContainedType(0), constants[i % numConstants]); } - return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numConstants))); + return V(llvm::ConstantVector::get(llvm::ArrayRef<llvm::Constant*>(constantVector, numElements))); } Type *Void::getType()