As an optimization, we maintain a cache of generated
___Block_byref_id_object_dispose and ___Block_byref_id_object_copy
functions so that we can simply reuse instead of creating a new one.
Additionally, add an assert to ensure no one yet tries to align a
__block variable beyond the alignment of a pointer as the codegen is
incomplete.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72974 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index ead689c..d5f803b 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -724,6 +724,8 @@
   const CGFunctionInfo &FI =
     CGM.getTypes().getFunctionInfo(R, Args);
 
+  // FIXME: We'd like to put these into a mergable by content, with
+  // internal linkage.
   std::string Name = std::string("__copy_helper_block_");
   CodeGenTypes &Types = CGM.getTypes();
   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@@ -803,6 +805,8 @@
   const CGFunctionInfo &FI =
     CGM.getTypes().getFunctionInfo(R, Args);
 
+  // FIXME: We'd like to put these into a mergable by content, with
+  // internal linkage.
   std::string Name = std::string("__destroy_helper_block_");
   CodeGenTypes &Types = CGM.getTypes();
   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
@@ -889,6 +893,8 @@
   CodeGenTypes &Types = CGM.getTypes();
   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
 
+  // FIXME: We'd like to put these into a mergable by content, with
+  // internal linkage.
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
                            Name,
@@ -950,6 +956,8 @@
   CodeGenTypes &Types = CGM.getTypes();
   const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
 
+  // FIXME: We'd like to put these into a mergable by content, with
+  // internal linkage.
   llvm::Function *Fn =
     llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
                            Name,
@@ -980,13 +988,36 @@
 }
 
 llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
-                                                    int flag) {
-  return CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag);
+                                                    int flag, unsigned Align) {
+  // All alignments below that of pointer alignment collpase down to just
+  // pointer alignment, as we always have at least that much alignment to begin
+  // with.
+  Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
+  // As an optimization, we only generate a single function of each kind we
+  // might need.  We need a different one for each alignment and for each
+  // setting of flags.  We mix Align and flag to get the kind.
+  uint64_t kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + flag;
+  llvm::Constant *& Entry = CGM.AssignCache[kind];
+  if (Entry)
+    return Entry;
+  return Entry=CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flag);
 }
 
 llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
-                                                       int flag) {
-  return CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag);
+                                                       int flag,
+                                                       unsigned Align) {
+  // All alignments below that of pointer alignment collpase down to just
+  // pointer alignment, as we always have at least that much alignment to begin
+  // with.
+  Align /= unsigned(CGF.Target.getPointerAlign(0)/8);
+  // As an optimization, we only generate a single function of each kind we
+  // might need.  We need a different one for each alignment and for each
+  // setting of flags.  We mix Align and flag to get the kind.
+  uint64_t kind = (uint64_t)Align*BLOCK_BYREF_CURRENT_MAX + flag;
+  llvm::Constant *& Entry = CGM.DestroyCache[kind];
+  if (Entry)
+    return Entry;
+  return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flag);
 }
 
 llvm::Value *BlockFunction::getBlockObjectDispose() {