Fix a crash in scalarrepl for memcpy/memmove where the source and destination
authorBob Wilson <bob.wilson@apple.com>
Tue, 19 Jan 2010 04:32:48 +0000 (04:32 +0000)
committerBob Wilson <bob.wilson@apple.com>
Tue, 19 Jan 2010 04:32:48 +0000 (04:32 +0000)
are the same.  I had already fixed a similar problem where the source and
destination were different bitcasts derived from the same alloca, but the
previous fix still did not handle the case where both operands are exactly
the same value.  Radar 7552893.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93848 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ScalarReplAggregates.cpp
test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll [new file with mode: 0644]

index 9e1e79a1c29cfb616b83c600b17ff8c2ce6379b1..336da509b48e33c6eaea1f062c81b40ec40276a7 100644 (file)
@@ -752,9 +752,16 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
       }
       break;
     }
-    // If OtherPtr has already been rewritten, this intrinsic will be dead.
-    if (OtherPtr == NewElts[0])
+    // Copying the alloca to itself is a no-op: just delete it.
+    if (OtherPtr == AI || OtherPtr == NewElts[0]) {
+      // This code will run twice for a no-op memcpy -- once for each operand.
+      // Put only one reference to MI on the DeadInsts list.
+      for (SmallVector<Value*, 32>::const_iterator I = DeadInsts.begin(),
+             E = DeadInsts.end(); I != E; ++I)
+        if (*I == MI) return;
+      DeadInsts.push_back(MI);
       return;
+    }
     
     if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr))
       if (BCE->getOpcode() == Instruction::BitCast)
@@ -779,10 +786,7 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,
     Value *OtherElt = 0;
     unsigned OtherEltAlign = MemAlignment;
     
-    if (OtherPtr == AI) {
-      OtherElt = NewElts[i];
-      OtherEltAlign = 0;
-    } else if (OtherPtr) {
+    if (OtherPtr) {
       Value *Idx[2] = { Zero,
                       ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) };
       OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2,
diff --git a/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll b/test/Transforms/ScalarRepl/2010-01-18-SelfCopy.ll
new file mode 100644 (file)
index 0000000..74cf251
--- /dev/null
@@ -0,0 +1,18 @@
+; RUN: opt < %s -scalarrepl -S | FileCheck %s
+; Radar 7552893
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32"
+
+%struct.test = type { [3 x double ] }
+
+define arm_apcscc void @test_memcpy_self() nounwind {
+; CHECK: @test_memcpy_self
+; CHECK-NOT: alloca
+; CHECK: ret void
+  %1 = alloca %struct.test
+  %2 = bitcast %struct.test* %1 to i8*
+  call void @llvm.memcpy.i32(i8* %2, i8* %2, i32 24, i32 4)
+  ret void
+}
+
+declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind