-/// performCallSlotOptzn - takes a memcpy and a call that it depends on,
-/// and checks for the possibility of a call slot optimization by having
-/// the call write its result directly into the destination of the memcpy.
-bool GVN::performCallSlotOptzn(MemCpyInst *cpy, CallInst *C,
- SmallVectorImpl<Instruction*> &toErase) {
- // 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.
-
- // Deliberately get the source and destination with bitcasts stripped away,
- // because we'll need to do type comparisons based on the underlying type.
- Value* cpyDest = cpy->getDest();
- Value* cpySrc = cpy->getSource();
- CallSite CS = CallSite::get(C);
-
- // We need to be able to reason about the size of the memcpy, so we require
- // that it be a constant.
- ConstantInt* cpyLength = dyn_cast<ConstantInt>(cpy->getLength());
- if (!cpyLength)
- return false;
-
- // Require that src be an alloca. This simplifies the reasoning considerably.
- AllocaInst* srcAlloca = dyn_cast<AllocaInst>(cpySrc);
- if (!srcAlloca)
- return false;
-
- // Check that all of src is copied to dest.
- TargetData& TD = getAnalysis<TargetData>();
-
- ConstantInt* srcArraySize = dyn_cast<ConstantInt>(srcAlloca->getArraySize());
- if (!srcArraySize)
- return false;
-
- uint64_t srcSize = TD.getABITypeSize(srcAlloca->getAllocatedType()) *
- srcArraySize->getZExtValue();
-
- if (cpyLength->getZExtValue() < srcSize)
- 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.
- if (AllocaInst* A = dyn_cast<AllocaInst>(cpyDest)) {
- // The destination is an alloca. Check it is larger than srcSize.
- ConstantInt* destArraySize = dyn_cast<ConstantInt>(A->getArraySize());
- if (!destArraySize)
- return false;
-
- uint64_t destSize = TD.getABITypeSize(A->getAllocatedType()) *
- destArraySize->getZExtValue();
-
- if (destSize < srcSize)
- return false;
- } else if (Argument* A = dyn_cast<Argument>(cpyDest)) {
- // 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;
-
- const Type* StructTy = cast<PointerType>(A->getType())->getElementType();
- uint64_t destSize = TD.getABITypeSize(StructTy);
-
- if (destSize < srcSize)
- return false;
- } else {
- return false;
- }
-
- // 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.
- SmallVector<User*, 8> srcUseList(srcAlloca->use_begin(),
- srcAlloca->use_end());
- while (!srcUseList.empty()) {
- User* UI = srcUseList.back();
- srcUseList.pop_back();
-
- if (isa<GetElementPtrInst>(UI) || isa<BitCastInst>(UI)) {
- for (User::use_iterator I = UI->use_begin(), E = UI->use_end();
- I != E; ++I)
- srcUseList.push_back(*I);
- } else if (UI != C && UI != cpy) {
- return false;
- }
- }
-
- // Since we're changing the parameter to the callsite, we need to make sure
- // that what would be the new parameter dominates the callsite.
- DominatorTree& DT = getAnalysis<DominatorTree>();
- if (Instruction* cpyDestInst = dyn_cast<Instruction>(cpyDest))
- 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.
- AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
- if (AA.getModRefInfo(C, cpy->getRawDest(), srcSize) !=
- AliasAnalysis::NoModRef)
- return false;
-
- // All the checks have passed, so do the transformation.
- for (unsigned i = 0; i < CS.arg_size(); ++i)
- if (CS.getArgument(i) == cpySrc) {
- if (cpySrc->getType() != cpyDest->getType())
- cpyDest = CastInst::createPointerCast(cpyDest, cpySrc->getType(),
- cpyDest->getName(), C);
- CS.setArgument(i, cpyDest);
- }
-
- // Drop any cached information about the call, because we may have changed
- // its dependence information by changing its parameter.
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
- MD.dropInstruction(C);
-
- // Remove the memcpy
- MD.removeInstruction(cpy);
- toErase.push_back(cpy);
-
- return true;
-}
-
-/// processMemCpy - perform simplication of memcpy's. If we have memcpy A 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.
-bool GVN::processMemCpy(MemCpyInst* M, MemCpyInst* MDep,
- SmallVectorImpl<Instruction*> &toErase) {
- // We can only transforms memcpy's where the dest of one is the source of the
- // other
- if (M->getSource() != MDep->getDest())
- return false;
-
- // Second, the length of the memcpy's must be the same, or the preceeding one
- // must be larger than the following one.
- ConstantInt* C1 = dyn_cast<ConstantInt>(MDep->getLength());
- ConstantInt* C2 = dyn_cast<ConstantInt>(M->getLength());
- if (!C1 || !C2)
- return false;
-
- uint64_t DepSize = C1->getValue().getZExtValue();
- uint64_t CpySize = C2->getValue().getZExtValue();
-
- if (DepSize < CpySize)
- return false;
-
- // Finally, we have to make sure that the dest of the second does not
- // alias the source of the first
- AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
- if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) !=
- AliasAnalysis::NoAlias)
- return false;
- else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) !=
- AliasAnalysis::NoAlias)
- return false;
- else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize)
- != AliasAnalysis::NoAlias)
- return false;
-
- // If all checks passed, then we can transform these memcpy's
- Function* MemCpyFun = Intrinsic::getDeclaration(
- M->getParent()->getParent()->getParent(),
- M->getIntrinsicID());
-
- std::vector<Value*> args;
- args.push_back(M->getRawDest());
- args.push_back(MDep->getRawSource());
- args.push_back(M->getLength());
- args.push_back(M->getAlignment());