-/// isReturnSlotOptznProfitable - Determine if performing a return slot
-/// fusion with the slot dest is profitable
-static bool isReturnSlotOptznProfitable(Value* dest, MemCpyInst* cpy) {
- // We currently consider it profitable if dest is otherwise dead.
- SmallVector<User*, 8> useList(dest->use_begin(), dest->use_end());
- while (!useList.empty()) {
- User* UI = useList.back();
-
- if (isa<GetElementPtrInst>(UI) || isa<BitCastInst>(UI)) {
- useList.pop_back();
- for (User::use_iterator I = UI->use_begin(), E = UI->use_end();
- I != E; ++I)
- useList.push_back(*I);
- } else if (UI == cpy)
- useList.pop_back();
- else
- return false;
- }
-
- return true;
-}
-
-/// performReturnSlotOptzn - takes a memcpy and a call that it depends on,
-/// and checks for the possibility of a return slot optimization by having
-/// the call write its result directly into the callees return parameter
-/// rather than using memcpy
-bool GVN::performReturnSlotOptzn(MemCpyInst* cpy, CallInst* C,
- SmallVector<Instruction*, 4>& toErase) {
- // Check that we're copying to an argument...
- Value* cpyDest = cpy->getDest();
- if (!isa<Argument>(cpyDest))
- return false;
-
- // And that the argument is the return slot
- Argument* sretArg = cast<Argument>(cpyDest);
- if (!sretArg->hasStructRetAttr())
- return false;
-
- // We only perform the transformation if it will be profitable.
- if (!isReturnSlotOptznProfitable(sretArg, cpy))
- return false;
-
- // Make sure the call cannot modify the return slot in some unpredicted way
- AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
- if (AA.getModRefInfo(C, cpy->getRawDest(), ~0UL) != AliasAnalysis::NoModRef)
- return false;
-
- // If all checks passed, then we can perform the transformation.
- CallSite CS = CallSite::get(C);
- if (CS.getArgument(0)->getType() != cpyDest->getType())
- return false;
-
- CS.setArgument(0, cpyDest);
-
- MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
- MD.dropInstruction(C);
-
- // Remove the memcpy
- 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,
- SmallVector<Instruction*, 4>& 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 CpySize = C1->getValue().getZExtValue();
- uint64_t DepSize = 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());