[cfe-commits] r72974 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CGDecl.cpp test/CodeGenObjC/blocks-3.m

Mike Stump mrs at apple.com
Fri Jun 5 16:26:37 PDT 2009


Author: mrs
Date: Fri Jun  5 18:26:36 2009
New Revision: 72974

URL: http://llvm.org/viewvc/llvm-project?rev=72974&view=rev
Log:
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.

Added:
    cfe/trunk/test/CodeGenObjC/blocks-3.m
Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.h
    cfe/trunk/lib/CodeGen/CGDecl.cpp

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=72974&r1=72973&r2=72974&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Fri Jun  5 18:26:36 2009
@@ -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() {

Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=72974&r1=72973&r2=72974&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.h Fri Jun  5 18:26:36 2009
@@ -98,6 +98,9 @@
   llvm::Value *BlockObjectDispose;
   const llvm::Type *PtrToInt8Ty;
 
+  std::map<uint64_t, llvm::Constant *> AssignCache;
+  std::map<uint64_t, llvm::Constant *> DestroyCache;
+
   BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
               CodeGenTypes &T, CodeGenModule &CodeGen)
     : Context(C), TheModule(M), TheTargetData(TD), Types(T),
@@ -131,8 +134,9 @@
                                       variable */
     BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy
                                       helpers */
-    BLOCK_BYREF_CALLER      = 128  /* called from __block (byref) copy/dispose
+    BLOCK_BYREF_CALLER      = 128,  /* called from __block (byref) copy/dispose
                                       support routines */
+    BLOCK_BYREF_CURRENT_MAX = 256
   };
 
   /// BlockInfo - Information to generate a block literal.
@@ -199,8 +203,10 @@
   llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
   llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
 
-  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag);
-  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag);
+  llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
+                                       unsigned Align);
+  llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
+                                          unsigned Align);
 
   llvm::Value *getBlockObjectAssign();
   llvm::Value *getBlockObjectDispose();

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=72974&r1=72973&r2=72974&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Fri Jun  5 18:26:36 2009
@@ -232,7 +232,9 @@
     Types[4] = PtrToInt8Ty;
     Types[5] = PtrToInt8Ty;
   }
-  // FIXME: Align this on at least an Align boundary.
+  // FIXME: Align this on at least an Align boundary, assert if we can't.
+  assert((Align <= unsigned(Target.getPointerAlign(0))/8)
+         && "Can't align more thqn pointer yet");
   Types[needsCopyDispose*2 + 4] = LTy;
   return llvm::StructType::get(Types, false);
 }
@@ -244,22 +246,22 @@
   QualType Ty = D.getType();
   bool isByRef = D.hasAttr<BlocksAttr>();
   bool needsDispose = false;
+  unsigned Align = 0;
 
   llvm::Value *DeclPtr;
   if (Ty->isConstantSizeType()) {
     if (!Target.useGlobalsForAutomaticVariables()) {
       // A normal fixed sized variable becomes an alloca in the entry block.
       const llvm::Type *LTy = ConvertTypeForMem(Ty);
+      Align = getContext().getDeclAlignInBytes(&D);
       if (isByRef)
-        LTy = BuildByRefType(Ty, getContext().getDeclAlignInBytes(&D));
+        LTy = BuildByRefType(Ty, Align);
       llvm::AllocaInst *Alloc = CreateTempAlloca(LTy);
       Alloc->setName(D.getNameAsString().c_str());
       
       if (isByRef)
-        Alloc->setAlignment(std::max(getContext().getDeclAlignInBytes(&D),
-                                     unsigned(Target.getPointerAlign(0) / 8)));
-      else
-        Alloc->setAlignment(getContext().getDeclAlignInBytes(&D));
+        Align = std::max(Align, unsigned(Target.getPointerAlign(0) / 8));
+      Alloc->setAlignment(Align);
       DeclPtr = Alloc;
     } else {
       // Targets that don't support recursion emit locals as globals.
@@ -401,11 +403,12 @@
     if (flags & BLOCK_HAS_COPY_DISPOSE) {
       BlockHasCopyDispose = true;
       llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
-      Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag),
+      Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag, Align),
                           copy_helper);
 
       llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
-      Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag),
+      Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag,
+                                                  Align),
                           destroy_helper);
     }
   }

Added: cfe/trunk/test/CodeGenObjC/blocks-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks-3.m?rev=72974&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks-3.m (added)
+++ cfe/trunk/test/CodeGenObjC/blocks-3.m Fri Jun  5 18:26:36 2009
@@ -0,0 +1,15 @@
+// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -fblocks -o %t %s &&
+// RUN: grep 'object_assign' %t | count 11 &&
+// RUN: grep 'object_dispose' %t | count 29
+
+int main() {
+  typedef id aid __attribute__((aligned(1)));
+  __block aid a1;
+  __block id a2 __attribute__((aligned(2)));
+  __block id a3 __attribute__((aligned(4)));
+  __block id a4 __attribute__((aligned(8)));
+  __block id a5, a6, a7;
+  __block void (^b)();
+  ^{ a1=a2=a3=a4=a5=a6=a7=0; b = 0; }();
+  return 0;
+}





More information about the cfe-commits mailing list