diff options
author | Chris Lattner <sabre@nondot.org> | 2009-12-06 05:29:56 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2009-12-06 05:29:56 +0000 |
commit | bc9a28dd544e37074693333ea96c508a3d3bc3b4 (patch) | |
tree | f1b8c55917c0a3bc7b96605763a0c26876a28220 /lib | |
parent | cb9cbc494975dc827465af32d806e7b9ae17090c (diff) | |
download | external_llvm-bc9a28dd544e37074693333ea96c508a3d3bc3b4.zip external_llvm-bc9a28dd544e37074693333ea96c508a3d3bc3b4.tar.gz external_llvm-bc9a28dd544e37074693333ea96c508a3d3bc3b4.tar.bz2 |
constant fold loads from memcpy's from global constants. This is important
because clang lowers nontrivial automatic struct/array inits to memcpy from
a global array.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90698 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Transforms/Scalar/GVN.cpp | 52 |
1 files changed, 46 insertions, 6 deletions
diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 7454f62..b703a76 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -31,8 +31,9 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/MemoryBuiltins.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Support/CFG.h" @@ -1094,11 +1095,39 @@ static int AnalyzeLoadFromClobberingMemInst(LoadInst *L, MemIntrinsic *MI, ConstantInt *SizeCst = dyn_cast<ConstantInt>(MI->getLength()); if (SizeCst == 0) return -1; uint64_t MemSizeInBits = SizeCst->getZExtValue()*8; - + + // If this is memset, we just need to see if the offset is valid in the size + // of the memset.. if (MI->getIntrinsicID() == Intrinsic::memset) return AnalyzeLoadFromClobberingWrite(L, MI->getDest(), MemSizeInBits, TD); - // Unhandled memcpy/memmove. + // If we have a memcpy/memmove, the only case we can handle is if this is a + // copy from constant memory. In that case, we can read directly from the + // constant memory. + MemTransferInst *MTI = cast<MemTransferInst>(MI); + + Constant *Src = dyn_cast<Constant>(MTI->getSource()); + if (Src == 0) return -1; + + GlobalVariable *GV = dyn_cast<GlobalVariable>(Src->getUnderlyingObject()); + if (GV == 0 || !GV->isConstant()) return -1; + + // See if the access is within the bounds of the transfer. + int Offset = + AnalyzeLoadFromClobberingWrite(L, MI->getDest(), MemSizeInBits, TD); + if (Offset == -1) + return Offset; + + // Otherwise, see if we can constant fold a load from the constant with the + // offset applied as appropriate. + Src = ConstantExpr::getBitCast(Src, + llvm::Type::getInt8PtrTy(Src->getContext())); + Constant *OffsetCst = + ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); + Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1); + Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(L->getType())); + if (ConstantFoldLoadFromConstPtr(Src, &TD)) + return Offset; return -1; } @@ -1182,9 +1211,20 @@ static Value *GetMemInstValueForLoad(MemIntrinsic *SrcInst, unsigned Offset, return CoerceAvailableValueToLoadType(Val, LoadTy, InsertPt, TD); } - - // ABORT; - return 0; + + // Otherwise, this is a memcpy/memmove from a constant global. + MemTransferInst *MTI = cast<MemTransferInst>(SrcInst); + Constant *Src = cast<Constant>(MTI->getSource()); + + // Otherwise, see if we can constant fold a load from the constant with the + // offset applied as appropriate. + Src = ConstantExpr::getBitCast(Src, + llvm::Type::getInt8PtrTy(Src->getContext())); + Constant *OffsetCst = + ConstantInt::get(Type::getInt64Ty(Src->getContext()), (unsigned)Offset); + Src = ConstantExpr::getGetElementPtr(Src, &OffsetCst, 1); + Src = ConstantExpr::getBitCast(Src, PointerType::getUnqual(LoadTy)); + return ConstantFoldLoadFromConstPtr(Src, &TD); } |