#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <map>
using namespace llvm;
#define DEBUG_TYPE "clone-function"
BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
const Twine &NameSuffix, Function *F,
ClonedCodeInfo *CodeInfo,
DebugInfoFinder *DIFinder) {
BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F);
if (BB->hasName())
NewBB->setName(BB->getName() + NameSuffix);
bool hasCalls = false, hasDynamicAllocas = false;
Module *TheModule = F ? F->getParent() : nullptr;
for (const Instruction &I : *BB) {
if (DIFinder && TheModule)
DIFinder->processInstruction(*TheModule, I);
Instruction *NewInst = I.clone();
if (I.hasName())
NewInst->setName(I.getName() + NameSuffix);
NewBB->getInstList().push_back(NewInst);
VMap[&I] = NewInst;
hasCalls |= (isa<CallInst>(I) && !I.isDebugOrPseudoInst());
if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
if (!AI->isStaticAlloca()) {
hasDynamicAllocas = true;
}
}
}
if (CodeInfo) {
CodeInfo->ContainsCalls |= hasCalls;
CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
}
return NewBB;
}
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
ValueToValueMapTy &VMap,
CloneFunctionChangeType Changes,
SmallVectorImpl<ReturnInst *> &Returns,
const char *NameSuffix, ClonedCodeInfo *CodeInfo,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
assert(NameSuffix && "NameSuffix cannot be null!");
#ifndef NDEBUG
for (const Argument &I : OldFunc->args())
assert(VMap.count(&I) && "No mapping from source argument specified!");
#endif
bool ModuleLevelChanges = Changes > CloneFunctionChangeType::LocalChangesOnly;
AttributeList NewAttrs = NewFunc->getAttributes();
NewFunc->copyAttributesFrom(OldFunc);
NewFunc->setAttributes(NewAttrs);
if (OldFunc->hasPersonalityFn())
NewFunc->setPersonalityFn(
MapValue(OldFunc->getPersonalityFn(), VMap,
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
TypeMapper, Materializer));
SmallVector<AttributeSet, 4> NewArgAttrs(NewFunc->arg_size());
AttributeList OldAttrs = OldFunc->getAttributes();
for (const Argument &OldArg : OldFunc->args()) {
if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) {
NewArgAttrs[NewArg->getArgNo()] =
OldAttrs.getParamAttrs(OldArg.getArgNo());
}
}
NewFunc->setAttributes(
AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttrs(),
OldAttrs.getRetAttrs(), NewArgAttrs));
if (OldFunc->isDeclaration())
return;
Optional<DebugInfoFinder> DIFinder;
DISubprogram *SPClonedWithinModule = nullptr;
if (Changes < CloneFunctionChangeType::DifferentModule) {
assert((NewFunc->getParent() == nullptr ||
NewFunc->getParent() == OldFunc->getParent()) &&
"Expected NewFunc to have the same parent, or no parent");
DIFinder.emplace();
SPClonedWithinModule = OldFunc->getSubprogram();
if (SPClonedWithinModule)
DIFinder->processSubprogram(SPClonedWithinModule);
} else {
assert((NewFunc->getParent() == nullptr ||
NewFunc->getParent() != OldFunc->getParent()) &&
"Expected NewFunc to have different parents, or no parent");
if (Changes == CloneFunctionChangeType::DifferentModule) {
assert(NewFunc->getParent() &&
"Need parent of new function to maintain debug info invariants");
DIFinder.emplace();
}
}
for (const BasicBlock &BB : *OldFunc) {
BasicBlock *CBB = CloneBasicBlock(&BB, VMap, NameSuffix, NewFunc, CodeInfo,
DIFinder ? &*DIFinder : nullptr);
VMap[&BB] = CBB;
if (BB.hasAddressTaken()) {
Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(OldFunc),
const_cast<BasicBlock *>(&BB));
VMap[OldBBAddr] = BlockAddress::get(NewFunc, CBB);
}
if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator()))
Returns.push_back(RI);
}
if (Changes < CloneFunctionChangeType::DifferentModule &&
DIFinder->subprogram_count() > 0) {
ModuleLevelChanges = true;
auto mapToSelfIfNew = [&VMap](MDNode *N) {
(void)VMap.MD().try_emplace(N, N);
};
SmallPtrSet<const DISubprogram *, 16> MappedToSelfSPs;
for (DISubprogram *ISP : DIFinder->subprograms()) {
if (ISP != SPClonedWithinModule) {
mapToSelfIfNew(ISP);
MappedToSelfSPs.insert(ISP);
}
}
for (DIScope *S : DIFinder->scopes()) {
auto *LScope = dyn_cast<DILocalScope>(S);
if (LScope && MappedToSelfSPs.count(LScope->getSubprogram()))
mapToSelfIfNew(S);
}
for (DICompileUnit *CU : DIFinder->compile_units())
mapToSelfIfNew(CU);
for (DIType *Type : DIFinder->types())
mapToSelfIfNew(Type);
} else {
assert(!SPClonedWithinModule &&
"Subprogram should be in DIFinder->subprogram_count()...");
}
const auto RemapFlag = ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges;
SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
OldFunc->getAllMetadata(MDs);
for (auto MD : MDs) {
NewFunc->addMetadata(MD.first, *MapMetadata(MD.second, VMap, RemapFlag,
TypeMapper, Materializer));
}
for (Function::iterator
BB = cast<BasicBlock>(VMap[&OldFunc->front()])->getIterator(),
BE = NewFunc->end();
BB != BE; ++BB)
for (Instruction &II : *BB)
RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer);
if (Changes != CloneFunctionChangeType::DifferentModule)
return;
auto *NewModule = NewFunc->getParent();
auto *NMD = NewModule->getOrInsertNamedMetadata("llvm.dbg.cu");
SmallPtrSet<const void *, 8> Visited;
for (auto *Operand : NMD->operands())
Visited.insert(Operand);
for (auto *Unit : DIFinder->compile_units()) {
MDNode *MappedUnit =
MapMetadata(Unit, VMap, RF_None, TypeMapper, Materializer);
if (Visited.insert(MappedUnit).second)
NMD->addOperand(MappedUnit);
}
}
Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap,
ClonedCodeInfo *CodeInfo) {
std::vector<Type *> ArgTypes;
for (const Argument &I : F->args())
if (VMap.count(&I) == 0) ArgTypes.push_back(I.getType());
FunctionType *FTy =
FunctionType::get(F->getFunctionType()->getReturnType(), ArgTypes,
F->getFunctionType()->isVarArg());
Function *NewF = Function::Create(FTy, F->getLinkage(), F->getAddressSpace(),
F->getName(), F->getParent());
Function::arg_iterator DestI = NewF->arg_begin();
for (const Argument &I : F->args())
if (VMap.count(&I) == 0) { DestI->setName(I.getName()); VMap[&I] = &*DestI++; }
SmallVector<ReturnInst *, 8> Returns; CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
Returns, "", CodeInfo);
return NewF;
}
namespace {
struct PruningFunctionCloner {
Function *NewFunc;
const Function *OldFunc;
ValueToValueMapTy &VMap;
bool ModuleLevelChanges;
const char *NameSuffix;
ClonedCodeInfo *CodeInfo;
bool HostFuncIsStrictFP;
Instruction *cloneInstruction(BasicBlock::const_iterator II);
public:
PruningFunctionCloner(Function *newFunc, const Function *oldFunc,
ValueToValueMapTy &valueMap, bool moduleLevelChanges,
const char *nameSuffix, ClonedCodeInfo *codeInfo)
: NewFunc(newFunc), OldFunc(oldFunc), VMap(valueMap),
ModuleLevelChanges(moduleLevelChanges), NameSuffix(nameSuffix),
CodeInfo(codeInfo) {
HostFuncIsStrictFP =
newFunc->getAttributes().hasFnAttr(Attribute::StrictFP);
}
void CloneBlock(const BasicBlock *BB, BasicBlock::const_iterator StartingInst,
std::vector<const BasicBlock *> &ToClone);
};
}
static bool hasRoundingModeOperand(Intrinsic::ID CIID) {
switch (CIID) {
#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \
case Intrinsic::INTRINSIC: \
return ROUND_MODE == 1;
#define FUNCTION INSTRUCTION
#include "llvm/IR/ConstrainedOps.def"
default:
llvm_unreachable("Unexpected constrained intrinsic id");
}
}
Instruction *
PruningFunctionCloner::cloneInstruction(BasicBlock::const_iterator II) {
const Instruction &OldInst = *II;
Instruction *NewInst = nullptr;
if (HostFuncIsStrictFP) {
Intrinsic::ID CIID = getConstrainedIntrinsicID(OldInst);
if (CIID != Intrinsic::not_intrinsic) {
SmallVector<Type *, 2> TParams;
SmallVector<Intrinsic::IITDescriptor, 8> Descriptor;
getIntrinsicInfoTableEntries(CIID, Descriptor);
for (unsigned I = 0, E = Descriptor.size(); I != E; ++I) {
Intrinsic::IITDescriptor Operand = Descriptor[I];
switch (Operand.Kind) {
case Intrinsic::IITDescriptor::Argument:
if (Operand.getArgumentKind() !=
Intrinsic::IITDescriptor::AK_MatchType) {
if (I == 0)
TParams.push_back(OldInst.getType());
else
TParams.push_back(OldInst.getOperand(I - 1)->getType());
}
break;
case Intrinsic::IITDescriptor::SameVecWidthArgument:
++I;
break;
default:
break;
}
}
LLVMContext &Ctx = NewFunc->getContext();
Function *IFn =
Intrinsic::getDeclaration(NewFunc->getParent(), CIID, TParams);
SmallVector<Value *, 4> Args;
unsigned NumOperands = OldInst.getNumOperands();
if (isa<CallInst>(OldInst))
--NumOperands;
for (unsigned I = 0; I < NumOperands; ++I) {
Value *Op = OldInst.getOperand(I);
Args.push_back(Op);
}
if (const auto *CmpI = dyn_cast<FCmpInst>(&OldInst)) {
FCmpInst::Predicate Pred = CmpI->getPredicate();
StringRef PredName = FCmpInst::getPredicateName(Pred);
Args.push_back(MetadataAsValue::get(Ctx, MDString::get(Ctx, PredName)));
}
if (hasRoundingModeOperand(CIID))
Args.push_back(
MetadataAsValue::get(Ctx, MDString::get(Ctx, "round.tonearest")));
Args.push_back(
MetadataAsValue::get(Ctx, MDString::get(Ctx, "fpexcept.ignore")));
NewInst = CallInst::Create(IFn, Args, OldInst.getName() + ".strict");
}
}
if (!NewInst)
NewInst = II->clone();
return NewInst;
}
void PruningFunctionCloner::CloneBlock(
const BasicBlock *BB, BasicBlock::const_iterator StartingInst,
std::vector<const BasicBlock *> &ToClone) {
WeakTrackingVH &BBEntry = VMap[BB];
if (BBEntry)
return;
BasicBlock *NewBB;
BBEntry = NewBB = BasicBlock::Create(BB->getContext());
if (BB->hasName())
NewBB->setName(BB->getName() + NameSuffix);
if (BB->hasAddressTaken()) {
Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(OldFunc),
const_cast<BasicBlock *>(BB));
VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
}
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
for (BasicBlock::const_iterator II = StartingInst, IE = --BB->end(); II != IE;
++II) {
Instruction *NewInst = cloneInstruction(II);
if (HostFuncIsStrictFP) {
if (auto *Call = dyn_cast<CallInst>(NewInst))
Call->addFnAttr(Attribute::StrictFP);
}
if (!isa<PHINode>(NewInst)) {
RemapInstruction(NewInst, VMap,
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges);
if (Value *V =
simplifyInstruction(NewInst, BB->getModule()->getDataLayout())) {
if (NewFunc != OldFunc)
if (Value *MappedV = VMap.lookup(V))
V = MappedV;
if (!NewInst->mayHaveSideEffects()) {
VMap[&*II] = V;
NewInst->deleteValue();
continue;
}
}
}
if (II->hasName())
NewInst->setName(II->getName() + NameSuffix);
VMap[&*II] = NewInst; NewBB->getInstList().push_back(NewInst);
hasCalls |= (isa<CallInst>(II) && !II->isDebugOrPseudoInst());
if (CodeInfo) {
CodeInfo->OrigVMap[&*II] = NewInst;
if (auto *CB = dyn_cast<CallBase>(&*II))
if (CB->hasOperandBundles())
CodeInfo->OperandBundleCallSites.push_back(NewInst);
}
if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
if (isa<ConstantInt>(AI->getArraySize()))
hasStaticAllocas = true;
else
hasDynamicAllocas = true;
}
}
const Instruction *OldTI = BB->getTerminator();
bool TerminatorDone = false;
if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
if (BI->isConditional()) {
ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
if (!Cond) {
Value *V = VMap.lookup(BI->getCondition());
Cond = dyn_cast_or_null<ConstantInt>(V);
}
if (Cond) {
BasicBlock *Dest = BI->getSuccessor(!Cond->getZExtValue());
VMap[OldTI] = BranchInst::Create(Dest, NewBB);
ToClone.push_back(Dest);
TerminatorDone = true;
}
}
} else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {
ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
if (!Cond) { Value *V = VMap.lookup(SI->getCondition());
Cond = dyn_cast_or_null<ConstantInt>(V);
}
if (Cond) { SwitchInst::ConstCaseHandle Case = *SI->findCaseValue(Cond);
BasicBlock *Dest = const_cast<BasicBlock *>(Case.getCaseSuccessor());
VMap[OldTI] = BranchInst::Create(Dest, NewBB);
ToClone.push_back(Dest);
TerminatorDone = true;
}
}
if (!TerminatorDone) {
Instruction *NewInst = OldTI->clone();
if (OldTI->hasName())
NewInst->setName(OldTI->getName() + NameSuffix);
NewBB->getInstList().push_back(NewInst);
VMap[OldTI] = NewInst;
if (CodeInfo) {
CodeInfo->OrigVMap[OldTI] = NewInst;
if (auto *CB = dyn_cast<CallBase>(OldTI))
if (CB->hasOperandBundles())
CodeInfo->OperandBundleCallSites.push_back(NewInst);
}
append_range(ToClone, successors(BB->getTerminator()));
}
if (CodeInfo) {
CodeInfo->ContainsCalls |= hasCalls;
CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
CodeInfo->ContainsDynamicAllocas |=
hasStaticAllocas && BB != &BB->getParent()->front();
}
}
void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
const Instruction *StartingInst,
ValueToValueMapTy &VMap,
bool ModuleLevelChanges,
SmallVectorImpl<ReturnInst *> &Returns,
const char *NameSuffix,
ClonedCodeInfo *CodeInfo) {
assert(NameSuffix && "NameSuffix cannot be null!");
ValueMapTypeRemapper *TypeMapper = nullptr;
ValueMaterializer *Materializer = nullptr;
#ifndef NDEBUG
if (!StartingInst)
for (const Argument &II : OldFunc->args())
assert(VMap.count(&II) && "No mapping from source argument specified!");
#endif
PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges,
NameSuffix, CodeInfo);
const BasicBlock *StartingBB;
if (StartingInst)
StartingBB = StartingInst->getParent();
else {
StartingBB = &OldFunc->getEntryBlock();
StartingInst = &StartingBB->front();
}
std::vector<const BasicBlock *> CloneWorklist;
PFC.CloneBlock(StartingBB, StartingInst->getIterator(), CloneWorklist);
while (!CloneWorklist.empty()) {
const BasicBlock *BB = CloneWorklist.back();
CloneWorklist.pop_back();
PFC.CloneBlock(BB, BB->begin(), CloneWorklist);
}
SmallVector<const PHINode *, 16> PHIToResolve;
for (const BasicBlock &BI : *OldFunc) {
Value *V = VMap.lookup(&BI);
BasicBlock *NewBB = cast_or_null<BasicBlock>(V);
if (!NewBB)
continue;
NewFunc->getBasicBlockList().push_back(NewBB);
for (const PHINode &PN : BI.phis()) {
if (isa<PHINode>(VMap[&PN]))
PHIToResolve.push_back(&PN);
else
break;
}
RemapInstruction(NewBB->getTerminator(), VMap,
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
TypeMapper, Materializer);
}
for (unsigned phino = 0, e = PHIToResolve.size(); phino != e;) {
const PHINode *OPN = PHIToResolve[phino];
unsigned NumPreds = OPN->getNumIncomingValues();
const BasicBlock *OldBB = OPN->getParent();
BasicBlock *NewBB = cast<BasicBlock>(VMap[OldBB]);
for (; phino != PHIToResolve.size() &&
PHIToResolve[phino]->getParent() == OldBB;
++phino) {
OPN = PHIToResolve[phino];
PHINode *PN = cast<PHINode>(VMap[OPN]);
for (unsigned pred = 0, e = NumPreds; pred != e; ++pred) {
Value *V = VMap.lookup(PN->getIncomingBlock(pred));
if (BasicBlock *MappedBlock = cast_or_null<BasicBlock>(V)) {
Value *InVal =
MapValue(PN->getIncomingValue(pred), VMap,
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges);
assert(InVal && "Unknown input value?");
PN->setIncomingValue(pred, InVal);
PN->setIncomingBlock(pred, MappedBlock);
} else {
PN->removeIncomingValue(pred, false);
--pred; --e;
}
}
}
PHINode *PN = cast<PHINode>(NewBB->begin());
NumPreds = pred_size(NewBB);
if (NumPreds != PN->getNumIncomingValues()) {
assert(NumPreds < PN->getNumIncomingValues());
std::map<BasicBlock *, unsigned> PredCount;
for (BasicBlock *Pred : predecessors(NewBB))
--PredCount[Pred];
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
++PredCount[PN->getIncomingBlock(i)];
BasicBlock::iterator I = NewBB->begin();
for (; (PN = dyn_cast<PHINode>(I)); ++I) {
for (const auto &PCI : PredCount) {
BasicBlock *Pred = PCI.first;
for (unsigned NumToRemove = PCI.second; NumToRemove; --NumToRemove)
PN->removeIncomingValue(Pred, false);
}
}
}
PN = cast<PHINode>(NewBB->begin());
if (PN->getNumIncomingValues() == 0) {
BasicBlock::iterator I = NewBB->begin();
BasicBlock::const_iterator OldI = OldBB->begin();
while ((PN = dyn_cast<PHINode>(I++))) {
Value *NV = PoisonValue::get(PN->getType());
PN->replaceAllUsesWith(NV);
assert(VMap[&*OldI] == PN && "VMap mismatch");
VMap[&*OldI] = NV;
PN->eraseFromParent();
++OldI;
}
}
}
const DataLayout &DL = NewFunc->getParent()->getDataLayout();
SmallSetVector<const Value *, 8> Worklist;
for (unsigned Idx = 0, Size = PHIToResolve.size(); Idx != Size; ++Idx)
if (isa<PHINode>(VMap[PHIToResolve[Idx]]))
Worklist.insert(PHIToResolve[Idx]);
for (unsigned Idx = 0; Idx != Worklist.size(); ++Idx) {
const Value *OrigV = Worklist[Idx];
auto *I = dyn_cast_or_null<Instruction>(VMap.lookup(OrigV));
if (!I)
continue;
CallBase *CB = dyn_cast<CallBase>(I);
if (CB && CB->getCalledFunction() &&
!CB->getCalledFunction()->isIntrinsic())
continue;
Value *SimpleV = simplifyInstruction(I, DL);
if (!SimpleV)
continue;
for (const User *U : OrigV->users())
Worklist.insert(cast<Instruction>(U));
I->replaceAllUsesWith(SimpleV);
if (isInstructionTriviallyDead(I))
I->eraseFromParent();
else
VMap[OrigV] = I;
}
Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator();
for (BasicBlock &BB : make_range(Begin, NewFunc->end()))
ConstantFoldTerminator(&BB);
{
SmallPtrSet<BasicBlock *, 16> ReachableBlocks;
SmallVector<BasicBlock *, 16> Worklist;
Worklist.push_back(&*Begin);
while (!Worklist.empty()) {
BasicBlock *BB = Worklist.pop_back_val();
if (ReachableBlocks.insert(BB).second)
append_range(Worklist, successors(BB));
}
SmallVector<BasicBlock *, 16> UnreachableBlocks;
for (BasicBlock &BB : make_range(Begin, NewFunc->end()))
if (!ReachableBlocks.contains(&BB))
UnreachableBlocks.push_back(&BB);
DeleteDeadBlocks(UnreachableBlocks);
}
Function::iterator I = Begin;
while (I != NewFunc->end()) {
BranchInst *BI = dyn_cast<BranchInst>(I->getTerminator());
if (!BI || BI->isConditional()) {
++I;
continue;
}
BasicBlock *Dest = BI->getSuccessor(0);
if (!Dest->getSinglePredecessor()) {
++I;
continue;
}
assert(!isa<PHINode>(Dest->begin()));
BI->eraseFromParent();
Dest->replaceAllUsesWith(&*I);
I->getInstList().splice(I->end(), Dest->getInstList());
Dest->eraseFromParent();
}
for (Function::iterator I = cast<BasicBlock>(VMap[StartingBB])->getIterator(),
E = NewFunc->end();
I != E; ++I)
if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator()))
Returns.push_back(RI);
}
void llvm::CloneAndPruneFunctionInto(
Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap,
bool ModuleLevelChanges, SmallVectorImpl<ReturnInst *> &Returns,
const char *NameSuffix, ClonedCodeInfo *CodeInfo) {
CloneAndPruneIntoFromInst(NewFunc, OldFunc, &OldFunc->front().front(), VMap,
ModuleLevelChanges, Returns, NameSuffix, CodeInfo);
}
void llvm::remapInstructionsInBlocks(
const SmallVectorImpl<BasicBlock *> &Blocks, ValueToValueMapTy &VMap) {
for (auto *BB : Blocks)
for (auto &Inst : *BB)
RemapInstruction(&Inst, VMap,
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
}
Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
Loop *OrigLoop, ValueToValueMapTy &VMap,
const Twine &NameSuffix, LoopInfo *LI,
DominatorTree *DT,
SmallVectorImpl<BasicBlock *> &Blocks) {
Function *F = OrigLoop->getHeader()->getParent();
Loop *ParentLoop = OrigLoop->getParentLoop();
DenseMap<Loop *, Loop *> LMap;
Loop *NewLoop = LI->AllocateLoop();
LMap[OrigLoop] = NewLoop;
if (ParentLoop)
ParentLoop->addChildLoop(NewLoop);
else
LI->addTopLevelLoop(NewLoop);
BasicBlock *OrigPH = OrigLoop->getLoopPreheader();
assert(OrigPH && "No preheader");
BasicBlock *NewPH = CloneBasicBlock(OrigPH, VMap, NameSuffix, F);
VMap[OrigPH] = NewPH;
Blocks.push_back(NewPH);
if (ParentLoop)
ParentLoop->addBasicBlockToLoop(NewPH, *LI);
DT->addNewBlock(NewPH, LoopDomBB);
for (Loop *CurLoop : OrigLoop->getLoopsInPreorder()) {
Loop *&NewLoop = LMap[CurLoop];
if (!NewLoop) {
NewLoop = LI->AllocateLoop();
Loop *OrigParent = CurLoop->getParentLoop();
assert(OrigParent && "Could not find the original parent loop");
Loop *NewParentLoop = LMap[OrigParent];
assert(NewParentLoop && "Could not find the new parent loop");
NewParentLoop->addChildLoop(NewLoop);
}
}
for (BasicBlock *BB : OrigLoop->getBlocks()) {
Loop *CurLoop = LI->getLoopFor(BB);
Loop *&NewLoop = LMap[CurLoop];
assert(NewLoop && "Expecting new loop to be allocated");
BasicBlock *NewBB = CloneBasicBlock(BB, VMap, NameSuffix, F);
VMap[BB] = NewBB;
NewLoop->addBasicBlockToLoop(NewBB, *LI);
DT->addNewBlock(NewBB, NewPH);
Blocks.push_back(NewBB);
}
for (BasicBlock *BB : OrigLoop->getBlocks()) {
Loop *CurLoop = LI->getLoopFor(BB);
if (BB == CurLoop->getHeader())
LMap[CurLoop]->moveToHeader(cast<BasicBlock>(VMap[BB]));
BasicBlock *IDomBB = DT->getNode(BB)->getIDom()->getBlock();
DT->changeImmediateDominator(cast<BasicBlock>(VMap[BB]),
cast<BasicBlock>(VMap[IDomBB]));
}
F->getBasicBlockList().splice(Before->getIterator(), F->getBasicBlockList(),
NewPH);
F->getBasicBlockList().splice(Before->getIterator(), F->getBasicBlockList(),
NewLoop->getHeader()->getIterator(), F->end());
return NewLoop;
}
BasicBlock *llvm::DuplicateInstructionsInSplitBetween(
BasicBlock *BB, BasicBlock *PredBB, Instruction *StopAt,
ValueToValueMapTy &ValueMapping, DomTreeUpdater &DTU) {
assert(count(successors(PredBB), BB) == 1 &&
"There must be a single edge between PredBB and BB!");
BasicBlock::iterator BI = BB->begin();
for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB);
BasicBlock *NewBB = SplitEdge(PredBB, BB);
NewBB->setName(PredBB->getName() + ".split");
Instruction *NewTerm = NewBB->getTerminator();
DTU.applyUpdates({{DominatorTree::Delete, PredBB, BB},
{DominatorTree::Insert, PredBB, NewBB},
{DominatorTree::Insert, NewBB, BB}});
for (; StopAt != &*BI && BB->getTerminator() != &*BI; ++BI) {
Instruction *New = BI->clone();
New->setName(BI->getName());
New->insertBefore(NewTerm);
ValueMapping[&*BI] = New;
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
if (Instruction *Inst = dyn_cast<Instruction>(New->getOperand(i))) {
auto I = ValueMapping.find(Inst);
if (I != ValueMapping.end())
New->setOperand(i, I->second);
}
}
return NewBB;
}
void llvm::cloneNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
DenseMap<MDNode *, MDNode *> &ClonedScopes,
StringRef Ext, LLVMContext &Context) {
MDBuilder MDB(Context);
for (auto *ScopeList : NoAliasDeclScopes) {
for (auto &MDOperand : ScopeList->operands()) {
if (MDNode *MD = dyn_cast<MDNode>(MDOperand)) {
AliasScopeNode SNANode(MD);
std::string Name;
auto ScopeName = SNANode.getName();
if (!ScopeName.empty())
Name = (Twine(ScopeName) + ":" + Ext).str();
else
Name = std::string(Ext);
MDNode *NewScope = MDB.createAnonymousAliasScope(
const_cast<MDNode *>(SNANode.getDomain()), Name);
ClonedScopes.insert(std::make_pair(MD, NewScope));
}
}
}
}
void llvm::adaptNoAliasScopes(Instruction *I,
const DenseMap<MDNode *, MDNode *> &ClonedScopes,
LLVMContext &Context) {
auto CloneScopeList = [&](const MDNode *ScopeList) -> MDNode * {
bool NeedsReplacement = false;
SmallVector<Metadata *, 8> NewScopeList;
for (auto &MDOp : ScopeList->operands()) {
if (MDNode *MD = dyn_cast<MDNode>(MDOp)) {
if (auto *NewMD = ClonedScopes.lookup(MD)) {
NewScopeList.push_back(NewMD);
NeedsReplacement = true;
continue;
}
NewScopeList.push_back(MD);
}
}
if (NeedsReplacement)
return MDNode::get(Context, NewScopeList);
return nullptr;
};
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(I))
if (auto *NewScopeList = CloneScopeList(Decl->getScopeList()))
Decl->setScopeList(NewScopeList);
auto replaceWhenNeeded = [&](unsigned MD_ID) {
if (const MDNode *CSNoAlias = I->getMetadata(MD_ID))
if (auto *NewScopeList = CloneScopeList(CSNoAlias))
I->setMetadata(MD_ID, NewScopeList);
};
replaceWhenNeeded(LLVMContext::MD_noalias);
replaceWhenNeeded(LLVMContext::MD_alias_scope);
}
void llvm::cloneAndAdaptNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
ArrayRef<BasicBlock *> NewBlocks,
LLVMContext &Context, StringRef Ext) {
if (NoAliasDeclScopes.empty())
return;
DenseMap<MDNode *, MDNode *> ClonedScopes;
LLVM_DEBUG(dbgs() << "cloneAndAdaptNoAliasScopes: cloning "
<< NoAliasDeclScopes.size() << " node(s)\n");
cloneNoAliasScopes(NoAliasDeclScopes, ClonedScopes, Ext, Context);
for (BasicBlock *NewBlock : NewBlocks)
for (Instruction &I : *NewBlock)
adaptNoAliasScopes(&I, ClonedScopes, Context);
}
void llvm::cloneAndAdaptNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
Instruction *IStart, Instruction *IEnd,
LLVMContext &Context, StringRef Ext) {
if (NoAliasDeclScopes.empty())
return;
DenseMap<MDNode *, MDNode *> ClonedScopes;
LLVM_DEBUG(dbgs() << "cloneAndAdaptNoAliasScopes: cloning "
<< NoAliasDeclScopes.size() << " node(s)\n");
cloneNoAliasScopes(NoAliasDeclScopes, ClonedScopes, Ext, Context);
assert(IStart->getParent() == IEnd->getParent() && "different basic block ?");
auto ItStart = IStart->getIterator();
auto ItEnd = IEnd->getIterator();
++ItEnd; for (auto &I : llvm::make_range(ItStart, ItEnd))
adaptNoAliasScopes(&I, ClonedScopes, Context);
}
void llvm::identifyNoAliasScopesToClone(
ArrayRef<BasicBlock *> BBs, SmallVectorImpl<MDNode *> &NoAliasDeclScopes) {
for (BasicBlock *BB : BBs)
for (Instruction &I : *BB)
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
NoAliasDeclScopes.push_back(Decl->getScopeList());
}
void llvm::identifyNoAliasScopesToClone(
BasicBlock::iterator Start, BasicBlock::iterator End,
SmallVectorImpl<MDNode *> &NoAliasDeclScopes) {
for (Instruction &I : make_range(Start, End))
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
NoAliasDeclScopes.push_back(Decl->getScopeList());
}