[llvm] r332674 - Revert r332657: "[AA] cfl-anders-aa with field sensitivity"

George Burgess IV via llvm-commits llvm-commits at lists.llvm.org
Thu May 17 14:56:40 PDT 2018


Author: gbiv
Date: Thu May 17 14:56:39 2018
New Revision: 332674

URL: http://llvm.org/viewvc/llvm-project?rev=332674&view=rev
Log:
Revert r332657: "[AA] cfl-anders-aa with field sensitivity"

I don't believe the person who LGTMed this review has appropriate
context on this code. I apologize if I'm wrong.

Removed:
    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=332674&r1=332673&r2=332674&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/AliasAnalysisSummary.h (original)
+++ llvm/trunk/lib/Analysis/AliasAnalysisSummary.h Thu May 17 14:56:39 2018
@@ -134,31 +134,18 @@ 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 FieldOffset UnknownOffset =
-    std::numeric_limits<FieldOffset>::max();
+static const int64_t UnknownOffset = INT64_MAX;
 
-inline FieldOffset addFieldOffset(FieldOffset LHS, FieldOffset RHS) {
+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;
 }
 
-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=332674&r1=332673&r2=332674&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CFLAndersAliasAnalysis.cpp Thu May 17 14:56:39 2018
@@ -153,59 +153,11 @@ 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<OffsetInstantiatedValue, StateSet>;
+  using ValueStateMap = DenseMap<InstantiatedValue, StateSet>;
   using ValueReachMap = DenseMap<InstantiatedValue, ValueStateMap>;
 
   ValueReachMap ReachMap;
@@ -214,11 +166,10 @@ public:
   using const_valuestate_iterator = ValueStateMap::const_iterator;
   using const_value_iterator = ValueReachMap::const_iterator;
 
-  // Insert edge 'From->To' at state 'State' with offset 'Offset'
-  bool insert(InstantiatedValue From, InstantiatedValue To, FieldOffset Offset,
-              MatchState State) {
+  // Insert edge 'From->To' at state 'State'
+  bool insert(InstantiatedValue From, InstantiatedValue To, MatchState State) {
     assert(From != To);
-    auto &States = ReachMap[To][OffsetInstantiatedValue{From, Offset}];
+    auto &States = ReachMap[To][From];
     auto Idx = static_cast<size_t>(State);
     if (!States.test(Idx)) {
       States.set(Idx);
@@ -303,7 +254,6 @@ public:
 struct WorkListItem {
   InstantiatedValue From;
   InstantiatedValue To;
-  FieldOffset Offset;
   MatchState State;
 };
 
@@ -311,13 +261,63 @@ 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,11 +389,9 @@ 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 (OVal.IVal.DerefLevel == 0)
-        AliasList.push_back(
-            OffsetValue{OVal.IVal.Val, negFieldOffset(OVal.Offset)});
+      if (InnerMapping.first.DerefLevel == 0)
+        AliasList.push_back(OffsetValue{InnerMapping.first.Val, UnknownOffset});
     }
 
     // Sort AliasList for faster lookup
@@ -432,27 +430,24 @@ 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(SrcIVal, RetVals)) {
+        if (auto Src = getInterfaceValue(InnerMapping.first, RetVals)) {
           // This may happen if both Dst and Src are return values
           if (*Dst == *Src)
             continue;
 
           if (hasReadOnlyState(InnerMapping.second))
-            ExtRelations.push_back(ExternalRelation{*Dst, *Src, Offset});
+            ExtRelations.push_back(ExternalRelation{*Dst, *Src, UnknownOffset});
           // No need to check for WriteOnly state, since ReachSet is symmetric
         } else {
           // If Src is not a param/return, add it to ValueMap
-
+          auto SrcIVal = InnerMapping.first;
           if (hasReadOnlyState(InnerMapping.second))
             ValueMap[SrcIVal.Val].FromRecords.push_back(
-                ValueSummary::Record{*Dst, SrcIVal.DerefLevel, Offset});
+                ValueSummary::Record{*Dst, SrcIVal.DerefLevel});
           if (hasWriteOnlyState(InnerMapping.second))
             ValueMap[SrcIVal.Val].ToRecords.push_back(
-                ValueSummary::Record{*Dst, SrcIVal.DerefLevel, Offset});
+                ValueSummary::Record{*Dst, SrcIVal.DerefLevel});
         }
       }
     }
@@ -471,20 +466,14 @@ 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},
-                             subFieldOffset(SrcOffset, DstOffset)});
+        ExtRelations.push_back(ExternalRelation{
+            InterfaceValue{SrcIndex, SrcLevel},
+            InterfaceValue{DstIndex, DstLevel}, UnknownOffset});
       }
     }
   }
