[cfe-commits] r120645 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp test/CodeGen/init.c

Chris Lattner sabre at nondot.org
Wed Dec 1 17:58:42 PST 2010


Author: lattner
Date: Wed Dec  1 19:58:41 2010
New Revision: 120645

URL: http://llvm.org/viewvc/llvm-project?rev=120645&view=rev
Log:
Enhance the init generation logic to emit a memset followed by a few stores when
a global is larger than 32 bytes and has fewer than 6 non-zero values in the
initializer.  Previously we'd turn something like this:

char test8(int X) {
  char str[10000] = "abc";

into a 10K global variable which we then memcpy'd from.  Now we generate:

  %str = alloca [10000 x i8], align 16
  %tmp = getelementptr inbounds [10000 x i8]* %str, i64 0, i64 0
  call void @llvm.memset.p0i8.i64(i8* %tmp, i8 0, i64 10000, i32 16, i1 false)
  store i8 97, i8* %tmp, align 16
  %0 = getelementptr [10000 x i8]* %str, i64 0, i64 1
  store i8 98, i8* %0, align 1
  %1 = getelementptr [10000 x i8]* %str, i64 0, i64 2
  store i8 99, i8* %1, align 2

Which is much smaller in space and also likely faster.

This is part of PR279


Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/test/CodeGen/init.c

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=120645&r1=120644&r2=120645&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Wed Dec  1 19:58:41 2010
@@ -513,8 +513,25 @@
 /// NumStores scalar stores.
 static bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
                                                 unsigned &NumStores) {
-  // Zero never requires any extra stores.
-  if (isa<llvm::ConstantAggregateZero>(Init)) return true;
+  // Zero and Undef never requires any extra stores.
+  if (isa<llvm::ConstantAggregateZero>(Init) ||
+      isa<llvm::ConstantPointerNull>(Init) ||
+      isa<llvm::UndefValue>(Init))
+    return true;
+  if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
+      isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
+      isa<llvm::ConstantExpr>(Init))
+    return Init->isNullValue() || NumStores--;
+
+  // See if we can emit each element.
+  if (isa<llvm::ConstantArray>(Init) || isa<llvm::ConstantStruct>(Init)) {
+    for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
+      llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i));
+      if (!canEmitInitWithFewStoresAfterMemset(Elt, NumStores))
+        return false;
+    }
+    return true;
+  }
   
   // Anything else is hard and scary.
   return false;
@@ -526,10 +543,30 @@
 static void emitStoresForInitAfterMemset(llvm::Constant *Init, llvm::Value *Loc,
                                          CGBuilderTy &Builder) {
   // Zero doesn't require any stores.
-  if (isa<llvm::ConstantAggregateZero>(Init)) return;
+  if (isa<llvm::ConstantAggregateZero>(Init) ||
+      isa<llvm::ConstantPointerNull>(Init) ||
+      isa<llvm::UndefValue>(Init))
+    return;
   
+  if (isa<llvm::ConstantInt>(Init) || isa<llvm::ConstantFP>(Init) ||
+      isa<llvm::ConstantVector>(Init) || isa<llvm::BlockAddress>(Init) ||
+      isa<llvm::ConstantExpr>(Init)) {
+    if (!Init->isNullValue())
+      Builder.CreateStore(Init, Loc);
+    return;
+  }
   
-  assert(0 && "Unknown value type!");
+  assert((isa<llvm::ConstantStruct>(Init) || isa<llvm::ConstantArray>(Init)) &&
+         "Unknown value type!");
+  
+  for (unsigned i = 0, e = Init->getNumOperands(); i != e; ++i) {
+    llvm::Constant *Elt = cast<llvm::Constant>(Init->getOperand(i));
+    if (Elt->isNullValue()) continue;
+    
+    // Otherwise, get a pointer to the element and emit it.
+    emitStoresForInitAfterMemset(Elt, Builder.CreateConstGEP2_32(Loc, 0, i),
+                                 Builder);
+  }
 }
 
 
@@ -778,8 +815,6 @@
                              getContext().getTypeSizeInChars(Ty).getQuantity());
       
       const llvm::Type *BP = llvm::Type::getInt8PtrTy(VMContext);
-      if (Loc->getType() != BP)
-        Loc = Builder.CreateBitCast(Loc, BP, "tmp");
       
       llvm::Value *NotVolatile = Builder.getFalse();
 

Modified: cfe/trunk/test/CodeGen/init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/init.c?rev=120645&r1=120644&r2=120645&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/init.c (original)
+++ cfe/trunk/test/CodeGen/init.c Wed Dec  1 19:58:41 2010
@@ -58,3 +58,15 @@
 };
 
 struct a7 test7 = { .b = 0, .v = "bar" };
+
+
+// PR279 comment #3
+char test8(int X) {
+  char str[100000] = "abc"; // tail should be memset.
+  return str[X];
+// CHECK: @test8(
+// CHECK: call void @llvm.memset
+// CHECK: store i8 97
+// CHECK: store i8 98
+// CHECK: store i8 99
+}





More information about the cfe-commits mailing list