aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/Scalar/GVN.cpp6
-rw-r--r--test/Transforms/GVN/2008-03-13-ReturnSlotBitcast.ll19
2 files changed, 24 insertions, 1 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp
index 545f7091cc..1d764af688 100644
--- a/lib/Transforms/Scalar/GVN.cpp
+++ b/lib/Transforms/Scalar/GVN.cpp
@@ -1171,8 +1171,12 @@ bool GVN::performCallSlotOptzn(MemCpyInst* cpy, CallInst* C,
// All the checks have passed, so do the transformation.
for (unsigned i = 0; i < CS.arg_size(); ++i)
- if (CS.getArgument(i) == cpySrc)
+ if (CS.getArgument(i) == cpySrc) {
+ if (cpySrc->getType() != cpyDest->getType())
+ cpyDest = CastInst::createPointerCast(cpyDest, cpySrc->getType(),
+ cpyDest->getName(), C);
CS.setArgument(i, cpyDest);
+ }
// Drop any cached information about the call, because we may have changed
// its dependence information by changing its parameter.
diff --git a/test/Transforms/GVN/2008-03-13-ReturnSlotBitcast.ll b/test/Transforms/GVN/2008-03-13-ReturnSlotBitcast.ll
new file mode 100644
index 0000000000..7757a92b24
--- /dev/null
+++ b/test/Transforms/GVN/2008-03-13-ReturnSlotBitcast.ll
@@ -0,0 +1,19 @@
+; RUN: llvm-as < %s | opt -gvn | llvm-dis | not grep {call.*memcpy.}
+ %a = type { i32 }
+ %b = type { float }
+
+declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind
+declare void @g(%a*)
+
+define float @f() {
+entry:
+ %a_var = alloca %a
+ %b_var = alloca %b
+ call void @g(%a *%a_var)
+ %a_i8 = bitcast %a* %a_var to i8*
+ %b_i8 = bitcast %b* %b_var to i8*
+ call void @llvm.memcpy.i32(i8* %b_i8, i8* %a_i8, i32 4, i32 4)
+ %tmp1 = getelementptr %b* %b_var, i32 0, i32 0
+ %tmp2 = load float* %tmp1
+ ret float %tmp2
+}