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