diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/libs/llvm12/include/llvm/Transforms/IPO | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/include/llvm/Transforms/IPO')
14 files changed, 1501 insertions, 1501 deletions
diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/AlwaysInliner.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/AlwaysInliner.h index 06ae0fecb4..4a9764b855 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/AlwaysInliner.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/AlwaysInliner.h @@ -41,7 +41,7 @@ public: : InsertLifetime(InsertLifetime) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &); - static bool isRequired() { return true; } + static bool isRequired() { return true; } }; /// Create a legacy pass manager instance of a pass to inline and remove diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Annotation2Metadata.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Annotation2Metadata.h index 17740ca383..198d4cfc2c 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Annotation2Metadata.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Annotation2Metadata.h @@ -1,41 +1,41 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Annotation2Metadata.h - Add !annotation metadata. --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// New pass manager pass to convert @llvm.global.annotations to !annotation -// metadata. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_ANNOTATION2METADATA_H -#define LLVM_TRANSFORMS_IPO_ANNOTATION2METADATA_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -class Module; - -/// Pass to convert @llvm.global.annotations to !annotation metadata. -struct Annotation2MetadataPass : public PassInfoMixin<Annotation2MetadataPass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_SCCP_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Annotation2Metadata.h - Add !annotation metadata. --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// New pass manager pass to convert @llvm.global.annotations to !annotation +// metadata. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_ANNOTATION2METADATA_H +#define LLVM_TRANSFORMS_IPO_ANNOTATION2METADATA_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Module; + +/// Pass to convert @llvm.global.annotations to !annotation metadata. +struct Annotation2MetadataPass : public PassInfoMixin<Annotation2MetadataPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_SCCP_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Attributor.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Attributor.h index 96681071db..fd82945466 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Attributor.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Attributor.h @@ -104,10 +104,10 @@ #ifndef LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H #define LLVM_TRANSFORMS_IPO_ATTRIBUTOR_H -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/MapVector.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AssumeBundleQueries.h" #include "llvm/Analysis/CFG.h" @@ -121,27 +121,27 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/PassManager.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/TimeProfiler.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/TimeProfiler.h" #include "llvm/Transforms/Utils/CallGraphUpdater.h" namespace llvm { -struct AADepGraphNode; -struct AADepGraph; +struct AADepGraphNode; +struct AADepGraph; struct Attributor; struct AbstractAttribute; struct InformationCache; struct AAIsDead; -class AAManager; -class AAResults; +class AAManager; +class AAResults; class Function; -/// The value passed to the line option that defines the maximal initialization -/// chain length. -extern unsigned MaxInitializationChainLength; - +/// The value passed to the line option that defines the maximal initialization +/// chain length. +extern unsigned MaxInitializationChainLength; + ///{ enum class ChangeStatus { CHANGED, @@ -157,74 +157,74 @@ enum class DepClassTy { }; ///} -/// The data structure for the nodes of a dependency graph -struct AADepGraphNode { -public: - virtual ~AADepGraphNode(){}; - using DepTy = PointerIntPair<AADepGraphNode *, 1>; - -protected: - /// Set of dependency graph nodes which should be updated if this one - /// is updated. The bit encodes if it is optional. - TinyPtrVector<DepTy> Deps; - - static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); } - static AbstractAttribute *DepGetValAA(DepTy &DT) { - return cast<AbstractAttribute>(DT.getPointer()); - } - - operator AbstractAttribute *() { return cast<AbstractAttribute>(this); } - -public: - using iterator = - mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>; - using aaiterator = - mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetValAA)>; - - aaiterator begin() { return aaiterator(Deps.begin(), &DepGetValAA); } - aaiterator end() { return aaiterator(Deps.end(), &DepGetValAA); } - iterator child_begin() { return iterator(Deps.begin(), &DepGetVal); } - iterator child_end() { return iterator(Deps.end(), &DepGetVal); } - - virtual void print(raw_ostream &OS) const { OS << "AADepNode Impl\n"; } - TinyPtrVector<DepTy> &getDeps() { return Deps; } - - friend struct Attributor; - friend struct AADepGraph; -}; - -/// The data structure for the dependency graph -/// -/// Note that in this graph if there is an edge from A to B (A -> B), -/// then it means that B depends on A, and when the state of A is -/// updated, node B should also be updated -struct AADepGraph { - AADepGraph() {} - ~AADepGraph() {} - - using DepTy = AADepGraphNode::DepTy; - static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); } - using iterator = - mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>; - - /// There is no root node for the dependency graph. But the SCCIterator - /// requires a single entry point, so we maintain a fake("synthetic") root - /// node that depends on every node. - AADepGraphNode SyntheticRoot; - AADepGraphNode *GetEntryNode() { return &SyntheticRoot; } - - iterator begin() { return SyntheticRoot.child_begin(); } - iterator end() { return SyntheticRoot.child_end(); } - - void viewGraph(); - - /// Dump graph to file - void dumpGraph(); - - /// Print dependency graph - void print(); -}; - +/// The data structure for the nodes of a dependency graph +struct AADepGraphNode { +public: + virtual ~AADepGraphNode(){}; + using DepTy = PointerIntPair<AADepGraphNode *, 1>; + +protected: + /// Set of dependency graph nodes which should be updated if this one + /// is updated. The bit encodes if it is optional. + TinyPtrVector<DepTy> Deps; + + static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); } + static AbstractAttribute *DepGetValAA(DepTy &DT) { + return cast<AbstractAttribute>(DT.getPointer()); + } + + operator AbstractAttribute *() { return cast<AbstractAttribute>(this); } + +public: + using iterator = + mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>; + using aaiterator = + mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetValAA)>; + + aaiterator begin() { return aaiterator(Deps.begin(), &DepGetValAA); } + aaiterator end() { return aaiterator(Deps.end(), &DepGetValAA); } + iterator child_begin() { return iterator(Deps.begin(), &DepGetVal); } + iterator child_end() { return iterator(Deps.end(), &DepGetVal); } + + virtual void print(raw_ostream &OS) const { OS << "AADepNode Impl\n"; } + TinyPtrVector<DepTy> &getDeps() { return Deps; } + + friend struct Attributor; + friend struct AADepGraph; +}; + +/// The data structure for the dependency graph +/// +/// Note that in this graph if there is an edge from A to B (A -> B), +/// then it means that B depends on A, and when the state of A is +/// updated, node B should also be updated +struct AADepGraph { + AADepGraph() {} + ~AADepGraph() {} + + using DepTy = AADepGraphNode::DepTy; + static AADepGraphNode *DepGetVal(DepTy &DT) { return DT.getPointer(); } + using iterator = + mapped_iterator<TinyPtrVector<DepTy>::iterator, decltype(&DepGetVal)>; + + /// There is no root node for the dependency graph. But the SCCIterator + /// requires a single entry point, so we maintain a fake("synthetic") root + /// node that depends on every node. + AADepGraphNode SyntheticRoot; + AADepGraphNode *GetEntryNode() { return &SyntheticRoot; } + + iterator begin() { return SyntheticRoot.child_begin(); } + iterator end() { return SyntheticRoot.child_end(); } + + void viewGraph(); + + /// Dump graph to file + void dumpGraph(); + + /// Print dependency graph + void print(); +}; + /// Helper to describe and deal with positions in the LLVM-IR. /// /// A position in the IR is described by an anchor value and an "offset" that @@ -344,14 +344,14 @@ struct IRPosition { /// Return the associated function, if any. Function *getAssociatedFunction() const { - if (auto *CB = dyn_cast<CallBase>(&getAnchorValue())) { - // We reuse the logic that associates callback calles to arguments of a - // call site here to identify the callback callee as the associated - // function. - if (Argument *Arg = getAssociatedArgument()) - return Arg->getParent(); + if (auto *CB = dyn_cast<CallBase>(&getAnchorValue())) { + // We reuse the logic that associates callback calles to arguments of a + // call site here to identify the callback callee as the associated + // function. + if (Argument *Arg = getAssociatedArgument()) + return Arg->getParent(); return CB->getCalledFunction(); - } + } return getAnchorScope(); } @@ -399,11 +399,11 @@ struct IRPosition { /// Return the value this abstract attribute is associated with. Value &getAssociatedValue() const { - if (getCallSiteArgNo() < 0 || isa<Argument>(&getAnchorValue())) + if (getCallSiteArgNo() < 0 || isa<Argument>(&getAnchorValue())) return getAnchorValue(); assert(isa<CallBase>(&getAnchorValue()) && "Expected a call base!"); - return *cast<CallBase>(&getAnchorValue()) - ->getArgOperand(getCallSiteArgNo()); + return *cast<CallBase>(&getAnchorValue()) + ->getArgOperand(getCallSiteArgNo()); } /// Return the type this abstract attribute is associated with. @@ -413,24 +413,24 @@ struct IRPosition { return getAssociatedValue().getType(); } - /// Return the callee argument number of the associated value if it is an - /// argument or call site argument, otherwise a negative value. In contrast to - /// `getCallSiteArgNo` this method will always return the "argument number" - /// from the perspective of the callee. This may not the same as the call site - /// if this is a callback call. - int getCalleeArgNo() const { - return getArgNo(/* CallbackCalleeArgIfApplicable */ true); - } - - /// Return the call site argument number of the associated value if it is an - /// argument or call site argument, otherwise a negative value. In contrast to - /// `getCalleArgNo` this method will always return the "operand number" from - /// the perspective of the call site. This may not the same as the callee - /// perspective if this is a callback call. - int getCallSiteArgNo() const { - return getArgNo(/* CallbackCalleeArgIfApplicable */ false); - } - + /// Return the callee argument number of the associated value if it is an + /// argument or call site argument, otherwise a negative value. In contrast to + /// `getCallSiteArgNo` this method will always return the "argument number" + /// from the perspective of the callee. This may not the same as the call site + /// if this is a callback call. + int getCalleeArgNo() const { + return getArgNo(/* CallbackCalleeArgIfApplicable */ true); + } + + /// Return the call site argument number of the associated value if it is an + /// argument or call site argument, otherwise a negative value. In contrast to + /// `getCalleArgNo` this method will always return the "operand number" from + /// the perspective of the call site. This may not the same as the callee + /// perspective if this is a callback call. + int getCallSiteArgNo() const { + return getArgNo(/* CallbackCalleeArgIfApplicable */ false); + } + /// Return the index in the attribute list for this position. unsigned getAttrIdx() const { switch (getPositionKind()) { @@ -445,7 +445,7 @@ struct IRPosition { return AttributeList::ReturnIndex; case IRPosition::IRP_ARGUMENT: case IRPosition::IRP_CALL_SITE_ARGUMENT: - return getCallSiteArgNo() + AttributeList::FirstArgIndex; + return getCallSiteArgNo() + AttributeList::FirstArgIndex; } llvm_unreachable( "There is no attribute index for a floating or invalid position!"); @@ -530,17 +530,17 @@ struct IRPosition { } } - /// Return true if the position is an argument or call site argument. - bool isArgumentPosition() const { - switch (getPositionKind()) { - case IRPosition::IRP_ARGUMENT: - case IRPosition::IRP_CALL_SITE_ARGUMENT: - return true; - default: - return false; - } - } - + /// Return true if the position is an argument or call site argument. + bool isArgumentPosition() const { + switch (getPositionKind()) { + case IRPosition::IRP_ARGUMENT: + case IRPosition::IRP_CALL_SITE_ARGUMENT: + return true; + default: + return false; + } + } + /// Special DenseMap key values. /// ///{ @@ -587,25 +587,25 @@ private: verify(); } - /// Return the callee argument number of the associated value if it is an - /// argument or call site argument. See also `getCalleeArgNo` and - /// `getCallSiteArgNo`. - int getArgNo(bool CallbackCalleeArgIfApplicable) const { - if (CallbackCalleeArgIfApplicable) - if (Argument *Arg = getAssociatedArgument()) - return Arg->getArgNo(); - switch (getPositionKind()) { - case IRPosition::IRP_ARGUMENT: - return cast<Argument>(getAsValuePtr())->getArgNo(); - case IRPosition::IRP_CALL_SITE_ARGUMENT: { - Use &U = *getAsUsePtr(); - return cast<CallBase>(U.getUser())->getArgOperandNo(&U); - } - default: - return -1; - } - } - + /// Return the callee argument number of the associated value if it is an + /// argument or call site argument. See also `getCalleeArgNo` and + /// `getCallSiteArgNo`. + int getArgNo(bool CallbackCalleeArgIfApplicable) const { + if (CallbackCalleeArgIfApplicable) + if (Argument *Arg = getAssociatedArgument()) + return Arg->getArgNo(); + switch (getPositionKind()) { + case IRPosition::IRP_ARGUMENT: + return cast<Argument>(getAsValuePtr())->getArgNo(); + case IRPosition::IRP_CALL_SITE_ARGUMENT: { + Use &U = *getAsUsePtr(); + return cast<CallBase>(U.getUser())->getArgOperandNo(&U); + } + default: + return -1; + } + } + /// IRPosition for the use \p U. The position kind \p PK needs to be /// IRP_CALL_SITE_ARGUMENT, the anchor value is the user, the associated value /// the used value. @@ -769,10 +769,10 @@ struct InformationCache { [&](const Function &F) { return AG.getAnalysis<PostDominatorTreeAnalysis>(F); }), - AG(AG), CGSCC(CGSCC) { - if (CGSCC) - initializeModuleSlice(*CGSCC); - } + AG(AG), CGSCC(CGSCC) { + if (CGSCC) + initializeModuleSlice(*CGSCC); + } ~InformationCache() { // The FunctionInfo objects are allocated via a BumpPtrAllocator, we call @@ -781,68 +781,68 @@ struct InformationCache { It.getSecond()->~FunctionInfo(); } - /// Apply \p CB to all uses of \p F. If \p LookThroughConstantExprUses is - /// true, constant expression users are not given to \p CB but their uses are - /// traversed transitively. - template <typename CBTy> - static void foreachUse(Function &F, CBTy CB, - bool LookThroughConstantExprUses = true) { - SmallVector<Use *, 8> Worklist(make_pointer_range(F.uses())); - - for (unsigned Idx = 0; Idx < Worklist.size(); ++Idx) { - Use &U = *Worklist[Idx]; - - // Allow use in constant bitcasts and simply look through them. - if (LookThroughConstantExprUses && isa<ConstantExpr>(U.getUser())) { - for (Use &CEU : cast<ConstantExpr>(U.getUser())->uses()) - Worklist.push_back(&CEU); - continue; - } - - CB(U); - } - } - - /// Initialize the ModuleSlice member based on \p SCC. ModuleSlices contains - /// (a subset of) all functions that we can look at during this SCC traversal. - /// This includes functions (transitively) called from the SCC and the - /// (transitive) callers of SCC functions. We also can look at a function if - /// there is a "reference edge", i.a., if the function somehow uses (!=calls) - /// a function in the SCC or a caller of a function in the SCC. - void initializeModuleSlice(SetVector<Function *> &SCC) { - ModuleSlice.insert(SCC.begin(), SCC.end()); - - SmallPtrSet<Function *, 16> Seen; - SmallVector<Function *, 16> Worklist(SCC.begin(), SCC.end()); - while (!Worklist.empty()) { - Function *F = Worklist.pop_back_val(); - ModuleSlice.insert(F); - - for (Instruction &I : instructions(*F)) - if (auto *CB = dyn_cast<CallBase>(&I)) - if (Function *Callee = CB->getCalledFunction()) - if (Seen.insert(Callee).second) - Worklist.push_back(Callee); - } - - Seen.clear(); - Worklist.append(SCC.begin(), SCC.end()); - while (!Worklist.empty()) { - Function *F = Worklist.pop_back_val(); - ModuleSlice.insert(F); - - // Traverse all transitive uses. - foreachUse(*F, [&](Use &U) { - if (auto *UsrI = dyn_cast<Instruction>(U.getUser())) - if (Seen.insert(UsrI->getFunction()).second) - Worklist.push_back(UsrI->getFunction()); - }); - } - } - - /// The slice of the module we are allowed to look at. - SmallPtrSet<Function *, 8> ModuleSlice; - + /// Apply \p CB to all uses of \p F. If \p LookThroughConstantExprUses is + /// true, constant expression users are not given to \p CB but their uses are + /// traversed transitively. + template <typename CBTy> + static void foreachUse(Function &F, CBTy CB, + bool LookThroughConstantExprUses = true) { + SmallVector<Use *, 8> Worklist(make_pointer_range(F.uses())); + + for (unsigned Idx = 0; Idx < Worklist.size(); ++Idx) { + Use &U = *Worklist[Idx]; + + // Allow use in constant bitcasts and simply look through them. + if (LookThroughConstantExprUses && isa<ConstantExpr>(U.getUser())) { + for (Use &CEU : cast<ConstantExpr>(U.getUser())->uses()) + Worklist.push_back(&CEU); + continue; + } + + CB(U); + } + } + + /// Initialize the ModuleSlice member based on \p SCC. ModuleSlices contains + /// (a subset of) all functions that we can look at during this SCC traversal. + /// This includes functions (transitively) called from the SCC and the + /// (transitive) callers of SCC functions. We also can look at a function if + /// there is a "reference edge", i.a., if the function somehow uses (!=calls) + /// a function in the SCC or a caller of a function in the SCC. + void initializeModuleSlice(SetVector<Function *> &SCC) { + ModuleSlice.insert(SCC.begin(), SCC.end()); + + SmallPtrSet<Function *, 16> Seen; + SmallVector<Function *, 16> Worklist(SCC.begin(), SCC.end()); + while (!Worklist.empty()) { + Function *F = Worklist.pop_back_val(); + ModuleSlice.insert(F); + + for (Instruction &I : instructions(*F)) + if (auto *CB = dyn_cast<CallBase>(&I)) + if (Function *Callee = CB->getCalledFunction()) + if (Seen.insert(Callee).second) + Worklist.push_back(Callee); + } + + Seen.clear(); + Worklist.append(SCC.begin(), SCC.end()); + while (!Worklist.empty()) { + Function *F = Worklist.pop_back_val(); + ModuleSlice.insert(F); + + // Traverse all transitive uses. + foreachUse(*F, [&](Use &U) { + if (auto *UsrI = dyn_cast<Instruction>(U.getUser())) + if (Seen.insert(UsrI->getFunction()).second) + Worklist.push_back(UsrI->getFunction()); + }); + } + } + + /// The slice of the module we are allowed to look at. + SmallPtrSet<Function *, 8> ModuleSlice; + /// A vector type to hold instructions. using InstructionVectorTy = SmallVector<Instruction *, 8>; @@ -871,7 +871,7 @@ struct InformationCache { } /// Return AliasAnalysis Result for function \p F. - AAResults *getAAResultsForFunction(const Function &F); + AAResults *getAAResultsForFunction(const Function &F); /// Return true if \p Arg is involved in a must-tail call, thus the argument /// of the caller or callee. @@ -899,26 +899,26 @@ struct InformationCache { /// Return the map conaining all the knowledge we have from `llvm.assume`s. const RetainedKnowledgeMap &getKnowledgeMap() const { return KnowledgeMap; } - /// Return if \p To is potentially reachable form \p From or not - /// If the same query was answered, return cached result - bool getPotentiallyReachable(const Instruction &From, const Instruction &To) { - auto KeyPair = std::make_pair(&From, &To); - auto Iter = PotentiallyReachableMap.find(KeyPair); - if (Iter != PotentiallyReachableMap.end()) - return Iter->second; - const Function &F = *From.getFunction(); - bool Result = isPotentiallyReachable( - &From, &To, nullptr, AG.getAnalysis<DominatorTreeAnalysis>(F), - AG.getAnalysis<LoopAnalysis>(F)); - PotentiallyReachableMap.insert(std::make_pair(KeyPair, Result)); - return Result; - } - - /// Check whether \p F is part of module slice. - bool isInModuleSlice(const Function &F) { - return ModuleSlice.count(const_cast<Function *>(&F)); - } - + /// Return if \p To is potentially reachable form \p From or not + /// If the same query was answered, return cached result + bool getPotentiallyReachable(const Instruction &From, const Instruction &To) { + auto KeyPair = std::make_pair(&From, &To); + auto Iter = PotentiallyReachableMap.find(KeyPair); + if (Iter != PotentiallyReachableMap.end()) + return Iter->second; + const Function &F = *From.getFunction(); + bool Result = isPotentiallyReachable( + &From, &To, nullptr, AG.getAnalysis<DominatorTreeAnalysis>(F), + AG.getAnalysis<LoopAnalysis>(F)); + PotentiallyReachableMap.insert(std::make_pair(KeyPair, Result)); + return Result; + } + + /// Check whether \p F is part of module slice. + bool isInModuleSlice(const Function &F) { + return ModuleSlice.count(const_cast<Function *>(&F)); + } + private: struct FunctionInfo { ~FunctionInfo(); @@ -978,10 +978,10 @@ private: /// Set of inlineable functions SmallPtrSet<const Function *, 8> InlineableFunctions; - /// A map for caching results of queries for isPotentiallyReachable - DenseMap<std::pair<const Instruction *, const Instruction *>, bool> - PotentiallyReachableMap; - + /// A map for caching results of queries for isPotentiallyReachable + DenseMap<std::pair<const Instruction *, const Instruction *>, bool> + PotentiallyReachableMap; + /// Give the Attributor access to the members so /// Attributor::identifyDefaultAbstractAttributes(...) can initialize them. friend struct Attributor; @@ -1084,7 +1084,7 @@ struct Attributor { /// attribute. Using this after Attributor started running is restricted to /// only the Attributor itself. Initial seeding of AAs can be done via this /// function. - /// NOTE: ForceUpdate is ignored in any stage other than the update stage. + /// NOTE: ForceUpdate is ignored in any stage other than the update stage. template <typename AAType> const AAType &getOrCreateAAFor(const IRPosition &IRP, const AbstractAttribute *QueryingAA = nullptr, @@ -1092,7 +1092,7 @@ struct Attributor { DepClassTy DepClass = DepClassTy::OPTIONAL, bool ForceUpdate = false) { if (AAType *AAPtr = lookupAAFor<AAType>(IRP, QueryingAA, TrackDependence)) { - if (ForceUpdate && Phase == AttributorPhase::UPDATE) + if (ForceUpdate && Phase == AttributorPhase::UPDATE) updateAA(*AAPtr); return *AAPtr; } @@ -1102,7 +1102,7 @@ struct Attributor { auto &AA = AAType::createForPosition(IRP, *this); // If we are currenty seeding attributes, enforce seeding rules. - if (Phase == AttributorPhase::SEEDING && !shouldSeedAttribute(AA)) { + if (Phase == AttributorPhase::SEEDING && !shouldSeedAttribute(AA)) { AA.getState().indicatePessimisticFixpoint(); return AA; } @@ -1116,9 +1116,9 @@ struct Attributor { Invalidate |= FnScope->hasFnAttribute(Attribute::Naked) || FnScope->hasFnAttribute(Attribute::OptimizeNone); - // Avoid too many nested initializations to prevent a stack overflow. - Invalidate |= InitializationChainLength > MaxInitializationChainLength; - + // Avoid too many nested initializations to prevent a stack overflow. + Invalidate |= InitializationChainLength > MaxInitializationChainLength; + // Bootstrap the new attribute with an initial update to propagate // information, e.g., function -> call site. If it is not on a given // Allowed we will not perform updates at all. @@ -1127,39 +1127,39 @@ struct Attributor { return AA; } - { - TimeTraceScope TimeScope(AA.getName() + "::initialize"); - ++InitializationChainLength; - AA.initialize(*this); - --InitializationChainLength; - } - - // Initialize and update is allowed for code outside of the current function - // set, but only if it is part of module slice we are allowed to look at. - // Only exception is AAIsDeadFunction whose initialization is prevented - // directly, since we don't to compute it twice. + { + TimeTraceScope TimeScope(AA.getName() + "::initialize"); + ++InitializationChainLength; + AA.initialize(*this); + --InitializationChainLength; + } + + // Initialize and update is allowed for code outside of the current function + // set, but only if it is part of module slice we are allowed to look at. + // Only exception is AAIsDeadFunction whose initialization is prevented + // directly, since we don't to compute it twice. if (FnScope && !Functions.count(const_cast<Function *>(FnScope))) { - if (!getInfoCache().isInModuleSlice(*FnScope)) { - AA.getState().indicatePessimisticFixpoint(); - return AA; - } - } - - // If this is queried in the manifest stage, we force the AA to indicate - // pessimistic fixpoint immediately. - if (Phase == AttributorPhase::MANIFEST) { + if (!getInfoCache().isInModuleSlice(*FnScope)) { + AA.getState().indicatePessimisticFixpoint(); + return AA; + } + } + + // If this is queried in the manifest stage, we force the AA to indicate + // pessimistic fixpoint immediately. + if (Phase == AttributorPhase::MANIFEST) { AA.getState().indicatePessimisticFixpoint(); return AA; } // Allow seeded attributes to declare dependencies. // Remember the seeding state. - AttributorPhase OldPhase = Phase; - Phase = AttributorPhase::UPDATE; + AttributorPhase OldPhase = Phase; + Phase = AttributorPhase::UPDATE; updateAA(AA); - Phase = OldPhase; + Phase = OldPhase; if (TrackDependence && AA.getState().isValidState()) recordDependence(AA, const_cast<AbstractAttribute &>(*QueryingAA), @@ -1228,11 +1228,11 @@ struct Attributor { assert(!AAPtr && "Attribute already in map!"); AAPtr = &AA; - // Register AA with the synthetic root only before the manifest stage. - if (Phase == AttributorPhase::SEEDING || Phase == AttributorPhase::UPDATE) - DG.SyntheticRoot.Deps.push_back( - AADepGraphNode::DepTy(&AA, unsigned(DepClassTy::REQUIRED))); - + // Register AA with the synthetic root only before the manifest stage. + if (Phase == AttributorPhase::SEEDING || Phase == AttributorPhase::UPDATE) + DG.SyntheticRoot.Deps.push_back( + AADepGraphNode::DepTy(&AA, unsigned(DepClassTy::REQUIRED))); + return AA; } @@ -1541,22 +1541,22 @@ struct Attributor { bool checkForAllReadWriteInstructions(function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA); - /// Create a shallow wrapper for \p F such that \p F has internal linkage - /// afterwards. It also sets the original \p F 's name to anonymous - /// - /// A wrapper is a function with the same type (and attributes) as \p F - /// that will only call \p F and return the result, if any. - /// - /// Assuming the declaration of looks like: - /// rty F(aty0 arg0, ..., atyN argN); - /// - /// The wrapper will then look as follows: - /// rty wrapper(aty0 arg0, ..., atyN argN) { - /// return F(arg0, ..., argN); - /// } - /// - static void createShallowWrapper(Function &F); - + /// Create a shallow wrapper for \p F such that \p F has internal linkage + /// afterwards. It also sets the original \p F 's name to anonymous + /// + /// A wrapper is a function with the same type (and attributes) as \p F + /// that will only call \p F and return the result, if any. + /// + /// Assuming the declaration of looks like: + /// rty F(aty0 arg0, ..., atyN argN); + /// + /// The wrapper will then look as follows: + /// rty wrapper(aty0 arg0, ..., atyN argN) { + /// return F(arg0, ..., argN); + /// } + /// + static void createShallowWrapper(Function &F); + /// Return the data layout associated with the anchor scope. const DataLayout &getDataLayout() const { return InfoCache.DL; } @@ -1580,10 +1580,10 @@ private: /// Rewrites function signitures and updates the call graph. ChangeStatus cleanupIR(); - /// Identify internal functions that are effectively dead, thus not reachable - /// from a live entry point. The functions are added to ToBeDeletedFunctions. - void identifyDeadInternalFunctions(); - + /// Identify internal functions that are effectively dead, thus not reachable + /// from a live entry point. The functions are added to ToBeDeletedFunctions. + void identifyDeadInternalFunctions(); + /// Run `::update` on \p AA and track the dependences queried while doing so. /// Also adjust the state if we know further updates are not necessary. ChangeStatus updateAA(AbstractAttribute &AA); @@ -1635,9 +1635,9 @@ private: /// Helper to update an underlying call graph. CallGraphUpdater &CGUpdater; - /// Abstract Attribute dependency graph - AADepGraph DG; - + /// Abstract Attribute dependency graph + AADepGraph DG; + /// Set of functions for which we modified the content such that it might /// impact the call graph. SmallPtrSet<Function *, 8> CGModifiedFunctions; @@ -1676,18 +1676,18 @@ private: /// Invoke instructions with at least a single dead successor block. SmallVector<WeakVH, 16> InvokeWithDeadSuccessor; - /// A flag that indicates which stage of the process we are in. Initially, the - /// phase is SEEDING. Phase is changed in `Attributor::run()` - enum class AttributorPhase { - SEEDING, - UPDATE, - MANIFEST, - CLEANUP, - } Phase = AttributorPhase::SEEDING; - - /// The current initialization chain length. Tracked to avoid stack overflows. - unsigned InitializationChainLength = 0; - + /// A flag that indicates which stage of the process we are in. Initially, the + /// phase is SEEDING. Phase is changed in `Attributor::run()` + enum class AttributorPhase { + SEEDING, + UPDATE, + MANIFEST, + CLEANUP, + } Phase = AttributorPhase::SEEDING; + + /// The current initialization chain length. Tracked to avoid stack overflows. + unsigned InitializationChainLength = 0; + /// Functions, blocks, and instructions we delete after manifest is done. /// ///{ @@ -1695,8 +1695,8 @@ private: SmallPtrSet<BasicBlock *, 8> ToBeDeletedBlocks; SmallDenseSet<WeakVH, 8> ToBeDeletedInsts; ///} - - friend AADepGraph; + + friend AADepGraph; }; /// An interface to query the internal state of an abstract attribute. @@ -2175,7 +2175,7 @@ struct StateWrapper : public BaseType, public StateTy { StateType &getState() override { return *this; } /// See AbstractAttribute::getState(...). - const StateType &getState() const override { return *this; } + const StateType &getState() const override { return *this; } }; /// Helper class that provides common functionality to manifest IR attributes. @@ -2269,7 +2269,7 @@ struct IRAttribute : public BaseType { /// both directions will be added in the future. /// NOTE: The mechanics of adding a new "concrete" abstract attribute are /// described in the file comment. -struct AbstractAttribute : public IRPosition, public AADepGraphNode { +struct AbstractAttribute : public IRPosition, public AADepGraphNode { using StateType = AbstractState; AbstractAttribute(const IRPosition &IRP) : IRPosition(IRP) {} @@ -2277,14 +2277,14 @@ struct AbstractAttribute : public IRPosition, public AADepGraphNode { /// Virtual destructor. virtual ~AbstractAttribute() {} - /// This function is used to identify if an \p DGN is of type - /// AbstractAttribute so that the dyn_cast and cast can use such information - /// to cast an AADepGraphNode to an AbstractAttribute. - /// - /// We eagerly return true here because all AADepGraphNodes except for the - /// Synthethis Node are of type AbstractAttribute - static bool classof(const AADepGraphNode *DGN) { return true; } - + /// This function is used to identify if an \p DGN is of type + /// AbstractAttribute so that the dyn_cast and cast can use such information + /// to cast an AADepGraphNode to an AbstractAttribute. + /// + /// We eagerly return true here because all AADepGraphNodes except for the + /// Synthethis Node are of type AbstractAttribute + static bool classof(const AADepGraphNode *DGN) { return true; } + /// Initialize the state with the information in the Attributor \p A. /// /// This function is called by the Attributor once all abstract attributes @@ -2305,8 +2305,8 @@ struct AbstractAttribute : public IRPosition, public AADepGraphNode { /// Helper functions, for debug purposes only. ///{ - void print(raw_ostream &OS) const override; - virtual void printWithDeps(raw_ostream &OS) const; + void print(raw_ostream &OS) const override; + virtual void printWithDeps(raw_ostream &OS) const; void dump() const { print(dbgs()); } /// This function should return the "summarized" assumed state as string. @@ -2635,17 +2635,17 @@ struct AAReachability : public StateWrapper<BooleanState, AbstractAttribute> { /// Returns true if 'From' instruction is assumed to reach, 'To' instruction. /// Users should provide two positions they are interested in, and the class /// determines (and caches) reachability. - bool isAssumedReachable(Attributor &A, const Instruction &From, - const Instruction &To) const { - return A.getInfoCache().getPotentiallyReachable(From, To); + bool isAssumedReachable(Attributor &A, const Instruction &From, + const Instruction &To) const { + return A.getInfoCache().getPotentiallyReachable(From, To); } /// Returns true if 'From' instruction is known to reach, 'To' instruction. /// Users should provide two positions they are interested in, and the class /// determines (and caches) reachability. - bool isKnownReachable(Attributor &A, const Instruction &From, - const Instruction &To) const { - return A.getInfoCache().getPotentiallyReachable(From, To); + bool isKnownReachable(Attributor &A, const Instruction &From, + const Instruction &To) const { + return A.getInfoCache().getPotentiallyReachable(From, To); } /// Create an abstract attribute view for the position \p IRP. @@ -2808,12 +2808,12 @@ public: return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F); } - /// Return if the edge from \p From BB to \p To BB is assumed dead. - /// This is specifically useful in AAReachability. - virtual bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const { - return false; - } - + /// Return if the edge from \p From BB to \p To BB is assumed dead. + /// This is specifically useful in AAReachability. + virtual bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const { + return false; + } + /// See AbstractAttribute::getName() const std::string getName() const override { return "AAIsDead"; } @@ -3470,7 +3470,7 @@ struct AAValueConstantRange /// See AbstractAttribute::getState(...). IntegerRangeState &getState() override { return *this; } - const IntegerRangeState &getState() const override { return *this; } + const IntegerRangeState &getState() const override { return *this; } /// Create an abstract attribute view for the position \p IRP. static AAValueConstantRange &createForPosition(const IRPosition &IRP, @@ -3518,279 +3518,279 @@ struct AAValueConstantRange static const char ID; }; -/// A class for a set state. -/// The assumed boolean state indicates whether the corresponding set is full -/// set or not. If the assumed state is false, this is the worst state. The -/// worst state (invalid state) of set of potential values is when the set -/// contains every possible value (i.e. we cannot in any way limit the value -/// that the target position can take). That never happens naturally, we only -/// force it. As for the conditions under which we force it, see -/// AAPotentialValues. -template <typename MemberTy, typename KeyInfo = DenseMapInfo<MemberTy>> -struct PotentialValuesState : AbstractState { - using SetTy = DenseSet<MemberTy, KeyInfo>; - - PotentialValuesState() : IsValidState(true), UndefIsContained(false) {} - - PotentialValuesState(bool IsValid) - : IsValidState(IsValid), UndefIsContained(false) {} - - /// See AbstractState::isValidState(...) - bool isValidState() const override { return IsValidState.isValidState(); } - - /// See AbstractState::isAtFixpoint(...) - bool isAtFixpoint() const override { return IsValidState.isAtFixpoint(); } - - /// See AbstractState::indicatePessimisticFixpoint(...) - ChangeStatus indicatePessimisticFixpoint() override { - return IsValidState.indicatePessimisticFixpoint(); - } - - /// See AbstractState::indicateOptimisticFixpoint(...) - ChangeStatus indicateOptimisticFixpoint() override { - return IsValidState.indicateOptimisticFixpoint(); - } - - /// Return the assumed state - PotentialValuesState &getAssumed() { return *this; } - const PotentialValuesState &getAssumed() const { return *this; } - - /// Return this set. We should check whether this set is valid or not by - /// isValidState() before calling this function. - const SetTy &getAssumedSet() const { - assert(isValidState() && "This set shoud not be used when it is invalid!"); - return Set; - } - - /// Returns whether this state contains an undef value or not. - bool undefIsContained() const { - assert(isValidState() && "This flag shoud not be used when it is invalid!"); - return UndefIsContained; - } - - bool operator==(const PotentialValuesState &RHS) const { - if (isValidState() != RHS.isValidState()) - return false; - if (!isValidState() && !RHS.isValidState()) - return true; - if (undefIsContained() != RHS.undefIsContained()) - return false; - return Set == RHS.getAssumedSet(); - } - - /// Maximum number of potential values to be tracked. - /// This is set by -attributor-max-potential-values command line option - static unsigned MaxPotentialValues; - - /// Return empty set as the best state of potential values. - static PotentialValuesState getBestState() { - return PotentialValuesState(true); - } - - static PotentialValuesState getBestState(PotentialValuesState &PVS) { - return getBestState(); - } - - /// Return full set as the worst state of potential values. - static PotentialValuesState getWorstState() { - return PotentialValuesState(false); - } - - /// Union assumed set with the passed value. - void unionAssumed(const MemberTy &C) { insert(C); } - - /// Union assumed set with assumed set of the passed state \p PVS. - void unionAssumed(const PotentialValuesState &PVS) { unionWith(PVS); } - - /// Union assumed set with an undef value. - void unionAssumedWithUndef() { unionWithUndef(); } - - /// "Clamp" this state with \p PVS. - PotentialValuesState operator^=(const PotentialValuesState &PVS) { - IsValidState ^= PVS.IsValidState; - unionAssumed(PVS); - return *this; - } - - PotentialValuesState operator&=(const PotentialValuesState &PVS) { - IsValidState &= PVS.IsValidState; - unionAssumed(PVS); - return *this; - } - -private: - /// Check the size of this set, and invalidate when the size is no - /// less than \p MaxPotentialValues threshold. - void checkAndInvalidate() { - if (Set.size() >= MaxPotentialValues) - indicatePessimisticFixpoint(); - } - - /// If this state contains both undef and not undef, we can reduce - /// undef to the not undef value. - void reduceUndefValue() { UndefIsContained = UndefIsContained & Set.empty(); } - - /// Insert an element into this set. - void insert(const MemberTy &C) { - if (!isValidState()) - return; - Set.insert(C); - checkAndInvalidate(); - } - - /// Take union with R. - void unionWith(const PotentialValuesState &R) { - /// If this is a full set, do nothing.; - if (!isValidState()) - return; - /// If R is full set, change L to a full set. - if (!R.isValidState()) { - indicatePessimisticFixpoint(); - return; - } - for (const MemberTy &C : R.Set) - Set.insert(C); - UndefIsContained |= R.undefIsContained(); - reduceUndefValue(); - checkAndInvalidate(); - } - - /// Take union with an undef value. - void unionWithUndef() { - UndefIsContained = true; - reduceUndefValue(); - } - - /// Take intersection with R. - void intersectWith(const PotentialValuesState &R) { - /// If R is a full set, do nothing. - if (!R.isValidState()) - return; - /// If this is a full set, change this to R. - if (!isValidState()) { - *this = R; - return; - } - SetTy IntersectSet; - for (const MemberTy &C : Set) { - if (R.Set.count(C)) - IntersectSet.insert(C); - } - Set = IntersectSet; - UndefIsContained &= R.undefIsContained(); - reduceUndefValue(); - } - - /// A helper state which indicate whether this state is valid or not. - BooleanState IsValidState; - - /// Container for potential values - SetTy Set; - - /// Flag for undef value - bool UndefIsContained; -}; - -using PotentialConstantIntValuesState = PotentialValuesState<APInt>; - -raw_ostream &operator<<(raw_ostream &OS, - const PotentialConstantIntValuesState &R); - -/// An abstract interface for potential values analysis. -/// -/// This AA collects potential values for each IR position. -/// An assumed set of potential values is initialized with the empty set (the -/// best state) and it will grow monotonically as we find more potential values -/// for this position. -/// The set might be forced to the worst state, that is, to contain every -/// possible value for this position in 2 cases. -/// 1. We surpassed the \p MaxPotentialValues threshold. This includes the -/// case that this position is affected (e.g. because of an operation) by a -/// Value that is in the worst state. -/// 2. We tried to initialize on a Value that we cannot handle (e.g. an -/// operator we do not currently handle). -/// -/// TODO: Support values other than constant integers. -struct AAPotentialValues - : public StateWrapper<PotentialConstantIntValuesState, AbstractAttribute> { - using Base = StateWrapper<PotentialConstantIntValuesState, AbstractAttribute>; - AAPotentialValues(const IRPosition &IRP, Attributor &A) : Base(IRP) {} - - /// See AbstractAttribute::getState(...). - PotentialConstantIntValuesState &getState() override { return *this; } - const PotentialConstantIntValuesState &getState() const override { - return *this; - } - - /// Create an abstract attribute view for the position \p IRP. - static AAPotentialValues &createForPosition(const IRPosition &IRP, - Attributor &A); - - /// Return assumed constant for the associated value - Optional<ConstantInt *> - getAssumedConstantInt(Attributor &A, - const Instruction *CtxI = nullptr) const { - if (!isValidState()) - return nullptr; - if (getAssumedSet().size() == 1) - return cast<ConstantInt>(ConstantInt::get(getAssociatedValue().getType(), - *(getAssumedSet().begin()))); - if (getAssumedSet().size() == 0) { - if (undefIsContained()) - return cast<ConstantInt>( - ConstantInt::get(getAssociatedValue().getType(), 0)); - return llvm::None; - } - - return nullptr; - } - - /// See AbstractAttribute::getName() - const std::string getName() const override { return "AAPotentialValues"; } - - /// See AbstractAttribute::getIdAddr() - const char *getIdAddr() const override { return &ID; } - - /// This function should return true if the type of the \p AA is - /// AAPotentialValues - static bool classof(const AbstractAttribute *AA) { - return (AA->getIdAddr() == &ID); - } - - /// Unique ID (due to the unique address) - static const char ID; -}; - -/// An abstract interface for all noundef attributes. -struct AANoUndef - : public IRAttribute<Attribute::NoUndef, - StateWrapper<BooleanState, AbstractAttribute>> { - AANoUndef(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {} - - /// Return true if we assume that the underlying value is noundef. - bool isAssumedNoUndef() const { return getAssumed(); } - - /// Return true if we know that underlying value is noundef. - bool isKnownNoUndef() const { return getKnown(); } - - /// Create an abstract attribute view for the position \p IRP. - static AANoUndef &createForPosition(const IRPosition &IRP, Attributor &A); - - /// See AbstractAttribute::getName() - const std::string getName() const override { return "AANoUndef"; } - - /// See AbstractAttribute::getIdAddr() - const char *getIdAddr() const override { return &ID; } - - /// This function should return true if the type of the \p AA is AANoUndef - static bool classof(const AbstractAttribute *AA) { - return (AA->getIdAddr() == &ID); - } - - /// Unique ID (due to the unique address) - static const char ID; -}; - +/// A class for a set state. +/// The assumed boolean state indicates whether the corresponding set is full +/// set or not. If the assumed state is false, this is the worst state. The +/// worst state (invalid state) of set of potential values is when the set +/// contains every possible value (i.e. we cannot in any way limit the value +/// that the target position can take). That never happens naturally, we only +/// force it. As for the conditions under which we force it, see +/// AAPotentialValues. +template <typename MemberTy, typename KeyInfo = DenseMapInfo<MemberTy>> +struct PotentialValuesState : AbstractState { + using SetTy = DenseSet<MemberTy, KeyInfo>; + + PotentialValuesState() : IsValidState(true), UndefIsContained(false) {} + + PotentialValuesState(bool IsValid) + : IsValidState(IsValid), UndefIsContained(false) {} + + /// See AbstractState::isValidState(...) + bool isValidState() const override { return IsValidState.isValidState(); } + + /// See AbstractState::isAtFixpoint(...) + bool isAtFixpoint() const override { return IsValidState.isAtFixpoint(); } + + /// See AbstractState::indicatePessimisticFixpoint(...) + ChangeStatus indicatePessimisticFixpoint() override { + return IsValidState.indicatePessimisticFixpoint(); + } + + /// See AbstractState::indicateOptimisticFixpoint(...) + ChangeStatus indicateOptimisticFixpoint() override { + return IsValidState.indicateOptimisticFixpoint(); + } + + /// Return the assumed state + PotentialValuesState &getAssumed() { return *this; } + const PotentialValuesState &getAssumed() const { return *this; } + + /// Return this set. We should check whether this set is valid or not by + /// isValidState() before calling this function. + const SetTy &getAssumedSet() const { + assert(isValidState() && "This set shoud not be used when it is invalid!"); + return Set; + } + + /// Returns whether this state contains an undef value or not. + bool undefIsContained() const { + assert(isValidState() && "This flag shoud not be used when it is invalid!"); + return UndefIsContained; + } + + bool operator==(const PotentialValuesState &RHS) const { + if (isValidState() != RHS.isValidState()) + return false; + if (!isValidState() && !RHS.isValidState()) + return true; + if (undefIsContained() != RHS.undefIsContained()) + return false; + return Set == RHS.getAssumedSet(); + } + + /// Maximum number of potential values to be tracked. + /// This is set by -attributor-max-potential-values command line option + static unsigned MaxPotentialValues; + + /// Return empty set as the best state of potential values. + static PotentialValuesState getBestState() { + return PotentialValuesState(true); + } + + static PotentialValuesState getBestState(PotentialValuesState &PVS) { + return getBestState(); + } + + /// Return full set as the worst state of potential values. + static PotentialValuesState getWorstState() { + return PotentialValuesState(false); + } + + /// Union assumed set with the passed value. + void unionAssumed(const MemberTy &C) { insert(C); } + + /// Union assumed set with assumed set of the passed state \p PVS. + void unionAssumed(const PotentialValuesState &PVS) { unionWith(PVS); } + + /// Union assumed set with an undef value. + void unionAssumedWithUndef() { unionWithUndef(); } + + /// "Clamp" this state with \p PVS. + PotentialValuesState operator^=(const PotentialValuesState &PVS) { + IsValidState ^= PVS.IsValidState; + unionAssumed(PVS); + return *this; + } + + PotentialValuesState operator&=(const PotentialValuesState &PVS) { + IsValidState &= PVS.IsValidState; + unionAssumed(PVS); + return *this; + } + +private: + /// Check the size of this set, and invalidate when the size is no + /// less than \p MaxPotentialValues threshold. + void checkAndInvalidate() { + if (Set.size() >= MaxPotentialValues) + indicatePessimisticFixpoint(); + } + + /// If this state contains both undef and not undef, we can reduce + /// undef to the not undef value. + void reduceUndefValue() { UndefIsContained = UndefIsContained & Set.empty(); } + + /// Insert an element into this set. + void insert(const MemberTy &C) { + if (!isValidState()) + return; + Set.insert(C); + checkAndInvalidate(); + } + + /// Take union with R. + void unionWith(const PotentialValuesState &R) { + /// If this is a full set, do nothing.; + if (!isValidState()) + return; + /// If R is full set, change L to a full set. + if (!R.isValidState()) { + indicatePessimisticFixpoint(); + return; + } + for (const MemberTy &C : R.Set) + Set.insert(C); + UndefIsContained |= R.undefIsContained(); + reduceUndefValue(); + checkAndInvalidate(); + } + + /// Take union with an undef value. + void unionWithUndef() { + UndefIsContained = true; + reduceUndefValue(); + } + + /// Take intersection with R. + void intersectWith(const PotentialValuesState &R) { + /// If R is a full set, do nothing. + if (!R.isValidState()) + return; + /// If this is a full set, change this to R. + if (!isValidState()) { + *this = R; + return; + } + SetTy IntersectSet; + for (const MemberTy &C : Set) { + if (R.Set.count(C)) + IntersectSet.insert(C); + } + Set = IntersectSet; + UndefIsContained &= R.undefIsContained(); + reduceUndefValue(); + } + + /// A helper state which indicate whether this state is valid or not. + BooleanState IsValidState; + + /// Container for potential values + SetTy Set; + + /// Flag for undef value + bool UndefIsContained; +}; + +using PotentialConstantIntValuesState = PotentialValuesState<APInt>; + +raw_ostream &operator<<(raw_ostream &OS, + const PotentialConstantIntValuesState &R); + +/// An abstract interface for potential values analysis. +/// +/// This AA collects potential values for each IR position. +/// An assumed set of potential values is initialized with the empty set (the +/// best state) and it will grow monotonically as we find more potential values +/// for this position. +/// The set might be forced to the worst state, that is, to contain every +/// possible value for this position in 2 cases. +/// 1. We surpassed the \p MaxPotentialValues threshold. This includes the +/// case that this position is affected (e.g. because of an operation) by a +/// Value that is in the worst state. +/// 2. We tried to initialize on a Value that we cannot handle (e.g. an +/// operator we do not currently handle). +/// +/// TODO: Support values other than constant integers. +struct AAPotentialValues + : public StateWrapper<PotentialConstantIntValuesState, AbstractAttribute> { + using Base = StateWrapper<PotentialConstantIntValuesState, AbstractAttribute>; + AAPotentialValues(const IRPosition &IRP, Attributor &A) : Base(IRP) {} + + /// See AbstractAttribute::getState(...). + PotentialConstantIntValuesState &getState() override { return *this; } + const PotentialConstantIntValuesState &getState() const override { + return *this; + } + + /// Create an abstract attribute view for the position \p IRP. + static AAPotentialValues &createForPosition(const IRPosition &IRP, + Attributor &A); + + /// Return assumed constant for the associated value + Optional<ConstantInt *> + getAssumedConstantInt(Attributor &A, + const Instruction *CtxI = nullptr) const { + if (!isValidState()) + return nullptr; + if (getAssumedSet().size() == 1) + return cast<ConstantInt>(ConstantInt::get(getAssociatedValue().getType(), + *(getAssumedSet().begin()))); + if (getAssumedSet().size() == 0) { + if (undefIsContained()) + return cast<ConstantInt>( + ConstantInt::get(getAssociatedValue().getType(), 0)); + return llvm::None; + } + + return nullptr; + } + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AAPotentialValues"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is + /// AAPotentialValues + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + /// Unique ID (due to the unique address) + static const char ID; +}; + +/// An abstract interface for all noundef attributes. +struct AANoUndef + : public IRAttribute<Attribute::NoUndef, + StateWrapper<BooleanState, AbstractAttribute>> { + AANoUndef(const IRPosition &IRP, Attributor &A) : IRAttribute(IRP) {} + + /// Return true if we assume that the underlying value is noundef. + bool isAssumedNoUndef() const { return getAssumed(); } + + /// Return true if we know that underlying value is noundef. + bool isKnownNoUndef() const { return getKnown(); } + + /// Create an abstract attribute view for the position \p IRP. + static AANoUndef &createForPosition(const IRPosition &IRP, Attributor &A); + + /// See AbstractAttribute::getName() + const std::string getName() const override { return "AANoUndef"; } + + /// See AbstractAttribute::getIdAddr() + const char *getIdAddr() const override { return &ID; } + + /// This function should return true if the type of the \p AA is AANoUndef + static bool classof(const AbstractAttribute *AA) { + return (AA->getIdAddr() == &ID); + } + + /// Unique ID (due to the unique address) + static const char ID; +}; + /// Run options, used by the pass manager. enum AttributorRunOption { NONE = 0, diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/BlockExtractor.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/BlockExtractor.h index 10ac54d79d..937c1cbb39 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/BlockExtractor.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/BlockExtractor.h @@ -1,36 +1,36 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- BlockExtractor.h - Extracts blocks into their own functions --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This pass extracts the specified basic blocks from the module into their -// own functions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H -#define LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { -struct BlockExtractorPass : PassInfoMixin<BlockExtractorPass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; -} // namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- BlockExtractor.h - Extracts blocks into their own functions --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass extracts the specified basic blocks from the module into their +// own functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H +#define LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +struct BlockExtractorPass : PassInfoMixin<BlockExtractorPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; +} // namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_BLOCKEXTRACTOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/IROutliner.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/IROutliner.h index 0b90589079..bb1f1beb5a 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/IROutliner.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/IROutliner.h @@ -1,369 +1,369 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- IROutliner.h - Extract similar IR regions into functions ------------==// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// \file -// The interface file for the IROutliner which is used by the IROutliner Pass. -// -// The outliner uses the IRSimilarityIdentifier to identify the similar regions -// of code. It evaluates each set of IRSimilarityCandidates with an estimate of -// whether it will provide code size reduction. Each region is extracted using -// the code extractor. These extracted functions are consolidated into a single -// function and called from the extracted call site. -// -// For example: -// \code -// %1 = add i32 %a, %b -// %2 = add i32 %b, %a -// %3 = add i32 %b, %a -// %4 = add i32 %a, %b -// \endcode -// would become function -// \code -// define internal void outlined_ir_function(i32 %0, i32 %1) { -// %1 = add i32 %0, %1 -// %2 = add i32 %1, %0 -// ret void -// } -// \endcode -// with calls: -// \code -// call void outlined_ir_function(i32 %a, i32 %b) -// call void outlined_ir_function(i32 %b, i32 %a) -// \endcode -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H -#define LLVM_TRANSFORMS_IPO_IROUTLINER_H - -#include "llvm/Analysis/IRSimilarityIdentifier.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/ValueMap.h" -#include "llvm/Support/InstructionCost.h" -#include "llvm/Transforms/Utils/CodeExtractor.h" -#include <set> - -struct OutlinableGroup; - -namespace llvm { -using namespace IRSimilarity; - -class Module; -class TargetTransformInfo; -class OptimizationRemarkEmitter; - -/// The OutlinableRegion holds all the information for a specific region, or -/// sequence of instructions. This includes what values need to be hoisted to -/// arguments from the extracted function, inputs and outputs to the region, and -/// mapping from the extracted function arguments to overall function arguments. -struct OutlinableRegion { - /// Describes the region of code. - IRSimilarityCandidate *Candidate; - - /// If this region is outlined, the front and back IRInstructionData could - /// potentially become invalidated if the only new instruction is a call. - /// This ensures that we replace in the instruction in the IRInstructionData. - IRInstructionData *NewFront = nullptr; - IRInstructionData *NewBack = nullptr; - - /// The number of extracted inputs from the CodeExtractor. - unsigned NumExtractedInputs; - - /// The corresponding BasicBlock with the appropriate stores for this - /// OutlinableRegion in the overall function. - unsigned OutputBlockNum; - - /// Mapping the extracted argument number to the argument number in the - /// overall function. Since there will be inputs, such as elevated constants - /// that are not the same in each region in a SimilarityGroup, or values that - /// cannot be sunk into the extracted section in every region, we must keep - /// track of which extracted argument maps to which overall argument. - DenseMap<unsigned, unsigned> ExtractedArgToAgg; - DenseMap<unsigned, unsigned> AggArgToExtracted; - - /// Mapping of the argument number in the deduplicated function - /// to a given constant, which is used when creating the arguments to the call - /// to the newly created deduplicated function. This is handled separately - /// since the CodeExtractor does not recognize constants. - DenseMap<unsigned, Constant *> AggArgToConstant; - - /// The global value numbers that are used as outputs for this section. Once - /// extracted, each output will be stored to an output register. This - /// documents the global value numbers that are used in this pattern. - SmallVector<unsigned, 4> GVNStores; - - /// Used to create an outlined function. - CodeExtractor *CE = nullptr; - - /// The call site of the extracted region. - CallInst *Call = nullptr; - - /// The function for the extracted region. - Function *ExtractedFunction = nullptr; - - /// Flag for whether we have split out the IRSimilarityCanidate. That is, - /// make the region contained the IRSimilarityCandidate its own BasicBlock. - bool CandidateSplit = false; - - /// Flag for whether we should not consider this region for extraction. - bool IgnoreRegion = false; - - /// The BasicBlock that is before the start of the region BasicBlock, - /// only defined when the region has been split. - BasicBlock *PrevBB = nullptr; - - /// The BasicBlock that contains the starting instruction of the region. - BasicBlock *StartBB = nullptr; - - /// The BasicBlock that contains the ending instruction of the region. - BasicBlock *EndBB = nullptr; - - /// The BasicBlock that is after the start of the region BasicBlock, - /// only defined when the region has been split. - BasicBlock *FollowBB = nullptr; - - /// The Outlinable Group that contains this region and structurally similar - /// regions to this region. - OutlinableGroup *Parent = nullptr; - - OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group) - : Candidate(&C), Parent(&Group) { - StartBB = C.getStartBB(); - EndBB = C.getEndBB(); - } - - /// For the contained region, split the parent BasicBlock at the starting and - /// ending instructions of the contained IRSimilarityCandidate. - void splitCandidate(); - - /// For the contained region, reattach the BasicBlock at the starting and - /// ending instructions of the contained IRSimilarityCandidate, or if the - /// function has been extracted, the start and end of the BasicBlock - /// containing the called function. - void reattachCandidate(); - - /// Get the size of the code removed from the region. - /// - /// \param [in] TTI - The TargetTransformInfo for the parent function. - /// \returns the code size of the region - InstructionCost getBenefit(TargetTransformInfo &TTI); -}; - -/// This class is a pass that identifies similarity in a Module, extracts -/// instances of the similarity, and then consolidating the similar regions -/// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass -/// to identify the similar regions of code, and then extracts the similar -/// sections into a single function. See the above for an example as to -/// how code is extracted and consolidated into a single function. -class IROutliner { -public: - IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI, - function_ref<IRSimilarityIdentifier &(Module &)> GIRSI, - function_ref<OptimizationRemarkEmitter &(Function &)> GORE) - : getTTI(GTTI), getIRSI(GIRSI), getORE(GORE) {} - bool run(Module &M); - -private: - /// Find repeated similar code sequences in \p M and outline them into new - /// Functions. - /// - /// \param [in] M - The module to outline from. - /// \returns The number of Functions created. - unsigned doOutline(Module &M); - - /// Remove all the IRSimilarityCandidates from \p CandidateVec that have - /// instructions contained in a previously outlined region and put the - /// remaining regions in \p CurrentGroup. - /// - /// \param [in] CandidateVec - List of similarity candidates for regions with - /// the same similarity structure. - /// \param [in,out] CurrentGroup - Contains the potential sections to - /// be outlined. - void - pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec, - OutlinableGroup &CurrentGroup); - - /// Create the function based on the overall types found in the current - /// regions being outlined. - /// - /// \param M - The module to outline from. - /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined. - /// \param [in] FunctionNameSuffix - How many functions have we previously - /// created. - /// \returns the newly created function. - Function *createFunction(Module &M, OutlinableGroup &CG, - unsigned FunctionNameSuffix); - - /// Identify the needed extracted inputs in a section, and add to the overall - /// function if needed. - /// - /// \param [in] M - The module to outline from. - /// \param [in,out] Region - The region to be extracted. - /// \param [in] NotSame - The global value numbers of the Values in the region - /// that do not have the same Constant in each strucutrally similar region. - void findAddInputsOutputs(Module &M, OutlinableRegion &Region, - DenseSet<unsigned> &NotSame); - - /// Find the number of instructions that will be removed by extracting the - /// OutlinableRegions in \p CurrentGroup. - /// - /// \param [in] CurrentGroup - The collection of OutlinableRegions to be - /// analyzed. - /// \returns the number of outlined instructions across all regions. - InstructionCost findBenefitFromAllRegions(OutlinableGroup &CurrentGroup); - - /// Find the number of instructions that will be added by reloading arguments. - /// - /// \param [in] CurrentGroup - The collection of OutlinableRegions to be - /// analyzed. - /// \returns the number of added reload instructions across all regions. - InstructionCost findCostOutputReloads(OutlinableGroup &CurrentGroup); - - /// Find the cost and the benefit of \p CurrentGroup and save it back to - /// \p CurrentGroup. - /// - /// \param [in] M - The module being analyzed - /// \param [in,out] CurrentGroup - The overall outlined section - void findCostBenefit(Module &M, OutlinableGroup &CurrentGroup); - - /// Update the output mapping based on the load instruction, and the outputs - /// of the extracted function. - /// - /// \param Region - The region extracted - /// \param Outputs - The outputs from the extracted function. - /// \param LI - The load instruction used to update the mapping. - void updateOutputMapping(OutlinableRegion &Region, - ArrayRef<Value *> Outputs, LoadInst *LI); - - /// Extract \p Region into its own function. - /// - /// \param [in] Region - The region to be extracted into its own function. - /// \returns True if it was successfully outlined. - bool extractSection(OutlinableRegion &Region); - - /// For the similarities found, and the extracted sections, create a single - /// outlined function with appropriate output blocks as necessary. - /// - /// \param [in] M - The module to outline from - /// \param [in] CurrentGroup - The set of extracted sections to consolidate. - /// \param [in,out] FuncsToRemove - List of functions to remove from the - /// module after outlining is completed. - /// \param [in,out] OutlinedFunctionNum - the number of new outlined - /// functions. - void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup, - std::vector<Function *> &FuncsToRemove, - unsigned &OutlinedFunctionNum); - - /// If true, enables us to outline from functions that have LinkOnceFromODR - /// linkages. - bool OutlineFromLinkODRs = false; - - /// If false, we do not worry if the cost is greater than the benefit. This - /// is for debugging and testing, so that we can test small cases to ensure - /// that the outlining is being done correctly. - bool CostModel = true; - - /// The set of outlined Instructions, identified by their location in the - /// sequential ordering of instructions in a Module. - DenseSet<unsigned> Outlined; - - /// TargetTransformInfo lambda for target specific information. - function_ref<TargetTransformInfo &(Function &)> getTTI; - - /// A mapping from newly created reloaded output values to the original value. - /// If an value is replace by an output from an outlined region, this maps - /// that Value, back to its original Value. - DenseMap<Value *, Value *> OutputMappings; - - /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier. - function_ref<IRSimilarityIdentifier &(Module &)> getIRSI; - - /// The optimization remark emitter for the pass. - function_ref<OptimizationRemarkEmitter &(Function &)> getORE; - - /// The memory allocator used to allocate the CodeExtractors. - SpecificBumpPtrAllocator<CodeExtractor> ExtractorAllocator; - - /// The memory allocator used to allocate the OutlinableRegions. - SpecificBumpPtrAllocator<OutlinableRegion> RegionAllocator; - - /// The memory allocator used to allocate new IRInstructionData. - SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator; - - /// Custom InstVisitor to classify different instructions for whether it can - /// be analyzed for similarity. This is needed as there may be instruction we - /// can identify as having similarity, but are more complicated to outline. - struct InstructionAllowed : public InstVisitor<InstructionAllowed, bool> { - InstructionAllowed() {} - - // TODO: Determine a scheme to resolve when the label is similar enough. - bool visitBranchInst(BranchInst &BI) { return false; } - // TODO: Determine a scheme to resolve when the labels are similar enough. - bool visitPHINode(PHINode &PN) { return false; } - // TODO: Handle allocas. - bool visitAllocaInst(AllocaInst &AI) { return false; } - // VAArg instructions are not allowed since this could cause difficulty when - // differentiating between different sets of variable instructions in - // the deduplicated outlined regions. - bool visitVAArgInst(VAArgInst &VI) { return false; } - // We exclude all exception handling cases since they are so context - // dependent. - bool visitLandingPadInst(LandingPadInst &LPI) { return false; } - bool visitFuncletPadInst(FuncletPadInst &FPI) { return false; } - // DebugInfo should be included in the regions, but should not be - // analyzed for similarity as it has no bearing on the outcome of the - // program. - bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return true; } - // TODO: Handle specific intrinsics individually from those that can be - // handled. - bool IntrinsicInst(IntrinsicInst &II) { return false; } - // We only handle CallInsts that are not indirect, since we cannot guarantee - // that they have a name in these cases. - bool visitCallInst(CallInst &CI) { - Function *F = CI.getCalledFunction(); - if (!F || CI.isIndirectCall() || !F->hasName()) - return false; - return true; - } - // TODO: Handle FreezeInsts. Since a frozen value could be frozen inside - // the outlined region, and then returned as an output, this will have to be - // handled differently. - bool visitFreezeInst(FreezeInst &CI) { return false; } - // TODO: We do not current handle similarity that changes the control flow. - bool visitInvokeInst(InvokeInst &II) { return false; } - // TODO: We do not current handle similarity that changes the control flow. - bool visitCallBrInst(CallBrInst &CBI) { return false; } - // TODO: Handle interblock similarity. - bool visitTerminator(Instruction &I) { return false; } - bool visitInstruction(Instruction &I) { return true; } - }; - - /// A InstVisitor used to exclude certain instructions from being outlined. - InstructionAllowed InstructionClassifier; -}; - -/// Pass to outline similar regions. -class IROutlinerPass : public PassInfoMixin<IROutlinerPass> { -public: - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- IROutliner.h - Extract similar IR regions into functions ------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// \file +// The interface file for the IROutliner which is used by the IROutliner Pass. +// +// The outliner uses the IRSimilarityIdentifier to identify the similar regions +// of code. It evaluates each set of IRSimilarityCandidates with an estimate of +// whether it will provide code size reduction. Each region is extracted using +// the code extractor. These extracted functions are consolidated into a single +// function and called from the extracted call site. +// +// For example: +// \code +// %1 = add i32 %a, %b +// %2 = add i32 %b, %a +// %3 = add i32 %b, %a +// %4 = add i32 %a, %b +// \endcode +// would become function +// \code +// define internal void outlined_ir_function(i32 %0, i32 %1) { +// %1 = add i32 %0, %1 +// %2 = add i32 %1, %0 +// ret void +// } +// \endcode +// with calls: +// \code +// call void outlined_ir_function(i32 %a, i32 %b) +// call void outlined_ir_function(i32 %b, i32 %a) +// \endcode +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_IROUTLINER_H +#define LLVM_TRANSFORMS_IPO_IROUTLINER_H + +#include "llvm/Analysis/IRSimilarityIdentifier.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/ValueMap.h" +#include "llvm/Support/InstructionCost.h" +#include "llvm/Transforms/Utils/CodeExtractor.h" +#include <set> + +struct OutlinableGroup; + +namespace llvm { +using namespace IRSimilarity; + +class Module; +class TargetTransformInfo; +class OptimizationRemarkEmitter; + +/// The OutlinableRegion holds all the information for a specific region, or +/// sequence of instructions. This includes what values need to be hoisted to +/// arguments from the extracted function, inputs and outputs to the region, and +/// mapping from the extracted function arguments to overall function arguments. +struct OutlinableRegion { + /// Describes the region of code. + IRSimilarityCandidate *Candidate; + + /// If this region is outlined, the front and back IRInstructionData could + /// potentially become invalidated if the only new instruction is a call. + /// This ensures that we replace in the instruction in the IRInstructionData. + IRInstructionData *NewFront = nullptr; + IRInstructionData *NewBack = nullptr; + + /// The number of extracted inputs from the CodeExtractor. + unsigned NumExtractedInputs; + + /// The corresponding BasicBlock with the appropriate stores for this + /// OutlinableRegion in the overall function. + unsigned OutputBlockNum; + + /// Mapping the extracted argument number to the argument number in the + /// overall function. Since there will be inputs, such as elevated constants + /// that are not the same in each region in a SimilarityGroup, or values that + /// cannot be sunk into the extracted section in every region, we must keep + /// track of which extracted argument maps to which overall argument. + DenseMap<unsigned, unsigned> ExtractedArgToAgg; + DenseMap<unsigned, unsigned> AggArgToExtracted; + + /// Mapping of the argument number in the deduplicated function + /// to a given constant, which is used when creating the arguments to the call + /// to the newly created deduplicated function. This is handled separately + /// since the CodeExtractor does not recognize constants. + DenseMap<unsigned, Constant *> AggArgToConstant; + + /// The global value numbers that are used as outputs for this section. Once + /// extracted, each output will be stored to an output register. This + /// documents the global value numbers that are used in this pattern. + SmallVector<unsigned, 4> GVNStores; + + /// Used to create an outlined function. + CodeExtractor *CE = nullptr; + + /// The call site of the extracted region. + CallInst *Call = nullptr; + + /// The function for the extracted region. + Function *ExtractedFunction = nullptr; + + /// Flag for whether we have split out the IRSimilarityCanidate. That is, + /// make the region contained the IRSimilarityCandidate its own BasicBlock. + bool CandidateSplit = false; + + /// Flag for whether we should not consider this region for extraction. + bool IgnoreRegion = false; + + /// The BasicBlock that is before the start of the region BasicBlock, + /// only defined when the region has been split. + BasicBlock *PrevBB = nullptr; + + /// The BasicBlock that contains the starting instruction of the region. + BasicBlock *StartBB = nullptr; + + /// The BasicBlock that contains the ending instruction of the region. + BasicBlock *EndBB = nullptr; + + /// The BasicBlock that is after the start of the region BasicBlock, + /// only defined when the region has been split. + BasicBlock *FollowBB = nullptr; + + /// The Outlinable Group that contains this region and structurally similar + /// regions to this region. + OutlinableGroup *Parent = nullptr; + + OutlinableRegion(IRSimilarityCandidate &C, OutlinableGroup &Group) + : Candidate(&C), Parent(&Group) { + StartBB = C.getStartBB(); + EndBB = C.getEndBB(); + } + + /// For the contained region, split the parent BasicBlock at the starting and + /// ending instructions of the contained IRSimilarityCandidate. + void splitCandidate(); + + /// For the contained region, reattach the BasicBlock at the starting and + /// ending instructions of the contained IRSimilarityCandidate, or if the + /// function has been extracted, the start and end of the BasicBlock + /// containing the called function. + void reattachCandidate(); + + /// Get the size of the code removed from the region. + /// + /// \param [in] TTI - The TargetTransformInfo for the parent function. + /// \returns the code size of the region + InstructionCost getBenefit(TargetTransformInfo &TTI); +}; + +/// This class is a pass that identifies similarity in a Module, extracts +/// instances of the similarity, and then consolidating the similar regions +/// in an effort to reduce code size. It uses the IRSimilarityIdentifier pass +/// to identify the similar regions of code, and then extracts the similar +/// sections into a single function. See the above for an example as to +/// how code is extracted and consolidated into a single function. +class IROutliner { +public: + IROutliner(function_ref<TargetTransformInfo &(Function &)> GTTI, + function_ref<IRSimilarityIdentifier &(Module &)> GIRSI, + function_ref<OptimizationRemarkEmitter &(Function &)> GORE) + : getTTI(GTTI), getIRSI(GIRSI), getORE(GORE) {} + bool run(Module &M); + +private: + /// Find repeated similar code sequences in \p M and outline them into new + /// Functions. + /// + /// \param [in] M - The module to outline from. + /// \returns The number of Functions created. + unsigned doOutline(Module &M); + + /// Remove all the IRSimilarityCandidates from \p CandidateVec that have + /// instructions contained in a previously outlined region and put the + /// remaining regions in \p CurrentGroup. + /// + /// \param [in] CandidateVec - List of similarity candidates for regions with + /// the same similarity structure. + /// \param [in,out] CurrentGroup - Contains the potential sections to + /// be outlined. + void + pruneIncompatibleRegions(std::vector<IRSimilarityCandidate> &CandidateVec, + OutlinableGroup &CurrentGroup); + + /// Create the function based on the overall types found in the current + /// regions being outlined. + /// + /// \param M - The module to outline from. + /// \param [in,out] CG - The OutlinableGroup for the regions to be outlined. + /// \param [in] FunctionNameSuffix - How many functions have we previously + /// created. + /// \returns the newly created function. + Function *createFunction(Module &M, OutlinableGroup &CG, + unsigned FunctionNameSuffix); + + /// Identify the needed extracted inputs in a section, and add to the overall + /// function if needed. + /// + /// \param [in] M - The module to outline from. + /// \param [in,out] Region - The region to be extracted. + /// \param [in] NotSame - The global value numbers of the Values in the region + /// that do not have the same Constant in each strucutrally similar region. + void findAddInputsOutputs(Module &M, OutlinableRegion &Region, + DenseSet<unsigned> &NotSame); + + /// Find the number of instructions that will be removed by extracting the + /// OutlinableRegions in \p CurrentGroup. + /// + /// \param [in] CurrentGroup - The collection of OutlinableRegions to be + /// analyzed. + /// \returns the number of outlined instructions across all regions. + InstructionCost findBenefitFromAllRegions(OutlinableGroup &CurrentGroup); + + /// Find the number of instructions that will be added by reloading arguments. + /// + /// \param [in] CurrentGroup - The collection of OutlinableRegions to be + /// analyzed. + /// \returns the number of added reload instructions across all regions. + InstructionCost findCostOutputReloads(OutlinableGroup &CurrentGroup); + + /// Find the cost and the benefit of \p CurrentGroup and save it back to + /// \p CurrentGroup. + /// + /// \param [in] M - The module being analyzed + /// \param [in,out] CurrentGroup - The overall outlined section + void findCostBenefit(Module &M, OutlinableGroup &CurrentGroup); + + /// Update the output mapping based on the load instruction, and the outputs + /// of the extracted function. + /// + /// \param Region - The region extracted + /// \param Outputs - The outputs from the extracted function. + /// \param LI - The load instruction used to update the mapping. + void updateOutputMapping(OutlinableRegion &Region, + ArrayRef<Value *> Outputs, LoadInst *LI); + + /// Extract \p Region into its own function. + /// + /// \param [in] Region - The region to be extracted into its own function. + /// \returns True if it was successfully outlined. + bool extractSection(OutlinableRegion &Region); + + /// For the similarities found, and the extracted sections, create a single + /// outlined function with appropriate output blocks as necessary. + /// + /// \param [in] M - The module to outline from + /// \param [in] CurrentGroup - The set of extracted sections to consolidate. + /// \param [in,out] FuncsToRemove - List of functions to remove from the + /// module after outlining is completed. + /// \param [in,out] OutlinedFunctionNum - the number of new outlined + /// functions. + void deduplicateExtractedSections(Module &M, OutlinableGroup &CurrentGroup, + std::vector<Function *> &FuncsToRemove, + unsigned &OutlinedFunctionNum); + + /// If true, enables us to outline from functions that have LinkOnceFromODR + /// linkages. + bool OutlineFromLinkODRs = false; + + /// If false, we do not worry if the cost is greater than the benefit. This + /// is for debugging and testing, so that we can test small cases to ensure + /// that the outlining is being done correctly. + bool CostModel = true; + + /// The set of outlined Instructions, identified by their location in the + /// sequential ordering of instructions in a Module. + DenseSet<unsigned> Outlined; + + /// TargetTransformInfo lambda for target specific information. + function_ref<TargetTransformInfo &(Function &)> getTTI; + + /// A mapping from newly created reloaded output values to the original value. + /// If an value is replace by an output from an outlined region, this maps + /// that Value, back to its original Value. + DenseMap<Value *, Value *> OutputMappings; + + /// IRSimilarityIdentifier lambda to retrieve IRSimilarityIdentifier. + function_ref<IRSimilarityIdentifier &(Module &)> getIRSI; + + /// The optimization remark emitter for the pass. + function_ref<OptimizationRemarkEmitter &(Function &)> getORE; + + /// The memory allocator used to allocate the CodeExtractors. + SpecificBumpPtrAllocator<CodeExtractor> ExtractorAllocator; + + /// The memory allocator used to allocate the OutlinableRegions. + SpecificBumpPtrAllocator<OutlinableRegion> RegionAllocator; + + /// The memory allocator used to allocate new IRInstructionData. + SpecificBumpPtrAllocator<IRInstructionData> InstDataAllocator; + + /// Custom InstVisitor to classify different instructions for whether it can + /// be analyzed for similarity. This is needed as there may be instruction we + /// can identify as having similarity, but are more complicated to outline. + struct InstructionAllowed : public InstVisitor<InstructionAllowed, bool> { + InstructionAllowed() {} + + // TODO: Determine a scheme to resolve when the label is similar enough. + bool visitBranchInst(BranchInst &BI) { return false; } + // TODO: Determine a scheme to resolve when the labels are similar enough. + bool visitPHINode(PHINode &PN) { return false; } + // TODO: Handle allocas. + bool visitAllocaInst(AllocaInst &AI) { return false; } + // VAArg instructions are not allowed since this could cause difficulty when + // differentiating between different sets of variable instructions in + // the deduplicated outlined regions. + bool visitVAArgInst(VAArgInst &VI) { return false; } + // We exclude all exception handling cases since they are so context + // dependent. + bool visitLandingPadInst(LandingPadInst &LPI) { return false; } + bool visitFuncletPadInst(FuncletPadInst &FPI) { return false; } + // DebugInfo should be included in the regions, but should not be + // analyzed for similarity as it has no bearing on the outcome of the + // program. + bool visitDbgInfoIntrinsic(DbgInfoIntrinsic &DII) { return true; } + // TODO: Handle specific intrinsics individually from those that can be + // handled. + bool IntrinsicInst(IntrinsicInst &II) { return false; } + // We only handle CallInsts that are not indirect, since we cannot guarantee + // that they have a name in these cases. + bool visitCallInst(CallInst &CI) { + Function *F = CI.getCalledFunction(); + if (!F || CI.isIndirectCall() || !F->hasName()) + return false; + return true; + } + // TODO: Handle FreezeInsts. Since a frozen value could be frozen inside + // the outlined region, and then returned as an output, this will have to be + // handled differently. + bool visitFreezeInst(FreezeInst &CI) { return false; } + // TODO: We do not current handle similarity that changes the control flow. + bool visitInvokeInst(InvokeInst &II) { return false; } + // TODO: We do not current handle similarity that changes the control flow. + bool visitCallBrInst(CallBrInst &CBI) { return false; } + // TODO: Handle interblock similarity. + bool visitTerminator(Instruction &I) { return false; } + bool visitInstruction(Instruction &I) { return true; } + }; + + /// A InstVisitor used to exclude certain instructions from being outlined. + InstructionAllowed InstructionClassifier; +}; + +/// Pass to outline similar regions. +class IROutlinerPass : public PassInfoMixin<IROutlinerPass> { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_IROUTLINER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Inliner.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Inliner.h index 2430425c60..a5b5934b73 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/Inliner.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/Inliner.h @@ -21,8 +21,8 @@ #include "llvm/Analysis/InlineAdvisor.h" #include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/LazyCallGraph.h" -#include "llvm/Analysis/ReplayInlineAdvisor.h" -#include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h" +#include "llvm/Analysis/ReplayInlineAdvisor.h" +#include "llvm/Analysis/Utils/ImportedFunctionsInliningStatistics.h" #include "llvm/IR/PassManager.h" #include <utility> @@ -104,8 +104,8 @@ protected: /// passes be composed to achieve the same end result. class InlinerPass : public PassInfoMixin<InlinerPass> { public: - InlinerPass(bool OnlyMandatory = false) : OnlyMandatory(OnlyMandatory) {} - InlinerPass(InlinerPass &&Arg) = default; + InlinerPass(bool OnlyMandatory = false) : OnlyMandatory(OnlyMandatory) {} + InlinerPass(InlinerPass &&Arg) = default; PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR); @@ -113,8 +113,8 @@ public: private: InlineAdvisor &getAdvisor(const ModuleAnalysisManagerCGSCCProxy::Result &MAM, FunctionAnalysisManager &FAM, Module &M); - std::unique_ptr<InlineAdvisor> OwnedAdvisor; - const bool OnlyMandatory; + std::unique_ptr<InlineAdvisor> OwnedAdvisor; + const bool OnlyMandatory; }; /// Module pass, wrapping the inliner pass. This works in conjunction with the @@ -127,7 +127,7 @@ class ModuleInlinerWrapperPass public: ModuleInlinerWrapperPass( InlineParams Params = getInlineParams(), bool Debugging = false, - bool MandatoryFirst = true, + bool MandatoryFirst = true, InliningAdvisorMode Mode = InliningAdvisorMode::Default, unsigned MaxDevirtIterations = 0); ModuleInlinerWrapperPass(ModuleInlinerWrapperPass &&Arg) = default; diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/LoopExtractor.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/LoopExtractor.h index ede8250980..3b721a1279 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/LoopExtractor.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/LoopExtractor.h @@ -1,43 +1,43 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- LoopExtractor.h - Extract each loop into a new function ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// A pass wrapper around the ExtractLoop() scalar transformation to extract each -// top-level loop into its own new function. If the loop is the ONLY loop in a -// given function, it is not touched. This is a pass most useful for debugging -// via bugpoint. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H -#define LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -struct LoopExtractorPass : public PassInfoMixin<LoopExtractorPass> { - LoopExtractorPass(unsigned NumLoops = ~0) : NumLoops(NumLoops) {} - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); - -private: - unsigned NumLoops; -}; -} // namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- LoopExtractor.h - Extract each loop into a new function ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// A pass wrapper around the ExtractLoop() scalar transformation to extract each +// top-level loop into its own new function. If the loop is the ONLY loop in a +// given function, it is not touched. This is a pass most useful for debugging +// via bugpoint. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H +#define LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct LoopExtractorPass : public PassInfoMixin<LoopExtractorPass> { + LoopExtractorPass(unsigned NumLoops = ~0) : NumLoops(NumLoops) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + +private: + unsigned NumLoops; +}; +} // namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_LOOPEXTRACTOR_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/LowerTypeTests.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/LowerTypeTests.h index 40761ef91e..8ad2193588 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/LowerTypeTests.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/LowerTypeTests.h @@ -205,14 +205,14 @@ bool isJumpTableCanonical(Function *F); } // end namespace lowertypetests class LowerTypeTestsPass : public PassInfoMixin<LowerTypeTestsPass> { - bool UseCommandLine = false; - - ModuleSummaryIndex *ExportSummary = nullptr; - const ModuleSummaryIndex *ImportSummary = nullptr; - bool DropTypeTests = true; - + bool UseCommandLine = false; + + ModuleSummaryIndex *ExportSummary = nullptr; + const ModuleSummaryIndex *ImportSummary = nullptr; + bool DropTypeTests = true; + public: - LowerTypeTestsPass() : UseCommandLine(true) {} + LowerTypeTestsPass() : UseCommandLine(true) {} LowerTypeTestsPass(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary, bool DropTypeTests = false) diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/OpenMPOpt.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/OpenMPOpt.h index 4e8071e60c..76aff7eb6f 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/OpenMPOpt.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/OpenMPOpt.h @@ -40,11 +40,11 @@ struct OpenMPInModule { bool isKnown() { return Value != OpenMP::UNKNOWN; } operator bool() { return Value != OpenMP::NOT_FOUND; } - /// Does this function \p F contain any OpenMP runtime calls? - bool containsOMPRuntimeCalls(Function *F) const { - return FuncsWithOMPRuntimeCalls.contains(F); - } - + /// Does this function \p F contain any OpenMP runtime calls? + bool containsOMPRuntimeCalls(Function *F) const { + return FuncsWithOMPRuntimeCalls.contains(F); + } + /// Return the known kernels (=GPU entry points) in the module. SmallPtrSetImpl<Kernel> &getKernels() { return Kernels; } @@ -54,11 +54,11 @@ struct OpenMPInModule { private: enum class OpenMP { FOUND, NOT_FOUND, UNKNOWN } Value = OpenMP::UNKNOWN; - friend bool containsOpenMP(Module &M, OpenMPInModule &OMPInModule); - - /// In which functions are OpenMP runtime calls present? - SmallPtrSet<Function *, 32> FuncsWithOMPRuntimeCalls; - + friend bool containsOpenMP(Module &M, OpenMPInModule &OMPInModule); + + /// In which functions are OpenMP runtime calls present? + SmallPtrSet<Function *, 32> FuncsWithOMPRuntimeCalls; + /// Collection of known kernels (=GPU entry points) in the module. SmallPtrSet<Kernel, 8> Kernels; }; diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleContextTracker.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleContextTracker.h index 11328fb5ac..e5f5e5b737 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleContextTracker.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleContextTracker.h @@ -1,163 +1,163 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Transforms/IPO/SampleContextTracker.h --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file provides the interface for context-sensitive profile tracker used -/// by CSSPGO. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H -#define LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H - -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Analysis/CallGraph.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Instructions.h" -#include "llvm/ProfileData/SampleProf.h" -#include <list> -#include <map> -#include <vector> - -using namespace llvm; -using namespace sampleprof; - -namespace llvm { - -// Internal trie tree representation used for tracking context tree and sample -// profiles. The path from root node to a given node represents the context of -// that nodes' profile. -class ContextTrieNode { -public: - ContextTrieNode(ContextTrieNode *Parent = nullptr, - StringRef FName = StringRef(), - FunctionSamples *FSamples = nullptr, - LineLocation CallLoc = {0, 0}) - : ParentContext(Parent), FuncName(FName), FuncSamples(FSamples), - CallSiteLoc(CallLoc){}; - ContextTrieNode *getChildContext(const LineLocation &CallSite, - StringRef CalleeName); - ContextTrieNode *getHottestChildContext(const LineLocation &CallSite); - ContextTrieNode *getOrCreateChildContext(const LineLocation &CallSite, - StringRef CalleeName, - bool AllowCreate = true); - - ContextTrieNode &moveToChildContext(const LineLocation &CallSite, - ContextTrieNode &&NodeToMove, - StringRef ContextStrToRemove, - bool DeleteNode = true); - void removeChildContext(const LineLocation &CallSite, StringRef CalleeName); - std::map<uint32_t, ContextTrieNode> &getAllChildContext(); - const StringRef getFuncName() const; - FunctionSamples *getFunctionSamples() const; - void setFunctionSamples(FunctionSamples *FSamples); - LineLocation getCallSiteLoc() const; - ContextTrieNode *getParentContext() const; - void setParentContext(ContextTrieNode *Parent); - void dump(); - -private: - static uint32_t nodeHash(StringRef ChildName, const LineLocation &Callsite); - - // Map line+discriminator location to child context - std::map<uint32_t, ContextTrieNode> AllChildContext; - - // Link to parent context node - ContextTrieNode *ParentContext; - - // Function name for current context - StringRef FuncName; - - // Function Samples for current context - FunctionSamples *FuncSamples; - - // Callsite location in parent context - LineLocation CallSiteLoc; -}; - -// Profile tracker that manages profiles and its associated context. It -// provides interfaces used by sample profile loader to query context profile or -// base profile for given function or location; it also manages context tree -// manipulation that is needed to accommodate inline decisions so we have -// accurate post-inline profile for functions. Internally context profiles -// are organized in a trie, with each node representing profile for specific -// calling context and the context is identified by path from root to the node. -class SampleContextTracker { -public: - using ContextSamplesTy = SmallSet<FunctionSamples *, 16>; - - SampleContextTracker(StringMap<FunctionSamples> &Profiles); - // Query context profile for a specific callee with given name at a given - // call-site. The full context is identified by location of call instruction. - FunctionSamples *getCalleeContextSamplesFor(const CallBase &Inst, - StringRef CalleeName); - // Get samples for indirect call targets for call site at given location. - std::vector<const FunctionSamples *> - getIndirectCalleeContextSamplesFor(const DILocation *DIL); - // Query context profile for a given location. The full context - // is identified by input DILocation. - FunctionSamples *getContextSamplesFor(const DILocation *DIL); - // Query context profile for a given sample contxt of a function. - FunctionSamples *getContextSamplesFor(const SampleContext &Context); - // Get all context profile for given function. - ContextSamplesTy &getAllContextSamplesFor(const Function &Func); - ContextSamplesTy &getAllContextSamplesFor(StringRef Name); - // Query base profile for a given function. A base profile is a merged view - // of all context profiles for contexts that are not inlined. - FunctionSamples *getBaseSamplesFor(const Function &Func, - bool MergeContext = true); - // Query base profile for a given function by name. - FunctionSamples *getBaseSamplesFor(StringRef Name, bool MergeContext); - // Mark a context profile as inlined when function is inlined. - // This makes sure that inlined context profile will be excluded in - // function's base profile. - void markContextSamplesInlined(const FunctionSamples *InlinedSamples); - void promoteMergeContextSamplesTree(const Instruction &Inst, - StringRef CalleeName); - void addCallGraphEdges(CallGraph &CG, StringMap<Function *> &SymbolMap); - // Dump the internal context profile trie. - void dump(); - -private: - ContextTrieNode *getContextFor(const DILocation *DIL); - ContextTrieNode *getContextFor(const SampleContext &Context); - ContextTrieNode *getCalleeContextFor(const DILocation *DIL, - StringRef CalleeName); - ContextTrieNode *getOrCreateContextPath(const SampleContext &Context, - bool AllowCreate); - ContextTrieNode *getTopLevelContextNode(StringRef FName); - ContextTrieNode &addTopLevelContextNode(StringRef FName); - ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &NodeToPromo); - void mergeContextNode(ContextTrieNode &FromNode, ContextTrieNode &ToNode, - StringRef ContextStrToRemove); - ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &FromNode, - ContextTrieNode &ToNodeParent, - StringRef ContextStrToRemove); - - // Map from function name to context profiles (excluding base profile) - StringMap<ContextSamplesTy> FuncToCtxtProfileSet; - - // Root node for context trie tree - ContextTrieNode RootContext; -}; - -} // end namespace llvm -#endif // LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Transforms/IPO/SampleContextTracker.h --------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file provides the interface for context-sensitive profile tracker used +/// by CSSPGO. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H +#define LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H + +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Instructions.h" +#include "llvm/ProfileData/SampleProf.h" +#include <list> +#include <map> +#include <vector> + +using namespace llvm; +using namespace sampleprof; + +namespace llvm { + +// Internal trie tree representation used for tracking context tree and sample +// profiles. The path from root node to a given node represents the context of +// that nodes' profile. +class ContextTrieNode { +public: + ContextTrieNode(ContextTrieNode *Parent = nullptr, + StringRef FName = StringRef(), + FunctionSamples *FSamples = nullptr, + LineLocation CallLoc = {0, 0}) + : ParentContext(Parent), FuncName(FName), FuncSamples(FSamples), + CallSiteLoc(CallLoc){}; + ContextTrieNode *getChildContext(const LineLocation &CallSite, + StringRef CalleeName); + ContextTrieNode *getHottestChildContext(const LineLocation &CallSite); + ContextTrieNode *getOrCreateChildContext(const LineLocation &CallSite, + StringRef CalleeName, + bool AllowCreate = true); + + ContextTrieNode &moveToChildContext(const LineLocation &CallSite, + ContextTrieNode &&NodeToMove, + StringRef ContextStrToRemove, + bool DeleteNode = true); + void removeChildContext(const LineLocation &CallSite, StringRef CalleeName); + std::map<uint32_t, ContextTrieNode> &getAllChildContext(); + const StringRef getFuncName() const; + FunctionSamples *getFunctionSamples() const; + void setFunctionSamples(FunctionSamples *FSamples); + LineLocation getCallSiteLoc() const; + ContextTrieNode *getParentContext() const; + void setParentContext(ContextTrieNode *Parent); + void dump(); + +private: + static uint32_t nodeHash(StringRef ChildName, const LineLocation &Callsite); + + // Map line+discriminator location to child context + std::map<uint32_t, ContextTrieNode> AllChildContext; + + // Link to parent context node + ContextTrieNode *ParentContext; + + // Function name for current context + StringRef FuncName; + + // Function Samples for current context + FunctionSamples *FuncSamples; + + // Callsite location in parent context + LineLocation CallSiteLoc; +}; + +// Profile tracker that manages profiles and its associated context. It +// provides interfaces used by sample profile loader to query context profile or +// base profile for given function or location; it also manages context tree +// manipulation that is needed to accommodate inline decisions so we have +// accurate post-inline profile for functions. Internally context profiles +// are organized in a trie, with each node representing profile for specific +// calling context and the context is identified by path from root to the node. +class SampleContextTracker { +public: + using ContextSamplesTy = SmallSet<FunctionSamples *, 16>; + + SampleContextTracker(StringMap<FunctionSamples> &Profiles); + // Query context profile for a specific callee with given name at a given + // call-site. The full context is identified by location of call instruction. + FunctionSamples *getCalleeContextSamplesFor(const CallBase &Inst, + StringRef CalleeName); + // Get samples for indirect call targets for call site at given location. + std::vector<const FunctionSamples *> + getIndirectCalleeContextSamplesFor(const DILocation *DIL); + // Query context profile for a given location. The full context + // is identified by input DILocation. + FunctionSamples *getContextSamplesFor(const DILocation *DIL); + // Query context profile for a given sample contxt of a function. + FunctionSamples *getContextSamplesFor(const SampleContext &Context); + // Get all context profile for given function. + ContextSamplesTy &getAllContextSamplesFor(const Function &Func); + ContextSamplesTy &getAllContextSamplesFor(StringRef Name); + // Query base profile for a given function. A base profile is a merged view + // of all context profiles for contexts that are not inlined. + FunctionSamples *getBaseSamplesFor(const Function &Func, + bool MergeContext = true); + // Query base profile for a given function by name. + FunctionSamples *getBaseSamplesFor(StringRef Name, bool MergeContext); + // Mark a context profile as inlined when function is inlined. + // This makes sure that inlined context profile will be excluded in + // function's base profile. + void markContextSamplesInlined(const FunctionSamples *InlinedSamples); + void promoteMergeContextSamplesTree(const Instruction &Inst, + StringRef CalleeName); + void addCallGraphEdges(CallGraph &CG, StringMap<Function *> &SymbolMap); + // Dump the internal context profile trie. + void dump(); + +private: + ContextTrieNode *getContextFor(const DILocation *DIL); + ContextTrieNode *getContextFor(const SampleContext &Context); + ContextTrieNode *getCalleeContextFor(const DILocation *DIL, + StringRef CalleeName); + ContextTrieNode *getOrCreateContextPath(const SampleContext &Context, + bool AllowCreate); + ContextTrieNode *getTopLevelContextNode(StringRef FName); + ContextTrieNode &addTopLevelContextNode(StringRef FName); + ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &NodeToPromo); + void mergeContextNode(ContextTrieNode &FromNode, ContextTrieNode &ToNode, + StringRef ContextStrToRemove); + ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &FromNode, + ContextTrieNode &ToNodeParent, + StringRef ContextStrToRemove); + + // Map from function name to context profiles (excluding base profile) + StringMap<ContextSamplesTy> FuncToCtxtProfileSet; + + // Root node for context trie tree + ContextTrieNode RootContext; +}; + +} // end namespace llvm +#endif // LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfile.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfile.h index 9cc502eba6..be24fac675 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfile.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfile.h @@ -31,18 +31,18 @@ class Module; /// The sample profiler data loader pass. class SampleProfileLoaderPass : public PassInfoMixin<SampleProfileLoaderPass> { public: - SampleProfileLoaderPass( - std::string File = "", std::string RemappingFile = "", - ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) + SampleProfileLoaderPass( + std::string File = "", std::string RemappingFile = "", + ThinOrFullLTOPhase LTOPhase = ThinOrFullLTOPhase::None) : ProfileFileName(File), ProfileRemappingFileName(RemappingFile), - LTOPhase(LTOPhase) {} + LTOPhase(LTOPhase) {} PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); private: std::string ProfileFileName; std::string ProfileRemappingFileName; - ThinOrFullLTOPhase LTOPhase; + ThinOrFullLTOPhase LTOPhase; }; } // end namespace llvm diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfileProbe.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfileProbe.h index 7163fe38c0..55d7546fe7 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfileProbe.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/SampleProfileProbe.h @@ -1,158 +1,158 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- Transforms/IPO/SampleProfileProbe.h ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// This file provides the interface for the pseudo probe implementation for -/// AutoFDO. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H -#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Analysis/CallGraphSCCPass.h" -#include "llvm/Analysis/LazyCallGraph.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/IR/PassInstrumentation.h" -#include "llvm/IR/PassManager.h" -#include "llvm/IR/PseudoProbe.h" -#include "llvm/ProfileData/SampleProf.h" -#include "llvm/Target/TargetMachine.h" -#include <unordered_map> - -namespace llvm { - -class Module; - -using namespace sampleprof; -using BlockIdMap = std::unordered_map<BasicBlock *, uint32_t>; -using InstructionIdMap = std::unordered_map<Instruction *, uint32_t>; -using ProbeFactorMap = std::unordered_map<uint64_t, float>; -using FuncProbeFactorMap = StringMap<ProbeFactorMap>; - -enum class PseudoProbeReservedId { Invalid = 0, Last = Invalid }; - -class PseudoProbeDescriptor { - uint64_t FunctionGUID; - uint64_t FunctionHash; - -public: - PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash) - : FunctionGUID(GUID), FunctionHash(Hash) {} - uint64_t getFunctionGUID() const { return FunctionGUID; } - uint64_t getFunctionHash() const { return FunctionHash; } -}; - -// A pseudo probe verifier that can be run after each IR passes to detect the -// violation of updating probe factors. In principle, the sum of distribution -// factor for a probe should be identical before and after a pass. For a -// function pass, the factor sum for a probe would be typically 100%. -class PseudoProbeVerifier { -public: - void registerCallbacks(PassInstrumentationCallbacks &PIC); - - // Implementation of pass instrumentation callbacks for new pass manager. - void runAfterPass(StringRef PassID, Any IR); - -private: - // Allow a little bias due the rounding to integral factors. - constexpr static float DistributionFactorVariance = 0.02f; - // Distribution factors from last pass. - FuncProbeFactorMap FunctionProbeFactors; - - void collectProbeFactors(const BasicBlock *BB, ProbeFactorMap &ProbeFactors); - void runAfterPass(const Module *M); - void runAfterPass(const LazyCallGraph::SCC *C); - void runAfterPass(const Function *F); - void runAfterPass(const Loop *L); - bool shouldVerifyFunction(const Function *F); - void verifyProbeFactors(const Function *F, - const ProbeFactorMap &ProbeFactors); -}; - -// This class serves sample counts correlation for SampleProfileLoader by -// analyzing pseudo probes and their function descriptors injected by -// SampleProfileProber. -class PseudoProbeManager { - DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap; - - const PseudoProbeDescriptor *getDesc(const Function &F) const; - -public: - PseudoProbeManager(const Module &M); - bool moduleIsProbed(const Module &M) const; - bool profileIsValid(const Function &F, const FunctionSamples &Samples) const; -}; - -/// Sample profile pseudo prober. -/// -/// Insert pseudo probes for block sampling and value sampling. -class SampleProfileProber { -public: - // Give an empty module id when the prober is not used for instrumentation. - SampleProfileProber(Function &F, const std::string &CurModuleUniqueId); - void instrumentOneFunc(Function &F, TargetMachine *TM); - -private: - Function *getFunction() const { return F; } - uint64_t getFunctionHash() const { return FunctionHash; } - uint32_t getBlockId(const BasicBlock *BB) const; - uint32_t getCallsiteId(const Instruction *Call) const; - void computeCFGHash(); - void computeProbeIdForBlocks(); - void computeProbeIdForCallsites(); - - Function *F; - - /// The current module ID that is used to name a static object as a comdat - /// group. - std::string CurModuleUniqueId; - - /// A CFG hash code used to identify a function code changes. - uint64_t FunctionHash; - - /// Map basic blocks to the their pseudo probe ids. - BlockIdMap BlockProbeIds; - - /// Map indirect calls to the their pseudo probe ids. - InstructionIdMap CallProbeIds; - - /// The ID of the last probe, Can be used to number a new probe. - uint32_t LastProbeId; -}; - -class SampleProfileProbePass : public PassInfoMixin<SampleProfileProbePass> { - TargetMachine *TM; - -public: - SampleProfileProbePass(TargetMachine *TM) : TM(TM) {} - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> { - void runOnFunction(Function &F, FunctionAnalysisManager &FAM); - -public: - PseudoProbeUpdatePass() {} - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm -#endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- Transforms/IPO/SampleProfileProbe.h ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file provides the interface for the pseudo probe implementation for +/// AutoFDO. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H +#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/CallGraphSCCPass.h" +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/IR/PassInstrumentation.h" +#include "llvm/IR/PassManager.h" +#include "llvm/IR/PseudoProbe.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Target/TargetMachine.h" +#include <unordered_map> + +namespace llvm { + +class Module; + +using namespace sampleprof; +using BlockIdMap = std::unordered_map<BasicBlock *, uint32_t>; +using InstructionIdMap = std::unordered_map<Instruction *, uint32_t>; +using ProbeFactorMap = std::unordered_map<uint64_t, float>; +using FuncProbeFactorMap = StringMap<ProbeFactorMap>; + +enum class PseudoProbeReservedId { Invalid = 0, Last = Invalid }; + +class PseudoProbeDescriptor { + uint64_t FunctionGUID; + uint64_t FunctionHash; + +public: + PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash) + : FunctionGUID(GUID), FunctionHash(Hash) {} + uint64_t getFunctionGUID() const { return FunctionGUID; } + uint64_t getFunctionHash() const { return FunctionHash; } +}; + +// A pseudo probe verifier that can be run after each IR passes to detect the +// violation of updating probe factors. In principle, the sum of distribution +// factor for a probe should be identical before and after a pass. For a +// function pass, the factor sum for a probe would be typically 100%. +class PseudoProbeVerifier { +public: + void registerCallbacks(PassInstrumentationCallbacks &PIC); + + // Implementation of pass instrumentation callbacks for new pass manager. + void runAfterPass(StringRef PassID, Any IR); + +private: + // Allow a little bias due the rounding to integral factors. + constexpr static float DistributionFactorVariance = 0.02f; + // Distribution factors from last pass. + FuncProbeFactorMap FunctionProbeFactors; + + void collectProbeFactors(const BasicBlock *BB, ProbeFactorMap &ProbeFactors); + void runAfterPass(const Module *M); + void runAfterPass(const LazyCallGraph::SCC *C); + void runAfterPass(const Function *F); + void runAfterPass(const Loop *L); + bool shouldVerifyFunction(const Function *F); + void verifyProbeFactors(const Function *F, + const ProbeFactorMap &ProbeFactors); +}; + +// This class serves sample counts correlation for SampleProfileLoader by +// analyzing pseudo probes and their function descriptors injected by +// SampleProfileProber. +class PseudoProbeManager { + DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap; + + const PseudoProbeDescriptor *getDesc(const Function &F) const; + +public: + PseudoProbeManager(const Module &M); + bool moduleIsProbed(const Module &M) const; + bool profileIsValid(const Function &F, const FunctionSamples &Samples) const; +}; + +/// Sample profile pseudo prober. +/// +/// Insert pseudo probes for block sampling and value sampling. +class SampleProfileProber { +public: + // Give an empty module id when the prober is not used for instrumentation. + SampleProfileProber(Function &F, const std::string &CurModuleUniqueId); + void instrumentOneFunc(Function &F, TargetMachine *TM); + +private: + Function *getFunction() const { return F; } + uint64_t getFunctionHash() const { return FunctionHash; } + uint32_t getBlockId(const BasicBlock *BB) const; + uint32_t getCallsiteId(const Instruction *Call) const; + void computeCFGHash(); + void computeProbeIdForBlocks(); + void computeProbeIdForCallsites(); + + Function *F; + + /// The current module ID that is used to name a static object as a comdat + /// group. + std::string CurModuleUniqueId; + + /// A CFG hash code used to identify a function code changes. + uint64_t FunctionHash; + + /// Map basic blocks to the their pseudo probe ids. + BlockIdMap BlockProbeIds; + + /// Map indirect calls to the their pseudo probe ids. + InstructionIdMap CallProbeIds; + + /// The ID of the last probe, Can be used to number a new probe. + uint32_t LastProbeId; +}; + +class SampleProfileProbePass : public PassInfoMixin<SampleProfileProbePass> { + TargetMachine *TM; + +public: + SampleProfileProbePass(TargetMachine *TM) : TM(TM) {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> { + void runOnFunction(Function &F, FunctionAnalysisManager &FAM); + +public: + PseudoProbeUpdatePass() {} + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm +#endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/StripSymbols.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/StripSymbols.h index 83829c1fa8..21ce7b836f 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/StripSymbols.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/StripSymbols.h @@ -1,58 +1,58 @@ -#pragma once - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#endif - -//===- StripSymbols.h - Strip symbols and debug info from a module --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// The StripSymbols transformation implements code stripping. Specifically, it -// can delete: -// -// * names for virtual registers -// * symbols for internal globals and functions -// * debug information -// -// Note that this transformation makes code much less readable, so it should -// only be used in situations where the 'strip' utility would be used, such as -// reducing code size or making it harder to reverse engineer code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H -#define LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { - -struct StripSymbolsPass : PassInfoMixin<StripSymbolsPass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -struct StripNonDebugSymbolsPass : PassInfoMixin<StripNonDebugSymbolsPass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -struct StripDebugDeclarePass : PassInfoMixin<StripDebugDeclarePass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -struct StripDeadDebugInfoPass : PassInfoMixin<StripDeadDebugInfoPass> { - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); -}; - -} // end namespace llvm - -#endif // LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif +#pragma once + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +//===- StripSymbols.h - Strip symbols and debug info from a module --------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// The StripSymbols transformation implements code stripping. Specifically, it +// can delete: +// +// * names for virtual registers +// * symbols for internal globals and functions +// * debug information +// +// Note that this transformation makes code much less readable, so it should +// only be used in situations where the 'strip' utility would be used, such as +// reducing code size or making it harder to reverse engineer code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H +#define LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +struct StripSymbolsPass : PassInfoMixin<StripSymbolsPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +struct StripNonDebugSymbolsPass : PassInfoMixin<StripNonDebugSymbolsPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +struct StripDebugDeclarePass : PassInfoMixin<StripDebugDeclarePass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +struct StripDeadDebugInfoPass : PassInfoMixin<StripDeadDebugInfoPass> { + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_IPO_STRIPSYMBOLS_H + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif diff --git a/contrib/libs/llvm12/include/llvm/Transforms/IPO/WholeProgramDevirt.h b/contrib/libs/llvm12/include/llvm/Transforms/IPO/WholeProgramDevirt.h index 135d78a1d3..0e0cc1fd16 100644 --- a/contrib/libs/llvm12/include/llvm/Transforms/IPO/WholeProgramDevirt.h +++ b/contrib/libs/llvm12/include/llvm/Transforms/IPO/WholeProgramDevirt.h @@ -230,9 +230,9 @@ void setAfterReturnValues(MutableArrayRef<VirtualCallTarget> Targets, struct WholeProgramDevirtPass : public PassInfoMixin<WholeProgramDevirtPass> { ModuleSummaryIndex *ExportSummary; const ModuleSummaryIndex *ImportSummary; - bool UseCommandLine = false; - WholeProgramDevirtPass() - : ExportSummary(nullptr), ImportSummary(nullptr), UseCommandLine(true) {} + bool UseCommandLine = false; + WholeProgramDevirtPass() + : ExportSummary(nullptr), ImportSummary(nullptr), UseCommandLine(true) {} WholeProgramDevirtPass(ModuleSummaryIndex *ExportSummary, const ModuleSummaryIndex *ImportSummary) : ExportSummary(ExportSummary), ImportSummary(ImportSummary) { |