Promote aggregate store to memset when possible

Summary: As per title. This will allow the optimizer to pick up on it.

Reviewers: craig.topper, spatel, dexonsmith, Prazek, chandlerc, joker.eph, majnemer

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D15923

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256969 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Amaury Sechet 2016-01-06 19:47:24 +00:00
parent e218641673
commit bb81476a28
2 changed files with 33 additions and 5 deletions

View File

@ -627,13 +627,39 @@ bool MemCpyOpt::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
// Ensure that the value being stored is something that can be memset'able a // Ensure that the value being stored is something that can be memset'able a
// byte at a time like "0" or "-1" or any width, as well as things like // byte at a time like "0" or "-1" or any width, as well as things like
// 0xA0A0A0A0 and 0.0. // 0xA0A0A0A0 and 0.0.
if (Value *ByteVal = isBytewiseValue(SI->getOperand(0))) auto *V = SI->getOperand(0);
if (Value *ByteVal = isBytewiseValue(V)) {
if (Instruction *I = tryMergingIntoMemset(SI, SI->getPointerOperand(), if (Instruction *I = tryMergingIntoMemset(SI, SI->getPointerOperand(),
ByteVal)) { ByteVal)) {
BBI = I->getIterator(); // Don't invalidate iterator. BBI = I->getIterator(); // Don't invalidate iterator.
return true; return true;
} }
// If we have an aggregate, we try to promote it to memset regardless
// of opportunity for merging as it can expose optimization opportunities
// in subsequent passes.
auto *T = V->getType();
if (T->isAggregateType()) {
uint64_t Size = DL.getTypeStoreSize(T);
unsigned Align = SI->getAlignment();
if (!Align)
Align = DL.getABITypeAlignment(T);
IRBuilder<> Builder(SI);
auto *M = Builder.CreateMemSet(SI->getPointerOperand(), ByteVal,
Size, Align, SI->isVolatile());
DEBUG(dbgs() << "Promoting " << *SI << " to " << *M << "\n");
MD->removeInstruction(SI);
SI->eraseFromParent();
NumMemSetInfer++;
// Make sure we do not invalidate the iterator.
BBI = M->getIterator();
return true;
}
}
return false; return false;
} }

View File

@ -3,7 +3,7 @@
target datalayout = "e-i64:64-f80:128-n8:16:32:64" target datalayout = "e-i64:64-f80:128-n8:16:32:64"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
%S = type { i8*, i32 } %S = type { i8*, i8, i32 }
define void @copy(%S* %src, %S* %dst) { define void @copy(%S* %src, %S* %dst) {
; CHECK-LABEL: copy ; CHECK-LABEL: copy
@ -37,8 +37,10 @@ define void @noaliasdst(%S* %src, %S* noalias %dst) {
define void @destroysrc(%S* %src, %S* %dst) { define void @destroysrc(%S* %src, %S* %dst) {
; CHECK-LABEL: destroysrc ; CHECK-LABEL: destroysrc
; CHECK-NOT: call ; CHECK: load %S, %S* %src
; CHECK: ret void ; CHECK: call void @llvm.memset.p0i8.i64
; CHECK-NEXT: store %S %1, %S* %dst
; CHECK-NEXT: ret void
%1 = load %S, %S* %src %1 = load %S, %S* %src
store %S zeroinitializer, %S* %src store %S zeroinitializer, %S* %src
store %S %1, %S* %dst store %S %1, %S* %dst
@ -49,7 +51,7 @@ define void @destroynoaliassrc(%S* noalias %src, %S* %dst) {
; CHECK-LABEL: destroynoaliassrc ; CHECK-LABEL: destroynoaliassrc
; CHECK-NOT: load ; CHECK-NOT: load
; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
; CHECK-NEXT: store %S zeroinitializer, %S* %src ; CHECK-NEXT: call void @llvm.memset.p0i8.i64
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
%1 = load %S, %S* %src %1 = load %S, %S* %src
store %S zeroinitializer, %S* %src store %S zeroinitializer, %S* %src