[cfe-commits] r120530 - /cfe/trunk/lib/CodeGen/CGDecl.cpp

Chris Lattner sabre at nondot.org
Tue Nov 30 18:05:19 PST 2010


Author: lattner
Date: Tue Nov 30 20:05:19 2010
New Revision: 120530

URL: http://llvm.org/viewvc/llvm-project?rev=120530&view=rev
Log:
add some infrastructure that will let us codegen
http://llvm.org/bugs/show_bug.cgi?id=279#c3 better.

No functionality change yet.

Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=120530&r1=120529&r2=120530&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Nov 30 20:05:19 2010
@@ -507,6 +507,54 @@
   };
 }
 
+
+/// canEmitInitWithFewStoresAfterMemset - Decide whether we can emit the
+/// non-zero parts of the specified initializer with equal or fewer than
+/// NumStores scalar stores.
+static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
+                                                unsigned &NumStores) {
+  // Zero never requires any extra stores.
+  if (isa<llvm::ConstantAggregateZero>(Init)) return true;
+  
+  // Anything else is hard and scary.
+  return false;
+}
+
+/// emitStoresForInitAfterMemset - For inits that
+/// canEmitInitWithFewStoresAfterMemset returned true for, emit the scalar
+/// stores that would be required.
+static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
+                                         CGBuilderTy &Builder) {
+  // Zero doesn't require any stores.
+  if (isa<llvm::ConstantAggregateZero>(Init)) return;
+  
+  
+  assert(0 && "Unknown value type!");
+}
+
+
+/// shouldUseMemSetPlusStoresToInitialize - Decide whether we should use memset
+/// plus some stores to initialize a local variable instead of using a memcpy
+/// from a constant global.  It is beneficial to use memset if the global is all
+/// zeros, or mostly zeros and large.
+static bool shouldUseMemSetPlusStoresToInitialize(llvm::Constant *Init,
+                                                  uint64_t GlobalSize) {
+  // If a global is all zeros, always use a memset.
+  if (isa<llvm::ConstantAggregateZero>(Init)) return true;
+
+
+  // If a non-zero global is <= 32 bytes, always use a memcpy.  If it is large,
+  // do it if it will require 6 or fewer scalar stores.
+  // TODO: Should budget depends on the size?  Avoiding a large global warrants
+  // plopping in more stores.
+  unsigned StoreBudget = 6;
+  uint64_t SizeLimit = 32;
+  
+  return GlobalSize > SizeLimit && 
+         canEmitInitWithFewStoresAfterMemset(Init, StoreBudget);
+}
+
+
 /// EmitLocalVarDecl - Emit code and set up an entry in LocalDeclMap for a
 /// variable declaration with auto, register, or no storage class specifier.
 /// These turn into simple stack objects, or GlobalValues depending on target.
@@ -680,7 +728,7 @@
       flag |= BLOCK_FIELD_IS_WEAK;
 
     int isa = 0;
-    if (flag&BLOCK_FIELD_IS_WEAK)
+    if (flag & BLOCK_FIELD_IS_WEAK)
       isa = 1;
     V = Builder.CreateIntToPtr(Builder.getInt32(isa), PtrToInt8Ty, "isa");
     Builder.CreateStore(V, isa_field);
@@ -735,11 +783,20 @@
       
       llvm::Value *NotVolatile = Builder.getFalse();
 
-      // If the initializer is all zeros, codegen with memset.
-      if (isa<llvm::ConstantAggregateZero>(Init)) {
-        llvm::Value *Zero = Builder.getInt8(0);
-        Builder.CreateCall5(CGM.getMemSetFn(Loc->getType(), SizeVal->getType()),
-                            Loc, Zero, SizeVal, AlignVal, NotVolatile);
+      // If the initializer is all or mostly zeros, codegen with memset then do
+      // a few stores afterward.
+      if (shouldUseMemSetPlusStoresToInitialize(Init, 
+                      CGM.getTargetData().getTypeAllocSize(Init->getType()))) {
+        const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+        llvm::Value *MemSetDest = Loc;
+        if (MemSetDest->getType() != BP)
+          MemSetDest = Builder.CreateBitCast(MemSetDest, BP, "tmp");
+        
+        Builder.CreateCall5(CGM.getMemSetFn(BP, SizeVal->getType()),
+                            MemSetDest, Builder.getInt8(0), SizeVal, AlignVal,
+                            NotVolatile);
+        emitStoresForInitAfterMemset(Init, Loc, Builder);
+        
       } else {
         // Otherwise, create a temporary global with the initializer then 
         // memcpy from the global to the alloca.
@@ -754,6 +811,10 @@
         if (SrcPtr->getType() != BP)
           SrcPtr = Builder.CreateBitCast(SrcPtr, BP, "tmp");
 
+        const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
+        if (Loc->getType() != BP)
+          Loc = Builder.CreateBitCast(Loc, BP, "tmp");
+        
         Builder.CreateCall5(CGM.getMemCpyFn(Loc->getType(), SrcPtr->getType(),
                                             SizeVal->getType()),
                             Loc, SrcPtr, SizeVal, AlignVal, NotVolatile);





More information about the cfe-commits mailing list