// Devirtualize and specialize a group of applies, returning a // worklist of newly exposed function references that should be // considered for inlining before continuing with the caller that has // the passed-in applies. // // The returned worklist is stacked such that the last things we want // to process are earlier on the list. // // Returns true if any changes were made. bool SILPerformanceInliner::devirtualizeAndSpecializeApplies( llvm::SmallVectorImpl<ApplySite> &Applies, SILModuleTransform *MT, ClassHierarchyAnalysis *CHA, llvm::SmallVectorImpl<SILFunction *> &WorkList) { assert(WorkList.empty() && "Expected empty worklist for return results!"); bool ChangedAny = false; // The set of all new function references generated by // devirtualization and specialization. llvm::SetVector<SILFunction *> NewRefs; // Process all applies passed in, plus any new ones that are pushed // on as a result of specializing the referenced functions. while (!Applies.empty()) { auto Apply = Applies.back(); Applies.pop_back(); bool ChangedApply = false; if (auto FullApply = FullApplySite::isa(Apply.getInstruction())) { if (auto NewApply = devirtualize(FullApply, CHA)) { ChangedApply = true; Apply = ApplySite(NewApply.getInstruction()); } } llvm::SmallVector<ApplySite, 4> NewApplies; if (auto NewApply = specializeGeneric(Apply, NewApplies)) { ChangedApply = true; Apply = NewApply; Applies.insert(Applies.end(), NewApplies.begin(), NewApplies.end()); } if (ChangedApply) { ChangedAny = true; auto *NewCallee = Apply.getCalleeFunction(); assert(NewCallee && "Expected directly referenced function!"); // Track all new references to function definitions. if (NewCallee->isDefinition()) NewRefs.insert(NewCallee); // TODO: Do we need to invalidate everything at this point? // What about side-effects analysis? What about type analysis? MT->invalidateAnalysis(Apply.getFunction(), SILAnalysis::InvalidationKind::Everything); } } // Copy out all the new function references gathered. if (ChangedAny) WorkList.insert(WorkList.end(), NewRefs.begin(), NewRefs.end()); return ChangedAny; }
void UUID::toString(llvm::SmallVectorImpl<char> &out) const { out.resize(UUID::StringBufferSize); uuid_unparse_upper(Value, out.data()); // Pop off the null terminator. assert(out.back() == '\0' && "did not null-terminate?!"); out.pop_back(); }
/// Parse an identifier in an MS-style inline assembly block. /// /// \param CastInfo - a void* so that we don't have to teach Parser.h /// about the actual type. ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, unsigned &NumLineToksConsumed, void *CastInfo, bool IsUnevaluatedContext) { llvm::InlineAsmIdentifierInfo &Info = *(llvm::InlineAsmIdentifierInfo *)CastInfo; // Push a fake token on the end so that we don't overrun the token // stream. We use ';' because it expression-parsing should never // overrun it. const tok::TokenKind EndOfStream = tok::semi; Token EndOfStreamTok; EndOfStreamTok.startToken(); EndOfStreamTok.setKind(EndOfStream); LineToks.push_back(EndOfStreamTok); // Also copy the current token over. LineToks.push_back(Tok); PP.EnterTokenStream(LineToks.begin(), LineToks.size(), /*disable macros*/ true, /*owns tokens*/ false); // Clear the current token and advance to the first token in LineToks. ConsumeAnyToken(); // Parse an optional scope-specifier if we're in C++. CXXScopeSpec SS; if (getLangOpts().CPlusPlus) { ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); } // Require an identifier here. SourceLocation TemplateKWLoc; UnqualifiedId Id; bool Invalid = true; ExprResult Result; if (Tok.is(tok::kw_this)) { Result = ParseCXXThis(); Invalid = false; } else { Invalid = ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, IsUnevaluatedContext); } // While the next two tokens are 'period' 'identifier', repeatedly parse it as // a field access. We have to avoid consuming assembler directives that look // like '.' 'else'. while (Result.isUsable() && Tok.is(tok::period)) { Token IdTok = PP.LookAhead(0); if (IdTok.isNot(tok::identifier)) break; ConsumeToken(); // Consume the period. IdentifierInfo *Id = Tok.getIdentifierInfo(); ConsumeToken(); // Consume the identifier. Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(), Info, Tok.getLocation()); } // Figure out how many tokens we are into LineToks. unsigned LineIndex = 0; if (Tok.is(EndOfStream)) { LineIndex = LineToks.size() - 2; } else { while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { LineIndex++; assert(LineIndex < LineToks.size() - 2); // we added two extra tokens } } // If we've run into the poison token we inserted before, or there // was a parsing error, then claim the entire line. if (Invalid || Tok.is(EndOfStream)) { NumLineToksConsumed = LineToks.size() - 2; } else { // Otherwise, claim up to the start of the next token. NumLineToksConsumed = LineIndex; } // Finally, restore the old parsing state by consuming all the tokens we // staged before, implicitly killing off the token-lexer we pushed. for (unsigned i = 0, e = LineToks.size() - LineIndex - 2; i != e; ++i) { ConsumeAnyToken(); } assert(Tok.is(EndOfStream)); ConsumeToken(); // Leave LineToks in its original state. LineToks.pop_back(); LineToks.pop_back(); return Result; }
Store BasicStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) { BindingsTy B = GetBindings(store); typedef SVal::symbol_iterator symbol_iterator; // Iterate over the variable bindings. for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) { if (const VarRegion *VR = dyn_cast<VarRegion>(I.getKey())) { if (SymReaper.isLive(Loc, VR)) RegionRoots.push_back(VR); else continue; } else if (isa<ObjCIvarRegion>(I.getKey())) { RegionRoots.push_back(I.getKey()); } else continue; // Mark the bindings in the data as live. SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.markLive(*SI); } // Scan for live variables and live symbols. llvm::SmallPtrSet<const MemRegion*, 10> Marked; while (!RegionRoots.empty()) { const MemRegion* MR = RegionRoots.back(); RegionRoots.pop_back(); while (MR) { if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(MR)) { SymReaper.markLive(SymR->getSymbol()); break; } else if (isa<VarRegion>(MR) || isa<ObjCIvarRegion>(MR)) { if (Marked.count(MR)) break; Marked.insert(MR); SVal X = Retrieve(store, loc::MemRegionVal(MR)); // FIXME: We need to handle symbols nested in region definitions. for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.markLive(*SI); if (!isa<loc::MemRegionVal>(X)) break; const loc::MemRegionVal& LVD = cast<loc::MemRegionVal>(X); RegionRoots.push_back(LVD.getRegion()); break; } else if (const SubRegion* R = dyn_cast<SubRegion>(MR)) MR = R->getSuperRegion(); else break; } } // Remove dead variable bindings. for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) { const MemRegion* R = I.getKey(); if (!Marked.count(R)) { store = Remove(store, ValMgr.makeLoc(R)); SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.maybeDead(*SI); } } return store; }