From bb81476a2869c30fcd85cfd4365f33211eeab061 Mon Sep 17 00:00:00 2001 From: Amaury Sechet Date: Wed, 6 Jan 2016 19:47:24 +0000 Subject: [PATCH] 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 --- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 28 ++++++++++++++++++++++- test/Transforms/MemCpyOpt/fca2memcpy.ll | 10 ++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index 849bd27b442..5711a775df8 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -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 // byte at a time like "0" or "-1" or any width, as well as things like // 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(), ByteVal)) { BBI = I->getIterator(); // Don't invalidate iterator. 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; } diff --git a/test/Transforms/MemCpyOpt/fca2memcpy.ll b/test/Transforms/MemCpyOpt/fca2memcpy.ll index 75a1a8f96e2..3c3b22bb335 100644 --- a/test/Transforms/MemCpyOpt/fca2memcpy.ll +++ b/test/Transforms/MemCpyOpt/fca2memcpy.ll @@ -3,7 +3,7 @@ target datalayout = "e-i64:64-f80:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" -%S = type { i8*, i32 } +%S = type { i8*, i8, i32 } define void @copy(%S* %src, %S* %dst) { ; CHECK-LABEL: copy @@ -37,8 +37,10 @@ define void @noaliasdst(%S* %src, %S* noalias %dst) { define void @destroysrc(%S* %src, %S* %dst) { ; CHECK-LABEL: destroysrc -; CHECK-NOT: call -; CHECK: ret void +; CHECK: load %S, %S* %src +; CHECK: call void @llvm.memset.p0i8.i64 +; CHECK-NEXT: store %S %1, %S* %dst +; CHECK-NEXT: ret void %1 = load %S, %S* %src store %S zeroinitializer, %S* %src store %S %1, %S* %dst @@ -49,7 +51,7 @@ define void @destroynoaliassrc(%S* noalias %src, %S* %dst) { ; CHECK-LABEL: destroynoaliassrc ; CHECK-NOT: load ; 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 %1 = load %S, %S* %src store %S zeroinitializer, %S* %src -- 2.34.1