mirror of
https://github.com/intel/llvm.git
synced 2026-01-31 16:29:50 +08:00
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
llvm-svn: 120645
This commit is contained in:
@@ -513,8 +513,25 @@ namespace {
|
||||
/// 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 bool canEmitInitWithFewStoresAfterMemset(llvm::Constant *Init,
|
||||
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 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
|
||||
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();
|
||||
|
||||
|
||||
@@ -58,3 +58,15 @@ struct a7 {
|
||||
};
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user