Reactor (LLVM): Fix GEP for Pointer<Pointer<T>> types
Also add a bunch of tests.
Bug: b/126028338
Change-Id: Ic8eb822dce3eff402e2a5f222c5077c6831f4505
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/25748
Tested-by: Ben Clayton <bclayton@google.com>
Presubmit-Ready: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/LLVMReactor.cpp b/src/Reactor/LLVMReactor.cpp
index ea1bebb..c8a5ed7 100644
--- a/src/Reactor/LLVMReactor.cpp
+++ b/src/Reactor/LLVMReactor.cpp
@@ -1246,25 +1246,37 @@
Value *Nucleus::createGEP(Value *ptr, Type *type, Value *index, bool unsignedIndex)
{
+ assert(V(ptr)->getType()->getContainedType(0) == T(type));
+
if(sizeof(void*) == 8)
{
- if(unsignedIndex)
- {
- index = createZExt(index, Long::getType());
- }
- else
- {
- index = createSExt(index, Long::getType());
- }
-
- index = createMul(index, createConstantLong((int64_t)typeSize(type)));
+ // LLVM manual: "When indexing into an array, pointer or vector,
+ // integers of any width are allowed, and they are not required to
+ // be constant. These integers are treated as signed values where
+ // relevant."
+ //
+ // Thus if we want indexes to be treated as unsigned we have to
+ // zero-extend them ourselves.
+ //
+ // Note that this is not because we want to address anywhere near
+ // 4 GB of data. Instead this is important for performance because
+ // x86 supports automatic zero-extending of 32-bit registers to
+ // 64-bit. Thus when indexing into an array using a uint32 is
+ // actually faster than an int32.
+ index = unsignedIndex ?
+ createZExt(index, Long::getType()) :
+ createSExt(index, Long::getType());
}
- else
+
+ if (reinterpret_cast<uintptr_t>(type) >= EmulatedTypeCount)
{
- index = createMul(index, createConstantInt((int)typeSize(type)));
+ return V(::builder->CreateGEP(V(ptr), V(index)));
}
- assert(V(ptr)->getType()->getContainedType(0) == T(type));
+ index = (sizeof(void*) == 8) ?
+ createMul(index, createConstantLong((int64_t)typeSize(type))) :
+ createMul(index, createConstantInt((int)typeSize(type)));
+
return createBitCast(
V(::builder->CreateGEP(V(createBitCast(ptr, T(llvm::PointerType::get(T(Byte::getType()), 0)))), V(index))),
T(llvm::PointerType::get(T(type), 0)));