Make sure scalarrepl picks the correct alloca when it rewrites a bitcast. Fixes...
authorEli Friedman <eli.friedman@gmail.com>
Sat, 12 Nov 2011 02:07:50 +0000 (02:07 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sat, 12 Nov 2011 02:07:50 +0000 (02:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144442 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ScalarReplAggregates.cpp
test/Transforms/ScalarRepl/2011-11-11-EmptyStruct.ll [new file with mode: 0644]

index b89f7306a28888bf5e5ab7d7fd93e4c67660766f..c12f403d57e177b96c35f7facdd27347a479eec9 100644 (file)
@@ -1875,8 +1875,14 @@ void SROA::RewriteBitCast(BitCastInst *BC, AllocaInst *AI, uint64_t Offset,
     return;
 
   // The bitcast references the original alloca.  Replace its uses with
-  // references to the first new element alloca.
-  Instruction *Val = NewElts[0];
+  // references to the alloca containing offset zero (which is normally at
+  // index zero, but might not be in cases involving structs with elements
+  // of size zero).
+  Type *T = AI->getAllocatedType();
+  uint64_t EltOffset = 0;
+  Type *IdxTy;
+  uint64_t Idx = FindElementAndOffset(T, EltOffset, IdxTy);
+  Instruction *Val = NewElts[Idx];
   if (Val->getType() != BC->getDestTy()) {
     Val = new BitCastInst(Val, BC->getDestTy(), "", BC);
     Val->takeName(BC);
@@ -2160,6 +2166,8 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
     }
 
     unsigned EltSize = TD->getTypeAllocSize(EltTy);
+    if (!EltSize)
+      continue;
 
     IRBuilder<> Builder(MI);
 
diff --git a/test/Transforms/ScalarRepl/2011-11-11-EmptyStruct.ll b/test/Transforms/ScalarRepl/2011-11-11-EmptyStruct.ll
new file mode 100644 (file)
index 0000000..da707b7
--- /dev/null
@@ -0,0 +1,26 @@
+; RUN: opt < %s -S -scalarrepl | FileCheck %s
+
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+
+%struct.S = type { [2 x %struct.anon], double }
+%struct.anon = type {}
+
+; CHECK: @test()
+; CHECK-NOT: alloca
+; CHECK: ret double 1.0
+
+define double @test() nounwind uwtable ssp {
+entry:
+  %retval = alloca %struct.S, align 8
+  %ret = alloca %struct.S, align 8
+  %b = getelementptr inbounds %struct.S* %ret, i32 0, i32 1
+  store double 1.000000e+00, double* %b, align 8
+  %0 = bitcast %struct.S* %retval to i8*
+  %1 = bitcast %struct.S* %ret to i8*
+  call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 8, i32 8, i1 false)
+  %2 = bitcast %struct.S* %retval to double*
+  %3 = load double* %2, align 1
+  ret double %3
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind