[PATCH] SelectionDAG: Use the correct address space size for GEP instructions

Tom Stellard tom at stellard.net
Tue Oct 15 11:12:42 PDT 2013


From: Tom Stellard <thomas.stellard at amd.com>

This fixes a crash in the SelectionDAGBuilder where GEP instructions
with a pointer to an array as its first argument would mix the pointer's
address space type with the default address space type while calculating
the offset for the array.
---
 lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 17 ++++++++++++++++-
 test/CodeGen/R600/address-space.ll               | 11 +++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 0cee3d7..7a5a4c9 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3234,6 +3234,22 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
   // element which holds a pointer.
   Type *Ty = I.getOperand(0)->getType()->getScalarType();
 
+  // As the loop below goes through the list of offsets, it also replaces Ty
+  // with the element type of Ty.  For a gep like:
+  // [2 x [264 x i32]] addrspace(3)* @local.mem, i32 0, i32 1, i32 %index
+  // Ty will have the following values:
+  // Iteration 0: [2 x [264 x i32]] addrspace(3)*
+  // Iteration 1: [2 x [264 x i32]]
+  // Iteration 2: [264 x i32]
+  //
+  // Once we have descended into the element type of the pointer we lose the
+  // address space information, which we need in order to generate pointer
+  // arithmetic instructions with the correct types.
+  //
+  // We must cache the address space information here, so that it
+  // is not overwritten with 0 by non-pointer types.
+  uint32_t AS = 0;
+
   for (GetElementPtrInst::const_op_iterator OI = I.op_begin()+1, E = I.op_end();
        OI != E; ++OI) {
     const Value *Idx = *OI;
@@ -3248,7 +3264,6 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
 
       Ty = StTy->getElementType(Field);
     } else {
-      uint32_t AS = 0;
       if (PointerType *PtrType = dyn_cast<PointerType>(Ty)) {
         AS = PtrType->getAddressSpace();
       }
diff --git a/test/CodeGen/R600/address-space.ll b/test/CodeGen/R600/address-space.ll
index 11289d2..d8e6c63 100644
--- a/test/CodeGen/R600/address-space.ll
+++ b/test/CodeGen/R600/address-space.ll
@@ -27,4 +27,15 @@ bb34:
   unreachable
 }
 
+; Test for a bug in SelectionDAGBuilder that were it was using the incorrect
+; address space size for pointers to arrays
+ at local.mem = internal addrspace(3) unnamed_addr global [2 x [264 x i32]] zeroinitializer, align 16
+
+; CHECK: DS_WRITE_B32 0
+define void @gep_array(i32 %index) {
+entry:
+  %0 = getelementptr [2 x [264 x i32]] addrspace(3)* @local.mem, i32 0, i32 1, i32 %index
+  store i32 4, i32 addrspace(3)* %0
+  ret void
+}
 
-- 
1.8.1.5




More information about the llvm-commits mailing list