@@ -602,14 +591,12 @@ bool CFLAndersAAResult::FunctionInfo::ma
 }
 
 static void propagate(InstantiatedValue From, InstantiatedValue To,
-                      FieldOffset Offset, MatchState State,
-                      ReachabilitySet &ReachSet,
+                      MatchState State, ReachabilitySet &ReachSet,
                       std::vector<WorkListItem> &WorkList) {
   if (From == To)
     return;
-
-  if (ReachSet.insert(From, To, Offset, State))
-    WorkList.push_back(WorkListItem{From, To, Offset, State});
+  if (ReachSet.insert(From, To, State))
+    WorkList.push_back(WorkListItem{From, To, State});
 }
 
 static void initializeWorkList(std::vector<WorkListItem> &WorkList,
@@ -623,15 +610,13 @@ 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 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
+      // 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
       for (auto &Edge : ValueInfo.getNodeInfoAtLevel(I).Edges) {
-        propagate(Edge.Other, Src, Edge.Offset, MatchState::FlowFromReadOnly,
-                  ReachSet, WorkList);
-        propagate(Src, Edge.Other, negFieldOffset(Edge.Offset),
-                  MatchState::FlowToWriteOnly, ReachSet, WorkList);
+        propagate(Edge.Other, Src, MatchState::FlowFromReadOnly, ReachSet,
+                  WorkList);
+        propagate(Src, Edge.Other, MatchState::FlowToWriteOnly, ReachSet,
+                  WorkList);
       }
     }
   }
@@ -650,41 +635,37 @@ 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.
-  // 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);
-      }
+  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);
     }
   }
 
@@ -697,23 +678,17 @@ 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,
-                subFieldOffset(Offset, AssignEdge.Offset), State, ReachSet,
-                WorkList);
-    }
+    for (const auto &AssignEdge : NodeInfo->Edges)
+      propagate(FromNode, AssignEdge.Other, State, ReachSet, WorkList);
   };
   auto NextRevAssignState = [&](MatchState State) {
-    for (const auto &RevAssignEdge : NodeInfo->ReverseEdges) {
-      propagate(FromNode, RevAssignEdge.Other,
-                addFieldOffset(Offset, RevAssignEdge.Offset), State, ReachSet,
-                WorkList);
-    }
+    for (const auto &RevAssignEdge : NodeInfo->ReverseEdges)
+      propagate(FromNode, RevAssignEdge.Other, State, ReachSet, WorkList);
   };
   auto NextMemState = [&](MatchState State) {
     if (auto AliasSet = MemSet.getMemoryAliases(ToNode)) {
       for (const auto &MemAlias : *AliasSet)
-        propagate(FromNode, MemAlias, Offset, State, ReachSet, WorkList);
+        propagate(FromNode, MemAlias, State, ReachSet, WorkList);
     }
   };
 
@@ -778,7 +753,7 @@ static AliasAttrMap buildAttrMap(const C
 
       // Propagate attr on the same level
       for (const auto &Mapping : ReachSet.reachableValueAliases(Dst)) {
-        auto Src = Mapping.first.IVal;
+        auto Src = Mapping.first;
         if (AttrMap.add(Src, DstAttr))
           NextList.push_back(Src);
       }
@@ -813,19 +788,11 @@ CFLAndersAAResult::buildInfoFrom(const F
 
   std::vector<WorkListItem> WorkList, NextList;
   initializeWorkList(WorkList, ReachSet, Graph);
-
-  bool LoopInGraph = false;
+  // TODO: make sure we don't stop before the fix point is reached
   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=332674&r1=332673&r2=332674&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CFLGraph.h (original)
+++ llvm/trunk/lib/Analysis/CFLGraph.h Thu May 17 14:56:39 2018
@@ -62,7 +62,7 @@ public:
 
   struct Edge {
     Node Other;
-    FieldOffset Offset;
+    int64_t Offset;
   };
 
   using EdgeList = std::vector<Edge>;
@@ -125,7 +125,7 @@ public:
     Info->Attr |= Attr;
   }
 
-  void addEdge(Node From, Node To, FieldOffset Offset = 0) {
+  void addEdge(Node From, Node To, int64_t 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, FieldOffset Offset = 0) {
+    void addAssignEdge(Value *From, Value *To, int64_t 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) {
-      FieldOffset Offset = UnknownOffset;
+      uint64_t 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, IRelation->Offset);
+            Graph.addEdge(IRelation->From, IRelation->To);
           }
         }
 

Removed: llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll?rev=332673&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/Andersen/field.ll (removed)
@@ -1,102 +0,0 @@
-; 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
-}




More information about the llvm-commits mailing list