[llvm] r332657 - [AA] cfl-anders-aa with field sensitivity

George Burgess IV via llvm-commits llvm-commits at lists.llvm.org
Thu May 17 15:01:00 PDT 2018


Reverted in r332674, since I don't believe the person who LGTMed this
review has appropriate context on this code. I apologize if I'm wrong. I'll
comment on the review thread shortly.

On Thu, May 17, 2018 at 1:27 PM David Bolvansky via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: xbolva00
> Date: Thu May 17 13:23:33 2018
> New Revision: 332657
>
> URL: http://llvm.org/viewvc/llvm-project?rev=332657&view=rev
> Log:
> [AA] cfl-anders-aa with field sensitivity
>
> Summary:
> There was some unfinished work started for offset tracking in CFLGraph by
> the author of implementation of Andersen algorithm. This work was completed
> and support for field sensitivity was added to the core of Andersen
> algorithm.
>
> The performance results seem promising.
>
> SPEC2006 int_base score was increased by 1.1 % (I  compared clang 6.0 with
> clang 6.0 with this patch). The avergae compile time was increased by +- 1
> % according my measures with small and medium C/C++ projects (I did not
> tested it on the large projects with milions of lines of code)
>
> Reviewers: chandlerc, george.burgess.iv, rja
>
> Reviewed By: rja
>
> Subscribers: rja, llvm-commits
>
> Differential Revision: https://reviews.llvm.org/D46282
>
> Added:
>     llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll
> Modified:
>     llvm/trunk/lib/Analysis/AliasAnalysisSummary.h
>     llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp
>     llvm/trunk/lib/Analysis/CFLGraph.h
>
> Modified: llvm/trunk/lib/Analysis/AliasAnalysisSummary.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysisSummary.h?rev=332657&r1=332656&r2=332657&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/AliasAnalysisSummary.h (original)
> +++ llvm/trunk/lib/Analysis/AliasAnalysisSummary.h Thu May 17 13:23:33 2018
> @@ -134,18 +134,31 @@ inline bool operator>=(InterfaceValue LH
>    return !(LHS < RHS);
>  }
>
> +using FieldOffset = int64_t;
>  // 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;
> +static const FieldOffset UnknownOffset =
> +    std::numeric_limits<FieldOffset>::max();
>
> -inline int64_t addOffset(int64_t LHS, int64_t RHS) {
> +inline FieldOffset addFieldOffset(FieldOffset LHS, FieldOffset RHS) {
>    if (LHS == UnknownOffset || RHS == UnknownOffset)
>      return UnknownOffset;
> -  // FIXME: Do we need to guard against integer overflow here?
> +
>    return LHS + RHS;
>  }
>
> +inline FieldOffset subFieldOffset(FieldOffset LHS, FieldOffset RHS) {
> +  if (LHS == UnknownOffset || RHS == UnknownOffset)
> +    return UnknownOffset;
> +
> +  return LHS - RHS;
> +}
> +
> +inline FieldOffset negFieldOffset(FieldOffset Offset) {
> +  return subFieldOffset(0, Offset);
> +}
> +
>  /// We use ExternalRelation to describe an externally visible aliasing
> relations
>  /// between parameters/return value of a function.
>  struct ExternalRelation {
>
> Modified: llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp?rev=332657&r1=332656&r2=332657&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp (original)
> +++ llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp Thu May 17 13:23:33
> 2018
> @@ -153,11 +153,59 @@ struct OffsetInstantiatedValue {
>  bool operator==(OffsetInstantiatedValue LHS, OffsetInstantiatedValue RHS)
> {
>    return LHS.IVal == RHS.IVal && LHS.Offset == RHS.Offset;
>  }
> +}
> +
> +namespace llvm {
> +
> +// Specialize DenseMapInfo for OffsetValue.
> +template <> struct DenseMapInfo<OffsetValue> {
> +  static OffsetValue getEmptyKey() {
> +    return OffsetValue{DenseMapInfo<const Value *>::getEmptyKey(),
> +                       DenseMapInfo<FieldOffset>::getEmptyKey()};
> +  }
> +  static OffsetValue getTombstoneKey() {
> +    return OffsetValue{DenseMapInfo<const Value *>::getTombstoneKey(),
> +                       DenseMapInfo<FieldOffset>::getEmptyKey()};
> +  }
> +  static unsigned getHashValue(const OffsetValue &OVal) {
> +    return DenseMapInfo<std::pair<const Value *,
> FieldOffset>>::getHashValue(
> +        std::make_pair(OVal.Val, OVal.Offset));
> +  }
> +  static bool isEqual(const OffsetValue &LHS, const OffsetValue &RHS) {
> +    return LHS == RHS;
> +  }
> +};
> +
> +// Specialize DenseMapInfo for OffsetInstantiatedValue.
> +template <> struct DenseMapInfo<OffsetInstantiatedValue> {
> +  static OffsetInstantiatedValue getEmptyKey() {
> +    return OffsetInstantiatedValue{
> +        DenseMapInfo<InstantiatedValue>::getEmptyKey(),
> +        DenseMapInfo<FieldOffset>::getEmptyKey()};
> +  }
> +  static OffsetInstantiatedValue getTombstoneKey() {
> +    return OffsetInstantiatedValue{
> +        DenseMapInfo<InstantiatedValue>::getTombstoneKey(),
> +        DenseMapInfo<FieldOffset>::getEmptyKey()};
> +  }
> +  static unsigned getHashValue(const OffsetInstantiatedValue &OVal) {
> +    return DenseMapInfo<std::pair<InstantiatedValue, FieldOffset>>::
> +        getHashValue(std::make_pair(OVal.IVal, OVal.Offset));
> +  }
> +  static bool isEqual(const OffsetInstantiatedValue &LHS,
> +                      const OffsetInstantiatedValue &RHS) {
> +    return LHS == RHS;
> +  }
> +};
> +
> +} // namespace llvm
> +
> +namespace {
>
>  // We use ReachabilitySet to keep track of value aliases (The nonterminal
> "V" in
>  // the paper) during the analysis.
>  class ReachabilitySet {
> -  using ValueStateMap = DenseMap<InstantiatedValue, StateSet>;
> +  using ValueStateMap = DenseMap<OffsetInstantiatedValue, StateSet>;
>    using ValueReachMap = DenseMap<InstantiatedValue, ValueStateMap>;
>
>    ValueReachMap ReachMap;
> @@ -166,10 +214,11 @@ public:
>    using const_valuestate_iterator = ValueStateMap::const_iterator;
>    using const_value_iterator = ValueReachMap::const_iterator;
>
> -  // Insert edge 'From->To' at state 'State'
> -  bool insert(InstantiatedValue From, InstantiatedValue To, MatchState
> State) {
> +  // Insert edge 'From->To' at state 'State' with offset 'Offset'
> +  bool insert(InstantiatedValue From, InstantiatedValue To, FieldOffset
> Offset,
> +              MatchState State) {
>      assert(From != To);
> -    auto &States = ReachMap[To][From];
> +    auto &States = ReachMap[To][OffsetInstantiatedValue{From, Offset}];
>      auto Idx = static_cast<size_t>(State);
>      if (!States.test(Idx)) {
>        States.set(Idx);
> @@ -254,6 +303,7 @@ public:
>  struct WorkListItem {
>    InstantiatedValue From;
>    InstantiatedValue To;
> +  FieldOffset Offset;
>    MatchState State;
>  };
>
> @@ -261,63 +311,13 @@ struct ValueSummary {
>    struct Record {
>      InterfaceValue IValue;
>      unsigned DerefLevel;
> +    FieldOffset Offset;
>    };
>    SmallVector<Record, 4> FromRecords, ToRecords;
>  };
>
>  } // end anonymous namespace
>
> -namespace llvm {
> -
> -// Specialize DenseMapInfo for OffsetValue.
> -template <> struct DenseMapInfo<OffsetValue> {
> -  static OffsetValue getEmptyKey() {
> -    return OffsetValue{DenseMapInfo<const Value *>::getEmptyKey(),
> -                       DenseMapInfo<int64_t>::getEmptyKey()};
> -  }
> -
> -  static OffsetValue getTombstoneKey() {
> -    return OffsetValue{DenseMapInfo<const Value *>::getTombstoneKey(),
> -                       DenseMapInfo<int64_t>::getEmptyKey()};
> -  }
> -
> -  static unsigned getHashValue(const OffsetValue &OVal) {
> -    return DenseMapInfo<std::pair<const Value *, int64_t>>::getHashValue(
> -        std::make_pair(OVal.Val, OVal.Offset));
> -  }
> -
> -  static bool isEqual(const OffsetValue &LHS, const OffsetValue &RHS) {
> -    return LHS == RHS;
> -  }
> -};
> -
> -// Specialize DenseMapInfo for OffsetInstantiatedValue.
> -template <> struct DenseMapInfo<OffsetInstantiatedValue> {
> -  static OffsetInstantiatedValue getEmptyKey() {
> -    return OffsetInstantiatedValue{
> -        DenseMapInfo<InstantiatedValue>::getEmptyKey(),
> -        DenseMapInfo<int64_t>::getEmptyKey()};
> -  }
> -
> -  static OffsetInstantiatedValue getTombstoneKey() {
> -    return OffsetInstantiatedValue{
> -        DenseMapInfo<InstantiatedValue>::getTombstoneKey(),
> -        DenseMapInfo<int64_t>::getEmptyKey()};
> -  }
> -
> -  static unsigned getHashValue(const OffsetInstantiatedValue &OVal) {
> -    return DenseMapInfo<std::pair<InstantiatedValue,
> int64_t>>::getHashValue(
> -        std::make_pair(OVal.IVal, OVal.Offset));
> -  }
> -
> -  static bool isEqual(const OffsetInstantiatedValue &LHS,
> -                      const OffsetInstantiatedValue &RHS) {
> -    return LHS == RHS;
> -  }
> -};
> -
> -} // end namespace llvm
> -
>  class CFLAndersAAResult::FunctionInfo {
>    /// Map a value to other values that may alias it
>    /// Since the alias relation is symmetric, to save some space we assume
> values
> @@ -389,9 +389,11 @@ populateAliasMap(DenseMap<const Value *,
>      auto Val = OuterMapping.first.Val;
>      auto &AliasList = AliasMap[Val];
>      for (const auto &InnerMapping : OuterMapping.second) {
> +      auto OVal = InnerMapping.first;
>        // Again, AliasMap only cares about top-level values
> -      if (InnerMapping.first.DerefLevel == 0)
> -        AliasList.push_back(OffsetValue{InnerMapping.first.Val,
> UnknownOffset});
> +      if (OVal.IVal.DerefLevel == 0)
> +        AliasList.push_back(
> +            OffsetValue{OVal.IVal.Val, negFieldOffset(OVal.Offset)});
>      }
>
>      // Sort AliasList for faster lookup
> @@ -430,24 +432,27 @@ static void populateExternalRelations(
>    for (const auto &OuterMapping : ReachSet.value_mappings()) {
>      if (auto Dst = getInterfaceValue(OuterMapping.first, RetVals)) {
>        for (const auto &InnerMapping : OuterMapping.second) {
> +        auto OVal = InnerMapping.first;
> +        auto SrcIVal = OVal.IVal;
> +        auto Offset = OVal.Offset;
>          // If Src is a param/return value, we get a same-level assignment.
> -        if (auto Src = getInterfaceValue(InnerMapping.first, RetVals)) {
> +        if (auto Src = getInterfaceValue(SrcIVal, RetVals)) {
>            // This may happen if both Dst and Src are return values
>            if (*Dst == *Src)
>              continue;
>
>            if (hasReadOnlyState(InnerMapping.second))
> -            ExtRelations.push_back(ExternalRelation{*Dst, *Src,
> UnknownOffset});
> +            ExtRelations.push_back(ExternalRelation{*Dst, *Src, Offset});
>            // No need to check for WriteOnly state, since ReachSet is
> symmetric
>          } else {
>            // If Src is not a param/return, add it to ValueMap
> -          auto SrcIVal = InnerMapping.first;
> +
>            if (hasReadOnlyState(InnerMapping.second))
>              ValueMap[SrcIVal.Val].FromRecords.push_back(
> -                ValueSummary::Record{*Dst, SrcIVal.DerefLevel});
> +                ValueSummary::Record{*Dst, SrcIVal.DerefLevel, Offset});
>            if (hasWriteOnlyState(InnerMapping.second))
>              ValueMap[SrcIVal.Val].ToRecords.push_back(
> -                ValueSummary::Record{*Dst, SrcIVal.DerefLevel});
> +                ValueSummary::Record{*Dst, SrcIVal.DerefLevel, Offset});
>          }
>        }
>      }
> @@ -466,14 +471,20 @@ static void populateExternalRelations(
>          auto SrcLevel = FromRecord.IValue.DerefLevel;
>          auto DstIndex = ToRecord.IValue.Index;
>          auto DstLevel = ToRecord.IValue.DerefLevel;
> +
> +        // Offsets to be pushed to External Relations
> +        auto SrcOffset = FromRecord.Offset;
> +        auto DstOffset = ToRecord.Offset;
> +
>          if (ToLevel > FromLevel)
>            SrcLevel += ToLevel - FromLevel;
>          else
>            DstLevel += FromLevel - ToLevel;
>
> -        ExtRelations.push_back(ExternalRelation{
> -            InterfaceValue{SrcIndex, SrcLevel},
> -            InterfaceValue{DstIndex, DstLevel}, UnknownOffset});
> +        ExtRelations.push_back(
> +            ExternalRelation{InterfaceValue{SrcIndex, SrcLevel},
> +                             InterfaceValue{DstIndex, DstLevel},
> +                             subFieldOffset(SrcOffset, DstOffset)});
>        }
>      }
>    }
> @@ -591,12 +602,14 @@ bool CFLAndersAAResult::FunctionInfo::ma
>  }
>
>  static void propagate(InstantiatedValue From, InstantiatedValue To,
> -                      MatchState State, ReachabilitySet &ReachSet,
> +                      FieldOffset Offset, MatchState State,
> +                      ReachabilitySet &ReachSet,
>                        std::vector<WorkListItem> &WorkList) {
>    if (From == To)
>      return;
> -  if (ReachSet.insert(From, To, State))
> -    WorkList.push_back(WorkListItem{From, To, State});
> +
> +  if (ReachSet.insert(From, To, Offset, State))
> +    WorkList.push_back(WorkListItem{From, To, Offset, State});
>  }
>
>  static void initializeWorkList(std::vector<WorkListItem> &WorkList,
> @@ -610,13 +623,15 @@ static void initializeWorkList(std::vect
>      // Insert all immediate assignment neighbors to the worklist
>      for (unsigned I = 0, E = ValueInfo.getNumLevels(); I < E; ++I) {
>        auto Src = InstantiatedValue{Val, I};
> -      // If there's an assignment edge from X to Y, it means Y is
> reachable from
> -      // X at S2 and X is reachable from Y at S1
> +      // If we have an assignment edge from X + Offset to Y, it means that
> +      // (Y - Offset) is reachable from X at the state FlowToWriteOnly
> +      // At the same time, (X + Offset) is reachable from Y at the state
> +      // FlowFromReadOnly
>        for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges) {
> -        propagate(Edge.Other, Src, MatchState::FlowFromReadOnly, ReachSet,
> -                  WorkList);
> -        propagate(Src, Edge.Other, MatchState::FlowToWriteOnly, ReachSet,
> -                  WorkList);
> +        propagate(Edge.Other, Src, Edge.Offset,
> MatchState::FlowFromReadOnly,
> +                  ReachSet, WorkList);
> +        propagate(Src, Edge.Other, negFieldOffset(Edge.Offset),
> +                  MatchState::FlowToWriteOnly, ReachSet, WorkList);
>        }
>      }
>    }
> @@ -635,37 +650,41 @@ static void processWorkListItem(const Wo
>                                  std::vector<WorkListItem> &WorkList) {
>    auto FromNode = Item.From;
>    auto ToNode = Item.To;
> +  auto Offset = Item.Offset;
>
>    auto NodeInfo = Graph.getNode(ToNode);
>    assert(NodeInfo != nullptr);
>
> -  // TODO: propagate field offsets
> -
>    // FIXME: Here is a neat trick we can do: since both ReachSet and
> MemSet holds
>    // relations that are symmetric, we could actually cut the storage by
> half by
>    // sorting FromNode and ToNode before insertion happens.
>
>    // The newly added value alias pair may potentially generate more memory
>    // alias pairs. Check for them here.
> -  auto FromNodeBelow = getNodeBelow(Graph, FromNode);
> -  auto ToNodeBelow = getNodeBelow(Graph, ToNode);
> -  if (FromNodeBelow && ToNodeBelow &&
> -      MemSet.insert(*FromNodeBelow, *ToNodeBelow)) {
> -    propagate(*FromNodeBelow, *ToNodeBelow,
> -              MatchState::FlowFromMemAliasNoReadWrite, ReachSet,
> WorkList);
> -    for (const auto &Mapping :
> ReachSet.reachableValueAliases(*FromNodeBelow)) {
> -      auto Src = Mapping.first;
> -      auto MemAliasPropagate = [&](MatchState FromState, MatchState
> ToState) {
> -        if (Mapping.second.test(static_cast<size_t>(FromState)))
> -          propagate(Src, *ToNodeBelow, ToState, ReachSet, WorkList);
> -      };
> -
> -      MemAliasPropagate(MatchState::FlowFromReadOnly,
> -                        MatchState::FlowFromMemAliasReadOnly);
> -      MemAliasPropagate(MatchState::FlowToWriteOnly,
> -                        MatchState::FlowToMemAliasWriteOnly);
> -      MemAliasPropagate(MatchState::FlowToReadWrite,
> -                        MatchState::FlowToMemAliasReadWrite);
> +  // MemAlias reachability can only be triggered when Offset is 0 or
> Unknown
> +  if (Offset == 0 || Offset == UnknownOffset) {
> +    auto FromNodeBelow = getNodeBelow(Graph, FromNode);
> +    auto ToNodeBelow = getNodeBelow(Graph, ToNode);
> +    if (FromNodeBelow && ToNodeBelow &&
> +        MemSet.insert(*FromNodeBelow, *ToNodeBelow)) {
> +      propagate(*FromNodeBelow, *ToNodeBelow, Offset,
> +                MatchState::FlowFromMemAliasNoReadWrite, ReachSet,
> WorkList);
> +      for (const auto &Mapping :
> +           ReachSet.reachableValueAliases(*FromNodeBelow)) {
> +        auto SrcOVal = Mapping.first;
> +        auto MemAliasPropagate = [&](MatchState FromState, MatchState
> ToState) {
> +          if (Mapping.second.test(static_cast<size_t>(FromState)))
> +            propagate(SrcOVal.IVal, *ToNodeBelow, SrcOVal.Offset, ToState,
> +                      ReachSet, WorkList);
> +        };
> +
> +        MemAliasPropagate(MatchState::FlowFromReadOnly,
> +                          MatchState::FlowFromMemAliasReadOnly);
> +        MemAliasPropagate(MatchState::FlowToWriteOnly,
> +                          MatchState::FlowToMemAliasWriteOnly);
> +        MemAliasPropagate(MatchState::FlowToReadWrite,
> +                          MatchState::FlowToMemAliasReadWrite);
> +      }
>      }
>    }
>
> @@ -678,17 +697,23 @@ static void processWorkListItem(const Wo
>    // - If Y is an alias of X, then reverse assignment edges (if there is
> any)
>    // should precede any assignment edges on the path from X to Y.
>    auto NextAssignState = [&](MatchState State) {
> -    for (const auto &AssignEdge : NodeInfo->Edges)
> -      propagate(FromNode, AssignEdge.Other, State, ReachSet, WorkList);
> +    for (const auto &AssignEdge : NodeInfo->Edges) {
> +      propagate(FromNode, AssignEdge.Other,
> +                subFieldOffset(Offset, AssignEdge.Offset), State,
> ReachSet,
> +                WorkList);
> +    }
>    };
>    auto NextRevAssignState = [&](MatchState State) {
> -    for (const auto &RevAssignEdge : NodeInfo->ReverseEdges)
> -      propagate(FromNode, RevAssignEdge.Other, State, ReachSet, WorkList);
> +    for (const auto &RevAssignEdge : NodeInfo->ReverseEdges) {
> +      propagate(FromNode, RevAssignEdge.Other,
> +                addFieldOffset(Offset, RevAssignEdge.Offset), State,
> ReachSet,
> +                WorkList);
> +    }
>    };
>    auto NextMemState = [&](MatchState State) {
>      if (auto AliasSet = MemSet.getMemoryAliases(ToNode)) {
>        for (const auto &MemAlias : *AliasSet)
> -        propagate(FromNode, MemAlias, State, ReachSet, WorkList);
> +        propagate(FromNode, MemAlias, Offset, State, ReachSet, WorkList);
>      }
>    };
>
> @@ -753,7 +778,7 @@ static AliasAttrMap buildAttrMap(const C
>
>        // Propagate attr on the same level
>        for (const auto &Mapping : ReachSet.reachableValueAliases(Dst)) {
> -        auto Src = Mapping.first;
> +        auto Src = Mapping.first.IVal;
>          if (AttrMap.add(Src, DstAttr))
>            NextList.push_back(Src);
>        }
> @@ -788,11 +813,19 @@ CFLAndersAAResult::buildInfoFrom(const F
>
>    std::vector<WorkListItem> WorkList, NextList;
>    initializeWorkList(WorkList, ReachSet, Graph);
> -  // TODO: make sure we don't stop before the fix point is reached
> +
> +  bool LoopInGraph = false;
>    while (!WorkList.empty()) {
>      for (const auto &Item : WorkList)
>        processWorkListItem(Item, Graph, ReachSet, MemSet, NextList);
>
> +    if (NextList.size() == WorkList.size()) {
> +      // stop if loop in CFL graph
> +      if (LoopInGraph)
> +        break;
> +      LoopInGraph = true;
> +    }
> +
>      NextList.swap(WorkList);
>      NextList.clear();
>    }
>
> Modified: llvm/trunk/lib/Analysis/CFLGraph.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CFLGraph.h?rev=332657&r1=332656&r2=332657&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Analysis/CFLGraph.h (original)
> +++ llvm/trunk/lib/Analysis/CFLGraph.h Thu May 17 13:23:33 2018
> @@ -62,7 +62,7 @@ public:
>
>    struct Edge {
>      Node Other;
> -    int64_t Offset;
> +    FieldOffset Offset;
>    };
>
>    using EdgeList = std::vector<Edge>;
> @@ -125,7 +125,7 @@ public:
>      Info->Attr |= Attr;
>    }
>
> -  void addEdge(Node From, Node To, int64_t Offset = 0) {
> +  void addEdge(Node From, Node To, FieldOffset Offset = 0) {
>      auto *FromInfo = getNode(From);
>      assert(FromInfo != nullptr);
>      auto *ToInfo = getNode(To);
> @@ -219,7 +219,7 @@ template <typename CFLAA> class CFLGraph
>          Graph.addNode(InstantiatedValue{Val, 0}, Attr);
>      }
>
> -    void addAssignEdge(Value *From, Value *To, int64_t Offset = 0) {
> +    void addAssignEdge(Value *From, Value *To, FieldOffset Offset = 0) {
>        assert(From != nullptr && To != nullptr);
>        if (!From->getType()->isPointerTy() ||
> !To->getType()->isPointerTy())
>          return;
> @@ -312,7 +312,7 @@ template <typename CFLAA> class CFLGraph
>      }
>
>      void visitGEP(GEPOperator &GEPOp) {
> -      uint64_t Offset = UnknownOffset;
> +      FieldOffset Offset = UnknownOffset;
>        APInt
> APOffset(DL.getPointerSizeInBits(GEPOp.getPointerAddressSpace()),
>                       0);
>        if (GEPOp.accumulateConstantOffset(DL, APOffset))
> @@ -397,7 +397,7 @@ template <typename CFLAA> class CFLGraph
>            if (IRelation.hasValue()) {
>              Graph.addNode(IRelation->From);
>              Graph.addNode(IRelation->To);
> -            Graph.addEdge(IRelation->From, IRelation->To);
> +            Graph.addEdge(IRelation->From, IRelation->To,
> IRelation->Offset);
>            }
>          }
>
>
> Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll?rev=332657&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll (added)
> +++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll Thu May 17
> 13:23:33 2018
> @@ -0,0 +1,102 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt < %s -disable-basicaa -cfl-anders-aa -aa-eval
> -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
> +; RUN: opt < %s -aa-pipeline=cfl-anders-aa -passes=aa-eval
> -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
> +
> +; CHECK: Function: test_simple_offsets
> +; CHECK: NoAlias: i64* %b, i64** %acast
> +; CHECK: NoAlias: i64** %acast, i64** %aoff
> +; CHECK: NoAlias: i64* %b, i64** %acastoff
> +; CHECK: NoAlias: i64** %acast, i64** %acastoff
> +; CHECK: NoAlias: [2 x i64*]* %a, i64* %acastload
> +; CHECK: MayAlias: i64* %acastload, i64* %b
> +; CHECK: NoAlias: i64* %acastload, i64** %aoff
> +; CHECK: NoAlias: i64* %acastload, i64** %acast
> +; CHECK: NoAlias: i64* %acastload, i64** %acastoff
> +define void @test_simple_offsets() {
> +  %a = alloca [2 x i64*], align 8
> +  %b = alloca i64, align 4
> +  %aoff = getelementptr inbounds [2 x i64*], [2 x i64*]* %a, i64 0, i64 1
> +  store i64* %b, i64** %aoff
> +
> +  %acast = bitcast [2 x i64*]* %a to i64**
> +  %acastoff = getelementptr inbounds i64*, i64** %acast, i64 1
> +  %acastload = load i64*, i64** %acastoff
> +  ret void
> +}
> +
> +; CHECK: Function: test_unknown_offset
> +; CHECK: MayAlias: [3 x i32]* %a, i32* %an
> +; CHECK: MayAlias: i32* %a4, i32* %an
> +; CHECK: MayAlias: i32* %a8, i32* %an
> +; CHECK: MayAlias: i32* %an, i32* %b
> +; CHECK: MayAlias: [3 x i32]* %a, i32* %bn
> +; CHECK: MayAlias: i32* %a4, i32* %bn
> +; CHECK: MayAlias: i32* %a8, i32* %bn
> +; CHECK: MayAlias: i32* %an, i32* %bn
> +; CHECK: MayAlias: i32* %b, i32* %bn
> +define void @test_unknown_offset(i32 %n) {
> +  %a = alloca [3 x i32], align 4
> +  %a4 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i32 0, i32 1
> +  %a8 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i32 0, i32 2
> +  %an = getelementptr inbounds [3 x i32], [3 x i32]* %a, i32 0, i32 %n
> +  %b = bitcast [3 x i32]* %a to i32*
> +  %bn = getelementptr inbounds i32, i32* %b, i32 %n
> +  ret void
> +}
> +
> +
> +%S = type { i32, i32, i32 }
> +
> +define i32* @return_arg(%S* %arg1, %S* %arg2) {
> +  %acast = bitcast %S* %arg1 to i32*
> +  %aoffset = getelementptr i32, i32* %acast, i32 1
> +  ret i32* %aoffset
> +}
> +
> +define i32* @return_derefence_arg(%S** %arg1) {
> +  %deref = load %S*, %S** %arg1
> +  %deref2 = getelementptr %S, %S* %deref, i32 0, i32 1
> +  ret i32* %deref2
> +}
> +
> +; CHECK-LABEL: Function: test_return_arg_offset
> +; CHECK: NoAlias: %S* %a, %S* %b
> +; CHECK: MayAlias: %S* %a, i32* %c
> +; CHECK: NoAlias: %S* %b, i32* %c
> +; CHECK: NoAlias: i32* %acast, i32* %c
> +; CHECK: NoAlias: i32* %acast, i32* %d
> +define void @test_return_arg_offset() {
> +  %a = alloca %S, align 8
> +  %b = alloca %S, align 8
> +
> +  %c = call i32* @return_arg(%S* %a, %S* %b)
> +  %d = getelementptr %S, %S* %a, i32 0, i32 1
> +  %acast = bitcast %S* %a to i32*
> +
> +  ret void
> +}
> +
> +; CHECK-LABEL: Function: test_return_derefence_arg
> +; CHECK: NoAlias: %S** %p, i32* %c
> +; CHECK: NoAlias: %S* %lp, %S** %p
> +; CHECK: MayAlias: %S* %lp, i32* %c
> +; CHECK: NoAlias: %S** %p, i32* %lp_off
> +; CHECK: MayAlias: i32* %c, i32* %lp_off
> +; CHECK: MayAlias: %S* %lp, i32* %lp_off
> +; CHECK: NoAlias: %S** %p, i32* %acast
> +; CHECK: NoAlias: i32* %acast, i32* %c
> +; CHECK: MayAlias: %S* %lp, i32* %acast
> +; CHECK: NoAlias: i32* %acast, i32* %lp_off
> +define void @test_return_derefence_arg() {
> +  %a = alloca %S, align 8
> +  %p = alloca %S*, align 8
> +
> +  store %S* %a, %S** %p
> +  %c = call i32* @return_derefence_arg(%S** %p)
> +
> +  %lp = load %S*, %S** %p
> +  %lp_off = getelementptr %S, %S* %lp, i32 0, i32 1
> +  %acast = bitcast %S* %a to i32*
> +
> +  ret void
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180517/a048ba7b/attachment.html>


More information about the llvm-commits mailing list