R600: Fix calculation of stack offset in AMDGPUFrameLowering
authorTom Stellard <thomas.stellard@amd.com>
Fri, 7 Jun 2013 20:52:05 +0000 (20:52 +0000)
committerTom Stellard <thomas.stellard@amd.com>
Fri, 7 Jun 2013 20:52:05 +0000 (20:52 +0000)
We weren't computing structure size correctly and we were relying on
the original alloca instruction to compute the offset, which isn't
always reliable.

Reviewed-by: Vincent Lejeune <vljn@ovi.com>
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183568 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/R600/AMDGPUFrameLowering.cpp
test/CodeGen/R600/indirect-addressing.ll

index 815d6f71c3be69749d11c8f265c2a7ace2505a11..40f14d2f67c51626e29872ea711a1b4b0de9cfa7 100644 (file)
@@ -78,27 +78,8 @@ int AMDGPUFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
   int UpperBound = FI == -1 ? MFI->getNumObjects() : FI;
 
   for (int i = MFI->getObjectIndexBegin(); i < UpperBound; ++i) {
-    const AllocaInst *Alloca = MFI->getObjectAllocation(i);
-    unsigned ArrayElements;
-    const Type *AllocaType = Alloca->getAllocatedType();
-    const Type *ElementType;
-
-    if (AllocaType->isArrayTy()) {
-      ArrayElements = AllocaType->getArrayNumElements();
-      ElementType = AllocaType->getArrayElementType();
-    } else {
-      ArrayElements = 1;
-      ElementType = AllocaType;
-    }
-
-    unsigned VectorElements;
-    if (ElementType->isVectorTy()) {
-      VectorElements = ElementType->getVectorNumElements();
-    } else {
-      VectorElements = 1;
-    }
-
-    Offset += (VectorElements / getStackWidth(MF)) * ArrayElements;
+    unsigned Size = MFI->getObjectSize(i);
+    Offset += (Size / (getStackWidth(MF) * 4));
   }
   return Offset;
 }
index 7291cb42e7fb9d0982309accc6e833d963e5a5fe..bd72cd96e2e5c2fada0e445c00de6d8173fda167 100644 (file)
@@ -30,3 +30,36 @@ entry:
   store i32 %3, i32 addrspace(1)* %arrayidx13
   ret void
 }
+
+; This test checks that the stack offset is calculated correctly for structs.
+; All register loads/stores should be optimized away, so there shouldn't be
+; any MOVA instructions.
+;
+; XXX: This generated code has unnecessary MOVs, we should be able to optimize
+; this.
+
+; CHECK: @multiple_structs
+; CHECK-NOT: MOVA_INT
+
+%struct.point = type { i32, i32 }
+
+define void @multiple_structs(i32 addrspace(1)* %out) {
+entry:
+  %a = alloca %struct.point
+  %b = alloca %struct.point
+  %a.x.ptr = getelementptr %struct.point* %a, i32 0, i32 0
+  %a.y.ptr = getelementptr %struct.point* %a, i32 0, i32 1
+  %b.x.ptr = getelementptr %struct.point* %b, i32 0, i32 0
+  %b.y.ptr = getelementptr %struct.point* %b, i32 0, i32 1
+  store i32 0, i32* %a.x.ptr
+  store i32 1, i32* %a.y.ptr
+  store i32 2, i32* %b.x.ptr
+  store i32 3, i32* %b.y.ptr
+  %a.indirect.ptr = getelementptr %struct.point* %a, i32 0, i32 0
+  %b.indirect.ptr = getelementptr %struct.point* %b, i32 0, i32 0
+  %a.indirect = load i32* %a.indirect.ptr
+  %b.indirect = load i32* %b.indirect.ptr
+  %0 = add i32 %a.indirect, %b.indirect
+  store i32 %0, i32 addrspace(1)* %out
+  ret void
+}