[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