[llvm] 7f30472 - [Analysis] Remove AliasAnalysisSummary.cpp
Kazu Hirata via llvm-commits
llvm-commits at lists.llvm.org
Wed May 17 08:40:01 PDT 2023
Author: Kazu Hirata
Date: 2023-05-17T08:39:48-07:00
New Revision: 7f3047219cf557fd161c3cd0dd32e7713438dc38
URL: https://github.com/llvm/llvm-project/commit/7f3047219cf557fd161c3cd0dd32e7713438dc38
DIFF: https://github.com/llvm/llvm-project/commit/7f3047219cf557fd161c3cd0dd32e7713438dc38.diff
LOG: [Analysis] Remove AliasAnalysisSummary.cpp
The last use was removed by:
commit 8005332835246c54a4a6b026eede930ed559deb4
Author: Nikita Popov <npopov at redhat.com>
Date: Fri Dec 9 11:57:50 2022 +0100
Differential Revision: https://reviews.llvm.org/D150748
Added:
Modified:
llvm/lib/Analysis/CMakeLists.txt
Removed:
llvm/lib/Analysis/AliasAnalysisSummary.cpp
llvm/lib/Analysis/AliasAnalysisSummary.h
llvm/lib/Analysis/StratifiedSets.h
################################################################################
diff --git a/llvm/lib/Analysis/AliasAnalysisSummary.cpp b/llvm/lib/Analysis/AliasAnalysisSummary.cpp
deleted file mode 100644
index a91791c0b4d5..000000000000
--- a/llvm/lib/Analysis/AliasAnalysisSummary.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-#include "AliasAnalysisSummary.h"
-#include "llvm/IR/Argument.h"
-#include "llvm/IR/InstrTypes.h"
-#include "llvm/IR/Type.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-namespace cflaa {
-
-namespace {
-const unsigned AttrEscapedIndex = 0;
-const unsigned AttrUnknownIndex = 1;
-const unsigned AttrGlobalIndex = 2;
-const unsigned AttrCallerIndex = 3;
-const unsigned AttrFirstArgIndex = 4;
-const unsigned AttrLastArgIndex = NumAliasAttrs;
-const unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
-
-// It would be *slightly* prettier if we changed these to AliasAttrs, but it
-// seems that both GCC and MSVC emit dynamic initializers for const bitsets.
-using AliasAttr = unsigned;
-const AliasAttr AttrNone = 0;
-const AliasAttr AttrEscaped = 1 << AttrEscapedIndex;
-const AliasAttr AttrUnknown = 1 << AttrUnknownIndex;
-const AliasAttr AttrGlobal = 1 << AttrGlobalIndex;
-const AliasAttr AttrCaller = 1 << AttrCallerIndex;
-const AliasAttr ExternalAttrMask = AttrEscaped | AttrUnknown | AttrGlobal;
-}
-
-AliasAttrs getAttrNone() { return AttrNone; }
-
-AliasAttrs getAttrUnknown() { return AttrUnknown; }
-bool hasUnknownAttr(AliasAttrs Attr) { return Attr.test(AttrUnknownIndex); }
-
-AliasAttrs getAttrCaller() { return AttrCaller; }
-bool hasCallerAttr(AliasAttrs Attr) { return Attr.test(AttrCaller); }
-bool hasUnknownOrCallerAttr(AliasAttrs Attr) {
- return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
-}
-
-AliasAttrs getAttrEscaped() { return AttrEscaped; }
-bool hasEscapedAttr(AliasAttrs Attr) { return Attr.test(AttrEscapedIndex); }
-
-static AliasAttr argNumberToAttr(unsigned ArgNum) {
- if (ArgNum >= AttrMaxNumArgs)
- return AttrUnknown;
- // N.B. MSVC complains if we use `1U` here, since AliasAttr' ctor takes
- // an unsigned long long.
- return AliasAttr(1ULL << (ArgNum + AttrFirstArgIndex));
-}
-
-AliasAttrs getGlobalOrArgAttrFromValue(const Value &Val) {
- if (isa<GlobalValue>(Val))
- return AttrGlobal;
-
- if (auto *Arg = dyn_cast<Argument>(&Val))
- // Only pointer arguments should have the argument attribute,
- // because things can't escape through scalars without us seeing a
- // cast, and thus, interaction with them doesn't matter.
- if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
- return argNumberToAttr(Arg->getArgNo());
- return AttrNone;
-}
-
-bool isGlobalOrArgAttr(AliasAttrs Attr) {
- return Attr.reset(AttrEscapedIndex)
- .reset(AttrUnknownIndex)
- .reset(AttrCallerIndex)
- .any();
-}
-
-AliasAttrs getExternallyVisibleAttrs(AliasAttrs Attr) {
- return Attr & AliasAttrs(ExternalAttrMask);
-}
-
-std::optional<InstantiatedValue>
-instantiateInterfaceValue(InterfaceValue IValue, CallBase &Call) {
- auto Index = IValue.Index;
- auto *V = (Index == 0) ? &Call : Call.getArgOperand(Index - 1);
- if (V->getType()->isPointerTy())
- return InstantiatedValue{V, IValue.DerefLevel};
- return std::nullopt;
-}
-
-std::optional<InstantiatedRelation>
-instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call) {
- auto From = instantiateInterfaceValue(ERelation.From, Call);
- if (!From)
- return std::nullopt;
- auto To = instantiateInterfaceValue(ERelation.To, Call);
- if (!To)
- return std::nullopt;
- return InstantiatedRelation{*From, *To, ERelation.Offset};
-}
-
-std::optional<InstantiatedAttr>
-instantiateExternalAttribute(ExternalAttribute EAttr, CallBase &Call) {
- auto Value = instantiateInterfaceValue(EAttr.IValue, Call);
- if (!Value)
- return std::nullopt;
- return InstantiatedAttr{*Value, EAttr.Attr};
-}
-}
-}
diff --git a/llvm/lib/Analysis/AliasAnalysisSummary.h b/llvm/lib/Analysis/AliasAnalysisSummary.h
deleted file mode 100644
index ab337bad22c7..000000000000
--- a/llvm/lib/Analysis/AliasAnalysisSummary.h
+++ /dev/null
@@ -1,268 +0,0 @@
-//=====- CFLSummary.h - Abstract stratified sets implementation. --------=====//
-//
-// 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 defines various utility types and functions useful to
-/// summary-based alias analysis.
-///
-/// Summary-based analysis, also known as bottom-up analysis, is a style of
-/// interprocedrual static analysis that tries to analyze the callees before the
-/// callers get analyzed. The key idea of summary-based analysis is to first
-/// process each function independently, outline its behavior in a condensed
-/// summary, and then instantiate the summary at the callsite when the said
-/// function is called elsewhere. This is often in contrast to another style
-/// called top-down analysis, in which callers are always analyzed first before
-/// the callees.
-///
-/// In a summary-based analysis, functions must be examined independently and
-/// out-of-context. We have no information on the state of the memory, the
-/// arguments, the global values, and anything else external to the function. To
-/// carry out the analysis conservative assumptions have to be made about those
-/// external states. In exchange for the potential loss of precision, the
-/// summary we obtain this way is highly reusable, which makes the analysis
-/// easier to scale to large programs even if carried out context-sensitively.
-///
-/// Currently, all CFL-based alias analyses adopt the summary-based approach
-/// and therefore heavily rely on this header.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
-#define LLVM_ANALYSIS_ALIASANALYSISSUMMARY_H
-
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/SmallVector.h"
-#include <bitset>
-#include <optional>
-
-namespace llvm {
-
-class CallBase;
-class Value;
-
-namespace cflaa {
-
-//===----------------------------------------------------------------------===//
-// AliasAttr related stuffs
-//===----------------------------------------------------------------------===//
-
-/// The number of attributes that AliasAttr should contain. Attributes are
-/// described below, and 32 was an arbitrary choice because it fits nicely in 32
-/// bits (because we use a bitset for AliasAttr).
-static const unsigned NumAliasAttrs = 32;
-
-/// These are attributes that an alias analysis can use to mark certain special
-/// properties of a given pointer. Refer to the related functions below to see
-/// what kinds of attributes are currently defined.
-typedef std::bitset<NumAliasAttrs> AliasAttrs;
-
-/// Attr represent whether the said pointer comes from an unknown source
-/// (such as opaque memory or an integer cast).
-AliasAttrs getAttrNone();
-
-/// AttrUnknown represent whether the said pointer comes from a source not known
-/// to alias analyses (such as opaque memory or an integer cast).
-AliasAttrs getAttrUnknown();
-bool hasUnknownAttr(AliasAttrs);
-
-/// AttrCaller represent whether the said pointer comes from a source not known
-/// to the current function but known to the caller. Values pointed to by the
-/// arguments of the current function have this attribute set
-AliasAttrs getAttrCaller();
-bool hasCallerAttr(AliasAttrs);
-bool hasUnknownOrCallerAttr(AliasAttrs);
-
-/// AttrEscaped represent whether the said pointer comes from a known source but
-/// escapes to the unknown world (e.g. casted to an integer, or passed as an
-/// argument to opaque function). Unlike non-escaped pointers, escaped ones may
-/// alias pointers coming from unknown sources.
-AliasAttrs getAttrEscaped();
-bool hasEscapedAttr(AliasAttrs);
-
-/// AttrGlobal represent whether the said pointer is a global value.
-/// AttrArg represent whether the said pointer is an argument, and if so, what
-/// index the argument has.
-AliasAttrs getGlobalOrArgAttrFromValue(const Value &);
-bool isGlobalOrArgAttr(AliasAttrs);
-
-/// Given an AliasAttrs, return a new AliasAttrs that only contains attributes
-/// meaningful to the caller. This function is primarily used for
-/// interprocedural analysis
-/// Currently, externally visible AliasAttrs include AttrUnknown, AttrGlobal,
-/// and AttrEscaped
-AliasAttrs getExternallyVisibleAttrs(AliasAttrs);
-
-//===----------------------------------------------------------------------===//
-// Function summary related stuffs
-//===----------------------------------------------------------------------===//
-
-/// The maximum number of arguments we can put into a summary.
-static const unsigned MaxSupportedArgsInSummary = 50;
-
-/// We use InterfaceValue to describe parameters/return value, as well as
-/// potential memory locations that are pointed to by parameters/return value,
-/// of a function.
-/// Index is an integer which represents a single parameter or a return value.
-/// When the index is 0, it refers to the return value. Non-zero index i refers
-/// to the i-th parameter.
-/// DerefLevel indicates the number of dereferences one must perform on the
-/// parameter/return value to get this InterfaceValue.
-struct InterfaceValue {
- unsigned Index;
- unsigned DerefLevel;
-};
-
-inline bool operator==(InterfaceValue LHS, InterfaceValue RHS) {
- return LHS.Index == RHS.Index && LHS.DerefLevel == RHS.DerefLevel;
-}
-inline bool operator!=(InterfaceValue LHS, InterfaceValue RHS) {
- return !(LHS == RHS);
-}
-inline bool operator<(InterfaceValue LHS, InterfaceValue RHS) {
- return LHS.Index < RHS.Index ||
- (LHS.Index == RHS.Index && LHS.DerefLevel < RHS.DerefLevel);
-}
-inline bool operator>(InterfaceValue LHS, InterfaceValue RHS) {
- return RHS < LHS;
-}
-inline bool operator<=(InterfaceValue LHS, InterfaceValue RHS) {
- return !(RHS < LHS);
-}
-inline bool operator>=(InterfaceValue LHS, InterfaceValue RHS) {
- return !(LHS < RHS);
-}
-
-// We use UnknownOffset to represent pointer offsets that cannot be determined
-// at compile time. Note that MemoryLocation::UnknownSize cannot be used here
-// because we require a signed value.
-static const int64_t UnknownOffset = INT64_MAX;
-
-inline int64_t addOffset(int64_t LHS, int64_t RHS) {
- if (LHS == UnknownOffset || RHS == UnknownOffset)
- return UnknownOffset;
- // FIXME: Do we need to guard against integer overflow here?
- return LHS + RHS;
-}
-
-/// We use ExternalRelation to describe an externally visible aliasing relations
-/// between parameters/return value of a function.
-struct ExternalRelation {
- InterfaceValue From, To;
- int64_t Offset;
-};
-
-inline bool operator==(ExternalRelation LHS, ExternalRelation RHS) {
- return LHS.From == RHS.From && LHS.To == RHS.To && LHS.Offset == RHS.Offset;
-}
-inline bool operator!=(ExternalRelation LHS, ExternalRelation RHS) {
- return !(LHS == RHS);
-}
-inline bool operator<(ExternalRelation LHS, ExternalRelation RHS) {
- if (LHS.From < RHS.From)
- return true;
- if (LHS.From > RHS.From)
- return false;
- if (LHS.To < RHS.To)
- return true;
- if (LHS.To > RHS.To)
- return false;
- return LHS.Offset < RHS.Offset;
-}
-inline bool operator>(ExternalRelation LHS, ExternalRelation RHS) {
- return RHS < LHS;
-}
-inline bool operator<=(ExternalRelation LHS, ExternalRelation RHS) {
- return !(RHS < LHS);
-}
-inline bool operator>=(ExternalRelation LHS, ExternalRelation RHS) {
- return !(LHS < RHS);
-}
-
-/// We use ExternalAttribute to describe an externally visible AliasAttrs
-/// for parameters/return value.
-struct ExternalAttribute {
- InterfaceValue IValue;
- AliasAttrs Attr;
-};
-
-/// AliasSummary is just a collection of ExternalRelation and ExternalAttribute
-struct AliasSummary {
- // RetParamRelations is a collection of ExternalRelations.
- SmallVector<ExternalRelation, 8> RetParamRelations;
-
- // RetParamAttributes is a collection of ExternalAttributes.
- SmallVector<ExternalAttribute, 8> RetParamAttributes;
-};
-
-/// This is the result of instantiating InterfaceValue at a particular call
-struct InstantiatedValue {
- Value *Val;
- unsigned DerefLevel;
-};
-std::optional<InstantiatedValue>
-instantiateInterfaceValue(InterfaceValue IValue, CallBase &Call);
-
-inline bool operator==(InstantiatedValue LHS, InstantiatedValue RHS) {
- return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
-}
-inline bool operator!=(InstantiatedValue LHS, InstantiatedValue RHS) {
- return !(LHS == RHS);
-}
-inline bool operator<(InstantiatedValue LHS, InstantiatedValue RHS) {
- return std::less<Value *>()(LHS.Val, RHS.Val) ||
- (LHS.Val == RHS.Val && LHS.DerefLevel < RHS.DerefLevel);
-}
-inline bool operator>(InstantiatedValue LHS, InstantiatedValue RHS) {
- return RHS < LHS;
-}
-inline bool operator<=(InstantiatedValue LHS, InstantiatedValue RHS) {
- return !(RHS < LHS);
-}
-inline bool operator>=(InstantiatedValue LHS, InstantiatedValue RHS) {
- return !(LHS < RHS);
-}
-
-/// This is the result of instantiating ExternalRelation at a particular
-/// callsite
-struct InstantiatedRelation {
- InstantiatedValue From, To;
- int64_t Offset;
-};
-std::optional<InstantiatedRelation>
-instantiateExternalRelation(ExternalRelation ERelation, CallBase &Call);
-
-/// This is the result of instantiating ExternalAttribute at a particular
-/// callsite
-struct InstantiatedAttr {
- InstantiatedValue IValue;
- AliasAttrs Attr;
-};
-std::optional<InstantiatedAttr>
-instantiateExternalAttribute(ExternalAttribute EAttr, CallBase &Call);
-}
-
-template <> struct DenseMapInfo<cflaa::InstantiatedValue> {
- static inline cflaa::InstantiatedValue getEmptyKey() {
- return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getEmptyKey(),
- DenseMapInfo<unsigned>::getEmptyKey()};
- }
- static inline cflaa::InstantiatedValue getTombstoneKey() {
- return cflaa::InstantiatedValue{DenseMapInfo<Value *>::getTombstoneKey(),
- DenseMapInfo<unsigned>::getTombstoneKey()};
- }
- static unsigned getHashValue(const cflaa::InstantiatedValue &IV) {
- return DenseMapInfo<std::pair<Value *, unsigned>>::getHashValue(
- std::make_pair(IV.Val, IV.DerefLevel));
- }
- static bool isEqual(const cflaa::InstantiatedValue &LHS,
- const cflaa::InstantiatedValue &RHS) {
- return LHS.Val == RHS.Val && LHS.DerefLevel == RHS.DerefLevel;
- }
-};
-}
-
-#endif
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 2f684e6ced3f..166a83e8bbfb 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -26,7 +26,6 @@ endif()
add_llvm_component_library(LLVMAnalysis
AliasAnalysis.cpp
AliasAnalysisEvaluator.cpp
- AliasAnalysisSummary.cpp
AliasSetTracker.cpp
Analysis.cpp
AssumeBundleQueries.cpp
diff --git a/llvm/lib/Analysis/StratifiedSets.h b/llvm/lib/Analysis/StratifiedSets.h
deleted file mode 100644
index 193e4a461e66..000000000000
--- a/llvm/lib/Analysis/StratifiedSets.h
+++ /dev/null
@@ -1,595 +0,0 @@
-//===- StratifiedSets.h - Abstract stratified sets implementation. --------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_ADT_STRATIFIEDSETS_H
-#define LLVM_ADT_STRATIFIEDSETS_H
-
-#include "AliasAnalysisSummary.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include <bitset>
-#include <cassert>
-#include <cmath>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-namespace cflaa {
-/// An index into Stratified Sets.
-typedef unsigned StratifiedIndex;
-/// NOTE: ^ This can't be a short -- bootstrapping clang has a case where
-/// ~1M sets exist.
-
-// Container of information related to a value in a StratifiedSet.
-struct StratifiedInfo {
- StratifiedIndex Index;
- /// For field sensitivity, etc. we can tack fields on here.
-};
-
-/// A "link" between two StratifiedSets.
-struct StratifiedLink {
- /// This is a value used to signify "does not exist" where the
- /// StratifiedIndex type is used.
- ///
- /// This is used instead of std::optional<StratifiedIndex> because
- /// std::optional<StratifiedIndex> would eat up a considerable amount of extra
- /// memory, after struct padding/alignment is taken into account.
- static const StratifiedIndex SetSentinel;
-
- /// The index for the set "above" current
- StratifiedIndex Above;
-
- /// The link for the set "below" current
- StratifiedIndex Below;
-
- /// Attributes for these StratifiedSets.
- AliasAttrs Attrs;
-
- StratifiedLink() : Above(SetSentinel), Below(SetSentinel) {}
-
- bool hasBelow() const { return Below != SetSentinel; }
- bool hasAbove() const { return Above != SetSentinel; }
-
- void clearBelow() { Below = SetSentinel; }
- void clearAbove() { Above = SetSentinel; }
-};
-
-/// These are stratified sets, as described in "Fast algorithms for
-/// Dyck-CFL-reachability with applications to Alias Analysis" by Zhang Q, Lyu M
-/// R, Yuan H, and Su Z. -- in short, this is meant to represent
diff erent sets
-/// of Value*s. If two Value*s are in the same set, or if both sets have
-/// overlapping attributes, then the Value*s are said to alias.
-///
-/// Sets may be related by position, meaning that one set may be considered as
-/// above or below another. In CFL Alias Analysis, this gives us an indication
-/// of how two variables are related; if the set of variable A is below a set
-/// containing variable B, then at some point, a variable that has interacted
-/// with B (or B itself) was either used in order to extract the variable A, or
-/// was used as storage of variable A.
-///
-/// Sets may also have attributes (as noted above). These attributes are
-/// generally used for noting whether a variable in the set has interacted with
-/// a variable whose origins we don't quite know (i.e. globals/arguments), or if
-/// the variable may have had operations performed on it (modified in a function
-/// call). All attributes that exist in a set A must exist in all sets marked as
-/// below set A.
-template <typename T> class StratifiedSets {
-public:
- StratifiedSets() = default;
- StratifiedSets(StratifiedSets &&) = default;
- StratifiedSets &operator=(StratifiedSets &&) = default;
-
- StratifiedSets(DenseMap<T, StratifiedInfo> Map,
- std::vector<StratifiedLink> Links)
- : Values(std::move(Map)), Links(std::move(Links)) {}
-
- std::optional<StratifiedInfo> find(const T &Elem) const {
- auto Iter = Values.find(Elem);
- if (Iter == Values.end())
- return std::nullopt;
- return Iter->second;
- }
-
- const StratifiedLink &getLink(StratifiedIndex Index) const {
- assert(inbounds(Index));
- return Links[Index];
- }
-
-private:
- DenseMap<T, StratifiedInfo> Values;
- std::vector<StratifiedLink> Links;
-
- bool inbounds(StratifiedIndex Idx) const { return Idx < Links.size(); }
-};
-
-/// Generic Builder class that produces StratifiedSets instances.
-///
-/// The goal of this builder is to efficiently produce correct StratifiedSets
-/// instances. To this end, we use a few tricks:
-/// > Set chains (A method for linking sets together)
-/// > Set remaps (A method for marking a set as an alias [irony?] of another)
-///
-/// ==== Set chains ====
-/// This builder has a notion of some value A being above, below, or with some
-/// other value B:
-/// > The `A above B` relationship implies that there is a reference edge
-/// going from A to B. Namely, it notes that A can store anything in B's set.
-/// > The `A below B` relationship is the opposite of `A above B`. It implies
-/// that there's a dereference edge going from A to B.
-/// > The `A with B` relationship states that there's an assignment edge going
-/// from A to B, and that A and B should be treated as equals.
-///
-/// As an example, take the following code snippet:
-///
-/// %a = alloca i32, align 4
-/// %ap = alloca i32*, align 8
-/// %app = alloca i32**, align 8
-/// store %a, %ap
-/// store %ap, %app
-/// %aw = getelementptr %ap, i32 0
-///
-/// Given this, the following relations exist:
-/// - %a below %ap & %ap above %a
-/// - %ap below %app & %app above %ap
-/// - %aw with %ap & %ap with %aw
-///
-/// These relations produce the following sets:
-/// [{%a}, {%ap, %aw}, {%app}]
-///
-/// ...Which state that the only MayAlias relationship in the above program is
-/// between %ap and %aw.
-///
-/// Because LLVM allows arbitrary casts, code like the following needs to be
-/// supported:
-/// %ip = alloca i64, align 8
-/// %ipp = alloca i64*, align 8
-/// %i = bitcast i64** ipp to i64
-/// store i64* %ip, i64** %ipp
-/// store i64 %i, i64* %ip
-///
-/// Which, because %ipp ends up *both* above and below %ip, is fun.
-///
-/// This is solved by merging %i and %ipp into a single set (...which is the
-/// only way to solve this, since their bit patterns are equivalent). Any sets
-/// that ended up in between %i and %ipp at the time of merging (in this case,
-/// the set containing %ip) also get conservatively merged into the set of %i
-/// and %ipp. In short, the resulting StratifiedSet from the above code would be
-/// {%ip, %ipp, %i}.
-///
-/// ==== Set remaps ====
-/// More of an implementation detail than anything -- when merging sets, we need
-/// to update the numbers of all of the elements mapped to those sets. Rather
-/// than doing this at each merge, we note in the BuilderLink structure that a
-/// remap has occurred, and use this information so we can defer renumbering set
-/// elements until build time.
-template <typename T> class StratifiedSetsBuilder {
- /// Represents a Stratified Set, with information about the Stratified
- /// Set above it, the set below it, and whether the current set has been
- /// remapped to another.
- struct BuilderLink {
- const StratifiedIndex Number;
-
- BuilderLink(StratifiedIndex N) : Number(N) {
- Remap = StratifiedLink::SetSentinel;
- }
-
- bool hasAbove() const {
- assert(!isRemapped());
- return Link.hasAbove();
- }
-
- bool hasBelow() const {
- assert(!isRemapped());
- return Link.hasBelow();
- }
-
- void setBelow(StratifiedIndex I) {
- assert(!isRemapped());
- Link.Below = I;
- }
-
- void setAbove(StratifiedIndex I) {
- assert(!isRemapped());
- Link.Above = I;
- }
-
- void clearBelow() {
- assert(!isRemapped());
- Link.clearBelow();
- }
-
- void clearAbove() {
- assert(!isRemapped());
- Link.clearAbove();
- }
-
- StratifiedIndex getBelow() const {
- assert(!isRemapped());
- assert(hasBelow());
- return Link.Below;
- }
-
- StratifiedIndex getAbove() const {
- assert(!isRemapped());
- assert(hasAbove());
- return Link.Above;
- }
-
- AliasAttrs getAttrs() {
- assert(!isRemapped());
- return Link.Attrs;
- }
-
- void setAttrs(AliasAttrs Other) {
- assert(!isRemapped());
- Link.Attrs |= Other;
- }
-
- bool isRemapped() const { return Remap != StratifiedLink::SetSentinel; }
-
- /// For initial remapping to another set
- void remapTo(StratifiedIndex Other) {
- assert(!isRemapped());
- Remap = Other;
- }
-
- StratifiedIndex getRemapIndex() const {
- assert(isRemapped());
- return Remap;
- }
-
- /// Should only be called when we're already remapped.
- void updateRemap(StratifiedIndex Other) {
- assert(isRemapped());
- Remap = Other;
- }
-
- /// Prefer the above functions to calling things directly on what's returned
- /// from this -- they guard against unexpected calls when the current
- /// BuilderLink is remapped.
- const StratifiedLink &getLink() const { return Link; }
-
- private:
- StratifiedLink Link;
- StratifiedIndex Remap;
- };
-
- /// This function performs all of the set unioning/value renumbering
- /// that we've been putting off, and generates a vector<StratifiedLink> that
- /// may be placed in a StratifiedSets instance.
- void finalizeSets(std::vector<StratifiedLink> &StratLinks) {
- DenseMap<StratifiedIndex, StratifiedIndex> Remaps;
- for (auto &Link : Links) {
- if (Link.isRemapped())
- continue;
-
- StratifiedIndex Number = StratLinks.size();
- Remaps.insert(std::make_pair(Link.Number, Number));
- StratLinks.push_back(Link.getLink());
- }
-
- for (auto &Link : StratLinks) {
- if (Link.hasAbove()) {
- auto &Above = linksAt(Link.Above);
- auto Iter = Remaps.find(Above.Number);
- assert(Iter != Remaps.end());
- Link.Above = Iter->second;
- }
-
- if (Link.hasBelow()) {
- auto &Below = linksAt(Link.Below);
- auto Iter = Remaps.find(Below.Number);
- assert(Iter != Remaps.end());
- Link.Below = Iter->second;
- }
- }
-
- for (auto &Pair : Values) {
- auto &Info = Pair.second;
- auto &Link = linksAt(Info.Index);
- auto Iter = Remaps.find(Link.Number);
- assert(Iter != Remaps.end());
- Info.Index = Iter->second;
- }
- }
-
- /// There's a guarantee in StratifiedLink where all bits set in a
- /// Link.externals will be set in all Link.externals "below" it.
- static void propagateAttrs(std::vector<StratifiedLink> &Links) {
- const auto getHighestParentAbove = [&Links](StratifiedIndex Idx) {
- const auto *Link = &Links[Idx];
- while (Link->hasAbove()) {
- Idx = Link->Above;
- Link = &Links[Idx];
- }
- return Idx;
- };
-
- SmallSet<StratifiedIndex, 16> Visited;
- for (unsigned I = 0, E = Links.size(); I < E; ++I) {
- auto CurrentIndex = getHighestParentAbove(I);
- if (!Visited.insert(CurrentIndex).second)
- continue;
-
- while (Links[CurrentIndex].hasBelow()) {
- auto &CurrentBits = Links[CurrentIndex].Attrs;
- auto NextIndex = Links[CurrentIndex].Below;
- auto &NextBits = Links[NextIndex].Attrs;
- NextBits |= CurrentBits;
- CurrentIndex = NextIndex;
- }
- }
- }
-
-public:
- /// Builds a StratifiedSet from the information we've been given since either
- /// construction or the prior build() call.
- StratifiedSets<T> build() {
- std::vector<StratifiedLink> StratLinks;
- finalizeSets(StratLinks);
- propagateAttrs(StratLinks);
- Links.clear();
- return StratifiedSets<T>(std::move(Values), std::move(StratLinks));
- }
-
- bool has(const T &Elem) const { return get(Elem).has_value(); }
-
- bool add(const T &Main) {
- if (get(Main))
- return false;
-
- auto NewIndex = getNewUnlinkedIndex();
- return addAtMerging(Main, NewIndex);
- }
-
- /// Restructures the stratified sets as necessary to make "ToAdd" in a
- /// set above "Main". There are some cases where this is not possible (see
- /// above), so we merge them such that ToAdd and Main are in the same set.
- bool addAbove(const T &Main, const T &ToAdd) {
- assert(has(Main));
- auto Index = *indexOf(Main);
- if (!linksAt(Index).hasAbove())
- addLinkAbove(Index);
-
- auto Above = linksAt(Index).getAbove();
- return addAtMerging(ToAdd, Above);
- }
-
- /// Restructures the stratified sets as necessary to make "ToAdd" in a
- /// set below "Main". There are some cases where this is not possible (see
- /// above), so we merge them such that ToAdd and Main are in the same set.
- bool addBelow(const T &Main, const T &ToAdd) {
- assert(has(Main));
- auto Index = *indexOf(Main);
- if (!linksAt(Index).hasBelow())
- addLinkBelow(Index);
-
- auto Below = linksAt(Index).getBelow();
- return addAtMerging(ToAdd, Below);
- }
-
- bool addWith(const T &Main, const T &ToAdd) {
- assert(has(Main));
- auto MainIndex = *indexOf(Main);
- return addAtMerging(ToAdd, MainIndex);
- }
-
- void noteAttributes(const T &Main, AliasAttrs NewAttrs) {
- assert(has(Main));
- auto *Info = *get(Main);
- auto &Link = linksAt(Info->Index);
- Link.setAttrs(NewAttrs);
- }
-
-private:
- DenseMap<T, StratifiedInfo> Values;
- std::vector<BuilderLink> Links;
-
- /// Adds the given element at the given index, merging sets if necessary.
- bool addAtMerging(const T &ToAdd, StratifiedIndex Index) {
- StratifiedInfo Info = {Index};
- auto Pair = Values.insert(std::make_pair(ToAdd, Info));
- if (Pair.second)
- return true;
-
- auto &Iter = Pair.first;
- auto &IterSet = linksAt(Iter->second.Index);
- auto &ReqSet = linksAt(Index);
-
- // Failed to add where we wanted to. Merge the sets.
- if (&IterSet != &ReqSet)
- merge(IterSet.Number, ReqSet.Number);
-
- return false;
- }
-
- /// Gets the BuilderLink at the given index, taking set remapping into
- /// account.
- BuilderLink &linksAt(StratifiedIndex Index) {
- auto *Start = &Links[Index];
- if (!Start->isRemapped())
- return *Start;
-
- auto *Current = Start;
- while (Current->isRemapped())
- Current = &Links[Current->getRemapIndex()];
-
- auto NewRemap = Current->Number;
-
- // Run through everything that has yet to be updated, and update them to
- // remap to NewRemap
- Current = Start;
- while (Current->isRemapped()) {
- auto *Next = &Links[Current->getRemapIndex()];
- Current->updateRemap(NewRemap);
- Current = Next;
- }
-
- return *Current;
- }
-
- /// Merges two sets into one another. Assumes that these sets are not
- /// already one in the same.
- void merge(StratifiedIndex Idx1, StratifiedIndex Idx2) {
- assert(inbounds(Idx1) && inbounds(Idx2));
- assert(&linksAt(Idx1) != &linksAt(Idx2) &&
- "Merging a set into itself is not allowed");
-
- // CASE 1: If the set at `Idx1` is above or below `Idx2`, we need to merge
- // both the
- // given sets, and all sets between them, into one.
- if (tryMergeUpwards(Idx1, Idx2))
- return;
-
- if (tryMergeUpwards(Idx2, Idx1))
- return;
-
- // CASE 2: The set at `Idx1` is not in the same chain as the set at `Idx2`.
- // We therefore need to merge the two chains together.
- mergeDirect(Idx1, Idx2);
- }
-
- /// Merges two sets assuming that the set at `Idx1` is unreachable from
- /// traversing above or below the set at `Idx2`.
- void mergeDirect(StratifiedIndex Idx1, StratifiedIndex Idx2) {
- assert(inbounds(Idx1) && inbounds(Idx2));
-
- auto *LinksInto = &linksAt(Idx1);
- auto *LinksFrom = &linksAt(Idx2);
- // Merging everything above LinksInto then proceeding to merge everything
- // below LinksInto becomes problematic, so we go as far "up" as possible!
- while (LinksInto->hasAbove() && LinksFrom->hasAbove()) {
- LinksInto = &linksAt(LinksInto->getAbove());
- LinksFrom = &linksAt(LinksFrom->getAbove());
- }
-
- if (LinksFrom->hasAbove()) {
- LinksInto->setAbove(LinksFrom->getAbove());
- auto &NewAbove = linksAt(LinksInto->getAbove());
- NewAbove.setBelow(LinksInto->Number);
- }
-
- // Merging strategy:
- // > If neither has links below, stop.
- // > If only `LinksInto` has links below, stop.
- // > If only `LinksFrom` has links below, reset `LinksInto.Below` to
- // match `LinksFrom.Below`
- // > If both have links above, deal with those next.
- while (LinksInto->hasBelow() && LinksFrom->hasBelow()) {
- auto FromAttrs = LinksFrom->getAttrs();
- LinksInto->setAttrs(FromAttrs);
-
- // Remap needs to happen after getBelow(), but before
- // assignment of LinksFrom
- auto *NewLinksFrom = &linksAt(LinksFrom->getBelow());
- LinksFrom->remapTo(LinksInto->Number);
- LinksFrom = NewLinksFrom;
- LinksInto = &linksAt(LinksInto->getBelow());
- }
-
- if (LinksFrom->hasBelow()) {
- LinksInto->setBelow(LinksFrom->getBelow());
- auto &NewBelow = linksAt(LinksInto->getBelow());
- NewBelow.setAbove(LinksInto->Number);
- }
-
- LinksInto->setAttrs(LinksFrom->getAttrs());
- LinksFrom->remapTo(LinksInto->Number);
- }
-
- /// Checks to see if lowerIndex is at a level lower than upperIndex. If so, it
- /// will merge lowerIndex with upperIndex (and all of the sets between) and
- /// return true. Otherwise, it will return false.
- bool tryMergeUpwards(StratifiedIndex LowerIndex, StratifiedIndex UpperIndex) {
- assert(inbounds(LowerIndex) && inbounds(UpperIndex));
- auto *Lower = &linksAt(LowerIndex);
- auto *Upper = &linksAt(UpperIndex);
- if (Lower == Upper)
- return true;
-
- SmallVector<BuilderLink *, 8> Found;
- auto *Current = Lower;
- auto Attrs = Current->getAttrs();
- while (Current->hasAbove() && Current != Upper) {
- Found.push_back(Current);
- Attrs |= Current->getAttrs();
- Current = &linksAt(Current->getAbove());
- }
-
- if (Current != Upper)
- return false;
-
- Upper->setAttrs(Attrs);
-
- if (Lower->hasBelow()) {
- auto NewBelowIndex = Lower->getBelow();
- Upper->setBelow(NewBelowIndex);
- auto &NewBelow = linksAt(NewBelowIndex);
- NewBelow.setAbove(UpperIndex);
- } else {
- Upper->clearBelow();
- }
-
- for (const auto &Ptr : Found)
- Ptr->remapTo(Upper->Number);
-
- return true;
- }
-
- std::optional<const StratifiedInfo *> get(const T &Val) const {
- auto Result = Values.find(Val);
- if (Result == Values.end())
- return std::nullopt;
- return &Result->second;
- }
-
- std::optional<StratifiedInfo *> get(const T &Val) {
- auto Result = Values.find(Val);
- if (Result == Values.end())
- return std::nullopt;
- return &Result->second;
- }
-
- std::optional<StratifiedIndex> indexOf(const T &Val) {
- auto MaybeVal = get(Val);
- if (!MaybeVal)
- return std::nullopt;
- auto *Info = *MaybeVal;
- auto &Link = linksAt(Info->Index);
- return Link.Number;
- }
-
- StratifiedIndex addLinkBelow(StratifiedIndex Set) {
- auto At = addLinks();
- Links[Set].setBelow(At);
- Links[At].setAbove(Set);
- return At;
- }
-
- StratifiedIndex addLinkAbove(StratifiedIndex Set) {
- auto At = addLinks();
- Links[At].setBelow(Set);
- Links[Set].setAbove(At);
- return At;
- }
-
- StratifiedIndex getNewUnlinkedIndex() { return addLinks(); }
-
- StratifiedIndex addLinks() {
- auto Link = Links.size();
- Links.push_back(BuilderLink(Link));
- return Link;
- }
-
- bool inbounds(StratifiedIndex N) const { return N < Links.size(); }
-};
-}
-}
-#endif // LLVM_ADT_STRATIFIEDSETS_H
More information about the llvm-commits
mailing list