Index: llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -627,13 +627,39 @@ // 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; } Index: llvm/trunk/test/Transforms/MemCpyOpt/fca2memcpy.ll =================================================================== --- llvm/trunk/test/Transforms/MemCpyOpt/fca2memcpy.ll +++ llvm/trunk/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 @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 @@ ; 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