本文整理汇总了C++中SmallVector::erase方法的典型用法代码示例。如果您正苦于以下问题:C++ SmallVector::erase方法的具体用法?C++ SmallVector::erase怎么用?C++ SmallVector::erase使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类SmallVector
的用法示例。
在下文中一共展示了SmallVector::erase方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: removeDeadFunctions
/// removeDeadFunctions - Remove dead functions that are not included in
/// DNR (Do Not Remove) list.
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
SmallVector<CallGraphNode*, 16> FunctionsToRemove;
// Scan for all of the functions, looking for ones that should now be removed
// from the program. Insert the dead ones in the FunctionsToRemove set.
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
CallGraphNode *CGN = I->second;
Function *F = CGN->getFunction();
if (!F || F->isDeclaration())
continue;
// Handle the case when this function is called and we only want to care
// about always-inline functions. This is a bit of a hack to share code
// between here and the InlineAlways pass.
if (AlwaysInlineOnly &&
!F->getAttributes().hasAttribute(AttributeSet::FunctionIndex,
Attribute::AlwaysInline))
continue;
// If the only remaining users of the function are dead constants, remove
// them.
F->removeDeadConstantUsers();
if (!F->isDefTriviallyDead())
continue;
// Remove any call graph edges from the function to its callees.
CGN->removeAllCalledFunctions();
// Remove any edges from the external node to the function's call graph
// node. These edges might have been made irrelegant due to
// optimization of the program.
CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);
// Removing the node for callee from the call graph and delete it.
FunctionsToRemove.push_back(CGN);
}
if (FunctionsToRemove.empty())
return false;
// Now that we know which functions to delete, do so. We didn't want to do
// this inline, because that would invalidate our CallGraph::iterator
// objects. :(
//
// Note that it doesn't matter that we are iterating over a non-stable order
// here to do this, it doesn't matter which order the functions are deleted
// in.
array_pod_sort(FunctionsToRemove.begin(), FunctionsToRemove.end());
FunctionsToRemove.erase(std::unique(FunctionsToRemove.begin(),
FunctionsToRemove.end()),
FunctionsToRemove.end());
for (SmallVectorImpl<CallGraphNode *>::iterator I = FunctionsToRemove.begin(),
E = FunctionsToRemove.end();
I != E; ++I) {
delete CG.removeFunctionFromModule(*I);
++NumDeleted;
}
return true;
}
示例2: getNames
ArrayRef<Identifier> getNames() {
llvm::array_pod_sort(names.begin(), names.end(),
[](const Identifier *lhs, const Identifier *rhs) {
return lhs->compare(*rhs);
});
names.erase(std::unique(names.begin(), names.end()), names.end());
return names;
}
示例3: simplify
Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {
// Gather constant terms.
SmallVector<Term, 32> Terms;
extractTerms(ExpressionTree, +1, Terms);
// If there are no terms, this is just a zero. The algorithm below assumes at
// least one term.
if (Terms.size() == 0)
return Counter::getZero();
// Group the terms by counter ID.
std::sort(Terms.begin(), Terms.end(), [](const Term &LHS, const Term &RHS) {
return LHS.CounterID < RHS.CounterID;
});
// Combine terms by counter ID to eliminate counters that sum to zero.
auto Prev = Terms.begin();
for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {
if (I->CounterID == Prev->CounterID) {
Prev->Factor += I->Factor;
continue;
}
++Prev;
*Prev = *I;
}
Terms.erase(++Prev, Terms.end());
Counter C;
// Create additions. We do this before subtractions to avoid constructs like
// ((0 - X) + Y), as opposed to (Y - X).
for (auto T : Terms) {
if (T.Factor <= 0)
continue;
for (int I = 0; I < T.Factor; ++I)
if (C.isZero())
C = Counter::getCounter(T.CounterID);
else
C = get(CounterExpression(CounterExpression::Add, C,
Counter::getCounter(T.CounterID)));
}
// Create subtractions.
for (auto T : Terms) {
if (T.Factor >= 0)
continue;
for (int I = 0; I < -T.Factor; ++I)
C = get(CounterExpression(CounterExpression::Subtract, C,
Counter::getCounter(T.CounterID)));
}
return C;
}
示例4: run
PreservedAnalyses AlwaysInlinerPass::run(Module &M, ModuleAnalysisManager &) {
InlineFunctionInfo IFI;
SmallSetVector<CallSite, 16> Calls;
bool Changed = false;
SmallVector<Function *, 16> InlinedFunctions;
for (Function &F : M)
if (!F.isDeclaration() && F.hasFnAttribute(Attribute::AlwaysInline) &&
isInlineViable(F)) {
Calls.clear();
for (User *U : F.users())
if (auto CS = CallSite(U))
if (CS.getCalledFunction() == &F)
Calls.insert(CS);
for (CallSite CS : Calls)
// FIXME: We really shouldn't be able to fail to inline at this point!
// We should do something to log or check the inline failures here.
Changed |= InlineFunction(CS, IFI);
// Remember to try and delete this function afterward. This both avoids
// re-walking the rest of the module and avoids dealing with any iterator
// invalidation issues while deleting functions.
InlinedFunctions.push_back(&F);
}
// Remove any live functions.
erase_if(InlinedFunctions, [&](Function *F) {
F->removeDeadConstantUsers();
return !F->isDefTriviallyDead();
});
// Delete the non-comdat ones from the module and also from our vector.
auto NonComdatBegin = partition(
InlinedFunctions, [&](Function *F) { return F->hasComdat(); });
for (Function *F : make_range(NonComdatBegin, InlinedFunctions.end()))
M.getFunctionList().erase(F);
InlinedFunctions.erase(NonComdatBegin, InlinedFunctions.end());
if (!InlinedFunctions.empty()) {
// Now we just have the comdat functions. Filter out the ones whose comdats
// are not actually dead.
filterDeadComdatFunctions(M, InlinedFunctions);
// The remaining functions are actually dead.
for (Function *F : InlinedFunctions)
M.getFunctionList().erase(F);
}
return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
}
示例5: bindExtensions
static void bindExtensions(SourceFile &SF, TypeChecker &TC) {
// Utility function to try and resolve the extended type without diagnosing.
// If we succeed, we go ahead and bind the extension. Otherwise, return false.
auto tryBindExtension = [&](ExtensionDecl *ext) -> bool {
if (auto nominal = ext->getExtendedNominal()) {
bindExtensionToNominal(ext, nominal);
return true;
}
return false;
};
// Phase 1 - try to bind each extension, adding those whose type cannot be
// resolved to a worklist.
SmallVector<ExtensionDecl *, 8> worklist;
// FIXME: The current source file needs to be handled specially, because of
// private extensions.
SF.forAllVisibleModules([&](ModuleDecl::ImportedModule import) {
// FIXME: Respect the access path?
for (auto file : import.second->getFiles()) {
auto SF = dyn_cast<SourceFile>(file);
if (!SF)
continue;
for (auto D : SF->Decls) {
if (auto ED = dyn_cast<ExtensionDecl>(D))
if (!tryBindExtension(ED))
worklist.push_back(ED);
}
}
});
// Phase 2 - repeatedly go through the worklist and attempt to bind each
// extension there, removing it from the worklist if we succeed.
bool changed;
do {
changed = false;
auto last = std::remove_if(worklist.begin(), worklist.end(),
tryBindExtension);
if (last != worklist.end()) {
worklist.erase(last, worklist.end());
changed = true;
}
} while(changed);
// Any remaining extensions are invalid. They will be diagnosed later by
// typeCheckDecl().
}
示例6: ComputeDeclsFound
/// \brief Computes the set of declarations referenced by these base
/// paths.
void CXXBasePaths::ComputeDeclsFound() {
assert(NumDeclsFound == 0 && !DeclsFound &&
"Already computed the set of declarations");
SmallVector<NamedDecl *, 8> Decls;
for (paths_iterator Path = begin(), PathEnd = end(); Path != PathEnd; ++Path)
Decls.push_back(*Path->Decls.first);
// Eliminate duplicated decls.
llvm::array_pod_sort(Decls.begin(), Decls.end());
Decls.erase(std::unique(Decls.begin(), Decls.end()), Decls.end());
NumDeclsFound = Decls.size();
DeclsFound = new NamedDecl * [NumDeclsFound];
std::copy(Decls.begin(), Decls.end(), DeclsFound);
}
示例7: filterByAccelName
/// Print only DIEs that have a certain name.
static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
raw_ostream &OS) {
SmallVector<uint64_t, 4> Offsets;
for (const auto &Name : Names) {
getDIEOffset(DICtx.getAppleNames(), Name, Offsets);
getDIEOffset(DICtx.getAppleTypes(), Name, Offsets);
getDIEOffset(DICtx.getAppleNamespaces(), Name, Offsets);
getDIEOffset(DICtx.getDebugNames(), Name, Offsets);
}
llvm::sort(Offsets.begin(), Offsets.end());
Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end());
for (uint64_t Off: Offsets) {
DWARFDie Die = DICtx.getDIEForOffset(Off);
Die.dump(OS, 0, getDumpOpts());
}
}
示例8: printSummary
void Job::printSummary(raw_ostream &os) const {
// Deciding how to describe our inputs is a bit subtle; if we are a Job built
// from a JobAction that itself has InputActions sources, then we collect
// those up. Otherwise it's more correct to talk about our inputs as the
// outputs of our input-jobs.
SmallVector<std::string, 4> Inputs;
for (const Action *A : getSource().getInputs())
if (const InputAction *IA = dyn_cast<InputAction>(A))
Inputs.push_back(IA->getInputArg().getValue());
for (const Job *J : getInputs())
for (const std::string &f : J->getOutput().getPrimaryOutputFilenames())
Inputs.push_back(f);
size_t limit = 3;
size_t actual = Inputs.size();
if (actual > limit) {
Inputs.erase(Inputs.begin() + limit, Inputs.end());
}
os << "{" << getSource().getClassName() << ": ";
interleave(getOutput().getPrimaryOutputFilenames(),
[&](const std::string &Arg) {
os << llvm::sys::path::filename(Arg);
},
[&] { os << ' '; });
os << " <= ";
interleave(Inputs,
[&](const std::string &Arg) {
os << llvm::sys::path::filename(Arg);
},
[&] { os << ' '; });
if (actual > limit) {
os << " ... " << (actual-limit) << " more";
}
os << "}";
}
示例9: analyzeFunction
bool CallingConvention_AnyArch_AnyCC::analyzeFunction(ParameterRegistry ®istry, CallInformation &fillOut, llvm::Function &func)
{
if (!isFullDisassembly() || md::isPrototype(func))
{
return false;
}
auto regs = &*func.arg_begin();
unordered_map<const TargetRegisterInfo*, ModRefInfo> resultMap;
// Find all GEPs
const auto& target = registry.getTargetInfo();
unordered_multimap<const TargetRegisterInfo*, User*> registerUsers;
for (User* user : regs->users())
{
if (const TargetRegisterInfo* maybeRegister = target.registerInfo(*user))
{
const TargetRegisterInfo& registerInfo = target.largestOverlappingRegister(*maybeRegister);
registerUsers.insert({®isterInfo, user});
}
}
// Find all users of these GEPs
DominatorsPerRegister gepUsers;
for (auto iter = registerUsers.begin(); iter != registerUsers.end(); iter++)
{
addAllUsers(*iter->second, iter->first, gepUsers);
}
DominatorTree& preDom = registry.getAnalysis<DominatorTreeWrapperPass>(func).getDomTree();
PostDominatorTree& postDom = registry.getAnalysis<PostDominatorTreeWrapperPass>(func).getPostDomTree();
// Add calls
SmallVector<CallInst*, 8> calls;
CallGraph& cg = registry.getAnalysis<CallGraphWrapperPass>().getCallGraph();
CallGraphNode* thisFunc = cg[&func];
for (const auto& pair : *thisFunc)
{
Function* callee = pair.second->getFunction();
if (const CallInformation* callInfo = registry.getCallInfo(*callee))
if (callInfo->getStage() == CallInformation::Completed)
{
// pair.first is a weak value handle and has a cast operator to get the pointee
CallInst* caller = cast<CallInst>((Value*)pair.first);
calls.push_back(caller);
for (const auto& vi : *callInfo)
{
if (vi.type == ValueInformation::IntegerRegister)
{
gepUsers[vi.registerInfo].insert(caller);
}
}
}
}
// Start out resultMap based on call dominance. Weed out calls until dominant call set has been established.
// This map will be refined by results from mod/ref instruction analysis. The purpose is mainly to define
// mod/ref behavior for registers that are used in callees of this function, but not in this function
// directly.
while (calls.size() > 0)
{
unordered_map<const TargetRegisterInfo*, unsigned> callResult;
auto dominant = findDominantValues(preDom, calls);
for (CallInst* call : dominant)
{
Function* callee = call->getCalledFunction();
for (const auto& pair : translateToModRef(*registry.getCallInfo(*callee)))
{
callResult[pair.first] |= pair.second;
}
calls.erase(find(calls.begin(), calls.end(), call));
}
for (const auto& pair : callResult)
{
resultMap[pair.first] = static_cast<ModRefInfo>(pair.second);
}
}
// Find the dominant use(s)
auto preDominatingUses = gepUsers;
for (auto& pair : preDominatingUses)
{
pair.second = findDominantValues(preDom, pair.second);
}
// Fill out ModRef use dictionary
// (Ref info is incomplete)
for (auto& pair : preDominatingUses)
{
ModRefInfo& r = resultMap[pair.first];
r = IncompleteRef;
for (auto inst : pair.second)
{
if (isa<StoreInst>(inst))
{
// If we see a dominant store, then the register is modified.
r = MRI_Mod;
//.........这里部分代码省略.........
示例10: run
//.........这里部分代码省略.........
else {
R << " with cost=" << NV("Cost", OIC->getCost());
R << " (threshold=" << NV("Threshold", OIC->getThreshold());
R << ")";
}
return R;
});
// Add any new callsites to defined functions to the worklist.
if (!IFI.InlinedCallSites.empty()) {
int NewHistoryID = InlineHistory.size();
InlineHistory.push_back({&Callee, InlineHistoryID});
for (CallSite &CS : reverse(IFI.InlinedCallSites))
if (Function *NewCallee = CS.getCalledFunction())
if (!NewCallee->isDeclaration())
Calls.push_back({CS, NewHistoryID});
}
if (InlinerFunctionImportStats != InlinerFunctionImportStatsOpts::No)
ImportedFunctionsStats->recordInline(F, Callee);
// Merge the attributes based on the inlining.
AttributeFuncs::mergeAttributesForInlining(F, Callee);
// For local functions, check whether this makes the callee trivially
// dead. In that case, we can drop the body of the function eagerly
// which may reduce the number of callers of other functions to one,
// changing inline cost thresholds.
if (Callee.hasLocalLinkage()) {
// To check this we also need to nuke any dead constant uses (perhaps
// made dead by this operation on other functions).
Callee.removeDeadConstantUsers();
if (Callee.use_empty() && !CG.isLibFunction(Callee)) {
Calls.erase(
std::remove_if(Calls.begin() + i + 1, Calls.end(),
[&Callee](const std::pair<CallSite, int> &Call) {
return Call.first.getCaller() == &Callee;
}),
Calls.end());
// Clear the body and queue the function itself for deletion when we
// finish inlining and call graph updates.
// Note that after this point, it is an error to do anything other
// than use the callee's address or delete it.
Callee.dropAllReferences();
assert(find(DeadFunctions, &Callee) == DeadFunctions.end() &&
"Cannot put cause a function to become dead twice!");
DeadFunctions.push_back(&Callee);
}
}
}
// Back the call index up by one to put us in a good position to go around
// the outer loop.
--i;
if (!DidInline)
continue;
Changed = true;
// Add all the inlined callees' edges as ref edges to the caller. These are
// by definition trivial edges as we always have *some* transitive ref edge
// chain. While in some cases these edges are direct calls inside the
// callee, they have to be modeled in the inliner as reference edges as
// there may be a reference edge anywhere along the chain from the current
// caller to the callee that causes the whole thing to appear like
// a (transitive) reference edge that will require promotion to a call edge
示例11: emitMacroExpansions
/// \brief Recursively emit notes for each macro expansion and caret
/// diagnostics where appropriate.
///
/// Walks up the macro expansion stack printing expansion notes, the code
/// snippet, caret, underlines and FixItHint display as appropriate at each
/// level.
///
/// \param Loc The location for this caret.
/// \param Level The diagnostic level currently being emitted.
/// \param Ranges The underlined ranges for this code snippet.
/// \param Hints The FixIt hints active for this diagnostic.
void DiagnosticRenderer::emitMacroExpansions(SourceLocation Loc,
DiagnosticsEngine::Level Level,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Hints,
const SourceManager &SM) {
assert(!Loc.isInvalid() && "must have a valid source location here");
// Produce a stack of macro backtraces.
SmallVector<SourceLocation, 8> LocationStack;
unsigned IgnoredEnd = 0;
while (Loc.isMacroID()) {
// If this is the expansion of a macro argument, point the caret at the
// use of the argument in the definition of the macro, not the expansion.
if (SM.isMacroArgExpansion(Loc))
LocationStack.push_back(SM.getImmediateExpansionRange(Loc).first);
else
LocationStack.push_back(Loc);
if (checkRangesForMacroArgExpansion(Loc, Ranges, SM))
IgnoredEnd = LocationStack.size();
Loc = SM.getImmediateMacroCallerLoc(Loc);
// Once the location no longer points into a macro, try stepping through
// the last found location. This sometimes produces additional useful
// backtraces.
if (Loc.isFileID())
Loc = SM.getImmediateMacroCallerLoc(LocationStack.back());
assert(!Loc.isInvalid() && "must have a valid source location here");
}
LocationStack.erase(LocationStack.begin(),
LocationStack.begin() + IgnoredEnd);
unsigned MacroDepth = LocationStack.size();
unsigned MacroLimit = DiagOpts->MacroBacktraceLimit;
if (MacroDepth <= MacroLimit || MacroLimit == 0) {
for (auto I = LocationStack.rbegin(), E = LocationStack.rend();
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
return;
}
unsigned MacroStartMessages = MacroLimit / 2;
unsigned MacroEndMessages = MacroLimit / 2 + MacroLimit % 2;
for (auto I = LocationStack.rbegin(),
E = LocationStack.rbegin() + MacroStartMessages;
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
SmallString<200> MessageStorage;
llvm::raw_svector_ostream Message(MessageStorage);
Message << "(skipping " << (MacroDepth - MacroLimit)
<< " expansions in backtrace; use -fmacro-backtrace-limit=0 to "
"see all)";
emitBasicNote(Message.str());
for (auto I = LocationStack.rend() - MacroEndMessages,
E = LocationStack.rend();
I != E; ++I)
emitSingleMacroExpansion(*I, Level, Ranges, SM);
}
示例12: RemoveBlockIfDead
/// RemoveBlockIfDead - If the specified block is dead, remove it, update loop
/// information, and remove any dead successors it has.
///
void LoopUnswitch::RemoveBlockIfDead(BasicBlock *BB,
std::vector<Instruction*> &Worklist,
Loop *L) {
if (pred_begin(BB) != pred_end(BB)) {
// This block isn't dead, since an edge to BB was just removed, see if there
// are any easy simplifications we can do now.
if (BasicBlock *Pred = BB->getSinglePredecessor()) {
// If it has one pred, fold phi nodes in BB.
while (isa<PHINode>(BB->begin()))
ReplaceUsesOfWith(BB->begin(),
cast<PHINode>(BB->begin())->getIncomingValue(0),
Worklist, L, LPM);
// If this is the header of a loop and the only pred is the latch, we now
// have an unreachable loop.
if (Loop *L = LI->getLoopFor(BB))
if (loopHeader == BB && L->contains(Pred)) {
// Remove the branch from the latch to the header block, this makes
// the header dead, which will make the latch dead (because the header
// dominates the latch).
LPM->deleteSimpleAnalysisValue(Pred->getTerminator(), L);
Pred->getTerminator()->eraseFromParent();
new UnreachableInst(BB->getContext(), Pred);
// The loop is now broken, remove it from LI.
RemoveLoopFromHierarchy(L);
// Reprocess the header, which now IS dead.
RemoveBlockIfDead(BB, Worklist, L);
return;
}
// If pred ends in a uncond branch, add uncond branch to worklist so that
// the two blocks will get merged.
if (BranchInst *BI = dyn_cast<BranchInst>(Pred->getTerminator()))
if (BI->isUnconditional())
Worklist.push_back(BI);
}
return;
}
DEBUG(dbgs() << "Nuking dead block: " << *BB);
// Remove the instructions in the basic block from the worklist.
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
RemoveFromWorklist(I, Worklist);
// Anything that uses the instructions in this basic block should have their
// uses replaced with undefs.
// If I is not void type then replaceAllUsesWith undef.
// This allows ValueHandlers and custom metadata to adjust itself.
if (!I->getType()->isVoidTy())
I->replaceAllUsesWith(UndefValue::get(I->getType()));
}
// If this is the edge to the header block for a loop, remove the loop and
// promote all subloops.
if (Loop *BBLoop = LI->getLoopFor(BB)) {
if (BBLoop->getLoopLatch() == BB)
RemoveLoopFromHierarchy(BBLoop);
}
// Remove the block from the loop info, which removes it from any loops it
// was in.
LI->removeBlock(BB);
// Remove phi node entries in successors for this block.
TerminatorInst *TI = BB->getTerminator();
SmallVector<BasicBlock*, 4> Succs;
for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
Succs.push_back(TI->getSuccessor(i));
TI->getSuccessor(i)->removePredecessor(BB);
}
// Unique the successors, remove anything with multiple uses.
array_pod_sort(Succs.begin(), Succs.end());
Succs.erase(std::unique(Succs.begin(), Succs.end()), Succs.end());
// Remove the basic block, including all of the instructions contained in it.
LPM->deleteSimpleAnalysisValue(BB, L);
BB->eraseFromParent();
// Remove successor blocks here that are not dead, so that we know we only
// have dead blocks in this list. Nondead blocks have a way of becoming dead,
// then getting removed before we revisit them, which is badness.
//
for (unsigned i = 0; i != Succs.size(); ++i)
if (pred_begin(Succs[i]) != pred_end(Succs[i])) {
// One exception is loop headers. If this block was the preheader for a
// loop, then we DO want to visit the loop so the loop gets deleted.
// We know that if the successor is a loop header, that this loop had to
// be the preheader: the case where this was the latch block was handled
// above and headers can only have two predecessors.
if (!LI->isLoopHeader(Succs[i])) {
Succs.erase(Succs.begin()+i);
--i;
}
//.........这里部分代码省略.........
示例13: insertTripCount
Value* LoopTripCount::insertTripCount(Loop* L, Instruction* InsertPos)
{
// inspired from Loop::getCanonicalInductionVariable
BasicBlock *H = L->getHeader();
BasicBlock* LoopPred = L->getLoopPredecessor();
BasicBlock* startBB = NULL;//which basicblock stores start value
int OneStep = 0;// the extra add or plus step for calc
Assert(LoopPred, "Require Loop has a Pred");
DEBUG(errs()<<"loop depth:"<<L->getLoopDepth()<<"\n");
/** whats difference on use of predecessor and preheader??*/
//RET_ON_FAIL(self->getLoopLatch()&&self->getLoopPreheader());
//assert(self->getLoopLatch() && self->getLoopPreheader() && "need loop simplify form" );
ret_null_fail(L->getLoopLatch(), "need loop simplify form");
BasicBlock* TE = NULL;//True Exit
SmallVector<BasicBlock*,4> Exits;
L->getExitingBlocks(Exits);
if(Exits.size()==1) TE = Exits.front();
else{
if(std::find(Exits.begin(),Exits.end(),L->getLoopLatch())!=Exits.end()) TE = L->getLoopLatch();
else{
SmallVector<llvm::Loop::Edge,4> ExitEdges;
L->getExitEdges(ExitEdges);
//stl 用法,先把所有满足条件的元素(出口的结束符是不可到达)移动到数组的末尾,再统一删除
ExitEdges.erase(std::remove_if(ExitEdges.begin(), ExitEdges.end(),
[](llvm::Loop::Edge& I){
return isa<UnreachableInst>(I.second->getTerminator());
}), ExitEdges.end());
if(ExitEdges.size()==1) TE = const_cast<BasicBlock*>(ExitEdges.front().first);
}
}
//process true exit
ret_null_fail(TE, "need have a true exit");
Instruction* IndOrNext = NULL;
Value* END = NULL;
//终止块的终止指令:分情况讨论branchinst,switchinst;
//跳转指令br bool a1,a2;condition<-->bool
if(isa<BranchInst>(TE->getTerminator())){
const BranchInst* EBR = cast<BranchInst>(TE->getTerminator());
Assert(EBR->isConditional(), "end branch is not conditional");
ICmpInst* EC = dyn_cast<ICmpInst>(EBR->getCondition());
if(EC->getPredicate() == EC->ICMP_SGT){
Assert(!L->contains(EBR->getSuccessor(0)), *EBR<<":abnormal exit with great than");//终止块的终止指令---->跳出执行循环外的指令
OneStep += 1;
} else if(EC->getPredicate() == EC->ICMP_EQ)
Assert(!L->contains(EBR->getSuccessor(0)), *EBR<<":abnormal exit with great than");
else if(EC->getPredicate() == EC->ICMP_SLT) {
ret_null_fail(!L->contains(EBR->getSuccessor(1)), *EBR<<":abnormal exit with less than");
} else {
ret_null_fail(0, *EC<<" unknow combination of end condition");
}
IndOrNext = dyn_cast<Instruction>(castoff(EC->getOperand(0)));//去掉类型转化
END = EC->getOperand(1);
DEBUG(errs()<<"end value:"<<*EC<<"\n");
}else if(isa<SwitchInst>(TE->getTerminator())){
SwitchInst* ESW = const_cast<SwitchInst*>(cast<SwitchInst>(TE->getTerminator()));
IndOrNext = dyn_cast<Instruction>(castoff(ESW->getCondition()));
for(auto I = ESW->case_begin(),E = ESW->case_end();I!=E;++I){
if(!L->contains(I.getCaseSuccessor())){
ret_null_fail(!END,"");
assert(!END && "shouldn't have two ends");
END = I.getCaseValue();
}
}
DEBUG(errs()<<"end value:"<<*ESW<<"\n");
}else{
assert(0 && "unknow terminator type");
}
ret_null_fail(L->isLoopInvariant(END), "end value should be loop invariant");//至此得END值
Value* start = NULL;
Value* ind = NULL;
Instruction* next = NULL;
bool addfirst = false;//add before icmp ed
DISABLE(errs()<<*IndOrNext<<"\n");
if(isa<LoadInst>(IndOrNext)){
//memory depend analysis
Value* PSi = IndOrNext->getOperand(0);//point type Step.i
int SICount[2] = {0};//store in predecessor count,store in loop body count
for( auto I = PSi->use_begin(),E = PSi->use_end();I!=E;++I){
DISABLE(errs()<<**I<<"\n");
StoreInst* SI = dyn_cast<StoreInst>(*I);
if(!SI || SI->getOperand(1) != PSi) continue;
if(!start&&L->isLoopInvariant(SI->getOperand(0))) {
if(SI->getParent() != LoopPred)
if(std::find(pred_begin(LoopPred),pred_end(LoopPred),SI->getParent()) == pred_end(LoopPred)) continue;
start = SI->getOperand(0);
startBB = SI->getParent();
++SICount[0];
}
Instruction* SI0 = dyn_cast<Instruction>(SI->getOperand(0));
if(L->contains(SI) && SI0 && SI0->getOpcode() == Instruction::Add){
next = SI0;
//.........这里部分代码省略.........
示例14: ParseMicrosoftAsmStatement
//.........这里部分代码省略.........
assert(!LBraceLocs.empty() && "Should have at least one location here");
// If we don't support assembly, or the assembly is empty, we don't
// need to instantiate the AsmParser, etc.
if (!TheTarget || AsmToks.empty()) {
return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, StringRef(),
/*NumOutputs*/ 0, /*NumInputs*/ 0,
ConstraintRefs, ClobberRefs, Exprs, EndLoc);
}
// Expand the tokens into a string buffer.
SmallString<512> AsmString;
SmallVector<unsigned, 8> TokOffsets;
if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
return StmtError();
std::unique_ptr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));
std::unique_ptr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT));
// Get the instruction descriptor.
std::unique_ptr<llvm::MCInstrInfo> MII(TheTarget->createMCInstrInfo());
std::unique_ptr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo());
std::unique_ptr<llvm::MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TT, "", ""));
llvm::SourceMgr TempSrcMgr;
llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
MOFI->InitMCObjectFileInfo(TheTriple, llvm::Reloc::Default,
llvm::CodeModel::Default, Ctx);
std::unique_ptr<llvm::MemoryBuffer> Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
// Tell SrcMgr about this buffer, which is what the parser will pick up.
TempSrcMgr.AddNewSourceBuffer(std::move(Buffer), llvm::SMLoc());
std::unique_ptr<llvm::MCStreamer> Str(createNullStreamer(Ctx));
std::unique_ptr<llvm::MCAsmParser> Parser(
createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
// FIXME: init MCOptions from sanitizer flags here.
llvm::MCTargetOptions MCOptions;
std::unique_ptr<llvm::MCTargetAsmParser> TargetParser(
TheTarget->createMCAsmParser(*STI, *Parser, *MII, MCOptions));
std::unique_ptr<llvm::MCInstPrinter> IP(
TheTarget->createMCInstPrinter(llvm::Triple(TT), 1, *MAI, *MII, *MRI));
// Change to the Intel dialect.
Parser->setAssemblerDialect(1);
Parser->setTargetParser(*TargetParser.get());
Parser->setParsingInlineAsm(true);
TargetParser->setParsingInlineAsm(true);
ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, AsmToks,
TokOffsets);
TargetParser->setSemaCallback(&Callback);
TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback,
&Callback);
unsigned NumOutputs;
unsigned NumInputs;
std::string AsmStringIR;
SmallVector<std::pair<void *, bool>, 4> OpExprs;
SmallVector<std::string, 4> Constraints;
SmallVector<std::string, 4> Clobbers;
if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, NumOutputs,
NumInputs, OpExprs, Constraints, Clobbers,
MII.get(), IP.get(), Callback))
return StmtError();
// Filter out "fpsw". Clang doesn't accept it, and it always lists flags and
// fpsr as clobbers.
auto End = std::remove(Clobbers.begin(), Clobbers.end(), "fpsw");
Clobbers.erase(End, Clobbers.end());
// Build the vector of clobber StringRefs.
ClobberRefs.insert(ClobberRefs.end(), Clobbers.begin(), Clobbers.end());
// Recast the void pointers and build the vector of constraint StringRefs.
unsigned NumExprs = NumOutputs + NumInputs;
ConstraintRefs.resize(NumExprs);
Exprs.resize(NumExprs);
for (unsigned i = 0, e = NumExprs; i != e; ++i) {
Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first);
if (!OpExpr)
return StmtError();
// Need address of variable.
if (OpExprs[i].second)
OpExpr =
Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr).get();
ConstraintRefs[i] = StringRef(Constraints[i]);
Exprs[i] = OpExpr;
}
// FIXME: We should be passing source locations for better diagnostics.
return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLocs[0], AsmToks, AsmStringIR,
NumOutputs, NumInputs, ConstraintRefs,
ClobberRefs, Exprs, EndLoc);
}
示例15: assert
//.........这里部分代码省略.........
// Include synthetic reference edges to known, defined lib functions.
for (auto *F : G.getLibFunctions())
// While the list of lib functions doesn't have repeats, don't re-visit
// anything handled above.
if (!Visited.count(F))
VisitRef(*F);
// First remove all of the edges that are no longer present in this function.
// The first step makes these edges uniformly ref edges and accumulates them
// into a separate data structure so removal doesn't invalidate anything.
SmallVector<Node *, 4> DeadTargets;
for (Edge &E : *N) {
if (RetainedEdges.count(&E.getNode()))
continue;
SCC &TargetC = *G.lookupSCC(E.getNode());
RefSCC &TargetRC = TargetC.getOuterRefSCC();
if (&TargetRC == RC && E.isCall()) {
if (C != &TargetC) {
// For separate SCCs this is trivial.
RC->switchTrivialInternalEdgeToRef(N, E.getNode());
} else {
// Now update the call graph.
C = incorporateNewSCCRange(RC->switchInternalEdgeToRef(N, E.getNode()),
G, N, C, AM, UR);
}
}
// Now that this is ready for actual removal, put it into our list.
DeadTargets.push_back(&E.getNode());
}
// Remove the easy cases quickly and actually pull them out of our list.
DeadTargets.erase(
llvm::remove_if(DeadTargets,
[&](Node *TargetN) {
SCC &TargetC = *G.lookupSCC(*TargetN);
RefSCC &TargetRC = TargetC.getOuterRefSCC();
// We can't trivially remove internal targets, so skip
// those.
if (&TargetRC == RC)
return false;
RC->removeOutgoingEdge(N, *TargetN);
LLVM_DEBUG(dbgs() << "Deleting outgoing edge from '"
<< N << "' to '" << TargetN << "'\n");
return true;
}),
DeadTargets.end());
// Now do a batch removal of the internal ref edges left.
auto NewRefSCCs = RC->removeInternalRefEdge(N, DeadTargets);
if (!NewRefSCCs.empty()) {
// The old RefSCC is dead, mark it as such.
UR.InvalidatedRefSCCs.insert(RC);
// Note that we don't bother to invalidate analyses as ref-edge
// connectivity is not really observable in any way and is intended
// exclusively to be used for ordering of transforms rather than for
// analysis conclusions.
// Update RC to the "bottom".
assert(G.lookupSCC(N) == C && "Changed the SCC when splitting RefSCCs!");
RC = &C->getOuterRefSCC();
assert(G.lookupRefSCC(N) == RC && "Failed to update current RefSCC!");