2008-04-09 16:23:16 +08:00
|
|
|
//===- MemCpyOptimizer.cpp - Optimize use of memcpy and friends -----------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This pass performs various transformations related to eliminating memcpy
|
|
|
|
// calls, or transforming sets of stores into memset's.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/Transforms/Scalar/MemCpyOptimizer.h"
|
2016-03-15 06:52:27 +08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2017-10-19 05:46:47 +08:00
|
|
|
#include "llvm/ADT/None.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2008-04-09 16:23:16 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/ADT/iterator_range.h"
|
2017-10-19 05:46:47 +08:00
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/Analysis/AssumptionCache.h"
|
|
|
|
#include "llvm/Analysis/GlobalsModRef.h"
|
|
|
|
#include "llvm/Analysis/MemoryDependenceAnalysis.h"
|
|
|
|
#include "llvm/Analysis/MemoryLocation.h"
|
|
|
|
#include "llvm/Analysis/TargetLibraryInfo.h"
|
2010-12-27 04:15:01 +08:00
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/IR/Argument.h"
|
2017-10-19 05:46:47 +08:00
|
|
|
#include "llvm/IR/BasicBlock.h"
|
|
|
|
#include "llvm/IR/CallSite.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Dominators.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
2014-03-04 18:40:04 +08:00
|
|
|
#include "llvm/IR/GetElementPtrTypeIterator.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/IR/IRBuilder.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
|
|
|
#include "llvm/IR/Operator.h"
|
2017-10-19 05:46:47 +08:00
|
|
|
#include "llvm/IR/PassManager.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/User.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
|
|
|
#include "llvm/Pass.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
2008-04-09 16:23:16 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2009-08-23 12:37:46 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-01-18 08:57:48 +08:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2012-06-29 20:38:19 +08:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2015-07-22 05:56:26 +08:00
|
|
|
#include <algorithm>
|
2017-01-18 08:57:48 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <cstdint>
|
2017-10-19 05:46:47 +08:00
|
|
|
#include <utility>
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:55:47 +08:00
|
|
|
#define DEBUG_TYPE "memcpyopt"
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
STATISTIC(NumMemCpyInstr, "Number of memcpy instructions deleted");
|
|
|
|
STATISTIC(NumMemSetInfer, "Number of memsets inferred");
|
2009-09-03 21:37:16 +08:00
|
|
|
STATISTIC(NumMoveToCpy, "Number of memmoves converted to memcpy");
|
2010-12-25 05:17:12 +08:00
|
|
|
STATISTIC(NumCpyToSet, "Number of memcpys converted to memset");
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2012-09-14 00:29:49 +08:00
|
|
|
static int64_t GetOffsetFromIndex(const GEPOperator *GEP, unsigned Idx,
|
2015-03-10 10:37:25 +08:00
|
|
|
bool &VariableIdxFound,
|
|
|
|
const DataLayout &DL) {
|
2008-04-09 16:23:16 +08:00
|
|
|
// Skip over the first indices.
|
|
|
|
gep_type_iterator GTI = gep_type_begin(GEP);
|
|
|
|
for (unsigned i = 1; i != Idx; ++i, ++GTI)
|
|
|
|
/*skip along*/;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Compute the offset implied by the rest of the indices.
|
|
|
|
int64_t Offset = 0;
|
|
|
|
for (unsigned i = Idx, e = GEP->getNumOperands(); i != e; ++i, ++GTI) {
|
|
|
|
ConstantInt *OpC = dyn_cast<ConstantInt>(GEP->getOperand(i));
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!OpC)
|
2008-04-09 16:23:16 +08:00
|
|
|
return VariableIdxFound = true;
|
|
|
|
if (OpC->isZero()) continue; // No offset.
|
|
|
|
|
|
|
|
// Handle struct indices, which add their field offset to the pointer.
|
2016-12-02 10:24:42 +08:00
|
|
|
if (StructType *STy = GTI.getStructTypeOrNull()) {
|
2015-03-10 10:37:25 +08:00
|
|
|
Offset += DL.getStructLayout(STy)->getElementOffset(OpC->getZExtValue());
|
2008-04-09 16:23:16 +08:00
|
|
|
continue;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Otherwise, we have a sequential type like an array or vector. Multiply
|
|
|
|
// the index by the ElementSize.
|
2015-03-10 10:37:25 +08:00
|
|
|
uint64_t Size = DL.getTypeAllocSize(GTI.getIndexedType());
|
2008-04-09 16:23:16 +08:00
|
|
|
Offset += Size*OpC->getSExtValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return Offset;
|
|
|
|
}
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// Return true if Ptr1 is provably equal to Ptr2 plus a constant offset, and
|
|
|
|
/// return that constant offset. For example, Ptr1 might be &A[42], and Ptr2
|
|
|
|
/// might be &A[40]. In this case offset would be -8.
|
2008-04-09 16:23:16 +08:00
|
|
|
static bool IsPointerOffset(Value *Ptr1, Value *Ptr2, int64_t &Offset,
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL) {
|
2011-01-12 09:43:46 +08:00
|
|
|
Ptr1 = Ptr1->stripPointerCasts();
|
|
|
|
Ptr2 = Ptr2->stripPointerCasts();
|
2014-03-11 05:05:13 +08:00
|
|
|
|
|
|
|
// Handle the trivial case first.
|
|
|
|
if (Ptr1 == Ptr2) {
|
|
|
|
Offset = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-14 00:29:49 +08:00
|
|
|
GEPOperator *GEP1 = dyn_cast<GEPOperator>(Ptr1);
|
|
|
|
GEPOperator *GEP2 = dyn_cast<GEPOperator>(Ptr2);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 05:07:56 +08:00
|
|
|
bool VariableIdxFound = false;
|
|
|
|
|
|
|
|
// If one pointer is a GEP and the other isn't, then see if the GEP is a
|
|
|
|
// constant offset from the base, as in "P" and "gep P, 1".
|
2014-04-25 13:29:35 +08:00
|
|
|
if (GEP1 && !GEP2 && GEP1->getOperand(0)->stripPointerCasts() == Ptr2) {
|
2015-03-10 10:37:25 +08:00
|
|
|
Offset = -GetOffsetFromIndex(GEP1, 1, VariableIdxFound, DL);
|
2011-01-09 05:07:56 +08:00
|
|
|
return !VariableIdxFound;
|
|
|
|
}
|
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
if (GEP2 && !GEP1 && GEP2->getOperand(0)->stripPointerCasts() == Ptr1) {
|
2015-03-10 10:37:25 +08:00
|
|
|
Offset = GetOffsetFromIndex(GEP2, 1, VariableIdxFound, DL);
|
2011-01-09 05:07:56 +08:00
|
|
|
return !VariableIdxFound;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Right now we handle the case when Ptr1/Ptr2 are both GEPs with an identical
|
|
|
|
// base. After that base, they may have some number of common (and
|
|
|
|
// potentially variable) indices. After that they handle some constant
|
|
|
|
// offset, which determines their offset from each other. At this point, we
|
|
|
|
// handle no other case.
|
|
|
|
if (!GEP1 || !GEP2 || GEP1->getOperand(0) != GEP2->getOperand(0))
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Skip any common indices and track the GEP types.
|
|
|
|
unsigned Idx = 1;
|
|
|
|
for (; Idx != GEP1->getNumOperands() && Idx != GEP2->getNumOperands(); ++Idx)
|
|
|
|
if (GEP1->getOperand(Idx) != GEP2->getOperand(Idx))
|
|
|
|
break;
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
int64_t Offset1 = GetOffsetFromIndex(GEP1, Idx, VariableIdxFound, DL);
|
|
|
|
int64_t Offset2 = GetOffsetFromIndex(GEP2, Idx, VariableIdxFound, DL);
|
2008-04-09 16:23:16 +08:00
|
|
|
if (VariableIdxFound) return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
Offset = Offset2-Offset1;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-18 08:57:48 +08:00
|
|
|
namespace {
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// Represents a range of memset'd bytes with the ByteVal value.
|
2008-04-09 16:23:16 +08:00
|
|
|
/// This allows us to analyze stores like:
|
|
|
|
/// store 0 -> P+1
|
|
|
|
/// store 0 -> P+0
|
|
|
|
/// store 0 -> P+3
|
|
|
|
/// store 0 -> P+2
|
|
|
|
/// which sometimes happens with stores to arrays of structs etc. When we see
|
|
|
|
/// the first store, we make a range [1, 2). The second store extends the range
|
|
|
|
/// to [0, 2). The third makes a new range [2, 3). The fourth store joins the
|
|
|
|
/// two ranges into [0, 3) which is memset'able.
|
2016-05-11 05:49:40 +08:00
|
|
|
struct MemsetRange {
|
2008-04-09 16:23:16 +08:00
|
|
|
// Start/End - A semi range that describes the span that this range covers.
|
2012-07-24 18:51:42 +08:00
|
|
|
// The range is closed at the start and open at the end: [Start, End).
|
2008-04-09 16:23:16 +08:00
|
|
|
int64_t Start, End;
|
|
|
|
|
|
|
|
/// StartPtr - The getelementptr instruction that points to the start of the
|
|
|
|
/// range.
|
2016-05-11 05:49:40 +08:00
|
|
|
Value *StartPtr;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
/// Alignment - The known alignment of the first store.
|
|
|
|
unsigned Alignment;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
/// TheStores - The actual stores that make up this range.
|
2011-01-09 04:54:51 +08:00
|
|
|
SmallVector<Instruction*, 16> TheStores;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
bool isProfitableToUseMemset(const DataLayout &DL) const;
|
2008-04-09 16:23:16 +08:00
|
|
|
};
|
2017-01-18 08:57:48 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
bool MemsetRange::isProfitableToUseMemset(const DataLayout &DL) const {
|
|
|
|
// If we found more than 4 stores to merge or 16 bytes, use memset.
|
2011-12-06 06:37:00 +08:00
|
|
|
if (TheStores.size() >= 4 || End-Start >= 16) return true;
|
2011-01-09 04:54:51 +08:00
|
|
|
|
|
|
|
// If there is nothing to merge, don't do anything.
|
|
|
|
if (TheStores.size() < 2) return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
// If any of the stores are a memset, then it is always good to extend the
|
|
|
|
// memset.
|
2015-11-20 15:18:48 +08:00
|
|
|
for (Instruction *SI : TheStores)
|
2016-05-11 05:49:40 +08:00
|
|
|
if (!isa<StoreInst>(SI))
|
2011-01-09 04:54:51 +08:00
|
|
|
return true;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Assume that the code generator is capable of merging pairs of stores
|
|
|
|
// together if it wants to.
|
2011-01-09 04:54:51 +08:00
|
|
|
if (TheStores.size() == 2) return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// If we have fewer than 8 stores, it can still be worthwhile to do this.
|
|
|
|
// For example, merging 4 i8 stores into an i32 store is useful almost always.
|
|
|
|
// However, merging 2 32-bit stores isn't useful on a 32-bit architecture (the
|
|
|
|
// memset will be split into 2 32-bit stores anyway) and doing so can
|
|
|
|
// pessimize the llvm optimizer.
|
|
|
|
//
|
|
|
|
// Since we don't have perfect knowledge here, make some assumptions: assume
|
2013-09-17 06:43:16 +08:00
|
|
|
// the maximum GPR width is the same size as the largest legal integer
|
|
|
|
// size. If so, check to see whether we will end up actually reducing the
|
|
|
|
// number of stores used.
|
2008-04-09 16:23:16 +08:00
|
|
|
unsigned Bytes = unsigned(End-Start);
|
2016-05-14 02:38:35 +08:00
|
|
|
unsigned MaxIntSize = DL.getLargestLegalIntTypeSizeInBits() / 8;
|
2013-09-17 06:43:16 +08:00
|
|
|
if (MaxIntSize == 0)
|
|
|
|
MaxIntSize = 1;
|
|
|
|
unsigned NumPointerStores = Bytes / MaxIntSize;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Assume the remaining bytes if any are done a byte at a time.
|
2015-11-22 01:44:42 +08:00
|
|
|
unsigned NumByteStores = Bytes % MaxIntSize;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// If we will reduce the # stores (according to this heuristic), do the
|
|
|
|
// transformation. This encourages merging 4 x i8 -> i32 and 2 x i16 -> i32
|
|
|
|
// etc.
|
|
|
|
return TheStores.size() > NumPointerStores+NumByteStores;
|
2012-07-24 18:51:42 +08:00
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
|
|
|
|
namespace {
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
class MemsetRanges {
|
2017-10-19 05:46:47 +08:00
|
|
|
using range_iterator = SmallVectorImpl<MemsetRange>::iterator;
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// A sorted list of the memset ranges.
|
2016-05-11 05:49:40 +08:00
|
|
|
SmallVector<MemsetRange, 8> Ranges;
|
2017-10-19 05:46:47 +08:00
|
|
|
|
2014-02-21 08:06:31 +08:00
|
|
|
const DataLayout &DL;
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
public:
|
2016-05-11 05:49:40 +08:00
|
|
|
MemsetRanges(const DataLayout &DL) : DL(DL) {}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2017-10-19 05:46:47 +08:00
|
|
|
using const_iterator = SmallVectorImpl<MemsetRange>::const_iterator;
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
const_iterator begin() const { return Ranges.begin(); }
|
|
|
|
const_iterator end() const { return Ranges.end(); }
|
|
|
|
bool empty() const { return Ranges.empty(); }
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
void addInst(int64_t OffsetFromFirst, Instruction *Inst) {
|
2011-01-09 04:54:51 +08:00
|
|
|
if (StoreInst *SI = dyn_cast<StoreInst>(Inst))
|
|
|
|
addStore(OffsetFromFirst, SI);
|
|
|
|
else
|
|
|
|
addMemSet(OffsetFromFirst, cast<MemSetInst>(Inst));
|
|
|
|
}
|
|
|
|
|
|
|
|
void addStore(int64_t OffsetFromFirst, StoreInst *SI) {
|
2014-02-21 08:06:31 +08:00
|
|
|
int64_t StoreSize = DL.getTypeStoreSize(SI->getOperand(0)->getType());
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
addRange(OffsetFromFirst, StoreSize,
|
2016-05-11 05:49:40 +08:00
|
|
|
SI->getPointerOperand(), SI->getAlignment(), SI);
|
2011-01-09 04:54:51 +08:00
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
void addMemSet(int64_t OffsetFromFirst, MemSetInst *MSI) {
|
|
|
|
int64_t Size = cast<ConstantInt>(MSI->getLength())->getZExtValue();
|
2016-05-11 05:49:40 +08:00
|
|
|
addRange(OffsetFromFirst, Size, MSI->getDest(), MSI->getAlignment(), MSI);
|
2011-01-09 04:24:01 +08:00
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
void addRange(int64_t Start, int64_t Size, Value *Ptr,
|
2011-01-09 04:54:51 +08:00
|
|
|
unsigned Alignment, Instruction *Inst);
|
2008-04-09 16:23:16 +08:00
|
|
|
};
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2017-01-18 08:57:48 +08:00
|
|
|
} // end anonymous namespace
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
/// Add a new store to the MemsetRanges data structure. This adds a
|
2008-04-09 16:23:16 +08:00
|
|
|
/// new range for the specified store at the specified offset, merging into
|
|
|
|
/// existing ranges as appropriate.
|
2016-05-11 05:49:40 +08:00
|
|
|
void MemsetRanges::addRange(int64_t Start, int64_t Size, Value *Ptr,
|
|
|
|
unsigned Alignment, Instruction *Inst) {
|
2011-01-09 04:54:51 +08:00
|
|
|
int64_t End = Start+Size;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2015-07-22 05:56:26 +08:00
|
|
|
range_iterator I = std::lower_bound(Ranges.begin(), Ranges.end(), Start,
|
2016-05-11 05:49:40 +08:00
|
|
|
[](const MemsetRange &LHS, int64_t RHS) { return LHS.End < RHS; });
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// We now know that I == E, in which case we didn't find anything to merge
|
|
|
|
// with, or that Start <= I->End. If End < I->Start or I == E, then we need
|
|
|
|
// to insert a new range. Handle this now.
|
2015-07-22 05:56:26 +08:00
|
|
|
if (I == Ranges.end() || End < I->Start) {
|
2016-05-11 05:49:40 +08:00
|
|
|
MemsetRange &R = *Ranges.insert(I, MemsetRange());
|
2008-04-09 16:23:16 +08:00
|
|
|
R.Start = Start;
|
|
|
|
R.End = End;
|
2016-05-11 05:49:40 +08:00
|
|
|
R.StartPtr = Ptr;
|
2011-01-09 04:54:51 +08:00
|
|
|
R.Alignment = Alignment;
|
|
|
|
R.TheStores.push_back(Inst);
|
2008-04-09 16:23:16 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// This store overlaps with I, add it.
|
2011-01-09 04:54:51 +08:00
|
|
|
I->TheStores.push_back(Inst);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// At this point, we may have an interval that completely contains our store.
|
|
|
|
// If so, just add it to the interval and return.
|
|
|
|
if (I->Start <= Start && I->End >= End)
|
|
|
|
return;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Now we know that Start <= I->End and End >= I->Start so the range overlaps
|
|
|
|
// but is not entirely contained within the range.
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// See if the range extends the start of the range. In this case, it couldn't
|
|
|
|
// possibly cause it to join the prior range, because otherwise we would have
|
|
|
|
// stopped on *it*.
|
|
|
|
if (Start < I->Start) {
|
|
|
|
I->Start = Start;
|
2016-05-11 05:49:40 +08:00
|
|
|
I->StartPtr = Ptr;
|
2011-01-09 04:54:51 +08:00
|
|
|
I->Alignment = Alignment;
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Now we know that Start <= I->End and Start >= I->Start (so the startpoint
|
|
|
|
// is in or right at the end of I), and that End >= I->Start. Extend I out to
|
|
|
|
// End.
|
|
|
|
if (End > I->End) {
|
|
|
|
I->End = End;
|
2009-03-19 13:51:39 +08:00
|
|
|
range_iterator NextI = I;
|
2015-07-22 05:56:26 +08:00
|
|
|
while (++NextI != Ranges.end() && End >= NextI->Start) {
|
2008-04-09 16:23:16 +08:00
|
|
|
// Merge the range in.
|
|
|
|
I->TheStores.append(NextI->TheStores.begin(), NextI->TheStores.end());
|
|
|
|
if (NextI->End > I->End)
|
|
|
|
I->End = NextI->End;
|
|
|
|
Ranges.erase(NextI);
|
|
|
|
NextI = I;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
2016-06-14 10:44:55 +08:00
|
|
|
// MemCpyOptLegacyPass Pass
|
2008-04-09 16:23:16 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace {
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2017-03-09 05:28:19 +08:00
|
|
|
class MemCpyOptLegacyPass : public FunctionPass {
|
|
|
|
MemCpyOptPass Impl;
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2017-03-09 05:28:19 +08:00
|
|
|
public:
|
|
|
|
static char ID; // Pass identification, replacement for typeid
|
2017-01-18 08:57:48 +08:00
|
|
|
|
2017-03-09 05:28:19 +08:00
|
|
|
MemCpyOptLegacyPass() : FunctionPass(ID) {
|
|
|
|
initializeMemCpyOptLegacyPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2017-03-09 05:28:19 +08:00
|
|
|
bool runOnFunction(Function &F) override;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// This transformation requires dominator postdominator info
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
|
|
|
AU.setPreservesCFG();
|
|
|
|
AU.addRequired<AssumptionCacheTracker>();
|
|
|
|
AU.addRequired<DominatorTreeWrapperPass>();
|
|
|
|
AU.addRequired<MemoryDependenceWrapperPass>();
|
|
|
|
AU.addRequired<AAResultsWrapperPass>();
|
|
|
|
AU.addRequired<TargetLibraryInfoWrapperPass>();
|
|
|
|
AU.addPreserved<GlobalsAAWrapperPass>();
|
|
|
|
AU.addPreserved<MemoryDependenceWrapperPass>();
|
|
|
|
}
|
|
|
|
};
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2017-01-18 08:57:48 +08:00
|
|
|
} // end anonymous namespace
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2017-10-19 05:46:47 +08:00
|
|
|
char MemCpyOptLegacyPass::ID = 0;
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// The public interface to this file...
|
2016-06-14 10:44:55 +08:00
|
|
|
FunctionPass *llvm::createMemCpyOptPass() { return new MemCpyOptLegacyPass(); }
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(MemCpyOptLegacyPass, "memcpyopt", "MemCpy Optimization",
|
2010-10-13 03:48:12 +08:00
|
|
|
false, false)
|
2016-12-19 16:22:17 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
|
2014-01-13 21:07:17 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
2016-03-10 08:55:30 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(MemoryDependenceWrapperPass)
|
2015-01-15 18:41:28 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
|
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups.
This builds essentially a ground-up new AA infrastructure stack for
LLVM. The core ideas are the same that are used throughout the new pass
manager: type erased polymorphism and direct composition. The design is
as follows:
- FunctionAAResults is a type-erasing alias analysis results aggregation
interface to walk a single query across a range of results from
different alias analyses. Currently this is function-specific as we
always assume that aliasing queries are *within* a function.
- AAResultBase is a CRTP utility providing stub implementations of
various parts of the alias analysis result concept, notably in several
cases in terms of other more general parts of the interface. This can
be used to implement only a narrow part of the interface rather than
the entire interface. This isn't really ideal, this logic should be
hoisted into FunctionAAResults as currently it will cause
a significant amount of redundant work, but it faithfully models the
behavior of the prior infrastructure.
- All the alias analysis passes are ported to be wrapper passes for the
legacy PM and new-style analysis passes for the new PM with a shared
result object. In some cases (most notably CFL), this is an extremely
naive approach that we should revisit when we can specialize for the
new pass manager.
- BasicAA has been restructured to reflect that it is much more
fundamentally a function analysis because it uses dominator trees and
loop info that need to be constructed for each function.
All of the references to getting alias analysis results have been
updated to use the new aggregation interface. All the preservation and
other pass management code has been updated accordingly.
The way the FunctionAAResultsWrapperPass works is to detect the
available alias analyses when run, and add them to the results object.
This means that we should be able to continue to respect when various
passes are added to the pipeline, for example adding CFL or adding TBAA
passes should just cause their results to be available and to get folded
into this. The exception to this rule is BasicAA which really needs to
be a function pass due to using dominator trees and loop info. As
a consequence, the FunctionAAResultsWrapperPass directly depends on
BasicAA and always includes it in the aggregation.
This has significant implications for preserving analyses. Generally,
most passes shouldn't bother preserving FunctionAAResultsWrapperPass
because rebuilding the results just updates the set of known AA passes.
The exception to this rule are LoopPass instances which need to preserve
all the function analyses that the loop pass manager will end up
needing. This means preserving both BasicAAWrapperPass and the
aggregating FunctionAAResultsWrapperPass.
Now, when preserving an alias analysis, you do so by directly preserving
that analysis. This is only necessary for non-immutable-pass-provided
alias analyses though, and there are only three of interest: BasicAA,
GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is
preserved when needed because it (like DominatorTree and LoopInfo) is
marked as a CFG-only pass. I've expanded GlobalsAA into the preserved
set everywhere we previously were preserving all of AliasAnalysis, and
I've added SCEVAA in the intersection of that with where we preserve
SCEV itself.
One significant challenge to all of this is that the CGSCC passes were
actually using the alias analysis implementations by taking advantage of
a pretty amazing set of loop holes in the old pass manager's analysis
management code which allowed analysis groups to slide through in many
cases. Moving away from analysis groups makes this problem much more
obvious. To fix it, I've leveraged the flexibility the design of the new
PM components provides to just directly construct the relevant alias
analyses for the relevant functions in the IPO passes that need them.
This is a bit hacky, but should go away with the new pass manager, and
is already in many ways cleaner than the prior state.
Another significant challenge is that various facilities of the old
alias analysis infrastructure just don't fit any more. The most
significant of these is the alias analysis 'counter' pass. That pass
relied on the ability to snoop on AA queries at different points in the
analysis group chain. Instead, I'm planning to build printing
functionality directly into the aggregation layer. I've not included
that in this patch merely to keep it smaller.
Note that all of this needs a nearly complete rewrite of the AA
documentation. I'm planning to do that, but I'd like to make sure the
new design settles, and to flesh out a bit more of what it looks like in
the new pass manager first.
Differential Revision: http://reviews.llvm.org/D12080
llvm-svn: 247167
2015-09-10 01:55:00 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
|
|
|
INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
|
2016-06-14 10:44:55 +08:00
|
|
|
INITIALIZE_PASS_END(MemCpyOptLegacyPass, "memcpyopt", "MemCpy Optimization",
|
2010-10-13 03:48:12 +08:00
|
|
|
false, false)
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// When scanning forward over instructions, we look for some other patterns to
|
|
|
|
/// fold away. In particular, this looks for stores to neighboring locations of
|
|
|
|
/// memory. If it sees enough consecutive ones, it attempts to merge them
|
|
|
|
/// together into a memcpy/memset.
|
2016-06-14 10:44:55 +08:00
|
|
|
Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,
|
|
|
|
Value *StartPtr,
|
|
|
|
Value *ByteVal) {
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL = StartInst->getModule()->getDataLayout();
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Okay, so we now have a single store that can be splatable. Scan to find
|
|
|
|
// all subsequent stores of the same value to offset from the same pointer.
|
|
|
|
// Join these together into ranges, so we can decide whether contiguous blocks
|
|
|
|
// are stored.
|
2016-05-11 05:49:40 +08:00
|
|
|
MemsetRanges Ranges(DL);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2015-10-14 03:26:58 +08:00
|
|
|
BasicBlock::iterator BI(StartInst);
|
2008-04-09 16:23:16 +08:00
|
|
|
for (++BI; !isa<TerminatorInst>(BI); ++BI) {
|
2011-01-09 04:54:51 +08:00
|
|
|
if (!isa<StoreInst>(BI) && !isa<MemSetInst>(BI)) {
|
|
|
|
// If the instruction is readnone, ignore it, otherwise bail out. We
|
|
|
|
// don't even allow readonly here because we don't want something like:
|
2008-04-09 16:23:16 +08:00
|
|
|
// A[1] = 2; strlen(A); A[2] = 2; -> memcpy(A, ...); strlen(A).
|
2011-01-09 04:54:51 +08:00
|
|
|
if (BI->mayWriteToMemory() || BI->mayReadFromMemory())
|
|
|
|
break;
|
|
|
|
continue;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
if (StoreInst *NextStore = dyn_cast<StoreInst>(BI)) {
|
|
|
|
// If this is a store, see if we can merge it in.
|
2011-08-18 06:22:24 +08:00
|
|
|
if (!NextStore->isSimple()) break;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
// Check to see if this stored value is of the same byte-splattable value.
|
|
|
|
if (ByteVal != isBytewiseValue(NextStore->getOperand(0)))
|
|
|
|
break;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
// Check to see if this store is to a constant offset from the start ptr.
|
|
|
|
int64_t Offset;
|
2015-03-10 10:37:25 +08:00
|
|
|
if (!IsPointerOffset(StartPtr, NextStore->getPointerOperand(), Offset,
|
|
|
|
DL))
|
2011-01-09 04:54:51 +08:00
|
|
|
break;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
Ranges.addStore(Offset, NextStore);
|
|
|
|
} else {
|
|
|
|
MemSetInst *MSI = cast<MemSetInst>(BI);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
if (MSI->isVolatile() || ByteVal != MSI->getValue() ||
|
|
|
|
!isa<ConstantInt>(MSI->getLength()))
|
|
|
|
break;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
// Check to see if this store is to a constant offset from the start ptr.
|
|
|
|
int64_t Offset;
|
2015-03-10 10:37:25 +08:00
|
|
|
if (!IsPointerOffset(StartPtr, MSI->getDest(), Offset, DL))
|
2011-01-09 04:54:51 +08:00
|
|
|
break;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:54:51 +08:00
|
|
|
Ranges.addMemSet(Offset, MSI);
|
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// If we have no ranges, then we just had a single store with nothing that
|
|
|
|
// could be merged in. This is a very common case of course.
|
|
|
|
if (Ranges.empty())
|
2014-04-25 13:29:35 +08:00
|
|
|
return nullptr;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// If we had at least one store that could be merged in, add the starting
|
|
|
|
// store as well. We try to avoid this unless there is at least something
|
|
|
|
// interesting as a small compile-time optimization.
|
2011-01-09 04:24:01 +08:00
|
|
|
Ranges.addInst(0, StartInst);
|
|
|
|
|
|
|
|
// If we create any memsets, we put it right before the first instruction that
|
|
|
|
// isn't part of the memset block. This ensure that the memset is dominated
|
|
|
|
// by any addressing instruction needed by the start of the block.
|
2015-10-14 03:26:58 +08:00
|
|
|
IRBuilder<> Builder(&*BI);
|
2011-01-09 04:24:01 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Now that we have full information about ranges, loop over the ranges and
|
|
|
|
// emit memset's for anything big enough to be worthwhile.
|
2014-04-25 13:29:35 +08:00
|
|
|
Instruction *AMemSet = nullptr;
|
2016-05-11 05:49:40 +08:00
|
|
|
for (const MemsetRange &Range : Ranges) {
|
2008-04-09 16:23:16 +08:00
|
|
|
if (Range.TheStores.size() == 1) continue;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// If it is profitable to lower this range to memset, do so now.
|
2016-05-11 05:49:40 +08:00
|
|
|
if (!Range.isProfitableToUseMemset(DL))
|
2008-04-09 16:23:16 +08:00
|
|
|
continue;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
// Otherwise, we do want to transform this! Create a new memset.
|
2008-04-09 16:23:16 +08:00
|
|
|
// Get the starting pointer of the block.
|
2016-05-11 05:49:40 +08:00
|
|
|
StartPtr = Range.StartPtr;
|
|
|
|
|
|
|
|
// Determine alignment
|
Reapply address space patch after fixing an issue in MemCopyOptimizer.
Added support for address spaces and added a isVolatile field to memcpy, memmove, and memset,
e.g., llvm.memcpy.i32(i8*, i8*, i32, i32) -> llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i32, i1)
llvm-svn: 100304
2010-04-04 11:10:48 +08:00
|
|
|
unsigned Alignment = Range.Alignment;
|
2016-05-11 05:49:40 +08:00
|
|
|
if (Alignment == 0) {
|
|
|
|
Type *EltType =
|
|
|
|
cast<PointerType>(StartPtr->getType())->getElementType();
|
|
|
|
Alignment = DL.getABITypeAlignment(EltType);
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
AMemSet =
|
|
|
|
Builder.CreateMemSet(StartPtr, ByteVal, Range.End-Range.Start, Alignment);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-01-05 09:27:47 +08:00
|
|
|
DEBUG(dbgs() << "Replace stores:\n";
|
2015-11-20 15:18:48 +08:00
|
|
|
for (Instruction *SI : Range.TheStores)
|
|
|
|
dbgs() << *SI << '\n';
|
2011-01-09 04:24:01 +08:00
|
|
|
dbgs() << "With: " << *AMemSet << '\n');
|
2011-05-05 05:58:58 +08:00
|
|
|
|
|
|
|
if (!Range.TheStores.empty())
|
|
|
|
AMemSet->setDebugLoc(Range.TheStores[0]->getDebugLoc());
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Zap all the stores.
|
2015-11-20 15:18:48 +08:00
|
|
|
for (Instruction *SI : Range.TheStores) {
|
|
|
|
MD->removeInstruction(SI);
|
|
|
|
SI->eraseFromParent();
|
2011-01-09 06:19:21 +08:00
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
++NumMemSetInfer;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
return AMemSet;
|
|
|
|
}
|
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
static unsigned findCommonAlignment(const DataLayout &DL, const StoreInst *SI,
|
|
|
|
const LoadInst *LI) {
|
|
|
|
unsigned StoreAlign = SI->getAlignment();
|
|
|
|
if (!StoreAlign)
|
|
|
|
StoreAlign = DL.getABITypeAlignment(SI->getOperand(0)->getType());
|
|
|
|
unsigned LoadAlign = LI->getAlignment();
|
|
|
|
if (!LoadAlign)
|
|
|
|
LoadAlign = DL.getABITypeAlignment(LI->getType());
|
2016-05-11 05:48:11 +08:00
|
|
|
|
2016-05-11 05:49:40 +08:00
|
|
|
return std::min(StoreAlign, LoadAlign);
|
2016-01-06 04:17:48 +08:00
|
|
|
}
|
2011-01-09 04:24:01 +08:00
|
|
|
|
2016-03-15 06:52:27 +08:00
|
|
|
// This method try to lift a store instruction before position P.
|
|
|
|
// It will lift the store and its argument + that anything that
|
2016-05-27 03:24:24 +08:00
|
|
|
// may alias with these.
|
2016-03-15 06:52:27 +08:00
|
|
|
// The method returns true if it was successful.
|
2016-12-28 01:58:12 +08:00
|
|
|
static bool moveUp(AliasAnalysis &AA, StoreInst *SI, Instruction *P,
|
|
|
|
const LoadInst *LI) {
|
2016-03-15 06:52:27 +08:00
|
|
|
// If the store alias this position, early bail out.
|
|
|
|
MemoryLocation StoreLoc = MemoryLocation::get(SI);
|
|
|
|
if (AA.getModRefInfo(P, StoreLoc) != MRI_NoModRef)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Keep track of the arguments of all instruction we plan to lift
|
|
|
|
// so we can make sure to lift them as well if apropriate.
|
|
|
|
DenseSet<Instruction*> Args;
|
|
|
|
if (auto *Ptr = dyn_cast<Instruction>(SI->getPointerOperand()))
|
|
|
|
if (Ptr->getParent() == SI->getParent())
|
|
|
|
Args.insert(Ptr);
|
|
|
|
|
|
|
|
// Instruction to lift before P.
|
|
|
|
SmallVector<Instruction*, 8> ToLift;
|
|
|
|
|
|
|
|
// Memory locations of lifted instructions.
|
2016-12-28 01:58:12 +08:00
|
|
|
SmallVector<MemoryLocation, 8> MemLocs{StoreLoc};
|
2016-03-15 06:52:27 +08:00
|
|
|
|
|
|
|
// Lifted callsites.
|
|
|
|
SmallVector<ImmutableCallSite, 8> CallSites;
|
|
|
|
|
2016-12-28 01:58:12 +08:00
|
|
|
const MemoryLocation LoadLoc = MemoryLocation::get(LI);
|
|
|
|
|
2016-03-15 06:52:27 +08:00
|
|
|
for (auto I = --SI->getIterator(), E = P->getIterator(); I != E; --I) {
|
|
|
|
auto *C = &*I;
|
|
|
|
|
2017-08-01 08:47:17 +08:00
|
|
|
bool MayAlias = AA.getModRefInfo(C, None) != MRI_NoModRef;
|
2016-03-15 06:52:27 +08:00
|
|
|
|
|
|
|
bool NeedLift = false;
|
|
|
|
if (Args.erase(C))
|
|
|
|
NeedLift = true;
|
|
|
|
else if (MayAlias) {
|
2017-01-18 08:57:48 +08:00
|
|
|
NeedLift = llvm::any_of(MemLocs, [C, &AA](const MemoryLocation &ML) {
|
2016-08-12 05:15:00 +08:00
|
|
|
return AA.getModRefInfo(C, ML);
|
|
|
|
});
|
2016-03-15 06:52:27 +08:00
|
|
|
|
|
|
|
if (!NeedLift)
|
2017-01-18 08:57:48 +08:00
|
|
|
NeedLift =
|
|
|
|
llvm::any_of(CallSites, [C, &AA](const ImmutableCallSite &CS) {
|
|
|
|
return AA.getModRefInfo(C, CS);
|
|
|
|
});
|
2016-03-15 06:52:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!NeedLift)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (MayAlias) {
|
2016-12-28 01:58:12 +08:00
|
|
|
// Since LI is implicitly moved downwards past the lifted instructions,
|
|
|
|
// none of them may modify its source.
|
|
|
|
if (AA.getModRefInfo(C, LoadLoc) & MRI_Mod)
|
|
|
|
return false;
|
|
|
|
else if (auto CS = ImmutableCallSite(C)) {
|
2016-03-15 06:52:27 +08:00
|
|
|
// If we can't lift this before P, it's game over.
|
|
|
|
if (AA.getModRefInfo(P, CS) != MRI_NoModRef)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CallSites.push_back(CS);
|
|
|
|
} else if (isa<LoadInst>(C) || isa<StoreInst>(C) || isa<VAArgInst>(C)) {
|
|
|
|
// If we can't lift this before P, it's game over.
|
|
|
|
auto ML = MemoryLocation::get(C);
|
|
|
|
if (AA.getModRefInfo(P, ML) != MRI_NoModRef)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MemLocs.push_back(ML);
|
|
|
|
} else
|
|
|
|
// We don't know how to lift this instruction.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ToLift.push_back(C);
|
|
|
|
for (unsigned k = 0, e = C->getNumOperands(); k != e; ++k)
|
|
|
|
if (auto *A = dyn_cast<Instruction>(C->getOperand(k)))
|
|
|
|
if (A->getParent() == SI->getParent())
|
|
|
|
Args.insert(A);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We made it, we need to lift
|
2017-01-18 08:57:48 +08:00
|
|
|
for (auto *I : llvm::reverse(ToLift)) {
|
2016-03-15 06:52:27 +08:00
|
|
|
DEBUG(dbgs() << "Lifting " << *I << " before " << *P << "\n");
|
|
|
|
I->moveBefore(P);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processStore(StoreInst *SI, BasicBlock::iterator &BBI) {
|
2011-08-18 06:22:24 +08:00
|
|
|
if (!SI->isSimple()) return false;
|
[MemCpyOpt] Fix wrong merging adjacent nontemporal stores into memset calls.
Pass MemCpyOpt doesn't check if a store instruction is nontemporal.
As a consequence, adjacent nontemporal stores are always merged into a
memset call.
Example:
;;;
define void @foo(<4 x float>* nocapture %p) {
entry:
store <4 x float> zeroinitializer, <4 x float>* %p, align 16, !nontemporal !0
%p1 = getelementptr inbounds <4 x float>, <4 x float>* %dst, i64 1
store <4 x float> zeroinitializer, <4 x float>* %p1, align 16, !nontemporal !0
ret void
}
!0 = !{i32 1}
;;;
In this example, the two nontemporal stores are combined to a memset of zero
which does not preserve the nontemporal hint. Later on the backend (tested on a
x86-64 corei7) expands that memset call into a sequence of two normal 16-byte
aligned vector stores.
opt -memcpyopt example.ll -S -o - | llc -mcpu=corei7 -o -
Before:
xorps %xmm0, %xmm0
movaps %xmm0, 16(%rdi)
movaps %xmm0, (%rdi)
With this patch, we no longer merge nontemporal stores into calls to memset.
In this example, llc correctly expands the two stores into two movntps:
xorps %xmm0, %xmm0
movntps %xmm0, 16(%rdi)
movntps %xmm0, (%rdi)
In theory, we could extend the usage of !nontemporal metadata to memcpy/memset
calls. However a change like that would only have the effect of forcing the
backend to expand !nontemporal memsets back to sequences of store instructions.
A memset library call would not have exactly the same semantic of a builtin
!nontemporal memset call. So, SelectionDAG will have to conservatively expand
it back to a sequence of !nontemporal stores (effectively undoing the merging).
Differential Revision: http://reviews.llvm.org/D13519
llvm-svn: 249820
2015-10-09 18:53:41 +08:00
|
|
|
|
|
|
|
// Avoid merging nontemporal stores since the resulting
|
|
|
|
// memcpy/memset would not be able to preserve the nontemporal hint.
|
|
|
|
// In theory we could teach how to propagate the !nontemporal metadata to
|
|
|
|
// memset calls. However, that change would force the backend to
|
|
|
|
// conservatively expand !nontemporal memset calls back to sequences of
|
|
|
|
// store instructions (effectively undoing the merging).
|
|
|
|
if (SI->getMetadata(LLVMContext::MD_nontemporal))
|
|
|
|
return false;
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL = SI->getModule()->getDataLayout();
|
2011-01-09 04:24:01 +08:00
|
|
|
|
2016-01-06 04:17:48 +08:00
|
|
|
// Load to store forwarding can be interpreted as memcpy.
|
2011-01-09 04:24:01 +08:00
|
|
|
if (LoadInst *LI = dyn_cast<LoadInst>(SI->getOperand(0))) {
|
2011-08-18 06:22:24 +08:00
|
|
|
if (LI->isSimple() && LI->hasOneUse() &&
|
2011-06-15 09:25:56 +08:00
|
|
|
LI->getParent() == SI->getParent()) {
|
2016-01-06 04:17:48 +08:00
|
|
|
|
|
|
|
auto *T = LI->getType();
|
|
|
|
if (T->isAggregateType()) {
|
2016-06-14 10:44:55 +08:00
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
2016-01-06 04:17:48 +08:00
|
|
|
MemoryLocation LoadLoc = MemoryLocation::get(LI);
|
|
|
|
|
|
|
|
// We use alias analysis to check if an instruction may store to
|
|
|
|
// the memory we load from in between the load and the store. If
|
2016-01-06 17:30:39 +08:00
|
|
|
// such an instruction is found, we try to promote there instead
|
|
|
|
// of at the store position.
|
|
|
|
Instruction *P = SI;
|
2016-03-15 06:52:27 +08:00
|
|
|
for (auto &I : make_range(++LI->getIterator(), SI->getIterator())) {
|
|
|
|
if (AA.getModRefInfo(&I, LoadLoc) & MRI_Mod) {
|
|
|
|
P = &I;
|
|
|
|
break;
|
2016-01-06 04:17:48 +08:00
|
|
|
}
|
2016-03-15 06:52:27 +08:00
|
|
|
}
|
2016-01-06 17:30:39 +08:00
|
|
|
|
2016-03-15 06:52:27 +08:00
|
|
|
// We found an instruction that may write to the loaded memory.
|
|
|
|
// We can try to promote at this position instead of the store
|
|
|
|
// position if nothing alias the store memory after this and the store
|
|
|
|
// destination is not in the range.
|
|
|
|
if (P && P != SI) {
|
2016-12-28 01:58:12 +08:00
|
|
|
if (!moveUp(AA, SI, P, LI))
|
2016-03-15 06:52:27 +08:00
|
|
|
P = nullptr;
|
2016-01-06 04:17:48 +08:00
|
|
|
}
|
|
|
|
|
2016-01-06 17:30:39 +08:00
|
|
|
// If a valid insertion position is found, then we can promote
|
|
|
|
// the load/store pair to a memcpy.
|
|
|
|
if (P) {
|
2016-01-06 04:17:48 +08:00
|
|
|
// If we load from memory that may alias the memory we store to,
|
|
|
|
// memmove must be used to preserve semantic. If not, memcpy can
|
|
|
|
// be used.
|
|
|
|
bool UseMemMove = false;
|
|
|
|
if (!AA.isNoAlias(MemoryLocation::get(SI), LoadLoc))
|
|
|
|
UseMemMove = true;
|
|
|
|
|
|
|
|
unsigned Align = findCommonAlignment(DL, SI, LI);
|
|
|
|
uint64_t Size = DL.getTypeStoreSize(T);
|
|
|
|
|
2016-01-06 17:30:39 +08:00
|
|
|
IRBuilder<> Builder(P);
|
2016-01-06 04:17:48 +08:00
|
|
|
Instruction *M;
|
|
|
|
if (UseMemMove)
|
|
|
|
M = Builder.CreateMemMove(SI->getPointerOperand(),
|
|
|
|
LI->getPointerOperand(), Size,
|
|
|
|
Align, SI->isVolatile());
|
|
|
|
else
|
|
|
|
M = Builder.CreateMemCpy(SI->getPointerOperand(),
|
|
|
|
LI->getPointerOperand(), Size,
|
|
|
|
Align, SI->isVolatile());
|
|
|
|
|
|
|
|
DEBUG(dbgs() << "Promoting " << *LI << " to " << *SI
|
|
|
|
<< " => " << *M << "\n");
|
|
|
|
|
|
|
|
MD->removeInstruction(SI);
|
|
|
|
SI->eraseFromParent();
|
|
|
|
MD->removeInstruction(LI);
|
|
|
|
LI->eraseFromParent();
|
|
|
|
++NumMemCpyInstr;
|
|
|
|
|
|
|
|
// Make sure we do not invalidate the iterator.
|
|
|
|
BBI = M->getIterator();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Detect cases where we're performing call slot forwarding, but
|
|
|
|
// happen to be using a load-store pair to implement it, rather than
|
|
|
|
// a memcpy.
|
2011-06-03 05:24:42 +08:00
|
|
|
MemDepResult ldep = MD->getDependency(LI);
|
2014-04-25 13:29:35 +08:00
|
|
|
CallInst *C = nullptr;
|
2011-06-03 05:24:42 +08:00
|
|
|
if (ldep.isClobber() && !isa<MemCpyInst>(ldep.getInst()))
|
|
|
|
C = dyn_cast<CallInst>(ldep.getInst());
|
|
|
|
|
|
|
|
if (C) {
|
|
|
|
// Check that nothing touches the dest of the "copy" between
|
|
|
|
// the call and the store.
|
2016-05-27 03:24:24 +08:00
|
|
|
Value *CpyDest = SI->getPointerOperand()->stripPointerCasts();
|
|
|
|
bool CpyDestIsLocal = isa<AllocaInst>(CpyDest);
|
2016-06-14 10:44:55 +08:00
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
2015-06-17 15:18:54 +08:00
|
|
|
MemoryLocation StoreLoc = MemoryLocation::get(SI);
|
2015-10-14 03:26:58 +08:00
|
|
|
for (BasicBlock::iterator I = --SI->getIterator(), E = C->getIterator();
|
|
|
|
I != E; --I) {
|
2015-07-23 07:15:57 +08:00
|
|
|
if (AA.getModRefInfo(&*I, StoreLoc) != MRI_NoModRef) {
|
2014-04-25 13:29:35 +08:00
|
|
|
C = nullptr;
|
2011-06-15 09:25:56 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-05-27 03:24:24 +08:00
|
|
|
// The store to dest may never happen if an exception can be thrown
|
|
|
|
// between the load and the store.
|
|
|
|
if (I->mayThrow() && !CpyDestIsLocal) {
|
|
|
|
C = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
2011-06-03 05:24:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
if (C) {
|
2015-03-10 10:37:25 +08:00
|
|
|
bool changed = performCallSlotOptzn(
|
|
|
|
LI, SI->getPointerOperand()->stripPointerCasts(),
|
|
|
|
LI->getPointerOperand()->stripPointerCasts(),
|
|
|
|
DL.getTypeStoreSize(SI->getOperand(0)->getType()),
|
2016-01-06 04:17:48 +08:00
|
|
|
findCommonAlignment(DL, SI, LI), C);
|
2011-01-09 04:24:01 +08:00
|
|
|
if (changed) {
|
|
|
|
MD->removeInstruction(SI);
|
|
|
|
SI->eraseFromParent();
|
2011-01-10 03:26:10 +08:00
|
|
|
MD->removeInstruction(LI);
|
2011-01-09 04:24:01 +08:00
|
|
|
LI->eraseFromParent();
|
|
|
|
++NumMemCpyInstr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
// There are two cases that are interesting for this code to handle: memcpy
|
|
|
|
// and memset. Right now we only handle memset.
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
// 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.
|
2016-01-07 03:47:24 +08:00
|
|
|
auto *V = SI->getOperand(0);
|
|
|
|
if (Value *ByteVal = isBytewiseValue(V)) {
|
2011-01-09 04:24:01 +08:00
|
|
|
if (Instruction *I = tryMergingIntoMemset(SI, SI->getPointerOperand(),
|
|
|
|
ByteVal)) {
|
2015-10-14 03:26:58 +08:00
|
|
|
BBI = I->getIterator(); // Don't invalidate iterator.
|
2011-01-09 04:24:01 +08:00
|
|
|
return true;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-01-07 03:47:24 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-09 04:24:01 +08:00
|
|
|
return false;
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processMemSet(MemSetInst *MSI, BasicBlock::iterator &BBI) {
|
2011-01-09 05:19:19 +08:00
|
|
|
// See if there is another memset or store neighboring this memset which
|
|
|
|
// allows us to widen out the memset to do a single larger store.
|
2011-01-09 06:11:56 +08:00
|
|
|
if (isa<ConstantInt>(MSI->getLength()) && !MSI->isVolatile())
|
|
|
|
if (Instruction *I = tryMergingIntoMemset(MSI, MSI->getDest(),
|
|
|
|
MSI->getValue())) {
|
2015-10-14 03:26:58 +08:00
|
|
|
BBI = I->getIterator(); // Don't invalidate iterator.
|
2011-01-09 06:11:56 +08:00
|
|
|
return true;
|
|
|
|
}
|
2011-01-09 05:19:19 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// Takes a memcpy and a call that it depends on,
|
2008-04-09 16:23:16 +08:00
|
|
|
/// and checks for the possibility of a call slot optimization by having
|
|
|
|
/// the call write its result directly into the destination of the memcpy.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpy, Value *cpyDest,
|
|
|
|
Value *cpySrc, uint64_t cpyLen,
|
|
|
|
unsigned cpyAlign, CallInst *C) {
|
2008-04-09 16:23:16 +08:00
|
|
|
// The general transformation to keep in mind is
|
|
|
|
//
|
|
|
|
// call @func(..., src, ...)
|
|
|
|
// memcpy(dest, src, ...)
|
|
|
|
//
|
|
|
|
// ->
|
|
|
|
//
|
|
|
|
// memcpy(dest, src, ...)
|
|
|
|
// call @func(..., dest, ...)
|
|
|
|
//
|
|
|
|
// Since moving the memcpy is technically awkward, we additionally check that
|
|
|
|
// src only holds uninitialized values at the moment of the call, meaning that
|
|
|
|
// the memcpy can be discarded rather than moved.
|
|
|
|
|
2016-06-09 03:42:32 +08:00
|
|
|
// Lifetime marks shouldn't be operated on.
|
|
|
|
if (Function *F = C->getCalledFunction())
|
|
|
|
if (F->isIntrinsic() && F->getIntrinsicID() == Intrinsic::lifetime_start)
|
|
|
|
return false;
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Deliberately get the source and destination with bitcasts stripped away,
|
|
|
|
// because we'll need to do type comparisons based on the underlying type.
|
2010-07-29 06:50:26 +08:00
|
|
|
CallSite CS(C);
|
2008-04-09 16:23:16 +08:00
|
|
|
|
|
|
|
// Require that src be an alloca. This simplifies the reasoning considerably.
|
2009-09-02 01:09:55 +08:00
|
|
|
AllocaInst *srcAlloca = dyn_cast<AllocaInst>(cpySrc);
|
2008-04-09 16:23:16 +08:00
|
|
|
if (!srcAlloca)
|
|
|
|
return false;
|
|
|
|
|
2009-09-02 01:09:55 +08:00
|
|
|
ConstantInt *srcArraySize = dyn_cast<ConstantInt>(srcAlloca->getArraySize());
|
2008-04-09 16:23:16 +08:00
|
|
|
if (!srcArraySize)
|
|
|
|
return false;
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL = cpy->getModule()->getDataLayout();
|
|
|
|
uint64_t srcSize = DL.getTypeAllocSize(srcAlloca->getAllocatedType()) *
|
|
|
|
srcArraySize->getZExtValue();
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2010-10-16 06:52:12 +08:00
|
|
|
if (cpyLen < srcSize)
|
2008-04-09 16:23:16 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Check that accessing the first srcSize bytes of dest will not cause a
|
|
|
|
// trap. Otherwise the transform is invalid since it might cause a trap
|
|
|
|
// to occur earlier than it otherwise would.
|
2009-09-02 01:09:55 +08:00
|
|
|
if (AllocaInst *A = dyn_cast<AllocaInst>(cpyDest)) {
|
2008-04-09 16:23:16 +08:00
|
|
|
// The destination is an alloca. Check it is larger than srcSize.
|
2009-09-02 01:09:55 +08:00
|
|
|
ConstantInt *destArraySize = dyn_cast<ConstantInt>(A->getArraySize());
|
2008-04-09 16:23:16 +08:00
|
|
|
if (!destArraySize)
|
|
|
|
return false;
|
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
uint64_t destSize = DL.getTypeAllocSize(A->getAllocatedType()) *
|
|
|
|
destArraySize->getZExtValue();
|
2008-04-09 16:23:16 +08:00
|
|
|
|
|
|
|
if (destSize < srcSize)
|
|
|
|
return false;
|
2009-09-02 01:09:55 +08:00
|
|
|
} else if (Argument *A = dyn_cast<Argument>(cpyDest)) {
|
2016-05-27 03:24:24 +08:00
|
|
|
// The store to dest may never happen if the call can throw.
|
|
|
|
if (C->mayThrow())
|
|
|
|
return false;
|
|
|
|
|
2014-10-17 03:43:08 +08:00
|
|
|
if (A->getDereferenceableBytes() < srcSize) {
|
|
|
|
// If the destination is an sret parameter then only accesses that are
|
|
|
|
// outside of the returned struct type can trap.
|
|
|
|
if (!A->hasStructRetAttr())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
Type *StructTy = cast<PointerType>(A->getType())->getElementType();
|
|
|
|
if (!StructTy->isSized()) {
|
|
|
|
// The call may never return and hence the copy-instruction may never
|
|
|
|
// be executed, and therefore it's not safe to say "the destination
|
|
|
|
// has at least <cpyLen> bytes, as implied by the copy-instruction",
|
|
|
|
return false;
|
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2015-03-10 10:37:25 +08:00
|
|
|
uint64_t destSize = DL.getTypeAllocSize(StructTy);
|
2014-10-17 03:43:08 +08:00
|
|
|
if (destSize < srcSize)
|
|
|
|
return false;
|
2013-06-08 12:56:05 +08:00
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-10-05 15:29:46 +08:00
|
|
|
// Check that dest points to memory that is at least as aligned as src.
|
|
|
|
unsigned srcAlign = srcAlloca->getAlignment();
|
|
|
|
if (!srcAlign)
|
2015-03-10 10:37:25 +08:00
|
|
|
srcAlign = DL.getABITypeAlignment(srcAlloca->getAllocatedType());
|
2012-10-05 15:29:46 +08:00
|
|
|
bool isDestSufficientlyAligned = srcAlign <= cpyAlign;
|
|
|
|
// If dest is not aligned enough and we can't increase its alignment then
|
|
|
|
// bail out.
|
|
|
|
if (!isDestSufficientlyAligned && !isa<AllocaInst>(cpyDest))
|
|
|
|
return false;
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Check that src is not accessed except via the call and the memcpy. This
|
|
|
|
// guarantees that it holds only undefined values when passed in (so the final
|
|
|
|
// memcpy can be dropped), that it is not read or written between the call and
|
|
|
|
// the memcpy, and that writing beyond the end of it is undefined.
|
2014-03-09 11:16:01 +08:00
|
|
|
SmallVector<User*, 8> srcUseList(srcAlloca->user_begin(),
|
|
|
|
srcAlloca->user_end());
|
2008-04-09 16:23:16 +08:00
|
|
|
while (!srcUseList.empty()) {
|
2014-03-09 11:16:01 +08:00
|
|
|
User *U = srcUseList.pop_back_val();
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2014-03-09 11:16:01 +08:00
|
|
|
if (isa<BitCastInst>(U) || isa<AddrSpaceCastInst>(U)) {
|
|
|
|
for (User *UU : U->users())
|
|
|
|
srcUseList.push_back(UU);
|
2014-09-01 18:09:18 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (GetElementPtrInst *G = dyn_cast<GetElementPtrInst>(U)) {
|
|
|
|
if (!G->hasAllZeroIndices())
|
2008-06-02 06:26:26 +08:00
|
|
|
return false;
|
2014-09-01 18:09:18 +08:00
|
|
|
|
|
|
|
for (User *UU : U->users())
|
|
|
|
srcUseList.push_back(UU);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (const IntrinsicInst *IT = dyn_cast<IntrinsicInst>(U))
|
|
|
|
if (IT->getIntrinsicID() == Intrinsic::lifetime_start ||
|
|
|
|
IT->getIntrinsicID() == Intrinsic::lifetime_end)
|
2014-09-01 14:03:11 +08:00
|
|
|
continue;
|
2014-09-01 18:09:18 +08:00
|
|
|
|
|
|
|
if (U != C && U != cpy)
|
2008-04-09 16:23:16 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-07-15 02:52:02 +08:00
|
|
|
// Check that src isn't captured by the called function since the
|
|
|
|
// transformation can cause aliasing issues in that case.
|
|
|
|
for (unsigned i = 0, e = CS.arg_size(); i != e; ++i)
|
|
|
|
if (CS.getArgument(i) == cpySrc && !CS.doesNotCapture(i))
|
|
|
|
return false;
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Since we're changing the parameter to the callsite, we need to make sure
|
|
|
|
// that what would be the new parameter dominates the callsite.
|
2016-06-14 10:44:55 +08:00
|
|
|
DominatorTree &DT = LookupDomTree();
|
2009-09-02 01:09:55 +08:00
|
|
|
if (Instruction *cpyDestInst = dyn_cast<Instruction>(cpyDest))
|
2008-04-09 16:23:16 +08:00
|
|
|
if (!DT.dominates(cpyDestInst, C))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// In addition to knowing that the call does not access src in some
|
|
|
|
// unexpected manner, for example via a global, which we deduce from
|
|
|
|
// the use analysis, we also need to know that it does not sneakily
|
|
|
|
// access dest. We rely on AA to figure this out for us.
|
2016-06-14 10:44:55 +08:00
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
2015-07-23 07:15:57 +08:00
|
|
|
ModRefInfo MR = AA.getModRefInfo(C, cpyDest, srcSize);
|
2012-05-15 04:35:04 +08:00
|
|
|
// If necessary, perform additional analysis.
|
2015-07-23 07:15:57 +08:00
|
|
|
if (MR != MRI_NoModRef)
|
2012-05-15 04:35:04 +08:00
|
|
|
MR = AA.callCapturesBefore(C, cpyDest, srcSize, &DT);
|
2015-07-23 07:15:57 +08:00
|
|
|
if (MR != MRI_NoModRef)
|
2008-04-09 16:23:16 +08:00
|
|
|
return false;
|
|
|
|
|
2017-03-15 06:37:38 +08:00
|
|
|
// We can't create address space casts here because we don't know if they're
|
|
|
|
// safe for the target.
|
|
|
|
if (cpySrc->getType()->getPointerAddressSpace() !=
|
|
|
|
cpyDest->getType()->getPointerAddressSpace())
|
|
|
|
return false;
|
|
|
|
for (unsigned i = 0; i < CS.arg_size(); ++i)
|
|
|
|
if (CS.getArgument(i)->stripPointerCasts() == cpySrc &&
|
|
|
|
cpySrc->getType()->getPointerAddressSpace() !=
|
|
|
|
CS.getArgument(i)->getType()->getPointerAddressSpace())
|
|
|
|
return false;
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// All the checks have passed, so do the transformation.
|
2008-06-02 05:52:16 +08:00
|
|
|
bool changedArgument = false;
|
2008-04-09 16:23:16 +08:00
|
|
|
for (unsigned i = 0; i < CS.arg_size(); ++i)
|
2008-06-02 06:26:26 +08:00
|
|
|
if (CS.getArgument(i)->stripPointerCasts() == cpySrc) {
|
2012-10-04 21:53:21 +08:00
|
|
|
Value *Dest = cpySrc->getType() == cpyDest->getType() ? cpyDest
|
|
|
|
: CastInst::CreatePointerCast(cpyDest, cpySrc->getType(),
|
|
|
|
cpyDest->getName(), C);
|
2008-06-02 05:52:16 +08:00
|
|
|
changedArgument = true;
|
2012-10-04 21:53:21 +08:00
|
|
|
if (CS.getArgument(i)->getType() == Dest->getType())
|
|
|
|
CS.setArgument(i, Dest);
|
2009-09-02 01:09:55 +08:00
|
|
|
else
|
2012-10-04 21:53:21 +08:00
|
|
|
CS.setArgument(i, CastInst::CreatePointerCast(Dest,
|
|
|
|
CS.getArgument(i)->getType(), Dest->getName(), C));
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
|
|
|
|
2008-06-02 05:52:16 +08:00
|
|
|
if (!changedArgument)
|
|
|
|
return false;
|
|
|
|
|
2012-10-04 18:54:40 +08:00
|
|
|
// If the destination wasn't sufficiently aligned then increase its alignment.
|
|
|
|
if (!isDestSufficientlyAligned) {
|
|
|
|
assert(isa<AllocaInst>(cpyDest) && "Can only increase alloca alignment!");
|
|
|
|
cast<AllocaInst>(cpyDest)->setAlignment(srcAlign);
|
|
|
|
}
|
|
|
|
|
2008-04-09 16:23:16 +08:00
|
|
|
// Drop any cached information about the call, because we may have changed
|
|
|
|
// its dependence information by changing its parameter.
|
2010-11-21 08:28:59 +08:00
|
|
|
MD->removeInstruction(C);
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2015-02-08 01:54:36 +08:00
|
|
|
// Update AA metadata
|
|
|
|
// FIXME: MD_tbaa_struct and MD_mem_parallel_loop_access should also be
|
|
|
|
// handled here, but combineMetadata doesn't support them yet
|
2015-10-03 06:12:22 +08:00
|
|
|
unsigned KnownIDs[] = {LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
|
|
|
|
LLVMContext::MD_noalias,
|
|
|
|
LLVMContext::MD_invariant_group};
|
2015-02-08 01:54:36 +08:00
|
|
|
combineMetadata(C, cpy, KnownIDs);
|
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
// Remove the memcpy.
|
|
|
|
MD->removeInstruction(cpy);
|
2010-06-22 23:08:57 +08:00
|
|
|
++NumMemCpyInstr;
|
2008-04-09 16:23:16 +08:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// We've found that the (upward scanning) memory dependence of memcpy 'M' is
|
|
|
|
/// the memcpy 'MDep'. Try to simplify M to copy from MDep's input if we can.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
|
|
|
|
MemCpyInst *MDep) {
|
2008-04-09 16:23:16 +08:00
|
|
|
// We can only transforms memcpy's where the dest of one is the source of the
|
2010-11-18 15:02:37 +08:00
|
|
|
// other.
|
2010-11-21 08:28:59 +08:00
|
|
|
if (M->getSource() != MDep->getDest() || MDep->isVolatile())
|
2008-04-09 16:23:16 +08:00
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-12-09 15:39:50 +08:00
|
|
|
// If dep instruction is reading from our current input, then it is a noop
|
|
|
|
// transfer and substituting the input won't change this instruction. Just
|
|
|
|
// ignore the input and let someone else zap MDep. This handles cases like:
|
|
|
|
// memcpy(a <- a)
|
|
|
|
// memcpy(b <- a)
|
|
|
|
if (M->getSource() == MDep->getSource())
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-04-15 13:18:47 +08:00
|
|
|
// Second, the length of the memcpy's must be the same, or the preceding one
|
2008-04-09 16:23:16 +08:00
|
|
|
// must be larger than the following one.
|
2011-01-22 06:07:57 +08:00
|
|
|
ConstantInt *MDepLen = dyn_cast<ConstantInt>(MDep->getLength());
|
|
|
|
ConstantInt *MLen = dyn_cast<ConstantInt>(M->getLength());
|
|
|
|
if (!MDepLen || !MLen || MDepLen->getZExtValue() < MLen->getZExtValue())
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
2010-11-21 16:06:10 +08:00
|
|
|
|
|
|
|
// Verify that the copied-from memory doesn't change in between the two
|
|
|
|
// transfers. For example, in:
|
|
|
|
// memcpy(a <- b)
|
|
|
|
// *b = 42;
|
|
|
|
// memcpy(c <- a)
|
|
|
|
// It would be invalid to transform the second memcpy into memcpy(c <- b).
|
|
|
|
//
|
|
|
|
// TODO: If the code between M and MDep is transparent to the destination "c",
|
|
|
|
// then we could still perform the xform by moving M up to the first memcpy.
|
|
|
|
//
|
|
|
|
// NOTE: This is conservative, it will stop on any read from the source loc,
|
|
|
|
// not just the defining memcpy.
|
2015-10-14 03:26:58 +08:00
|
|
|
MemDepResult SourceDep =
|
|
|
|
MD->getPointerDependencyFrom(MemoryLocation::getForSource(MDep), false,
|
|
|
|
M->getIterator(), M->getParent());
|
2010-11-21 16:06:10 +08:00
|
|
|
if (!SourceDep.isClobber() || SourceDep.getInst() != MDep)
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-18 16:00:57 +08:00
|
|
|
// If the dest of the second might alias the source of the first, then the
|
|
|
|
// source and dest might overlap. We still want to eliminate the intermediate
|
|
|
|
// value, but we have to generate a memmove instead of memcpy.
|
2010-12-27 06:57:41 +08:00
|
|
|
bool UseMemMove = false;
|
2015-06-04 10:03:15 +08:00
|
|
|
if (!AA.isNoAlias(MemoryLocation::getForDest(M),
|
|
|
|
MemoryLocation::getForSource(MDep)))
|
2010-12-27 06:57:41 +08:00
|
|
|
UseMemMove = true;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
// If all checks passed, then we can transform M.
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2015-11-19 13:56:52 +08:00
|
|
|
// Make sure to use the lesser of the alignment of the source and the dest
|
|
|
|
// since we're changing where we're reading from, but don't want to increase
|
|
|
|
// the alignment past what can be read from or written to.
|
2010-09-25 08:57:26 +08:00
|
|
|
// TODO: Is this worth it if we're creating a less aligned memcpy? For
|
|
|
|
// example we could be moving from movaps -> movq on x86.
|
2015-11-19 13:56:52 +08:00
|
|
|
unsigned Align = std::min(MDep->getAlignment(), M->getAlignment());
|
|
|
|
|
2010-12-27 06:57:41 +08:00
|
|
|
IRBuilder<> Builder(M);
|
|
|
|
if (UseMemMove)
|
|
|
|
Builder.CreateMemMove(M->getRawDest(), MDep->getRawSource(), M->getLength(),
|
2015-11-19 13:56:52 +08:00
|
|
|
Align, M->isVolatile());
|
2010-12-27 06:57:41 +08:00
|
|
|
else
|
|
|
|
Builder.CreateMemCpy(M->getRawDest(), MDep->getRawSource(), M->getLength(),
|
2015-11-19 13:56:52 +08:00
|
|
|
Align, M->isVolatile());
|
2010-11-18 16:07:09 +08:00
|
|
|
|
2010-11-21 16:06:10 +08:00
|
|
|
// Remove the instruction we're replacing.
|
2010-11-21 08:28:59 +08:00
|
|
|
MD->removeInstruction(M);
|
2010-11-18 16:07:09 +08:00
|
|
|
M->eraseFromParent();
|
|
|
|
++NumMemCpyInstr;
|
|
|
|
return true;
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
|
|
|
|
2015-04-18 06:20:57 +08:00
|
|
|
/// We've found that the (upward scanning) memory dependence of \p MemCpy is
|
|
|
|
/// \p MemSet. Try to simplify \p MemSet to only set the trailing bytes that
|
|
|
|
/// weren't copied over by \p MemCpy.
|
|
|
|
///
|
|
|
|
/// In other words, transform:
|
|
|
|
/// \code
|
|
|
|
/// memset(dst, c, dst_size);
|
|
|
|
/// memcpy(dst, src, src_size);
|
|
|
|
/// \endcode
|
|
|
|
/// into:
|
|
|
|
/// \code
|
|
|
|
/// memcpy(dst, src, src_size);
|
|
|
|
/// memset(dst + src_size, c, dst_size <= src_size ? 0 : dst_size - src_size);
|
|
|
|
/// \endcode
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
|
|
|
|
MemSetInst *MemSet) {
|
2015-04-18 06:20:57 +08:00
|
|
|
// We can only transform memset/memcpy with the same destination.
|
|
|
|
if (MemSet->getDest() != MemCpy->getDest())
|
|
|
|
return false;
|
|
|
|
|
2015-05-21 09:43:39 +08:00
|
|
|
// Check that there are no other dependencies on the memset destination.
|
2015-10-14 03:26:58 +08:00
|
|
|
MemDepResult DstDepInfo =
|
|
|
|
MD->getPointerDependencyFrom(MemoryLocation::getForDest(MemSet), false,
|
|
|
|
MemCpy->getIterator(), MemCpy->getParent());
|
2015-05-21 09:43:39 +08:00
|
|
|
if (DstDepInfo.getInst() != MemSet)
|
|
|
|
return false;
|
|
|
|
|
[MemCpyOpt] Use the raw i8* dest when optimizing memset+memcpy.
MemIntrinsic::getDest() looks through pointer casts, and using it
directly when building the new GEP+memset results in stuff like:
%0 = getelementptr i64* %p, i32 16
%1 = bitcast i64* %0 to i8*
call ..memset(i8* %1, ...)
instead of the correct:
%0 = bitcast i64* %p to i8*
%1 = getelementptr i8* %0, i32 16
call ..memset(i8* %1, ...)
Instead, use getRawDest, which just gives you the i8* value.
While there, use the memcpy's dest, as it's live anyway.
In most cases, when the optimization triggers, the memset and memcpy
sizes are the same, so the built memset is 0-sized and eliminated.
The problem occurs when they're different.
Fixes a regression caused by r235232: PR23300.
llvm-svn: 235419
2015-04-22 05:28:33 +08:00
|
|
|
// Use the same i8* dest as the memcpy, killing the memset dest if different.
|
|
|
|
Value *Dest = MemCpy->getRawDest();
|
2015-04-18 06:20:57 +08:00
|
|
|
Value *DestSize = MemSet->getLength();
|
|
|
|
Value *SrcSize = MemCpy->getLength();
|
|
|
|
|
|
|
|
// By default, create an unaligned memset.
|
|
|
|
unsigned Align = 1;
|
|
|
|
// If Dest is aligned, and SrcSize is constant, use the minimum alignment
|
|
|
|
// of the sum.
|
|
|
|
const unsigned DestAlign =
|
2015-11-19 13:56:52 +08:00
|
|
|
std::max(MemSet->getAlignment(), MemCpy->getAlignment());
|
2015-04-18 06:20:57 +08:00
|
|
|
if (DestAlign > 1)
|
|
|
|
if (ConstantInt *SrcSizeC = dyn_cast<ConstantInt>(SrcSize))
|
|
|
|
Align = MinAlign(SrcSizeC->getZExtValue(), DestAlign);
|
|
|
|
|
2015-05-21 09:43:39 +08:00
|
|
|
IRBuilder<> Builder(MemCpy);
|
2015-04-18 06:20:57 +08:00
|
|
|
|
2015-04-19 07:06:04 +08:00
|
|
|
// If the sizes have different types, zext the smaller one.
|
2015-04-19 01:57:41 +08:00
|
|
|
if (DestSize->getType() != SrcSize->getType()) {
|
2015-04-19 07:06:04 +08:00
|
|
|
if (DestSize->getType()->getIntegerBitWidth() >
|
|
|
|
SrcSize->getType()->getIntegerBitWidth())
|
|
|
|
SrcSize = Builder.CreateZExt(SrcSize, DestSize->getType());
|
|
|
|
else
|
|
|
|
DestSize = Builder.CreateZExt(DestSize, SrcSize->getType());
|
2015-04-19 01:57:41 +08:00
|
|
|
}
|
|
|
|
|
2016-11-08 01:47:28 +08:00
|
|
|
Value *Ule = Builder.CreateICmpULE(DestSize, SrcSize);
|
|
|
|
Value *SizeDiff = Builder.CreateSub(DestSize, SrcSize);
|
|
|
|
Value *MemsetLen = Builder.CreateSelect(
|
|
|
|
Ule, ConstantInt::getNullValue(DestSize->getType()), SizeDiff);
|
2015-04-18 06:20:57 +08:00
|
|
|
Builder.CreateMemSet(Builder.CreateGEP(Dest, SrcSize), MemSet->getOperand(1),
|
|
|
|
MemsetLen, Align);
|
|
|
|
|
|
|
|
MD->removeInstruction(MemSet);
|
|
|
|
MemSet->eraseFromParent();
|
|
|
|
return true;
|
|
|
|
}
|
2010-11-18 15:02:37 +08:00
|
|
|
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
/// Transform memcpy to memset when its source was just memset.
|
|
|
|
/// In other words, turn:
|
|
|
|
/// \code
|
|
|
|
/// memset(dst1, c, dst1_size);
|
|
|
|
/// memcpy(dst2, dst1, dst2_size);
|
|
|
|
/// \endcode
|
|
|
|
/// into:
|
|
|
|
/// \code
|
|
|
|
/// memset(dst1, c, dst1_size);
|
|
|
|
/// memset(dst2, c, dst2_size);
|
|
|
|
/// \endcode
|
|
|
|
/// When dst2_size <= dst1_size.
|
|
|
|
///
|
|
|
|
/// The \p MemCpy must have a Constant length.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
|
|
|
|
MemSetInst *MemSet) {
|
2016-08-26 03:27:26 +08:00
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
|
|
|
|
2016-08-26 05:03:46 +08:00
|
|
|
// Make sure that memcpy(..., memset(...), ...), that is we are memsetting and
|
|
|
|
// memcpying from the same address. Otherwise it is hard to reason about.
|
2016-08-26 03:27:26 +08:00
|
|
|
if (!AA.isMustAlias(MemSet->getRawDest(), MemCpy->getRawSource()))
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ConstantInt *CopySize = cast<ConstantInt>(MemCpy->getLength());
|
|
|
|
ConstantInt *MemSetSize = dyn_cast<ConstantInt>(MemSet->getLength());
|
|
|
|
// Make sure the memcpy doesn't read any more than what the memset wrote.
|
|
|
|
// Don't worry about sizes larger than i64.
|
|
|
|
if (!MemSetSize || CopySize->getZExtValue() > MemSetSize->getZExtValue())
|
|
|
|
return false;
|
|
|
|
|
2015-05-21 08:08:35 +08:00
|
|
|
IRBuilder<> Builder(MemCpy);
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
Builder.CreateMemSet(MemCpy->getRawDest(), MemSet->getOperand(1),
|
2015-11-19 13:56:52 +08:00
|
|
|
CopySize, MemCpy->getAlignment());
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// Perform simplification of memcpy's. If we have memcpy A
|
2010-11-18 15:02:37 +08:00
|
|
|
/// which copies X to Y, and memcpy B which copies Y to Z, then we can rewrite
|
|
|
|
/// B to be a memcpy from X to Z (or potentially a memmove, depending on
|
|
|
|
/// circumstances). This allows later passes to remove the first memcpy
|
|
|
|
/// altogether.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processMemCpy(MemCpyInst *M) {
|
2014-02-04 08:18:54 +08:00
|
|
|
// We can only optimize non-volatile memcpy's.
|
|
|
|
if (M->isVolatile()) return false;
|
2010-11-18 15:02:37 +08:00
|
|
|
|
2010-12-09 15:45:45 +08:00
|
|
|
// If the source and destination of the memcpy are the same, then zap it.
|
|
|
|
if (M->getSource() == M->getDest()) {
|
|
|
|
MD->removeInstruction(M);
|
|
|
|
M->eraseFromParent();
|
|
|
|
return false;
|
|
|
|
}
|
2010-12-25 05:17:12 +08:00
|
|
|
|
|
|
|
// If copying from a constant, try to turn the memcpy into a memset.
|
2010-12-25 06:23:59 +08:00
|
|
|
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(M->getSource()))
|
2010-12-26 23:23:45 +08:00
|
|
|
if (GV->isConstant() && GV->hasDefinitiveInitializer())
|
2010-12-25 06:23:59 +08:00
|
|
|
if (Value *ByteVal = isBytewiseValue(GV->getInitializer())) {
|
2010-12-27 06:57:41 +08:00
|
|
|
IRBuilder<> Builder(M);
|
2014-02-04 08:18:54 +08:00
|
|
|
Builder.CreateMemSet(M->getRawDest(), ByteVal, M->getLength(),
|
2015-11-19 13:56:52 +08:00
|
|
|
M->getAlignment(), false);
|
2010-12-25 06:23:59 +08:00
|
|
|
MD->removeInstruction(M);
|
|
|
|
M->eraseFromParent();
|
|
|
|
++NumCpyToSet;
|
|
|
|
return true;
|
|
|
|
}
|
2010-12-25 05:17:12 +08:00
|
|
|
|
2015-05-12 07:09:46 +08:00
|
|
|
MemDepResult DepInfo = MD->getDependency(M);
|
2015-04-18 06:20:57 +08:00
|
|
|
|
|
|
|
// Try to turn a partially redundant memset + memcpy into
|
|
|
|
// memcpy + smaller memset. We don't need the memcpy size for this.
|
2015-05-12 07:09:46 +08:00
|
|
|
if (DepInfo.isClobber())
|
|
|
|
if (MemSetInst *MDep = dyn_cast<MemSetInst>(DepInfo.getInst()))
|
2015-04-18 06:20:57 +08:00
|
|
|
if (processMemSetMemCpyDependence(M, MDep))
|
|
|
|
return true;
|
|
|
|
|
2014-02-04 08:18:54 +08:00
|
|
|
// The optimizations after this point require the memcpy size.
|
|
|
|
ConstantInt *CopySize = dyn_cast<ConstantInt>(M->getLength());
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!CopySize) return false;
|
2014-02-04 08:18:54 +08:00
|
|
|
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
// There are four possible optimizations we can do for memcpy:
|
2010-11-18 15:02:37 +08:00
|
|
|
// a) memcpy-memcpy xform which exposes redundance for DSE.
|
|
|
|
// b) call-memcpy xform for return slot optimization.
|
2014-03-27 07:45:15 +08:00
|
|
|
// c) memcpy from freshly alloca'd space or space that has just started its
|
|
|
|
// lifetime copies undefined data, and we can therefore eliminate the
|
|
|
|
// memcpy in favor of the data that was already at the destination.
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
// d) memcpy from a just-memset'd source can be turned into memset.
|
2011-10-17 04:13:32 +08:00
|
|
|
if (DepInfo.isClobber()) {
|
|
|
|
if (CallInst *C = dyn_cast<CallInst>(DepInfo.getInst())) {
|
|
|
|
if (performCallSlotOptzn(M, M->getDest(), M->getSource(),
|
2015-11-19 13:56:52 +08:00
|
|
|
CopySize->getZExtValue(), M->getAlignment(),
|
2012-10-04 18:54:40 +08:00
|
|
|
C)) {
|
2011-10-17 04:13:32 +08:00
|
|
|
MD->removeInstruction(M);
|
|
|
|
M->eraseFromParent();
|
|
|
|
return true;
|
|
|
|
}
|
2010-12-09 15:45:45 +08:00
|
|
|
}
|
2010-11-18 15:02:37 +08:00
|
|
|
}
|
2012-02-13 14:30:56 +08:00
|
|
|
|
2015-06-17 15:18:54 +08:00
|
|
|
MemoryLocation SrcLoc = MemoryLocation::getForSource(M);
|
2015-10-14 03:26:58 +08:00
|
|
|
MemDepResult SrcDepInfo = MD->getPointerDependencyFrom(
|
|
|
|
SrcLoc, true, M->getIterator(), M->getParent());
|
2015-05-12 07:09:46 +08:00
|
|
|
|
2011-10-17 04:13:32 +08:00
|
|
|
if (SrcDepInfo.isClobber()) {
|
|
|
|
if (MemCpyInst *MDep = dyn_cast<MemCpyInst>(SrcDepInfo.getInst()))
|
2015-05-16 09:23:47 +08:00
|
|
|
return processMemCpyMemCpyDependence(M, MDep);
|
2014-02-06 14:29:19 +08:00
|
|
|
} else if (SrcDepInfo.isDef()) {
|
2014-03-27 07:45:15 +08:00
|
|
|
Instruction *I = SrcDepInfo.getInst();
|
|
|
|
bool hasUndefContents = false;
|
|
|
|
|
|
|
|
if (isa<AllocaInst>(I)) {
|
|
|
|
hasUndefContents = true;
|
|
|
|
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
|
|
|
|
if (II->getIntrinsicID() == Intrinsic::lifetime_start)
|
|
|
|
if (ConstantInt *LTSize = dyn_cast<ConstantInt>(II->getArgOperand(0)))
|
|
|
|
if (LTSize->getZExtValue() >= CopySize->getZExtValue())
|
|
|
|
hasUndefContents = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasUndefContents) {
|
2014-02-06 14:29:19 +08:00
|
|
|
MD->removeInstruction(M);
|
|
|
|
M->eraseFromParent();
|
|
|
|
++NumMemCpyInstr;
|
|
|
|
return true;
|
|
|
|
}
|
2011-10-17 04:13:32 +08:00
|
|
|
}
|
|
|
|
|
[MemCpyOpt] Turn memcpy from just-memset'd source into memset.
There's no point in copying around constants, so, when all else fails,
we can still transform memcpy of memset into two independent memsets.
To quote the example, we can turn:
memset(dst1, c, dst1_size);
memcpy(dst2, dst1, dst2_size);
into:
memset(dst1, c, dst1_size);
memset(dst2, c, dst2_size);
When dst2_size <= dst1_size.
Like r235232 for copy constructors, this can occur in move constructors.
Differential Revision: http://reviews.llvm.org/D9682
llvm-svn: 237506
2015-05-16 09:32:26 +08:00
|
|
|
if (SrcDepInfo.isClobber())
|
|
|
|
if (MemSetInst *MDep = dyn_cast<MemSetInst>(SrcDepInfo.getInst()))
|
|
|
|
if (performMemCpyToMemSetOptzn(M, MDep)) {
|
|
|
|
MD->removeInstruction(M);
|
|
|
|
M->eraseFromParent();
|
|
|
|
++NumCpyToSet;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-11-18 15:02:37 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// Transforms memmove calls to memcpy calls when the src/dst are guaranteed
|
|
|
|
/// not to alias.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processMemMove(MemMoveInst *M) {
|
|
|
|
AliasAnalysis &AA = LookupAliasAnalysis();
|
2009-09-02 01:56:32 +08:00
|
|
|
|
[Analysis] Add LibFunc_ prefix to enums in TargetLibraryInfo. (NFC)
Summary:
The LibFunc::Func enum holds enumerators named for libc functions.
Unfortunately, there are real situations, including libc implementations, where
function names are actually macros (musl uses "#define fopen64 fopen", for
example; any other transitively visible macro would have similar effects).
Strictly speaking, a conforming C++ Standard Library should provide any such
macros as functions instead (via <cstdio>). However, there are some "library"
functions which are not part of the standard, and thus not subject to this
rule (fopen64, for example). So, in order to be both portable and consistent,
the enum should not use the bare function names.
The old enum naming used a namespace LibFunc and an enum Func, with bare
enumerators. This patch changes LibFunc to be an enum with enumerators prefixed
with "LibFFunc_". (Unfortunately, a scoped enum is not sufficient to override
macros.)
There are additional changes required in clang.
Reviewers: rsmith
Subscribers: mehdi_amini, mzolotukhin, nemanjai, llvm-commits
Differential Revision: https://reviews.llvm.org/D28476
llvm-svn: 292848
2017-01-24 07:16:46 +08:00
|
|
|
if (!TLI->has(LibFunc_memmove))
|
2011-05-02 02:27:11 +08:00
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2009-09-02 01:56:32 +08:00
|
|
|
// See if the pointers alias.
|
2015-06-04 10:03:15 +08:00
|
|
|
if (!AA.isNoAlias(MemoryLocation::getForDest(M),
|
|
|
|
MemoryLocation::getForSource(M)))
|
2009-09-02 01:56:32 +08:00
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
DEBUG(dbgs() << "MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
|
|
|
|
<< "\n");
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2009-09-02 01:56:32 +08:00
|
|
|
// If not, then we know we can transform this.
|
2011-07-12 22:06:48 +08:00
|
|
|
Type *ArgTys[3] = { M->getRawDest()->getType(),
|
|
|
|
M->getRawSource()->getType(),
|
|
|
|
M->getLength()->getType() };
|
2015-12-15 01:24:23 +08:00
|
|
|
M->setCalledFunction(Intrinsic::getDeclaration(M->getModule(),
|
|
|
|
Intrinsic::memcpy, ArgTys));
|
2009-09-03 21:37:16 +08:00
|
|
|
|
2009-09-02 01:56:32 +08:00
|
|
|
// MemDep may have over conservative information about this instruction, just
|
|
|
|
// conservatively flush it from the cache.
|
2010-11-21 08:28:59 +08:00
|
|
|
MD->removeInstruction(M);
|
2009-09-03 21:37:16 +08:00
|
|
|
|
|
|
|
++NumMoveToCpy;
|
2009-09-02 01:56:32 +08:00
|
|
|
return true;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2015-08-14 06:53:20 +08:00
|
|
|
/// This is called on every byval argument in call sites.
|
2016-06-14 10:44:55 +08:00
|
|
|
bool MemCpyOptPass::processByValArgument(CallSite CS, unsigned ArgNo) {
|
2015-03-10 10:37:25 +08:00
|
|
|
const DataLayout &DL = CS.getCaller()->getParent()->getDataLayout();
|
2010-11-21 16:06:10 +08:00
|
|
|
// Find out what feeds this byval argument.
|
2010-11-21 08:28:59 +08:00
|
|
|
Value *ByValArg = CS.getArgument(ArgNo);
|
2011-10-12 08:14:31 +08:00
|
|
|
Type *ByValTy = cast<PointerType>(ByValArg->getType())->getElementType();
|
2015-03-10 10:37:25 +08:00
|
|
|
uint64_t ByValSize = DL.getTypeAllocSize(ByValTy);
|
2015-06-17 15:18:54 +08:00
|
|
|
MemDepResult DepInfo = MD->getPointerDependencyFrom(
|
2015-10-14 03:26:58 +08:00
|
|
|
MemoryLocation(ByValArg, ByValSize), true,
|
|
|
|
CS.getInstruction()->getIterator(), CS.getInstruction()->getParent());
|
2010-11-21 08:28:59 +08:00
|
|
|
if (!DepInfo.isClobber())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If the byval argument isn't fed by a memcpy, ignore it. If it is fed by
|
|
|
|
// a memcpy, see if we can byval from the source of the memcpy instead of the
|
|
|
|
// result.
|
|
|
|
MemCpyInst *MDep = dyn_cast<MemCpyInst>(DepInfo.getInst());
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!MDep || MDep->isVolatile() ||
|
2010-11-21 08:28:59 +08:00
|
|
|
ByValArg->stripPointerCasts() != MDep->getDest())
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
// The length of the memcpy must be larger or equal to the size of the byval.
|
|
|
|
ConstantInt *C1 = dyn_cast<ConstantInt>(MDep->getLength());
|
2014-04-25 13:29:35 +08:00
|
|
|
if (!C1 || C1->getValue().getZExtValue() < ByValSize)
|
2010-11-21 08:28:59 +08:00
|
|
|
return false;
|
|
|
|
|
2011-05-23 08:03:39 +08:00
|
|
|
// Get the alignment of the byval. If the call doesn't specify the alignment,
|
|
|
|
// then it is some target specific value that we can't know.
|
2017-04-29 04:34:27 +08:00
|
|
|
unsigned ByValAlign = CS.getParamAlignment(ArgNo);
|
2011-05-23 08:03:39 +08:00
|
|
|
if (ByValAlign == 0) return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-05-23 08:03:39 +08:00
|
|
|
// If it is greater than the memcpy, then we check to see if we can force the
|
|
|
|
// source of the memcpy to the alignment we need. If we fail, we bail out.
|
2016-12-19 16:22:17 +08:00
|
|
|
AssumptionCache &AC = LookupAssumptionCache();
|
2016-06-14 10:44:55 +08:00
|
|
|
DominatorTree &DT = LookupDomTree();
|
2015-11-19 13:56:52 +08:00
|
|
|
if (MDep->getAlignment() < ByValAlign &&
|
2015-03-10 10:37:25 +08:00
|
|
|
getOrEnforceKnownAlignment(MDep->getSource(), ByValAlign, DL,
|
2016-12-19 16:22:17 +08:00
|
|
|
CS.getInstruction(), &AC, &DT) < ByValAlign)
|
2011-05-23 08:03:39 +08:00
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2017-04-11 03:00:25 +08:00
|
|
|
// The address space of the memcpy source must match the byval argument
|
|
|
|
if (MDep->getSource()->getType()->getPointerAddressSpace() !=
|
|
|
|
ByValArg->getType()->getPointerAddressSpace())
|
|
|
|
return false;
|
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
// Verify that the copied-from memory doesn't change in between the memcpy and
|
|
|
|
// the byval call.
|
|
|
|
// memcpy(a <- b)
|
|
|
|
// *b = 42;
|
|
|
|
// foo(*a)
|
|
|
|
// It would be invalid to transform the second memcpy into foo(*b).
|
2010-11-21 16:06:10 +08:00
|
|
|
//
|
|
|
|
// NOTE: This is conservative, it will stop on any read from the source loc,
|
|
|
|
// not just the defining memcpy.
|
2015-10-14 03:26:58 +08:00
|
|
|
MemDepResult SourceDep = MD->getPointerDependencyFrom(
|
|
|
|
MemoryLocation::getForSource(MDep), false,
|
|
|
|
CS.getInstruction()->getIterator(), MDep->getParent());
|
2010-11-21 16:06:10 +08:00
|
|
|
if (!SourceDep.isClobber() || SourceDep.getInst() != MDep)
|
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
Value *TmpCast = MDep->getSource();
|
|
|
|
if (MDep->getSource()->getType() != ByValArg->getType())
|
|
|
|
TmpCast = new BitCastInst(MDep->getSource(), ByValArg->getType(),
|
|
|
|
"tmpcast", CS.getInstruction());
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
DEBUG(dbgs() << "MemCpyOptPass: Forwarding memcpy to byval:\n"
|
2010-11-21 08:28:59 +08:00
|
|
|
<< " " << *MDep << "\n"
|
|
|
|
<< " " << *CS.getInstruction() << "\n");
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
// Otherwise we're good! Update the byval argument.
|
|
|
|
CS.setArgument(ArgNo, TmpCast);
|
|
|
|
++NumMemCpyInstr;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
/// Executes one iteration of MemCpyOptPass.
|
|
|
|
bool MemCpyOptPass::iterateOnFunction(Function &F) {
|
2009-09-02 01:09:55 +08:00
|
|
|
bool MadeChange = false;
|
2008-04-09 16:23:16 +08:00
|
|
|
|
2009-09-02 01:09:55 +08:00
|
|
|
// Walk all instruction in the function.
|
2016-06-26 20:28:59 +08:00
|
|
|
for (BasicBlock &BB : F) {
|
|
|
|
for (BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;) {
|
2009-09-02 01:09:55 +08:00
|
|
|
// Avoid invalidating the iterator.
|
2015-10-14 03:26:58 +08:00
|
|
|
Instruction *I = &*BI++;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2010-11-21 08:28:59 +08:00
|
|
|
bool RepeatInstruction = false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2008-04-21 15:45:10 +08:00
|
|
|
if (StoreInst *SI = dyn_cast<StoreInst>(I))
|
2009-09-02 01:09:55 +08:00
|
|
|
MadeChange |= processStore(SI, BI);
|
2011-01-09 05:19:19 +08:00
|
|
|
else if (MemSetInst *M = dyn_cast<MemSetInst>(I))
|
|
|
|
RepeatInstruction = processMemSet(M, BI);
|
|
|
|
else if (MemCpyInst *M = dyn_cast<MemCpyInst>(I))
|
2016-05-11 05:49:40 +08:00
|
|
|
RepeatInstruction = processMemCpy(M);
|
2011-01-09 05:19:19 +08:00
|
|
|
else if (MemMoveInst *M = dyn_cast<MemMoveInst>(I))
|
2010-11-21 08:28:59 +08:00
|
|
|
RepeatInstruction = processMemMove(M);
|
2015-04-10 22:50:08 +08:00
|
|
|
else if (auto CS = CallSite(I)) {
|
2010-11-21 08:28:59 +08:00
|
|
|
for (unsigned i = 0, e = CS.arg_size(); i != e; ++i)
|
2011-11-21 03:09:04 +08:00
|
|
|
if (CS.isByValArgument(i))
|
2010-11-21 08:28:59 +08:00
|
|
|
MadeChange |= processByValArgument(CS, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reprocess the instruction if desired.
|
|
|
|
if (RepeatInstruction) {
|
2016-06-26 20:28:59 +08:00
|
|
|
if (BI != BB.begin())
|
|
|
|
--BI;
|
2010-11-21 08:28:59 +08:00
|
|
|
MadeChange = true;
|
2009-09-02 01:56:32 +08:00
|
|
|
}
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2009-09-02 01:09:55 +08:00
|
|
|
return MadeChange;
|
2008-04-09 16:23:16 +08:00
|
|
|
}
|
2009-09-02 01:09:55 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
PreservedAnalyses MemCpyOptPass::run(Function &F, FunctionAnalysisManager &AM) {
|
|
|
|
auto &MD = AM.getResult<MemoryDependenceAnalysis>(F);
|
|
|
|
auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
|
|
|
|
|
|
|
|
auto LookupAliasAnalysis = [&]() -> AliasAnalysis & {
|
|
|
|
return AM.getResult<AAManager>(F);
|
|
|
|
};
|
2016-12-19 16:22:17 +08:00
|
|
|
auto LookupAssumptionCache = [&]() -> AssumptionCache & {
|
|
|
|
return AM.getResult<AssumptionAnalysis>(F);
|
|
|
|
};
|
2016-06-14 10:44:55 +08:00
|
|
|
auto LookupDomTree = [&]() -> DominatorTree & {
|
|
|
|
return AM.getResult<DominatorTreeAnalysis>(F);
|
|
|
|
};
|
|
|
|
|
2016-12-19 16:22:17 +08:00
|
|
|
bool MadeChange = runImpl(F, &MD, &TLI, LookupAliasAnalysis,
|
|
|
|
LookupAssumptionCache, LookupDomTree);
|
2016-06-14 10:44:55 +08:00
|
|
|
if (!MadeChange)
|
|
|
|
return PreservedAnalyses::all();
|
2017-01-15 14:32:49 +08:00
|
|
|
|
2016-06-14 10:44:55 +08:00
|
|
|
PreservedAnalyses PA;
|
2017-01-15 14:32:49 +08:00
|
|
|
PA.preserveSet<CFGAnalyses>();
|
2016-06-14 10:44:55 +08:00
|
|
|
PA.preserve<GlobalsAA>();
|
|
|
|
PA.preserve<MemoryDependenceAnalysis>();
|
|
|
|
return PA;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MemCpyOptPass::runImpl(
|
|
|
|
Function &F, MemoryDependenceResults *MD_, TargetLibraryInfo *TLI_,
|
|
|
|
std::function<AliasAnalysis &()> LookupAliasAnalysis_,
|
2016-12-19 16:22:17 +08:00
|
|
|
std::function<AssumptionCache &()> LookupAssumptionCache_,
|
2016-06-14 10:44:55 +08:00
|
|
|
std::function<DominatorTree &()> LookupDomTree_) {
|
2009-09-02 01:09:55 +08:00
|
|
|
bool MadeChange = false;
|
2016-06-14 10:44:55 +08:00
|
|
|
MD = MD_;
|
|
|
|
TLI = TLI_;
|
2016-06-18 04:41:14 +08:00
|
|
|
LookupAliasAnalysis = std::move(LookupAliasAnalysis_);
|
2016-12-19 16:22:17 +08:00
|
|
|
LookupAssumptionCache = std::move(LookupAssumptionCache_);
|
2016-06-18 04:41:14 +08:00
|
|
|
LookupDomTree = std::move(LookupDomTree_);
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2011-05-02 02:27:11 +08:00
|
|
|
// If we don't have at least memset and memcpy, there is little point of doing
|
|
|
|
// anything here. These are required by a freestanding implementation, so if
|
|
|
|
// even they are disabled, there is no point in trying hard.
|
[Analysis] Add LibFunc_ prefix to enums in TargetLibraryInfo. (NFC)
Summary:
The LibFunc::Func enum holds enumerators named for libc functions.
Unfortunately, there are real situations, including libc implementations, where
function names are actually macros (musl uses "#define fopen64 fopen", for
example; any other transitively visible macro would have similar effects).
Strictly speaking, a conforming C++ Standard Library should provide any such
macros as functions instead (via <cstdio>). However, there are some "library"
functions which are not part of the standard, and thus not subject to this
rule (fopen64, for example). So, in order to be both portable and consistent,
the enum should not use the bare function names.
The old enum naming used a namespace LibFunc and an enum Func, with bare
enumerators. This patch changes LibFunc to be an enum with enumerators prefixed
with "LibFFunc_". (Unfortunately, a scoped enum is not sufficient to override
macros.)
There are additional changes required in clang.
Reviewers: rsmith
Subscribers: mehdi_amini, mzolotukhin, nemanjai, llvm-commits
Differential Revision: https://reviews.llvm.org/D28476
llvm-svn: 292848
2017-01-24 07:16:46 +08:00
|
|
|
if (!TLI->has(LibFunc_memset) || !TLI->has(LibFunc_memcpy))
|
2011-05-02 02:27:11 +08:00
|
|
|
return false;
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2017-01-18 08:57:48 +08:00
|
|
|
while (true) {
|
2009-09-02 01:09:55 +08:00
|
|
|
if (!iterateOnFunction(F))
|
|
|
|
break;
|
|
|
|
MadeChange = true;
|
|
|
|
}
|
2012-07-24 18:51:42 +08:00
|
|
|
|
2014-04-25 13:29:35 +08:00
|
|
|
MD = nullptr;
|
2009-09-02 01:09:55 +08:00
|
|
|
return MadeChange;
|
|
|
|
}
|
2016-06-14 10:44:55 +08:00
|
|
|
|
|
|
|
/// This is the main transformation entry point for a function.
|
|
|
|
bool MemCpyOptLegacyPass::runOnFunction(Function &F) {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
auto *MD = &getAnalysis<MemoryDependenceWrapperPass>().getMemDep();
|
|
|
|
auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
|
|
|
|
|
|
|
|
auto LookupAliasAnalysis = [this]() -> AliasAnalysis & {
|
|
|
|
return getAnalysis<AAResultsWrapperPass>().getAAResults();
|
|
|
|
};
|
2016-12-19 16:22:17 +08:00
|
|
|
auto LookupAssumptionCache = [this, &F]() -> AssumptionCache & {
|
|
|
|
return getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
|
|
|
|
};
|
2016-06-14 10:44:55 +08:00
|
|
|
auto LookupDomTree = [this]() -> DominatorTree & {
|
|
|
|
return getAnalysis<DominatorTreeWrapperPass>().getDomTree();
|
|
|
|
};
|
|
|
|
|
2016-12-19 16:22:17 +08:00
|
|
|
return Impl.runImpl(F, MD, TLI, LookupAliasAnalysis, LookupAssumptionCache,
|
|
|
|
LookupDomTree);
|
2016-06-14 10:44:55 +08:00
|
|
|
}
|