void ConformanceLookupTable::getAllConformances( NominalTypeDecl *nominal, LazyResolver *resolver, bool sorted, SmallVectorImpl<ProtocolConformance *> &scratch) { // We need to expand and resolve all conformances to enumerate them. updateLookupTable(nominal, ConformanceStage::Resolved, resolver); // Gather all of the protocols. for (const auto &conformance : AllConformances) { for (auto entry : conformance.second) { if (auto conformance = getConformance(nominal, resolver, entry)) scratch.push_back(conformance); } } // If requested, sort the results. if (sorted) { llvm::array_pod_sort(scratch.begin(), scratch.end(), &compareProtocolConformances); } }
void Sema::EraseUnwantedCUDAMatches( const FunctionDecl *Caller, SmallVectorImpl<std::pair<DeclAccessPair, FunctionDecl *>> &Matches) { if (Matches.size() <= 1) return; using Pair = std::pair<DeclAccessPair, FunctionDecl*>; // Gets the CUDA function preference for a call from Caller to Match. auto GetCFP = [&](const Pair &Match) { return IdentifyCUDAPreference(Caller, Match.second); }; // Find the best call preference among the functions in Matches. CUDAFunctionPreference BestCFP = GetCFP(*std::max_element( Matches.begin(), Matches.end(), [&](const Pair &M1, const Pair &M2) { return GetCFP(M1) < GetCFP(M2); })); // Erase all functions with lower priority. llvm::erase_if(Matches, [&](const Pair &Match) { return GetCFP(Match) < BestCFP; }); }
void AArch64CallLowering::splitToValueTypes( const ArgInfo &OrigArg, SmallVectorImpl<ArgInfo> &SplitArgs, const DataLayout &DL, MachineRegisterInfo &MRI, const SplitArgTy &PerformArgSplit) const { const AArch64TargetLowering &TLI = *getTLI<AArch64TargetLowering>(); LLVMContext &Ctx = OrigArg.Ty->getContext(); SmallVector<EVT, 4> SplitVTs; SmallVector<uint64_t, 4> Offsets; ComputeValueVTs(TLI, DL, OrigArg.Ty, SplitVTs, &Offsets, 0); if (SplitVTs.size() == 1) { // No splitting to do, but we want to replace the original type (e.g. [1 x // double] -> double). SplitArgs.emplace_back(OrigArg.Reg, SplitVTs[0].getTypeForEVT(Ctx), OrigArg.Flags, OrigArg.IsFixed); return; } unsigned FirstRegIdx = SplitArgs.size(); for (auto SplitVT : SplitVTs) { // FIXME: set split flags if they're actually used (e.g. i128 on AAPCS). Type *SplitTy = SplitVT.getTypeForEVT(Ctx); SplitArgs.push_back( ArgInfo{MRI.createGenericVirtualRegister(LLT{*SplitTy, DL}), SplitTy, OrigArg.Flags, OrigArg.IsFixed}); } SmallVector<uint64_t, 4> BitOffsets; for (auto Offset : Offsets) BitOffsets.push_back(Offset * 8); SmallVector<unsigned, 8> SplitRegs; for (auto I = &SplitArgs[FirstRegIdx]; I != SplitArgs.end(); ++I) SplitRegs.push_back(I->Reg); PerformArgSplit(SplitRegs, BitOffsets); }
// Helper function to fix up source ranges. It takes in an array of ranges, // and outputs an array of ranges where we want to draw the range highlighting // around the location specified by CaretLoc. // // To find locations which correspond to the caret, we crawl the macro caller // chain for the beginning and end of each range. If the caret location // is in a macro expansion, we search each chain for a location // in the same expansion as the caret; otherwise, we crawl to the top of // each chain. Two locations are part of the same macro expansion // iff the FileID is the same. static void mapDiagnosticRanges( SourceLocation CaretLoc, const SmallVectorImpl<CharSourceRange>& Ranges, SmallVectorImpl<CharSourceRange>& SpellingRanges, const SourceManager *SM) { FileID CaretLocFileID = SM->getFileID(CaretLoc); for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { SourceLocation Begin = I->getBegin(), End = I->getEnd(); bool IsTokenRange = I->isTokenRange(); // Search the macro caller chain for the beginning of the range. while (Begin.isMacroID() && SM->getFileID(Begin) != CaretLocFileID) Begin = SM->getImmediateMacroCallerLoc(Begin); // Search the macro caller chain for the beginning of the range. while (End.isMacroID() && SM->getFileID(End) != CaretLocFileID) { // The computation of the next End is an inlined version of // getImmediateMacroCallerLoc, except it chooses the end of an // expansion range. if (SM->isMacroArgExpansion(End)) { End = SM->getImmediateSpellingLoc(End); } else { End = SM->getImmediateExpansionRange(End).second; } } // Return the spelling location of the beginning and end of the range. Begin = SM->getSpellingLoc(Begin); End = SM->getSpellingLoc(End); SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), IsTokenRange)); } }
void Instruction::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned, MDNode*> > &Result) const { Result.clear(); // Handle 'dbg' as a special case since it is not stored in the hash table. if (!DbgLoc.isUnknown()) { Result.push_back(std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode(getContext()))); if (!hasMetadataHashEntry()) return; } assert(hasMetadataHashEntry() && getContext().pImpl->MetadataStore.count(this) && "Shouldn't have called this"); const LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore.find(this)->second; assert(!Info.empty() && "Shouldn't have called this"); Result.append(Info.begin(), Info.end()); // Sort the resulting array so it is stable. if (Result.size() > 1) array_pod_sort(Result.begin(), Result.end()); }
// OutputPossibleOverflows - We've found a possible overflow earlier, // now check whether Body might contain a comparison which might be // preventing the overflow. // This doesn't do flow analysis, range analysis, or points-to analysis; it's // just a dumb "is there a comparison" scan. The aim here is to // detect the most blatent cases of overflow and educate the // programmer. void MallocOverflowSecurityChecker::OutputPossibleOverflows( SmallVectorImpl<MallocOverflowCheck> &PossibleMallocOverflows, const Decl *D, BugReporter &BR, AnalysisManager &mgr) const { // By far the most common case: nothing to check. if (PossibleMallocOverflows.empty()) return; // Delete any possible overflows which have a comparison. CheckOverflowOps c(PossibleMallocOverflows, BR.getContext()); c.Visit(mgr.getAnalysisDeclContext(D)->getBody()); // Output warnings for all overflows that are left. for (CheckOverflowOps::theVecType::iterator i = PossibleMallocOverflows.begin(), e = PossibleMallocOverflows.end(); i != e; ++i) { SourceRange R = i->mulop->getSourceRange(); BR.EmitBasicReport(D, "malloc() size overflow", categories::UnixAPI, "the computation of the size of the memory allocation may overflow", PathDiagnosticLocation::createOperatorLoc(i->mulop, BR.getSourceManager()), &R, 1); } }
/// ComputeActionsTable - Compute the actions table and gather the first action /// index for each landing pad site. unsigned DwarfException:: ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, SmallVectorImpl<ActionEntry> &Actions, SmallVectorImpl<unsigned> &FirstActions) { // The action table follows the call-site table in the LSDA. The individual // records are of two types: // // * Catch clause // * Exception specification // // The two record kinds have the same format, with only small differences. // They are distinguished by the "switch value" field: Catch clauses // (TypeInfos) have strictly positive switch values, and exception // specifications (FilterIds) have strictly negative switch values. Value 0 // indicates a catch-all clause. // // Negative type IDs index into FilterIds. Positive type IDs index into // TypeInfos. The value written for a positive type ID is just the type ID // itself. For a negative type ID, however, the value written is the // (negative) byte offset of the corresponding FilterIds entry. The byte // offset is usually equal to the type ID (because the FilterIds entries are // written using a variable width encoding, which outputs one byte per entry // as long as the value written is not too large) but can differ. This kind // of complication does not occur for positive type IDs because type infos are // output using a fixed width encoding. FilterOffsets[i] holds the byte // offset corresponding to FilterIds[i]. const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); SmallVector<int, 16> FilterOffsets; FilterOffsets.reserve(FilterIds.size()); int Offset = -1; for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { FilterOffsets.push_back(Offset); Offset -= MCAsmInfo::getULEB128Size(*I); } FirstActions.reserve(LandingPads.size()); int FirstAction = 0; unsigned SizeActions = 0; const LandingPadInfo *PrevLPI = 0; for (SmallVectorImpl<const LandingPadInfo *>::const_iterator I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { const LandingPadInfo *LPI = *I; const std::vector<int> &TypeIds = LPI->TypeIds; unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; unsigned PrevAction = (unsigned)-1; if (NumShared) { unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = Actions.size() - 1; SizeAction = MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); SizeAction -= MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); SizeAction += -Actions[PrevAction].NextAction; PrevAction = Actions[PrevAction].Previous; } } // Compute the actions. for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { int TypeID = TypeIds[J]; assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); SizeSiteActions += SizeAction; ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); PrevAction = Actions.size() - 1; } // Record the first action of the landing pad site. FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; } // else identical - re-use previous FirstAction // Information used when created the call-site table. The action record // field of the call site record is the offset of the first associated // action record, relative to the start of the actions table. This value is // biased by 1 (1 indicating the start of the actions table), and 0 // indicates that there are no actions. FirstActions.push_back(FirstAction); // Compute this sites contribution to size. SizeActions += SizeSiteActions; PrevLPI = LPI; } return SizeActions; }
static void populateExternalRelations( SmallVectorImpl<ExternalRelation> &ExtRelations, const Function &Fn, const SmallVectorImpl<Value *> &RetVals, const ReachabilitySet &ReachSet) { // If a function only returns one of its argument X, then X will be both an // argument and a return value at the same time. This is an edge case that // needs special handling here. for (const auto &Arg : Fn.args()) { if (is_contained(RetVals, &Arg)) { auto ArgVal = InterfaceValue{Arg.getArgNo() + 1, 0}; auto RetVal = InterfaceValue{0, 0}; ExtRelations.push_back(ExternalRelation{ArgVal, RetVal, 0}); } } // Below is the core summary construction logic. // A naive solution of adding only the value aliases that are parameters or // return values in ReachSet to the summary won't work: It is possible that a // parameter P is written into an intermediate value I, and the function // subsequently returns *I. In that case, *I is does not value alias anything // in ReachSet, and the naive solution will miss a summary edge from (P, 1) to // (I, 1). // To account for the aforementioned case, we need to check each non-parameter // and non-return value for the possibility of acting as an intermediate. // 'ValueMap' here records, for each value, which InterfaceValues read from or // write into it. If both the read list and the write list of a given value // are non-empty, we know that a particular value is an intermidate and we // need to add summary edges from the writes to the reads. DenseMap<Value *, ValueSummary> ValueMap; for (const auto &OuterMapping : ReachSet.value_mappings()) { if (auto Dst = getInterfaceValue(OuterMapping.first, RetVals)) { for (const auto &InnerMapping : OuterMapping.second) { // If Src is a param/return value, we get a same-level assignment. if (auto Src = getInterfaceValue(InnerMapping.first, RetVals)) { // This may happen if both Dst and Src are return values if (*Dst == *Src) continue; if (hasReadOnlyState(InnerMapping.second)) ExtRelations.push_back(ExternalRelation{*Dst, *Src, UnknownOffset}); // No need to check for WriteOnly state, since ReachSet is symmetric } else { // If Src is not a param/return, add it to ValueMap auto SrcIVal = InnerMapping.first; if (hasReadOnlyState(InnerMapping.second)) ValueMap[SrcIVal.Val].FromRecords.push_back( ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); if (hasWriteOnlyState(InnerMapping.second)) ValueMap[SrcIVal.Val].ToRecords.push_back( ValueSummary::Record{*Dst, SrcIVal.DerefLevel}); } } } } for (const auto &Mapping : ValueMap) { for (const auto &FromRecord : Mapping.second.FromRecords) { for (const auto &ToRecord : Mapping.second.ToRecords) { auto ToLevel = ToRecord.DerefLevel; auto FromLevel = FromRecord.DerefLevel; // Same-level assignments should have already been processed by now if (ToLevel == FromLevel) continue; auto SrcIndex = FromRecord.IValue.Index; auto SrcLevel = FromRecord.IValue.DerefLevel; auto DstIndex = ToRecord.IValue.Index; auto DstLevel = ToRecord.IValue.DerefLevel; if (ToLevel > FromLevel) SrcLevel += ToLevel - FromLevel; else DstLevel += FromLevel - ToLevel; ExtRelations.push_back(ExternalRelation{ InterfaceValue{SrcIndex, SrcLevel}, InterfaceValue{DstIndex, DstLevel}, UnknownOffset}); } } } // Remove duplicates in ExtRelations llvm::sort(ExtRelations.begin(), ExtRelations.end()); ExtRelations.erase(std::unique(ExtRelations.begin(), ExtRelations.end()), ExtRelations.end()); }
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, Module &M, bool isConst, unsigned AddrSpace) const { // FIXME: Find better heuristics std::stable_sort(Globals.begin(), Globals.end(), [this](const GlobalVariable *GV1, const GlobalVariable *GV2) { Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); }); Type *Int32Ty = Type::getInt32Ty(M.getContext()); assert(Globals.size() > 1); // FIXME: This simple solution merges globals all together as maximum as // possible. However, with this solution it would be hard to remove dead // global symbols at link-time. An alternative solution could be checking // global symbols references function by function, and make the symbols // being referred in the same function merged and we would probably need // to introduce heuristic algorithm to solve the merge conflict from // different functions. for (size_t i = 0, e = Globals.size(); i != e; ) { size_t j = 0; uint64_t MergedSize = 0; std::vector<Type*> Tys; std::vector<Constant*> Inits; bool HasExternal = false; GlobalVariable *TheFirstExternal = 0; for (j = i; j != e; ++j) { Type *Ty = Globals[j]->getType()->getElementType(); MergedSize += DL->getTypeAllocSize(Ty); if (MergedSize > MaxOffset) { break; } Tys.push_back(Ty); Inits.push_back(Globals[j]->getInitializer()); if (Globals[j]->hasExternalLinkage() && !HasExternal) { HasExternal = true; TheFirstExternal = Globals[j]; } } // If merged variables doesn't have external linkage, we needn't to expose // the symbol after merging. GlobalValue::LinkageTypes Linkage = HasExternal ? GlobalValue::ExternalLinkage : GlobalValue::InternalLinkage; StructType *MergedTy = StructType::get(M.getContext(), Tys); Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); // If merged variables have external linkage, we use symbol name of the // first variable merged as the suffix of global symbol name. This would // be able to avoid the link-time naming conflict for globalm symbols. GlobalVariable *MergedGV = new GlobalVariable( M, MergedTy, isConst, Linkage, MergedInit, HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() : "_MergedGlobals", nullptr, GlobalVariable::NotThreadLocal, AddrSpace); for (size_t k = i; k < j; ++k) { GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); std::string Name = Globals[k]->getName(); Constant *Idx[2] = { ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, k-i) }; Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); Globals[k]->replaceAllUsesWith(GEP); Globals[k]->eraseFromParent(); if (Linkage != GlobalValue::InternalLinkage) { // Generate a new alias... auto *PTy = cast<PointerType>(GEP->getType()); GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), Linkage, Name, GEP, &M); } NumMerged++; } i = j; } return true; }
bool LoadAndStorePromoter::isInstInList(Instruction *I, const SmallVectorImpl<Instruction*> &Insts) const { return std::find(Insts.begin(), Insts.end(), I) != Insts.end(); }
/// Return true if the specified block is in the list. static bool isExitBlock(BasicBlock *BB, const SmallVectorImpl<BasicBlock *> &ExitBlocks) { return find(ExitBlocks, BB) != ExitBlocks.end(); }
static void lookupInModule(Module *module, Module::AccessPathTy accessPath, SmallVectorImpl<ValueDecl *> &decls, ResolutionKind resolutionKind, bool canReturnEarly, LazyResolver *typeResolver, ModuleLookupCache &cache, const DeclContext *moduleScopeContext, bool respectAccessControl, ArrayRef<Module::ImportedModule> extraImports, CallbackTy callback) { assert(module); assert(std::none_of(extraImports.begin(), extraImports.end(), [](Module::ImportedModule import) -> bool { return !import.second; })); ModuleLookupCache::iterator iter; bool isNew; std::tie(iter, isNew) = cache.insert({{accessPath, module}, {}}); if (!isNew) { decls.append(iter->second.begin(), iter->second.end()); return; } size_t initialCount = decls.size(); SmallVector<ValueDecl *, 4> localDecls; callback(module, accessPath, localDecls); if (respectAccessControl) { auto newEndIter = std::remove_if(localDecls.begin(), localDecls.end(), [=](ValueDecl *VD) { if (typeResolver) { typeResolver->resolveAccessibility(VD); } if (!VD->hasAccessibility()) return false; return !VD->isAccessibleFrom(moduleScopeContext); }); localDecls.erase(newEndIter, localDecls.end()); // This only applies to immediate imports of the top-level module. if (moduleScopeContext && moduleScopeContext->getParentModule() != module) moduleScopeContext = nullptr; } OverloadSetTy overloads; resolutionKind = recordImportDecls(typeResolver, decls, localDecls, overloads, resolutionKind); bool foundDecls = decls.size() > initialCount; if (!foundDecls || !canReturnEarly || resolutionKind == ResolutionKind::Overloadable) { SmallVector<Module::ImportedModule, 8> reexports; module->getImportedModulesForLookup(reexports); assert(std::none_of(reexports.begin(), reexports.end(), [](Module::ImportedModule import) -> bool { return !import.second; })); reexports.append(extraImports.begin(), extraImports.end()); // Prefer scoped imports (import func Swift.max) to whole-module imports. SmallVector<ValueDecl *, 8> unscopedValues; SmallVector<ValueDecl *, 8> scopedValues; for (auto next : reexports) { // Filter any whole-module imports, and skip specific-decl imports if the // import path doesn't match exactly. Module::AccessPathTy combinedAccessPath; if (accessPath.empty()) { combinedAccessPath = next.first; } else if (!next.first.empty() && !Module::isSameAccessPath(next.first, accessPath)) { // If we ever allow importing non-top-level decls, it's possible the // rule above isn't what we want. assert(next.first.size() == 1 && "import of non-top-level decl"); continue; } else { combinedAccessPath = accessPath; } auto &resultSet = next.first.empty() ? unscopedValues : scopedValues; lookupInModule<OverloadSetTy>(next.second, combinedAccessPath, resultSet, resolutionKind, canReturnEarly, typeResolver, cache, moduleScopeContext, respectAccessControl, {}, callback); } // Add the results from scoped imports. resolutionKind = recordImportDecls(typeResolver, decls, scopedValues, overloads, resolutionKind); // Add the results from unscoped imports. foundDecls = decls.size() > initialCount; if (!foundDecls || !canReturnEarly || resolutionKind == ResolutionKind::Overloadable) { resolutionKind = recordImportDecls(typeResolver, decls, unscopedValues, overloads, resolutionKind); } } // Remove duplicated declarations. llvm::SmallPtrSet<ValueDecl *, 4> knownDecls; decls.erase(std::remove_if(decls.begin() + initialCount, decls.end(), [&](ValueDecl *d) -> bool { return !knownDecls.insert(d).second; }), decls.end()); auto &cachedValues = cache[{accessPath, module}]; cachedValues.insert(cachedValues.end(), decls.begin() + initialCount, decls.end()); }
static void createVectorVariantWrapper(llvm::Function *ScalarFunc, llvm::Function *VectorFunc, unsigned VLen, const SmallVectorImpl<ParamInfo> &Info) { assert(ScalarFunc->arg_size() == Info.size() && "Wrong number of parameter infos"); assert((VLen & (VLen - 1)) == 0 && "VLen must be a power-of-2"); bool IsMasked = VectorFunc->arg_size() == ScalarFunc->arg_size() + 1; llvm::LLVMContext &Context = ScalarFunc->getContext(); llvm::BasicBlock *Entry = llvm::BasicBlock::Create(Context, "entry", VectorFunc); llvm::BasicBlock *LoopCond = llvm::BasicBlock::Create(Context, "loop.cond", VectorFunc); llvm::BasicBlock *LoopBody = llvm::BasicBlock::Create(Context, "loop.body", VectorFunc); llvm::BasicBlock *MaskOn = IsMasked ? llvm::BasicBlock::Create(Context, "mask_on", VectorFunc) : 0; llvm::BasicBlock *MaskOff = IsMasked ? llvm::BasicBlock::Create(Context, "mask_off", VectorFunc) : 0; llvm::BasicBlock *LoopStep = llvm::BasicBlock::Create(Context, "loop.step", VectorFunc); llvm::BasicBlock *LoopEnd = llvm::BasicBlock::Create(Context, "loop.end", VectorFunc); llvm::Value *VectorRet = 0; SmallVector<llvm::Value*, 4> VectorArgs; // The loop counter. llvm::Type *IndexTy = llvm::Type::getInt32Ty(Context); llvm::Value *Index = 0; llvm::Value *Mask = 0; // Copy the names from the scalar args to the vector args. { llvm::Function::arg_iterator SI = ScalarFunc->arg_begin(), SE = ScalarFunc->arg_end(), VI = VectorFunc->arg_begin(); for ( ; SI != SE; ++SI, ++VI) VI->setName(SI->getName()); if (IsMasked) VI->setName("mask"); } llvm::IRBuilder<> Builder(Entry); { if (!VectorFunc->getReturnType()->isVoidTy()) VectorRet = Builder.CreateAlloca(VectorFunc->getReturnType()); Index = Builder.CreateAlloca(IndexTy, 0, "index"); Builder.CreateStore(llvm::ConstantInt::get(IndexTy, 0), Index); llvm::Function::arg_iterator VI = VectorFunc->arg_begin(); for (SmallVectorImpl<ParamInfo>::const_iterator I = Info.begin(), IE = Info.end(); I != IE; ++I, ++VI) { llvm::Value *Arg = VI; switch (I->Kind) { case PK_Vector: assert(Arg->getType()->isVectorTy() && "Not a vector"); assert(VLen == Arg->getType()->getVectorNumElements() && "Wrong number of elements"); break; case PK_LinearConst: Arg = buildLinearArg(Builder, VLen, Arg, cast<llvm::ConstantAsMetadata>(I->Step)->getValue()); Arg->setName(VI->getName() + ".linear"); break; case PK_Linear: { unsigned Number = cast<llvm::ConstantInt>( cast<llvm::ConstantAsMetadata>(I->Step)->getValue())->getZExtValue(); llvm::Function::arg_iterator ArgI = VectorFunc->arg_begin(); std::advance(ArgI, Number); llvm::Value *Step = ArgI; Arg = buildLinearArg(Builder, VLen, Arg, Step); Arg->setName(VI->getName() + ".linear"); } break; case PK_Uniform: Arg = Builder.CreateVectorSplat(VLen, Arg); Arg->setName(VI->getName() + ".uniform"); break; } VectorArgs.push_back(Arg); } if (IsMasked) Mask = buildMask(Builder, VLen, VI); Builder.CreateBr(LoopCond); } Builder.SetInsertPoint(LoopCond); { llvm::Value *Cond = Builder.CreateICmpULT( Builder.CreateLoad(Index), llvm::ConstantInt::get(IndexTy, VLen)); Builder.CreateCondBr(Cond, LoopBody, LoopEnd); } llvm::Value *VecIndex = 0; Builder.SetInsertPoint(LoopBody); { VecIndex = Builder.CreateLoad(Index); if (IsMasked) { llvm::Value *ScalarMask = Builder.CreateExtractElement(Mask, VecIndex); Builder.CreateCondBr(ScalarMask, MaskOn, MaskOff); } } Builder.SetInsertPoint(IsMasked ? MaskOn : LoopBody); { // Build the argument list for the scalar function by extracting element // 'VecIndex' from the vector arguments. SmallVector<llvm::Value*, 4> ScalarArgs; for (SmallVectorImpl<llvm::Value*>::iterator VI = VectorArgs.begin(), VE = VectorArgs.end(); VI != VE; ++VI) { assert((*VI)->getType()->isVectorTy() && "Not a vector"); ScalarArgs.push_back(Builder.CreateExtractElement(*VI, VecIndex)); } // Call the scalar function with the extracted scalar arguments. llvm::Value *ScalarRet = Builder.CreateCall(ScalarFunc, ScalarArgs); // If the function returns a value insert the scalar return value into the // vector return value. if (VectorRet) { llvm::Value *V = Builder.CreateLoad(VectorRet); V = Builder.CreateInsertElement(V, ScalarRet, VecIndex); Builder.CreateStore(V, VectorRet); } Builder.CreateBr(LoopStep); } if (IsMasked) { Builder.SetInsertPoint(MaskOff); if (VectorRet) { llvm::Value *V = Builder.CreateLoad(VectorRet); llvm::Value *Zero = llvm::Constant::getNullValue(ScalarFunc->getReturnType()); V = Builder.CreateInsertElement(V, Zero, VecIndex); Builder.CreateStore(V, VectorRet); } Builder.CreateBr(LoopStep); } Builder.SetInsertPoint(LoopStep); { // Index = Index + 1 VecIndex = Builder.CreateAdd(VecIndex, llvm::ConstantInt::get(IndexTy, 1)); Builder.CreateStore(VecIndex, Index); Builder.CreateBr(LoopCond); } Builder.SetInsertPoint(LoopEnd); { if (VectorRet) Builder.CreateRet(Builder.CreateLoad(VectorRet)); else Builder.CreateRetVoid(); } }
bool swift::removeShadowedDecls(SmallVectorImpl<ValueDecl*> &decls, const Module *curModule, LazyResolver *typeResolver) { // Category declarations by their signatures. llvm::SmallDenseMap<std::pair<CanType, Identifier>, llvm::TinyPtrVector<ValueDecl *>> CollidingDeclGroups; /// Objective-C initializers are tracked by their context type and /// full name. llvm::SmallDenseMap<std::pair<CanType, DeclName>, llvm::TinyPtrVector<ConstructorDecl *>> ObjCCollidingConstructors; bool anyCollisions = false; for (auto decl : decls) { // Determine the signature of this declaration. // FIXME: the canonical type makes a poor signature, because we don't // canonicalize away default arguments and don't canonicalize polymorphic // types well. CanType signature; // FIXME: Egregious hack to avoid failing when there are no declared types. if (!decl->hasType() || isa<TypeAliasDecl>(decl) || isa<AbstractTypeParamDecl>(decl)) { // FIXME: Pass this down instead of getting it from the ASTContext. if (typeResolver && !decl->isBeingTypeChecked()) typeResolver->resolveDeclSignature(decl); if (!decl->hasType()) continue; if (auto assocType = dyn_cast<AssociatedTypeDecl>(decl)) if (!assocType->getArchetype()) continue; } // If the decl is currently being validated, this is likely a recursive // reference and we'll want to skip ahead so as to avoid having its type // attempt to desugar itself. if (decl->isBeingTypeChecked()) continue; signature = decl->getType()->getCanonicalType(); // FIXME: The type of a variable or subscript doesn't include // enough context to distinguish entities from different // constrained extensions, so use the overload signature's // type. This is layering a partial fix upon a total hack. if (auto asd = dyn_cast<AbstractStorageDecl>(decl)) signature = asd->getOverloadSignature().InterfaceType; // If we've seen a declaration with this signature before, note it. auto &knownDecls = CollidingDeclGroups[std::make_pair(signature, decl->getName())]; if (!knownDecls.empty()) anyCollisions = true; knownDecls.push_back(decl); // Specifically keep track of Objective-C initializers, which can come from // either init methods or factory methods. if (decl->hasClangNode()) { if (auto ctor = dyn_cast<ConstructorDecl>(decl)) { auto ctorSignature = std::make_pair(ctor->getExtensionType()->getCanonicalType(), decl->getFullName()); auto &knownCtors = ObjCCollidingConstructors[ctorSignature]; if (!knownCtors.empty()) anyCollisions = true; knownCtors.push_back(ctor); } } } // If there were no signature collisions, there is nothing to do. if (!anyCollisions) return false; // Determine the set of declarations that are shadowed by other declarations. llvm::SmallPtrSet<ValueDecl *, 4> shadowed; ASTContext &ctx = decls[0]->getASTContext(); for (auto &collidingDecls : CollidingDeclGroups) { // If only one declaration has this signature, it isn't shadowed by // anything. if (collidingDecls.second.size() == 1) continue; // Compare each declaration to every other declaration. This is // unavoidably O(n^2) in the number of declarations, but because they // all have the same signature, we expect n to remain small. for (unsigned firstIdx = 0, n = collidingDecls.second.size(); firstIdx != n; ++firstIdx) { auto firstDecl = collidingDecls.second[firstIdx]; auto firstModule = firstDecl->getModuleContext(); for (unsigned secondIdx = firstIdx + 1; secondIdx != n; ++secondIdx) { // Determine whether one module takes precedence over another. auto secondDecl = collidingDecls.second[secondIdx]; auto secondModule = secondDecl->getModuleContext(); // If one declaration is in a protocol or extension thereof and the // other is not, prefer the one that is not. if ((bool)firstDecl->getDeclContext() ->getAsProtocolOrProtocolExtensionContext() != (bool)secondDecl->getDeclContext() ->getAsProtocolOrProtocolExtensionContext()) { if (firstDecl->getDeclContext() ->getAsProtocolOrProtocolExtensionContext()) { shadowed.insert(firstDecl); break; } else { shadowed.insert(secondDecl); continue; } } // If one declaration is available and the other is not, prefer the // available one. if (firstDecl->getAttrs().isUnavailable(ctx) != secondDecl->getAttrs().isUnavailable(ctx)) { if (firstDecl->getAttrs().isUnavailable(ctx)) { shadowed.insert(firstDecl); break; } else { shadowed.insert(secondDecl); continue; } } // Don't apply module-shadowing rules to members of protocol types. if (isa<ProtocolDecl>(firstDecl->getDeclContext()) || isa<ProtocolDecl>(secondDecl->getDeclContext())) continue; // Prefer declarations in the current module over those in another // module. // FIXME: This is a hack. We should query a (lazily-built, cached) // module graph to determine shadowing. if ((firstModule == curModule) == (secondModule == curModule)) continue; // If the first module is the current module, the second declaration // is shadowed by the first. if (firstModule == curModule) { shadowed.insert(secondDecl); continue; } // Otherwise, the first declaration is shadowed by the second. There is // no point in continuing to compare the first declaration to others. shadowed.insert(firstDecl); break; } } } // Check for collisions among Objective-C initializers. When such collisions // exist, we pick the for (const auto &colliding : ObjCCollidingConstructors) { if (colliding.second.size() == 1) continue; // Find the "best" constructor with this signature. ConstructorDecl *bestCtor = colliding.second[0]; for (auto ctor : colliding.second) { auto comparison = compareConstructors(ctor, bestCtor, ctx); if (comparison == ConstructorComparison::Better) bestCtor = ctor; } // Shadow any initializers that are worse. for (auto ctor : colliding.second) { auto comparison = compareConstructors(ctor, bestCtor, ctx); if (comparison == ConstructorComparison::Worse) shadowed.insert(ctor); } } // If none of the declarations were shadowed, we're done. if (shadowed.empty()) return false; // Remove shadowed declarations from the list of declarations. bool anyRemoved = false; decls.erase(std::remove_if(decls.begin(), decls.end(), [&](ValueDecl *vd) { if (shadowed.count(vd) > 0) { anyRemoved = true; return true; } return false; }), decls.end()); return anyRemoved; }
bool GlobalMerge::doInitialization(Module &M) { if (!EnableGlobalMerge) return false; auto &DL = M.getDataLayout(); DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, BSSGlobals; bool Changed = false; setMustKeepGlobalVariables(M); // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal or external globals only if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) continue; if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && !I->hasInternalLinkage()) continue; PointerType *PT = dyn_cast<PointerType>(I->getType()); assert(PT && "Global variable is not a pointer!"); unsigned AddressSpace = PT->getAddressSpace(); // Ignore fancy-aligned globals for now. unsigned Alignment = DL.getPreferredAlignment(I); Type *Ty = I->getType()->getElementType(); if (Alignment > DL.getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; // Ignore all "required" globals: if (isMustKeepGlobalVariable(I)) continue; if (DL.getTypeAllocSize(Ty) < MaxOffset) { if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) BSSGlobals[AddressSpace].push_back(I); else if (I->isConstant()) ConstGlobals[AddressSpace].push_back(I); else Globals[AddressSpace].push_back(I); } } for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = Globals.begin(), E = Globals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); if (EnableGlobalMergeOnConst) for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, true, I->first); return Changed; }
CheckPredicateMatcher::CheckPredicateMatcher( const TreePredicateFn &pred, const SmallVectorImpl<unsigned> &Ops) : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()), Operands(Ops.begin(), Ops.end()) {}
static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, std::set<std::string> &SavedStrings, Driver &TheDriver) { // Try to infer frontend type and default target from the program name. // suffixes[] contains the list of known driver suffixes. // Suffixes are compared against the program name in order. // If there is a match, the frontend type is updated as necessary (CPP/C++). // If there is no match, a second round is done after stripping the last // hyphen and everything following it. This allows using something like // "clang++-2.9". // If there is a match in either the first or second round, // the function tries to identify a target as prefix. E.g. // "x86_64-linux-clang" as interpreted as suffix "clang" with // target prefix "x86_64-linux". If such a target prefix is found, // is gets added via -target as implicit first argument. static const struct { const char *Suffix; const char *ModeFlag; } suffixes [] = { { "templight", nullptr }, { "templight++", "--driver-mode=g++" }, { "templight-c++", "--driver-mode=g++" }, { "templight-cc", nullptr }, { "templight-cpp", "--driver-mode=cpp" }, { "templight-g++", "--driver-mode=g++" }, { "templight-gcc", nullptr }, { "templight-cl", "--driver-mode=cl" }, { "cc", nullptr }, { "cpp", "--driver-mode=cpp" }, { "cl" , "--driver-mode=cl" }, { "++", "--driver-mode=g++" }, }; std::string ProgName(llvm::sys::path::stem(ArgVector[0])); #ifdef LLVM_ON_WIN32 // Transform to lowercase for case insensitive file systems. std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), toLowercase); #endif StringRef ProgNameRef(ProgName); StringRef Prefix; for (int Components = 2; Components; --Components) { bool FoundMatch = false; size_t i; for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { if (ProgNameRef.endswith(suffixes[i].Suffix)) { FoundMatch = true; SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); if (it != ArgVector.end()) ++it; if (suffixes[i].ModeFlag) ArgVector.insert(it, suffixes[i].ModeFlag); break; } } if (FoundMatch) { StringRef::size_type LastComponent = ProgNameRef.rfind('-', ProgNameRef.size() - strlen(suffixes[i].Suffix)); if (LastComponent != StringRef::npos) Prefix = ProgNameRef.slice(0, LastComponent); break; } StringRef::size_type LastComponent = ProgNameRef.rfind('-'); if (LastComponent == StringRef::npos) break; ProgNameRef = ProgNameRef.slice(0, LastComponent); } if (Prefix.empty()) return; std::string IgnoredError; if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); if (it != ArgVector.end()) ++it; const char* Strings[] = { GetStableCStr(SavedStrings, std::string("-target")), GetStableCStr(SavedStrings, Prefix) }; ArgVector.insert(it, Strings, Strings + llvm::array_lengthof(Strings)); } }
/// Emit a code snippet and caret line. /// /// This routine emits a single line's code snippet and caret line.. /// /// \param Loc The location for the caret. /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. void TextDiagnostic::emitSnippetAndCaret( FullSourceLoc Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange> &Ranges, ArrayRef<FixItHint> Hints) { assert(Loc.isValid() && "must have a valid source location here"); assert(Loc.isFileID() && "must have a file location here"); // If caret diagnostics are enabled and we have location, we want to // emit the caret. However, we only do this if the location moved // from the last diagnostic, if the last diagnostic was a note that // was part of a different warning or error diagnostic, or if the // diagnostic has ranges. We don't want to emit the same caret // multiple times if one loc has multiple diagnostics. if (!DiagOpts->ShowCarets) return; if (Loc == LastLoc && Ranges.empty() && Hints.empty() && (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) return; // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = Loc.getDecomposedLoc(); FileID FID = LocInfo.first; const SourceManager &SM = Loc.getManager(); // Get information about the buffer it points into. bool Invalid = false; StringRef BufData = Loc.getBufferData(&Invalid); if (Invalid) return; unsigned CaretLineNo = Loc.getLineNumber(); unsigned CaretColNo = Loc.getColumnNumber(); // Arbitrarily stop showing snippets when the line is too long. static const size_t MaxLineLengthToPrint = 4096; if (CaretColNo > MaxLineLengthToPrint) return; // Find the set of lines to include. const unsigned MaxLines = DiagOpts->SnippetLineLimit; std::pair<unsigned, unsigned> Lines = {CaretLineNo, CaretLineNo}; for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) if (auto OptionalRange = findLinesForRange(*I, FID, SM)) Lines = maybeAddRange(Lines, *OptionalRange, MaxLines); for (unsigned LineNo = Lines.first; LineNo != Lines.second + 1; ++LineNo) { const char *BufStart = BufData.data(); const char *BufEnd = BufStart + BufData.size(); // Rewind from the current position to the start of the line. const char *LineStart = BufStart + SM.getDecomposedLoc(SM.translateLineCol(FID, LineNo, 1)).second; if (LineStart == BufEnd) break; // Compute the line end. const char *LineEnd = LineStart; while (*LineEnd != '\n' && *LineEnd != '\r' && LineEnd != BufEnd) ++LineEnd; // Arbitrarily stop showing snippets when the line is too long. // FIXME: Don't print any lines in this case. if (size_t(LineEnd - LineStart) > MaxLineLengthToPrint) return; // Trim trailing null-bytes. StringRef Line(LineStart, LineEnd - LineStart); while (!Line.empty() && Line.back() == '\0' && (LineNo != CaretLineNo || Line.size() > CaretColNo)) Line = Line.drop_back(); // Copy the line of code into an std::string for ease of manipulation. std::string SourceLine(Line.begin(), Line.end()); // Build the byte to column map. const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop); // Create a line for the caret that is filled with spaces that is the same // number of columns as the line of source code. std::string CaretLine(sourceColMap.columns(), ' '); // Highlight all of the characters covered by Ranges with ~ characters. for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); // Next, insert the caret itself. if (CaretLineNo == LineNo) { CaretColNo = sourceColMap.byteToContainingColumn(CaretColNo - 1); if (CaretLine.size() < CaretColNo + 1) CaretLine.resize(CaretColNo + 1, ' '); CaretLine[CaretColNo] = '^'; } std::string FixItInsertionLine = buildFixItInsertionLine( FID, LineNo, sourceColMap, Hints, SM, DiagOpts.get()); // If the source line is too long for our terminal, select only the // "interesting" source region within that line. unsigned Columns = DiagOpts->MessageLength; if (Columns) selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, Columns, sourceColMap); // If we are in -fdiagnostics-print-source-range-info mode, we are trying // to produce easily machine parsable output. Add a space before the // source line and the caret to make it trivial to tell the main diagnostic // line from what the user is intended to see. if (DiagOpts->ShowSourceRanges) { SourceLine = ' ' + SourceLine; CaretLine = ' ' + CaretLine; } // Finally, remove any blank spaces from the end of CaretLine. while (!CaretLine.empty() && CaretLine[CaretLine.size() - 1] == ' ') CaretLine.erase(CaretLine.end() - 1); // Emit what we have computed. emitSnippet(SourceLine); if (!CaretLine.empty()) { if (DiagOpts->ShowColors) OS.changeColor(caretColor, true); OS << CaretLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); } if (!FixItInsertionLine.empty()) { if (DiagOpts->ShowColors) // Print fixit line in color OS.changeColor(fixitColor, false); if (DiagOpts->ShowSourceRanges) OS << ' '; OS << FixItInsertionLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); } } // Print out any parseable fixit information requested by the options. emitParseableFixits(Hints, SM); }
/// TailDuplicate - If it is profitable, duplicate TailBB's contents in each /// of its predecessors. bool TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, bool IsSimple, MachineFunction &MF, SmallVectorImpl<MachineBasicBlock *> &TDBBs, SmallVectorImpl<MachineInstr *> &Copies) { DEBUG(dbgs() << "\n*** Tail-duplicating BB#" << TailBB->getNumber() << '\n'); DenseSet<unsigned> UsedByPhi; getRegsUsedByPHIs(*TailBB, &UsedByPhi); if (IsSimple) return duplicateSimpleBB(TailBB, TDBBs, UsedByPhi, Copies); // Iterate through all the unique predecessors and tail-duplicate this // block into them, if possible. Copying the list ahead of time also // avoids trouble with the predecessor list reallocating. bool Changed = false; SmallSetVector<MachineBasicBlock*, 8> Preds(TailBB->pred_begin(), TailBB->pred_end()); for (SmallSetVector<MachineBasicBlock *, 8>::iterator PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { MachineBasicBlock *PredBB = *PI; assert(TailBB != PredBB && "Single-block loop should have been rejected earlier!"); // EH edges are ignored by AnalyzeBranch. if (PredBB->succ_size() > 1) continue; MachineBasicBlock *PredTBB, *PredFBB; SmallVector<MachineOperand, 4> PredCond; if (TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true)) continue; if (!PredCond.empty()) continue; // Don't duplicate into a fall-through predecessor (at least for now). if (PredBB->isLayoutSuccessor(TailBB) && PredBB->canFallThrough()) continue; DEBUG(dbgs() << "\nTail-duplicating into PredBB: " << *PredBB << "From Succ: " << *TailBB); TDBBs.push_back(PredBB); // Remove PredBB's unconditional branch. TII->RemoveBranch(*PredBB); if (RS && !TailBB->livein_empty()) { // Update PredBB livein. RS->enterBasicBlock(PredBB); if (!PredBB->empty()) RS->forward(std::prev(PredBB->end())); for (MachineBasicBlock::livein_iterator I = TailBB->livein_begin(), E = TailBB->livein_end(); I != E; ++I) { if (!RS->isRegUsed(*I, false)) // If a register is previously livein to the tail but it's not live // at the end of predecessor BB, then it should be added to its // livein list. PredBB->addLiveIn(*I); } } // Clone the contents of TailBB into PredBB. DenseMap<unsigned, unsigned> LocalVRMap; SmallVector<std::pair<unsigned,unsigned>, 4> CopyInfos; // Use instr_iterator here to properly handle bundles, e.g. // ARM Thumb2 IT block. MachineBasicBlock::instr_iterator I = TailBB->instr_begin(); while (I != TailBB->instr_end()) { MachineInstr *MI = &*I; ++I; if (MI->isPHI()) { // Replace the uses of the def of the PHI with the register coming // from PredBB. ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos, UsedByPhi, true); } else { // Replace def of virtual registers with new registers, and update // uses with PHI source register or the new registers. DuplicateInstruction(MI, TailBB, PredBB, MF, LocalVRMap, UsedByPhi); } } MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(), TII->get(TargetOpcode::COPY), CopyInfos[i].first).addReg(CopyInfos[i].second)); } // Simplify TII->AnalyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true); NumInstrDups += TailBB->size() - 1; // subtract one for removed branch // Update the CFG. PredBB->removeSuccessor(PredBB->succ_begin()); assert(PredBB->succ_empty() && "TailDuplicate called on block with multiple successors!"); for (MachineBasicBlock::succ_iterator I = TailBB->succ_begin(), E = TailBB->succ_end(); I != E; ++I) PredBB->addSuccessor(*I, MBPI->getEdgeWeight(TailBB, I)); Changed = true; ++NumTailDups; } // If TailBB was duplicated into all its predecessors except for the prior // block, which falls through unconditionally, move the contents of this // block into the prior block. MachineBasicBlock *PrevBB = std::prev(MachineFunction::iterator(TailBB)); MachineBasicBlock *PriorTBB = nullptr, *PriorFBB = nullptr; SmallVector<MachineOperand, 4> PriorCond; // This has to check PrevBB->succ_size() because EH edges are ignored by // AnalyzeBranch. if (PrevBB->succ_size() == 1 && !TII->AnalyzeBranch(*PrevBB, PriorTBB, PriorFBB, PriorCond, true) && PriorCond.empty() && !PriorTBB && TailBB->pred_size() == 1 && !TailBB->hasAddressTaken()) { DEBUG(dbgs() << "\nMerging into block: " << *PrevBB << "From MBB: " << *TailBB); if (PreRegAlloc) { DenseMap<unsigned, unsigned> LocalVRMap; SmallVector<std::pair<unsigned,unsigned>, 4> CopyInfos; MachineBasicBlock::iterator I = TailBB->begin(); // Process PHI instructions first. while (I != TailBB->end() && I->isPHI()) { // Replace the uses of the def of the PHI with the register coming // from PredBB. MachineInstr *MI = &*I++; ProcessPHI(MI, TailBB, PrevBB, LocalVRMap, CopyInfos, UsedByPhi, true); if (MI->getParent()) MI->eraseFromParent(); } // Now copy the non-PHI instructions. while (I != TailBB->end()) { // Replace def of virtual registers with new registers, and update // uses with PHI source register or the new registers. MachineInstr *MI = &*I++; assert(!MI->isBundle() && "Not expecting bundles before regalloc!"); DuplicateInstruction(MI, TailBB, PrevBB, MF, LocalVRMap, UsedByPhi); MI->eraseFromParent(); } MachineBasicBlock::iterator Loc = PrevBB->getFirstTerminator(); for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { Copies.push_back(BuildMI(*PrevBB, Loc, DebugLoc(), TII->get(TargetOpcode::COPY), CopyInfos[i].first) .addReg(CopyInfos[i].second)); } } else { // No PHIs to worry about, just splice the instructions over. PrevBB->splice(PrevBB->end(), TailBB, TailBB->begin(), TailBB->end()); } PrevBB->removeSuccessor(PrevBB->succ_begin()); assert(PrevBB->succ_empty()); PrevBB->transferSuccessors(TailBB); TDBBs.push_back(PrevBB); Changed = true; } // If this is after register allocation, there are no phis to fix. if (!PreRegAlloc) return Changed; // If we made no changes so far, we are safe. if (!Changed) return Changed; // Handle the nasty case in that we duplicated a block that is part of a loop // into some but not all of its predecessors. For example: // 1 -> 2 <-> 3 | // \ | // \---> rest | // if we duplicate 2 into 1 but not into 3, we end up with // 12 -> 3 <-> 2 -> rest | // \ / | // \----->-----/ | // If there was a "var = phi(1, 3)" in 2, it has to be ultimately replaced // with a phi in 3 (which now dominates 2). // What we do here is introduce a copy in 3 of the register defined by the // phi, just like when we are duplicating 2 into 3, but we don't copy any // real instructions or remove the 3 -> 2 edge from the phi in 2. for (SmallSetVector<MachineBasicBlock *, 8>::iterator PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { MachineBasicBlock *PredBB = *PI; if (std::find(TDBBs.begin(), TDBBs.end(), PredBB) != TDBBs.end()) continue; // EH edges if (PredBB->succ_size() != 1) continue; DenseMap<unsigned, unsigned> LocalVRMap; SmallVector<std::pair<unsigned,unsigned>, 4> CopyInfos; MachineBasicBlock::iterator I = TailBB->begin(); // Process PHI instructions first. while (I != TailBB->end() && I->isPHI()) { // Replace the uses of the def of the PHI with the register coming // from PredBB. MachineInstr *MI = &*I++; ProcessPHI(MI, TailBB, PredBB, LocalVRMap, CopyInfos, UsedByPhi, false); } MachineBasicBlock::iterator Loc = PredBB->getFirstTerminator(); for (unsigned i = 0, e = CopyInfos.size(); i != e; ++i) { Copies.push_back(BuildMI(*PredBB, Loc, DebugLoc(), TII->get(TargetOpcode::COPY), CopyInfos[i].first).addReg(CopyInfos[i].second)); } } return Changed; }
void IndexSwiftASTWalker::getRecursiveModuleImports(Module &Mod, SmallVectorImpl<Module *> &Imports) { auto It = ImportsMap.find(&Mod); if (It != ImportsMap.end()) { Imports.append(It->second.begin(), It->second.end()); return; } llvm::SmallPtrSet<Module *, 16> Visited; collectRecursiveModuleImports(Mod, Visited); Visited.erase(&Mod); if (Logger::isLoggingEnabledForLevel(Logger::Level::Warning)) { std::for_each(Imports.begin(), Imports.end(), [](Module *M) { if (M->getModuleFilename().empty()) { std::string Info = "swift::Module with empty file name!! \nDetails: \n"; Info += " name: "; Info += M->getName().get(); Info += "\n"; auto Files = M->getFiles(); std::for_each(Files.begin(), Files.end(), [&](FileUnit *FU) { Info += " file unit: "; switch (FU->getKind()) { case FileUnitKind::Builtin: Info += "builtin"; break; case FileUnitKind::Derived: Info += "derived"; break; case FileUnitKind::Source: Info += "source, file=\""; Info += cast<SourceFile>(FU)->getFilename(); Info += "\""; break; case FileUnitKind::SerializedAST: Info += "serialized ast, file=\""; Info += cast<LoadedFile>(FU)->getFilename(); Info += "\""; break; case FileUnitKind::ClangModule: Info += "clang module, file=\""; Info += cast<LoadedFile>(FU)->getFilename(); Info += "\""; } Info += "\n"; }); LOG_WARN_FUNC("swift::Module with empty file name! " << Info); } }); } Imports.append(Visited.begin(), Visited.end()); std::sort(Imports.begin(), Imports.end(), [](Module *LHS, Module *RHS) { return LHS->getModuleFilename() < RHS->getModuleFilename(); }); // Cache it. ImportsMap[&Mod].append(Imports.begin(), Imports.end()); }
unsigned ConstraintGraph::computeConnectedComponents( SmallVectorImpl<TypeVariableType *> &typeVars, SmallVectorImpl<unsigned> &components) { // Track those type variables that the caller cares about. llvm::SmallPtrSet<TypeVariableType *, 4> typeVarSubset(typeVars.begin(), typeVars.end()); typeVars.clear(); // Initialize the components with component == # of type variables, // a sentinel value indicating unsigned numTypeVariables = TypeVariables.size(); components.assign(numTypeVariables, numTypeVariables); // Perform a depth-first search from each type variable to identify // what component it is in. unsigned numComponents = 0; for (unsigned i = 0; i != numTypeVariables; ++i) { auto typeVar = TypeVariables[i]; // Look up the node for this type variable. auto nodeAndIndex = lookupNode(typeVar); // If we're already assigned a component for this node, skip it. unsigned &curComponent = components[nodeAndIndex.second]; if (curComponent != numTypeVariables) continue; // Record this component. unsigned component = numComponents++; // Note that this node is part of this component, then visit it. curComponent = component; connectedComponentsDFS(*this, nodeAndIndex.first, component, components); } // Figure out which components have unbound type variables; these // are the only components and type variables we want to report. SmallVector<bool, 4> componentHasUnboundTypeVar(numComponents, false); for (unsigned i = 0; i != numTypeVariables; ++i) { // If this type variable has a fixed type, skip it. if (CS.getFixedType(TypeVariables[i])) continue; // If we only care about a subset, and this type variable isn't in that // subset, skip it. if (!typeVarSubset.empty() && typeVarSubset.count(TypeVariables[i]) == 0) continue; componentHasUnboundTypeVar[components[i]] = true; } // Renumber the old components to the new components. SmallVector<unsigned, 4> componentRenumbering(numComponents, 0); numComponents = 0; for (unsigned i = 0, n = componentHasUnboundTypeVar.size(); i != n; ++i) { // Skip components that have no unbound type variables. if (!componentHasUnboundTypeVar[i]) continue; componentRenumbering[i] = numComponents++; } // Copy over the type variables in the live components and remap // component numbers. unsigned outIndex = 0; for (unsigned i = 0, n = TypeVariables.size(); i != n; ++i) { // Skip type variables in dead components. if (!componentHasUnboundTypeVar[components[i]]) continue; typeVars.push_back(TypeVariables[i]); components[outIndex] = componentRenumbering[components[i]]; ++outIndex; } components.erase(components.begin() + outIndex, components.end()); return numComponents; }
/// \brief Convert the given type to a string suitable for printing as part of /// a diagnostic. /// /// There are four main criteria when determining whether we should have an /// a.k.a. clause when pretty-printing a type: /// /// 1) Some types provide very minimal sugar that doesn't impede the /// user's understanding --- for example, elaborated type /// specifiers. If this is all the sugar we see, we don't want an /// a.k.a. clause. /// 2) Some types are technically sugared but are much more familiar /// when seen in their sugared form --- for example, va_list, /// vector types, and the magic Objective C types. We don't /// want to desugar these, even if we do produce an a.k.a. clause. /// 3) Some types may have already been desugared previously in this diagnostic. /// if this is the case, doing another "aka" would just be clutter. /// 4) Two different types within the same diagnostic have the same output /// string. In this case, force an a.k.a with the desugared type when /// doing so will provide additional information. /// /// \param Context the context in which the type was allocated /// \param Ty the type to print /// \param QualTypeVals pointer values to QualTypes which are used in the /// diagnostic message static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, const DiagnosticsEngine::ArgumentValue *PrevArgs, unsigned NumPrevArgs, SmallVectorImpl<intptr_t> &QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); std::string S = Ty.getAsString(Context.getPrintingPolicy()); std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); for (SmallVectorImpl<intptr_t>::iterator I = QualTypeVals.begin(), E = QualTypeVals.end(); I != E; ++I) { QualType CompareTy = QualType::getFromOpaquePtr(reinterpret_cast<void*>(*I)); if (CompareTy == Ty) continue; // Same types QualType CompareCanTy = CompareTy.getCanonicalType(); if (CompareCanTy == CanTy) continue; // Same canonical types std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); bool aka; QualType CompareDesugar = Desugar(Context, CompareTy, aka); std::string CompareDesugarStr = CompareDesugar.getAsString(Context.getPrintingPolicy()); if (CompareS != S && CompareDesugarStr != S) continue; // The type string is different than the comparison string // and the desugared comparison string. std::string CompareCanS = CompareCanTy.getAsString(Context.getPrintingPolicy()); if (CompareCanS == CanS) continue; // No new info from canonical type ForceAKA = true; break; } // Check to see if we already desugared this type in this // diagnostic. If so, don't do it again. bool Repeated = false; for (unsigned i = 0; i != NumPrevArgs; ++i) { // TODO: Handle ak_declcontext case. if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { void *Ptr = (void*)PrevArgs[i].second; QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); if (PrevTy == Ty) { Repeated = true; break; } } } // Consider producing an a.k.a. clause if removing all the direct // sugar gives us something "significantly different". if (!Repeated) { bool ShouldAKA = false; QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); if (ShouldAKA || ForceAKA) { if (DesugaredTy == Ty) { DesugaredTy = Ty.getCanonicalType(); } std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); if (akaStr != S) { S = "'" + S + "' (aka '" + akaStr + "')"; return S; } } } S = "'" + S + "'"; return S; }
bool DeclContext::lookupQualified(Type type, DeclName member, NLOptions options, LazyResolver *typeResolver, SmallVectorImpl<ValueDecl *> &decls) const { using namespace namelookup; assert(decls.empty() && "additive lookup not supported"); if (type->is<ErrorType>()) return false; auto checkLookupCascading = [this, options]() -> Optional<bool> { switch (static_cast<unsigned>(options & NL_KnownDependencyMask)) { case 0: return isCascadingContextForLookup(/*excludeFunctions=*/false); case NL_KnownNonCascadingDependency: return false; case NL_KnownCascadingDependency: return true; case NL_KnownNoDependency: return None; default: // FIXME: Use llvm::CountPopulation_64 when that's declared constexpr. static_assert(__builtin_popcountll(NL_KnownDependencyMask) == 2, "mask should only include four values"); llvm_unreachable("mask only includes four values"); } }; // Look through lvalue and inout types. type = type->getLValueOrInOutObjectType(); // Look through metatypes. if (auto metaTy = type->getAs<AnyMetatypeType>()) type = metaTy->getInstanceType(); // Look through DynamicSelf. if (auto dynamicSelf = type->getAs<DynamicSelfType>()) type = dynamicSelf->getSelfType(); // Look for module references. if (auto moduleTy = type->getAs<ModuleType>()) { Module *module = moduleTy->getModule(); auto topLevelScope = getModuleScopeContext(); if (module == topLevelScope->getParentModule()) { if (auto maybeLookupCascade = checkLookupCascading()) { recordLookupOfTopLevelName(topLevelScope, member, maybeLookupCascade.getValue()); } lookupInModule(module, /*accessPath=*/{}, member, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, typeResolver, topLevelScope); } else { // Note: This is a lookup into another module. Unless we're compiling // multiple modules at once, or if the other module re-exports this one, // it shouldn't be possible to have a dependency from that module on // anything in this one. // Perform the lookup in all imports of this module. forAllVisibleModules(this, [&](const Module::ImportedModule &import) -> bool { if (import.second != module) return true; lookupInModule(import.second, import.first, member, decls, NLKind::QualifiedLookup, ResolutionKind::Overloadable, typeResolver, topLevelScope); // If we're able to do an unscoped lookup, we see everything. No need // to keep going. return !import.first.empty(); }); } llvm::SmallPtrSet<ValueDecl *, 4> knownDecls; decls.erase(std::remove_if(decls.begin(), decls.end(), [&](ValueDecl *vd) -> bool { // If we're performing a type lookup, don't even attempt to validate // the decl if its not a type. if ((options & NL_OnlyTypes) && !isa<TypeDecl>(vd)) return true; return !knownDecls.insert(vd).second; }), decls.end()); if (auto *debugClient = topLevelScope->getParentModule()->getDebugClient()) filterForDiscriminator(decls, debugClient); return !decls.empty(); } auto &ctx = getASTContext(); if (!ctx.LangOpts.EnableAccessControl) options |= NL_IgnoreAccessibility; // The set of nominal type declarations we should (and have) visited. SmallVector<NominalTypeDecl *, 4> stack; llvm::SmallPtrSet<NominalTypeDecl *, 4> visited; // Handle nominal types. bool wantProtocolMembers = false; bool wantLookupInAllClasses = false; if (auto nominal = type->getAnyNominal()) { visited.insert(nominal); stack.push_back(nominal); wantProtocolMembers = (options & NL_ProtocolMembers) && !isa<ProtocolDecl>(nominal); // If we want dynamic lookup and we're searching in the // AnyObject protocol, note this for later. if (options & NL_DynamicLookup) { if (auto proto = dyn_cast<ProtocolDecl>(nominal)) { if (proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) wantLookupInAllClasses = true; } } } // Handle archetypes else if (auto archetypeTy = type->getAs<ArchetypeType>()) { // Look in the protocols to which the archetype conforms (always). for (auto proto : archetypeTy->getConformsTo()) if (visited.insert(proto).second) stack.push_back(proto); // If requested, look into the superclasses of this archetype. if (options & NL_VisitSupertypes) { if (auto superclassTy = archetypeTy->getSuperclass()) { if (auto superclassDecl = superclassTy->getAnyNominal()) { if (visited.insert(superclassDecl).second) { stack.push_back(superclassDecl); wantProtocolMembers = (options & NL_ProtocolMembers) && !isa<ProtocolDecl>(superclassDecl); } } } } } // Handle protocol compositions. else if (auto compositionTy = type->getAs<ProtocolCompositionType>()) { SmallVector<ProtocolDecl *, 4> protocols; if (compositionTy->isExistentialType(protocols)) { for (auto proto : protocols) { if (visited.insert(proto).second) { stack.push_back(proto); // If we want dynamic lookup and this is the AnyObject // protocol, note this for later. if ((options & NL_DynamicLookup) && proto->isSpecificProtocol(KnownProtocolKind::AnyObject)) wantLookupInAllClasses = true; } } } } // Allow filtering of the visible declarations based on various // criteria. bool onlyCompleteObjectInits = false; auto isAcceptableDecl = [&](NominalTypeDecl *current, Decl *decl) -> bool { // If the decl is currently being type checked, then we have something // cyclic going on. Instead of poking at parts that are potentially not // set up, just assume it is acceptable. This will make sure we produce an // error later. if (decl->isBeingTypeChecked()) return true; // Filter out designated initializers, if requested. if (onlyCompleteObjectInits) { if (auto ctor = dyn_cast<ConstructorDecl>(decl)) { if (!ctor->isInheritable()) return false; } else { return false; } } // Ignore stub implementations. if (auto ctor = dyn_cast<ConstructorDecl>(decl)) { if (ctor->hasStubImplementation()) return false; } // Check access. if (!(options & NL_IgnoreAccessibility)) if (auto VD = dyn_cast<ValueDecl>(decl)) return VD->isAccessibleFrom(this); return true; }; ReferencedNameTracker *tracker = nullptr; if (auto containingSourceFile = dyn_cast<SourceFile>(getModuleScopeContext())) tracker = containingSourceFile->getReferencedNameTracker(); bool isLookupCascading; if (tracker) { if (auto maybeLookupCascade = checkLookupCascading()) isLookupCascading = maybeLookupCascade.getValue(); else tracker = nullptr; } // Visit all of the nominal types we know about, discovering any others // we need along the way. while (!stack.empty()) { auto current = stack.back(); stack.pop_back(); if (tracker) tracker->addUsedMember({current, member.getBaseName()},isLookupCascading); // Make sure we've resolved implicit constructors, if we need them. if (member.getBaseName() == ctx.Id_init && typeResolver) typeResolver->resolveImplicitConstructors(current); // Look for results within the current nominal type and its extensions. bool currentIsProtocol = isa<ProtocolDecl>(current); for (auto decl : current->lookupDirect(member)) { // If we're performing a type lookup, don't even attempt to validate // the decl if its not a type. if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl)) continue; // Resolve the declaration signature when we find the // declaration. if (typeResolver && !decl->isBeingTypeChecked()) { typeResolver->resolveDeclSignature(decl); if (!decl->hasType()) continue; } if (isAcceptableDecl(current, decl)) decls.push_back(decl); } // If we're not supposed to visit our supertypes, we're done. if ((options & NL_VisitSupertypes) == 0) continue; // Visit superclass. if (auto classDecl = dyn_cast<ClassDecl>(current)) { // If we're looking for initializers, only look at the superclass if the // current class permits inheritance. Even then, only find complete // object initializers. bool visitSuperclass = true; if (member.getBaseName() == ctx.Id_init) { if (classDecl->inheritsSuperclassInitializers(typeResolver)) onlyCompleteObjectInits = true; else visitSuperclass = false; } if (visitSuperclass) { if (auto superclassType = classDecl->getSuperclass()) if (auto superclassDecl = superclassType->getClassOrBoundGenericClass()) if (visited.insert(superclassDecl).second) stack.push_back(superclassDecl); } } // If we're not looking at a protocol and we're not supposed to // visit the protocols that this type conforms to, skip the next // step. if (!wantProtocolMembers && !currentIsProtocol) continue; SmallVector<ProtocolDecl *, 4> protocols; for (auto proto : current->getAllProtocols()) { if (visited.insert(proto).second) { stack.push_back(proto); } } // For a class, we don't need to visit the protocol members of the // superclass: that's already handled. if (isa<ClassDecl>(current)) wantProtocolMembers = false; } // If we want to perform lookup into all classes, do so now. if (wantLookupInAllClasses) { if (tracker) tracker->addDynamicLookupName(member.getBaseName(), isLookupCascading); // Collect all of the visible declarations. SmallVector<ValueDecl *, 4> allDecls; forAllVisibleModules(this, [&](Module::ImportedModule import) { import.second->lookupClassMember(import.first, member, allDecls); }); // For each declaration whose context is not something we've // already visited above, add it to the list of declarations. llvm::SmallPtrSet<ValueDecl *, 4> knownDecls; for (auto decl : allDecls) { // If we're performing a type lookup, don't even attempt to validate // the decl if its not a type. if ((options & NL_OnlyTypes) && !isa<TypeDecl>(decl)) continue; if (typeResolver && !decl->isBeingTypeChecked()) { typeResolver->resolveDeclSignature(decl); if (!decl->hasType()) continue; } // If the declaration has an override, name lookup will also have // found the overridden method. Skip this declaration, because we // prefer the overridden method. if (decl->getOverriddenDecl()) continue; auto dc = decl->getDeclContext(); auto nominal = dyn_cast<NominalTypeDecl>(dc); if (!nominal) { auto ext = cast<ExtensionDecl>(dc); nominal = ext->getExtendedType()->getAnyNominal(); assert(nominal && "Couldn't find nominal type?"); } // If we didn't visit this nominal type above, add this // declaration to the list. if (!visited.count(nominal) && knownDecls.insert(decl).second && isAcceptableDecl(nominal, decl)) decls.push_back(decl); } } // If we're supposed to remove overridden declarations, do so now. if (options & NL_RemoveOverridden) removeOverriddenDecls(decls); // If we're supposed to remove shadowed/hidden declarations, do so now. Module *M = getParentModule(); if (options & NL_RemoveNonVisible) removeShadowedDecls(decls, M, typeResolver); if (auto *debugClient = M->getDebugClient()) filterForDiscriminator(decls, debugClient); // We're done. Report success/failure. return !decls.empty(); }
Optional<unsigned> ConstraintSystem::findBestSolution(SmallVectorImpl<Solution> &viable, bool minimize) { if (viable.empty()) return None; if (viable.size() == 1) return 0; SolutionDiff diff(viable); // Find a potential best. SmallVector<bool, 16> losers(viable.size(), false); unsigned bestIdx = 0; for (unsigned i = 1, n = viable.size(); i != n; ++i) { switch (compareSolutions(*this, viable, diff, i, bestIdx)) { case SolutionCompareResult::Identical: // FIXME: Might want to warn about this in debug builds, so we can // find a way to eliminate the redundancy in the search space. case SolutionCompareResult::Incomparable: break; case SolutionCompareResult::Worse: losers[i] = true; break; case SolutionCompareResult::Better: losers[bestIdx] = true; bestIdx = i; break; } } // Make sure that our current best is better than all of the solved systems. bool ambiguous = false; for (unsigned i = 0, n = viable.size(); i != n && !ambiguous; ++i) { if (i == bestIdx) continue; switch (compareSolutions(*this, viable, diff, bestIdx, i)) { case SolutionCompareResult::Identical: // FIXME: Might want to warn about this in debug builds, so we can // find a way to eliminate the redundancy in the search space. break; case SolutionCompareResult::Better: losers[i] = true; break; case SolutionCompareResult::Worse: losers[bestIdx] = true; SWIFT_FALLTHROUGH; case SolutionCompareResult::Incomparable: // If we're not supposed to minimize the result set, just return eagerly. if (!minimize) return None; ambiguous = true; break; } } // If the result was not ambiguous, we're done. if (!ambiguous) { NumDiscardedSolutions += viable.size() - 1; return bestIdx; } // The comparison was ambiguous. Identify any solutions that are worse than // any other solution. for (unsigned i = 0, n = viable.size(); i != n; ++i) { // If the first solution has already lost once, don't bother looking // further. if (losers[i]) continue; for (unsigned j = i + 1; j != n; ++j) { // If the second solution has already lost once, don't bother looking // further. if (losers[j]) continue; switch (compareSolutions(*this, viable, diff, i, j)) { case SolutionCompareResult::Identical: // FIXME: Dub one of these the loser arbitrarily? break; case SolutionCompareResult::Better: losers[j] = true; break; case SolutionCompareResult::Worse: losers[i] = true; break; case SolutionCompareResult::Incomparable: break; } } } // Remove any solution that is worse than some other solution. unsigned outIndex = 0; for (unsigned i = 0, n = viable.size(); i != n; ++i) { // Skip over the losing solutions. if (losers[i]) continue; // If we have skipped any solutions, move this solution into the next // open position. if (outIndex < i) viable[outIndex] = std::move(viable[i]); ++outIndex; } viable.erase(viable.begin() + outIndex, viable.end()); NumDiscardedSolutions += viable.size() - outIndex; return None; }
bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, Module &M, bool isConst, unsigned AddrSpace) const { auto &DL = M.getDataLayout(); // FIXME: Find better heuristics std::stable_sort(Globals.begin(), Globals.end(), [&DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { return DL.getTypeAllocSize(GV1->getValueType()) < DL.getTypeAllocSize(GV2->getValueType()); }); // If we want to just blindly group all globals together, do so. if (!GlobalMergeGroupByUse) { BitVector AllGlobals(Globals.size()); AllGlobals.set(); return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); } // If we want to be smarter, look at all uses of each global, to try to // discover all sets of globals used together, and how many times each of // these sets occurred. // // Keep this reasonably efficient, by having an append-only list of all sets // discovered so far (UsedGlobalSet), and mapping each "together-ness" unit of // code (currently, a Function) to the set of globals seen so far that are // used together in that unit (GlobalUsesByFunction). // // When we look at the Nth global, we know that any new set is either: // - the singleton set {N}, containing this global only, or // - the union of {N} and a previously-discovered set, containing some // combination of the previous N-1 globals. // Using that knowledge, when looking at the Nth global, we can keep: // - a reference to the singleton set {N} (CurGVOnlySetIdx) // - a list mapping each previous set to its union with {N} (EncounteredUGS), // if it actually occurs. // We keep track of the sets of globals used together "close enough". struct UsedGlobalSet { BitVector Globals; unsigned UsageCount = 1; UsedGlobalSet(size_t Size) : Globals(Size) {} }; // Each set is unique in UsedGlobalSets. std::vector<UsedGlobalSet> UsedGlobalSets; // Avoid repeating the create-global-set pattern. auto CreateGlobalSet = [&]() -> UsedGlobalSet & { UsedGlobalSets.emplace_back(Globals.size()); return UsedGlobalSets.back(); }; // The first set is the empty set. CreateGlobalSet().UsageCount = 0; // We define "close enough" to be "in the same function". // FIXME: Grouping uses by function is way too aggressive, so we should have // a better metric for distance between uses. // The obvious alternative would be to group by BasicBlock, but that's in // turn too conservative.. // Anything in between wouldn't be trivial to compute, so just stick with // per-function grouping. // The value type is an index into UsedGlobalSets. // The default (0) conveniently points to the empty set. DenseMap<Function *, size_t /*UsedGlobalSetIdx*/> GlobalUsesByFunction; // Now, look at each merge-eligible global in turn. // Keep track of the sets we already encountered to which we added the // current global. // Each element matches the same-index element in UsedGlobalSets. // This lets us efficiently tell whether a set has already been expanded to // include the current global. std::vector<size_t> EncounteredUGS; for (size_t GI = 0, GE = Globals.size(); GI != GE; ++GI) { GlobalVariable *GV = Globals[GI]; // Reset the encountered sets for this global... std::fill(EncounteredUGS.begin(), EncounteredUGS.end(), 0); // ...and grow it in case we created new sets for the previous global. EncounteredUGS.resize(UsedGlobalSets.size()); // We might need to create a set that only consists of the current global. // Keep track of its index into UsedGlobalSets. size_t CurGVOnlySetIdx = 0; // For each global, look at all its Uses. for (auto &U : GV->uses()) { // This Use might be a ConstantExpr. We're interested in Instruction // users, so look through ConstantExpr... Use *UI, *UE; if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) { if (CE->use_empty()) continue; UI = &*CE->use_begin(); UE = nullptr; } else if (isa<Instruction>(U.getUser())) { UI = &U; UE = UI->getNext(); } else { continue; } // ...to iterate on all the instruction users of the global. // Note that we iterate on Uses and not on Users to be able to getNext(). for (; UI != UE; UI = UI->getNext()) { Instruction *I = dyn_cast<Instruction>(UI->getUser()); if (!I) continue; Function *ParentFn = I->getParent()->getParent(); // If we're only optimizing for size, ignore non-minsize functions. if (OnlyOptimizeForSize && !ParentFn->optForMinSize()) continue; size_t UGSIdx = GlobalUsesByFunction[ParentFn]; // If this is the first global the basic block uses, map it to the set // consisting of this global only. if (!UGSIdx) { // If that set doesn't exist yet, create it. if (!CurGVOnlySetIdx) { CurGVOnlySetIdx = UsedGlobalSets.size(); CreateGlobalSet().Globals.set(GI); } else { ++UsedGlobalSets[CurGVOnlySetIdx].UsageCount; } GlobalUsesByFunction[ParentFn] = CurGVOnlySetIdx; continue; } // If we already encountered this BB, just increment the counter. if (UsedGlobalSets[UGSIdx].Globals.test(GI)) { ++UsedGlobalSets[UGSIdx].UsageCount; continue; } // If not, the previous set wasn't actually used in this function. --UsedGlobalSets[UGSIdx].UsageCount; // If we already expanded the previous set to include this global, just // reuse that expanded set. if (size_t ExpandedIdx = EncounteredUGS[UGSIdx]) { ++UsedGlobalSets[ExpandedIdx].UsageCount; GlobalUsesByFunction[ParentFn] = ExpandedIdx; continue; } // If not, create a new set consisting of the union of the previous set // and this global. Mark it as encountered, so we can reuse it later. GlobalUsesByFunction[ParentFn] = EncounteredUGS[UGSIdx] = UsedGlobalSets.size(); UsedGlobalSet &NewUGS = CreateGlobalSet(); NewUGS.Globals.set(GI); NewUGS.Globals |= UsedGlobalSets[UGSIdx].Globals; } } } // Now we found a bunch of sets of globals used together. We accumulated // the number of times we encountered the sets (i.e., the number of blocks // that use that exact set of globals). // // Multiply that by the size of the set to give us a crude profitability // metric. std::stable_sort(UsedGlobalSets.begin(), UsedGlobalSets.end(), [](const UsedGlobalSet &UGS1, const UsedGlobalSet &UGS2) { return UGS1.Globals.count() * UGS1.UsageCount < UGS2.Globals.count() * UGS2.UsageCount; }); // We can choose to merge all globals together, but ignore globals never used // with another global. This catches the obviously non-profitable cases of // having a single global, but is aggressive enough for any other case. if (GlobalMergeIgnoreSingleUse) { BitVector AllGlobals(Globals.size()); for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; if (UGS.UsageCount == 0) continue; if (UGS.Globals.count() > 1) AllGlobals |= UGS.Globals; } return doMerge(Globals, AllGlobals, M, isConst, AddrSpace); } // Starting from the sets with the best (=biggest) profitability, find a // good combination. // The ideal (and expensive) solution can only be found by trying all // combinations, looking for the one with the best profitability. // Don't be smart about it, and just pick the first compatible combination, // starting with the sets with the best profitability. BitVector PickedGlobals(Globals.size()); bool Changed = false; for (size_t i = 0, e = UsedGlobalSets.size(); i != e; ++i) { const UsedGlobalSet &UGS = UsedGlobalSets[e - i - 1]; if (UGS.UsageCount == 0) continue; if (PickedGlobals.anyCommon(UGS.Globals)) continue; PickedGlobals |= UGS.Globals; // If the set only contains one global, there's no point in merging. // Ignore the global for inclusion in other sets though, so keep it in // PickedGlobals. if (UGS.Globals.count() < 2) continue; Changed |= doMerge(Globals, UGS.Globals, M, isConst, AddrSpace); } return Changed; }
/// \brief Emit a code snippet and caret line. /// /// This routine emits a single line's code snippet and caret line.. /// /// \param Loc The location for the caret. /// \param Ranges The underlined ranges for this code snippet. /// \param Hints The FixIt hints active for this diagnostic. void TextDiagnostic::emitSnippetAndCaret( SourceLocation Loc, DiagnosticsEngine::Level Level, SmallVectorImpl<CharSourceRange>& Ranges, ArrayRef<FixItHint> Hints, const SourceManager &SM) { assert(!Loc.isInvalid() && "must have a valid source location here"); assert(Loc.isFileID() && "must have a file location here"); // If caret diagnostics are enabled and we have location, we want to // emit the caret. However, we only do this if the location moved // from the last diagnostic, if the last diagnostic was a note that // was part of a different warning or error diagnostic, or if the // diagnostic has ranges. We don't want to emit the same caret // multiple times if one loc has multiple diagnostics. if (!DiagOpts->ShowCarets) return; if (Loc == LastLoc && Ranges.empty() && Hints.empty() && (LastLevel != DiagnosticsEngine::Note || Level == LastLevel)) return; // Decompose the location into a FID/Offset pair. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); FileID FID = LocInfo.first; unsigned FileOffset = LocInfo.second; // Get information about the buffer it points into. bool Invalid = false; const char *BufStart = SM.getBufferData(FID, &Invalid).data(); if (Invalid) return; unsigned LineNo = SM.getLineNumber(FID, FileOffset); unsigned ColNo = SM.getColumnNumber(FID, FileOffset); // Rewind from the current position to the start of the line. const char *TokPtr = BufStart+FileOffset; const char *LineStart = TokPtr-ColNo+1; // Column # is 1-based. // Compute the line end. Scan forward from the error position to the end of // the line. const char *LineEnd = TokPtr; while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0') ++LineEnd; // Copy the line of code into an std::string for ease of manipulation. std::string SourceLine(LineStart, LineEnd); // Create a line for the caret that is filled with spaces that is the same // length as the line of source code. std::string CaretLine(LineEnd-LineStart, ' '); const SourceColumnMap sourceColMap(SourceLine, DiagOpts->TabStop); // Highlight all of the characters covered by Ranges with ~ characters. for (SmallVectorImpl<CharSourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I != E; ++I) highlightRange(*I, LineNo, FID, sourceColMap, CaretLine, SM, LangOpts); // Next, insert the caret itself. ColNo = sourceColMap.byteToContainingColumn(ColNo-1); if (CaretLine.size()<ColNo+1) CaretLine.resize(ColNo+1, ' '); CaretLine[ColNo] = '^'; std::string FixItInsertionLine = buildFixItInsertionLine(LineNo, sourceColMap, Hints, SM, DiagOpts.getPtr()); // If the source line is too long for our terminal, select only the // "interesting" source region within that line. unsigned Columns = DiagOpts->MessageLength; if (Columns) selectInterestingSourceRegion(SourceLine, CaretLine, FixItInsertionLine, Columns, sourceColMap); // If we are in -fdiagnostics-print-source-range-info mode, we are trying // to produce easily machine parsable output. Add a space before the // source line and the caret to make it trivial to tell the main diagnostic // line from what the user is intended to see. if (DiagOpts->ShowSourceRanges) { SourceLine = ' ' + SourceLine; CaretLine = ' ' + CaretLine; } // Finally, remove any blank spaces from the end of CaretLine. while (CaretLine[CaretLine.size()-1] == ' ') CaretLine.erase(CaretLine.end()-1); // Emit what we have computed. emitSnippet(SourceLine); if (DiagOpts->ShowColors) OS.changeColor(caretColor, true); OS << CaretLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); if (!FixItInsertionLine.empty()) { if (DiagOpts->ShowColors) // Print fixit line in color OS.changeColor(fixitColor, false); if (DiagOpts->ShowSourceRanges) OS << ' '; OS << FixItInsertionLine << '\n'; if (DiagOpts->ShowColors) OS.resetColor(); } // Print out any parseable fixit information requested by the options. emitParseableFixits(Hints, SM); }
bool GuardWideningImpl::combineRangeChecks( SmallVectorImpl<GuardWideningImpl::RangeCheck> &Checks, SmallVectorImpl<GuardWideningImpl::RangeCheck> &RangeChecksOut) { unsigned OldCount = Checks.size(); while (!Checks.empty()) { // Pick all of the range checks with a specific base and length, and try to // merge them. Value *CurrentBase = Checks.front().getBase(); Value *CurrentLength = Checks.front().getLength(); SmallVector<GuardWideningImpl::RangeCheck, 3> CurrentChecks; auto IsCurrentCheck = [&](GuardWideningImpl::RangeCheck &RC) { return RC.getBase() == CurrentBase && RC.getLength() == CurrentLength; }; copy_if(Checks, std::back_inserter(CurrentChecks), IsCurrentCheck); Checks.erase(remove_if(Checks, IsCurrentCheck), Checks.end()); assert(CurrentChecks.size() != 0 && "We know we have at least one!"); if (CurrentChecks.size() < 3) { RangeChecksOut.insert(RangeChecksOut.end(), CurrentChecks.begin(), CurrentChecks.end()); continue; } // CurrentChecks.size() will typically be 3 here, but so far there has been // no need to hard-code that fact. std::sort(CurrentChecks.begin(), CurrentChecks.end(), [&](const GuardWideningImpl::RangeCheck &LHS, const GuardWideningImpl::RangeCheck &RHS) { return LHS.getOffsetValue().slt(RHS.getOffsetValue()); }); // Note: std::sort should not invalidate the ChecksStart iterator. ConstantInt *MinOffset = CurrentChecks.front().getOffset(), *MaxOffset = CurrentChecks.back().getOffset(); unsigned BitWidth = MaxOffset->getValue().getBitWidth(); if ((MaxOffset->getValue() - MinOffset->getValue()) .ugt(APInt::getSignedMinValue(BitWidth))) return false; APInt MaxDiff = MaxOffset->getValue() - MinOffset->getValue(); const APInt &HighOffset = MaxOffset->getValue(); auto OffsetOK = [&](const GuardWideningImpl::RangeCheck &RC) { return (HighOffset - RC.getOffsetValue()).ult(MaxDiff); }; if (MaxDiff.isMinValue() || !std::all_of(std::next(CurrentChecks.begin()), CurrentChecks.end(), OffsetOK)) return false; // We have a series of f+1 checks as: // // I+k_0 u< L ... Chk_0 // I_k_1 u< L ... Chk_1 // ... // I_k_f u< L ... Chk_(f+1) // // with forall i in [0,f): k_f-k_i u< k_f-k_0 ... Precond_0 // k_f-k_0 u< INT_MIN+k_f ... Precond_1 // k_f != k_0 ... Precond_2 // // Claim: // Chk_0 AND Chk_(f+1) implies all the other checks // // Informal proof sketch: // // We will show that the integer range [I+k_0,I+k_f] does not unsigned-wrap // (i.e. going from I+k_0 to I+k_f does not cross the -1,0 boundary) and // thus I+k_f is the greatest unsigned value in that range. // // This combined with Ckh_(f+1) shows that everything in that range is u< L. // Via Precond_0 we know that all of the indices in Chk_0 through Chk_(f+1) // lie in [I+k_0,I+k_f], this proving our claim. // // To see that [I+k_0,I+k_f] is not a wrapping range, note that there are // two possibilities: I+k_0 u< I+k_f or I+k_0 >u I+k_f (they can't be equal // since k_0 != k_f). In the former case, [I+k_0,I+k_f] is not a wrapping // range by definition, and the latter case is impossible: // // 0-----I+k_f---I+k_0----L---INT_MAX,INT_MIN------------------(-1) // xxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // // For Chk_0 to succeed, we'd have to have k_f-k_0 (the range highlighted // with 'x' above) to be at least >u INT_MIN. RangeChecksOut.emplace_back(CurrentChecks.front()); RangeChecksOut.emplace_back(CurrentChecks.back()); } assert(RangeChecksOut.size() <= OldCount && "We pessimized!"); return RangeChecksOut.size() != OldCount; }
void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex, unsigned RecordCode, SmallVectorImpl<uint64_t> &Values) { if (DebugEmitRecord) { errs() << "Emit " << AbbrevIndex << ": <" << RecordCode; for (size_t i = 0; i < Values.size(); ++i) { errs() << ", " << Values[i]; } errs() << ">\n"; } switch (RecordCode) { case naclbitc::BLK_CODE_ENTER: { unsigned NumBits = naclbitc::DEFAULT_MAX_ABBREV; WriteBlockID = -1; if (AbbrevIndex != naclbitc::ENTER_SUBBLOCK) { Fatal() << "Enter block record code " << RecordCode << " uses illegal abbreviation index " << AbbrevIndex << "\n"; ReportFatalError(); } if (Values.size() == 2) { WriteBlockID = Values[0]; NumBits = Values[1]; if (NumBits > 32) { Fatal() << "Error: Bit size " << NumBits << " for record should be <= 32\n"; ReportFatalError(); } if (NumBits < 2) { Fatal() << "Error: Bit size " << NumBits << " for record should be >= 2\n"; ReportFatalError(); } } else { Fatal() << "Error: Values for enter record should be of size 2. Found: " << Values.size(); ReportFatalError(); } uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; AbbrevIndexLimitStack.push_back(MaxAbbrev); if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { if (NumBits != naclbitc::DEFAULT_MAX_ABBREV) { Fatal() << "Error: Numbits entry for abbreviations record not 2. Found: " << NumBits << "\n"; ReportFatalError(); } Writer->EnterBlockInfoBlock(); } else { NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); Writer->EnterSubblock(WriteBlockID, CurCodeLen); } return; } case naclbitc::BLK_CODE_EXIT: if (AbbrevIndex != naclbitc::END_BLOCK) { Fatal() << "Error: Exit block record code " << RecordCode << " uses illegal abbreviation index " << AbbrevIndex << "\n"; ReportFatalError(); } if (!Values.empty()) { Fatal() << "Error: Exit block should not have values. Found: " << Values.size() << "\n"; ReportFatalError(); } if (!AbbrevIndexLimitStack.empty()) AbbrevIndexLimitStack.pop_back(); Writer->ExitBlock(); return; case naclbitc::BLK_CODE_DEFINE_ABBREV: { if (AbbrevIndex != naclbitc::DEFINE_ABBREV) { Fatal() << "Error: Define abbreviation record code " << RecordCode << " uses illegal abbreviation index " << AbbrevIndex << "\n"; ReportFatalError(); } NaClBitCodeAbbrev *Abbrev = buildAbbrev(RecordCode, Values); if (Abbrev == NULL) return; if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { Writer->EmitBlockInfoAbbrev(SetBID, Abbrev); } else { Writer->EmitAbbrev(Abbrev); } return; } case naclbitc::BLK_CODE_HEADER: // Note: There is no abbreviation index here. Ignore. for (SmallVectorImpl<uint64_t>::const_iterator Iter = Values.begin(), IterEnd = Values.end(); Iter != IterEnd; ++Iter) { Writer->Emit(*Iter, 8); } return; default: if ((AbbrevIndex != naclbitc::UNABBREV_RECORD && !Writer->isUserRecordAbbreviation(AbbrevIndex))) { uint64_t BlockAbbrevIndexLimit = 0; if (!AbbrevIndexLimitStack.empty()) BlockAbbrevIndexLimit = AbbrevIndexLimitStack.back(); if (AbbrevIndex > BlockAbbrevIndexLimit) { Fatal() << "Error: Record code " << RecordCode << " uses illegal abbreviation index " << AbbrevIndex << ". Must not exceed " << BlockAbbrevIndexLimit << "\n"; ReportFatalError(); } // Note: If this point is reached, the abbreviation is // bad. However, that may be the point of munge being // applied. Hence, emit the bad abbreviation and the data so // that the reader can be tested on this bad input. For // simplicity, we output the record data using the default // abbreviation pattern. errs() << "Warning: Record code " << RecordCode << " uses illegal abbreviation index " << AbbrevIndex << "\n"; Writer->EmitCode(AbbrevIndex); Writer->EmitVBR(RecordCode, 6); uint32_t NumValues = static_cast<uint32_t>(Values.size()); Writer->EmitVBR(NumValues, 6); for (uint32_t i = 0; i < NumValues; ++i) { Writer->EmitVBR64(Values[i], 6); } return; } if (AbbrevIndex == naclbitc::UNABBREV_RECORD) Writer->EmitRecord(RecordCode, Values); else Writer->EmitRecord(RecordCode, Values, AbbrevIndex); return; } Fatal() << "emitRecord on unimplemented code" << "\n"; ReportFatalError(); }
static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, std::set<std::string> &SavedStrings, Driver &TheDriver) { // Try to infer frontend type and default target from the program name. // suffixes[] contains the list of known driver suffixes. // Suffixes are compared against the program name in order. // If there is a match, the frontend type is updated as necessary (CPP/C++). // If there is no match, a second round is done after stripping the last // hyphen and everything following it. This allows using something like // "clang++-2.9". // If there is a match in either the first or second round, // the function tries to identify a target as prefix. E.g. // "x86_64-linux-clang" as interpreted as suffix "clang" with // target prefix "x86_64-linux". If such a target prefix is found, // is gets added via -target as implicit first argument. static const struct { const char *Suffix; bool IsCXX; bool IsCPP; } suffixes [] = { { "clang", false, false }, { "clang++", true, false }, { "clang-c++", true, false }, { "clang-cc", false, false }, { "clang-cpp", false, true }, { "clang-g++", true, false }, { "clang-gcc", false, false }, { "cc", false, false }, { "cpp", false, true }, { "++", true, false }, }; std::string ProgName(llvm::sys::path::stem(ArgVector[0])); StringRef ProgNameRef(ProgName); StringRef Prefix; for (int Components = 2; Components; --Components) { bool FoundMatch = false; size_t i; for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { if (ProgNameRef.endswith(suffixes[i].Suffix)) { FoundMatch = true; if (suffixes[i].IsCXX) TheDriver.CCCIsCXX = true; if (suffixes[i].IsCPP) TheDriver.CCCIsCPP = true; break; } } if (FoundMatch) { StringRef::size_type LastComponent = ProgNameRef.rfind('-', ProgNameRef.size() - strlen(suffixes[i].Suffix)); if (LastComponent != StringRef::npos) Prefix = ProgNameRef.slice(0, LastComponent); break; } StringRef::size_type LastComponent = ProgNameRef.rfind('-'); if (LastComponent == StringRef::npos) break; ProgNameRef = ProgNameRef.slice(0, LastComponent); } if (Prefix.empty()) return; std::string IgnoredError; if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { SmallVectorImpl<const char *>::iterator it = ArgVector.begin(); if (it != ArgVector.end()) ++it; ArgVector.insert(it, SaveStringInSet(SavedStrings, Prefix)); ArgVector.insert(it, SaveStringInSet(SavedStrings, std::string("-target"))); } }
/// ProcessInstruction - Given an instruction in the loop, check to see if it /// has any uses that are outside the current loop. If so, insert LCSSA PHI /// nodes and rewrite the uses. bool LCSSA::ProcessInstruction(Instruction *Inst, const SmallVectorImpl<BasicBlock*> &ExitBlocks) { SmallVector<Use*, 16> UsesToRewrite; BasicBlock *InstBB = Inst->getParent(); for (Value::use_iterator UI = Inst->use_begin(), E = Inst->use_end(); UI != E; ++UI) { User *U = *UI; BasicBlock *UserBB = cast<Instruction>(U)->getParent(); if (PHINode *PN = dyn_cast<PHINode>(U)) UserBB = PN->getIncomingBlock(UI); if (InstBB != UserBB && !inLoop(UserBB)) UsesToRewrite.push_back(&UI.getUse()); } // If there are no uses outside the loop, exit with no change. if (UsesToRewrite.empty()) return false; ++NumLCSSA; // We are applying the transformation // Invoke instructions are special in that their result value is not available // along their unwind edge. The code below tests to see whether DomBB dominates // the value, so adjust DomBB to the normal destination block, which is // effectively where the value is first usable. BasicBlock *DomBB = Inst->getParent(); if (InvokeInst *Inv = dyn_cast<InvokeInst>(Inst)) DomBB = Inv->getNormalDest(); DomTreeNode *DomNode = DT->getNode(DomBB); SSAUpdater SSAUpdate; SSAUpdate.Initialize(Inst->getType(), Inst->getName()); // Insert the LCSSA phi's into all of the exit blocks dominated by the // value, and add them to the Phi's map. for (SmallVectorImpl<BasicBlock*>::const_iterator BBI = ExitBlocks.begin(), BBE = ExitBlocks.end(); BBI != BBE; ++BBI) { BasicBlock *ExitBB = *BBI; if (!DT->dominates(DomNode, DT->getNode(ExitBB))) continue; // If we already inserted something for this BB, don't reprocess it. if (SSAUpdate.HasValueForBlock(ExitBB)) continue; PHINode *PN = PHINode::Create(Inst->getType(), Inst->getName()+".lcssa", ExitBB->begin()); PN->reserveOperandSpace(PredCache.GetNumPreds(ExitBB)); // Add inputs from inside the loop for this PHI. for (BasicBlock **PI = PredCache.GetPreds(ExitBB); *PI; ++PI) { PN->addIncoming(Inst, *PI); // If the exit block has a predecessor not within the loop, arrange for // the incoming value use corresponding to that predecessor to be // rewritten in terms of a different LCSSA PHI. if (!inLoop(*PI)) UsesToRewrite.push_back( &PN->getOperandUse( PN->getOperandNumForIncomingValue(PN->getNumIncomingValues()-1))); } // Remember that this phi makes the value alive in this block. SSAUpdate.AddAvailableValue(ExitBB, PN); } // Rewrite all uses outside the loop in terms of the new PHIs we just // inserted. for (unsigned i = 0, e = UsesToRewrite.size(); i != e; ++i) { // If this use is in an exit block, rewrite to use the newly inserted PHI. // This is required for correctness because SSAUpdate doesn't handle uses in // the same block. It assumes the PHI we inserted is at the end of the // block. Instruction *User = cast<Instruction>(UsesToRewrite[i]->getUser()); BasicBlock *UserBB = User->getParent(); if (PHINode *PN = dyn_cast<PHINode>(User)) UserBB = PN->getIncomingBlock(*UsesToRewrite[i]); if (isa<PHINode>(UserBB->begin()) && isExitBlock(UserBB, ExitBlocks)) { UsesToRewrite[i]->set(UserBB->begin()); continue; } // Otherwise, do full PHI insertion. SSAUpdate.RewriteUse(*UsesToRewrite[i]); } return true; }