diff --git a/lib/SILOptimizer/Transforms/TempRValueElimination.cpp b/lib/SILOptimizer/Transforms/TempRValueElimination.cpp
index f07c66b8a8c5c..5e86f2330c7fe 100644
--- a/lib/SILOptimizer/Transforms/TempRValueElimination.cpp
+++ b/lib/SILOptimizer/Transforms/TempRValueElimination.cpp
@@ -282,6 +282,10 @@ collectLoads(Operand *addressUse, CopyAddrInst *originalCopy,
LLVM_DEBUG(llvm::dbgs() << " Temp written or taken" << *user);
return false;
}
+ // As with load [take], only accept copy_addr [take] if it takes the whole
+ // temporary object.
+ if (copyFromTmp->isTakeOfSrc() && address != originalCopy->getDest())
+ return false;
loadInsts.insert(copyFromTmp);
return true;
}
diff --git a/test/SILOptimizer/temp_rvalue_opt_ossa.sil b/test/SILOptimizer/temp_rvalue_opt_ossa.sil
index e8e6d8984283e..594bca1701863 100644
--- a/test/SILOptimizer/temp_rvalue_opt_ossa.sil
+++ b/test/SILOptimizer/temp_rvalue_opt_ossa.sil
@@ -16,6 +16,11 @@ struct GS {
class Klass {}
+struct Two {
+ var a: Klass
+ var b: Klass
+}
+
sil @unknown : $@convention(thin) () -> ()
sil [ossa] @guaranteed_user : $@convention(thin) (@guaranteed Klass) -> ()
@@ -208,6 +213,26 @@ bb0(%0 : $*Builtin.NativeObject):
%v = tuple ()
return %v : $()
}
+
+// CHECK-LABEL: sil [ossa] @dont_allow_copy_take_from_projection
+// CHECK: [[STK:%[0-9]+]] = alloc_stack
+// CHECK: copy_addr [take] %1 to [initialization] [[STK]]
+// CHECK: } // end sil function 'dont_allow_copy_take_from_projection'
+sil [ossa] @dont_allow_copy_take_from_projection : $@convention(thin) (@in Two) -> @out Two {
+bb0(%0 : $*Two, %1 : $*Two):
+ %a0 = struct_element_addr %0 : $*Two, #Two.a
+ %b0 = struct_element_addr %0 : $*Two, #Two.b
+ %s = alloc_stack $Two
+ copy_addr [take] %1 to [initialization] %s : $*Two
+ %as = struct_element_addr %s : $*Two, #Two.a
+ %bs = struct_element_addr %s : $*Two, #Two.b
+ copy_addr [take] %as to [initialization] %a0 : $*Klass
+ copy_addr [take] %bs to [initialization] %b0 : $*Klass
+ dealloc_stack %s : $*Two
+ %r = tuple ()
+ return %r : $()
+}
+
// CHECK-LABEL: sil [ossa] @load_in_wrong_block
// CHECK: bb0(%0 : $*GS):
// CHECK-NEXT: alloc_stack