[llvm] r273219 - [CFLAA] Add interprocedural function summaries.
George Burgess IV via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 20 16:10:56 PDT 2016
Author: gbiv
Date: Mon Jun 20 18:10:56 2016
New Revision: 273219
URL: http://llvm.org/viewvc/llvm-project?rev=273219&view=rev
Log:
[CFLAA] Add interprocedural function summaries.
This patch adds function summaries, so that we don't need to recompute
various properties about function parameters/return values at each
callsite of a function. It also adds many interprocedural tests for
CFLAA.
Patch by Jia Chen.
Differential Revision: http://reviews.llvm.org/D21475#inline-182390
Added:
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg-multilevel.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg-multilevel.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-unknown.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-multilevel.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-unknown.ll
llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg.ll
Modified:
llvm/trunk/include/llvm/Analysis/CFLAliasAnalysis.h
llvm/trunk/lib/Analysis/CFLAliasAnalysis.cpp
llvm/trunk/test/Analysis/CFLAliasAnalysis/basic-interproc.ll
Modified: llvm/trunk/include/llvm/Analysis/CFLAliasAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CFLAliasAnalysis.h?rev=273219&r1=273218&r2=273219&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CFLAliasAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/CFLAliasAnalysis.h Mon Jun 20 18:10:56 2016
@@ -30,8 +30,7 @@ class TargetLibraryInfo;
class CFLAAResult : public AAResultBase<CFLAAResult> {
friend AAResultBase<CFLAAResult>;
-
- struct FunctionInfo;
+ class FunctionInfo;
public:
explicit CFLAAResult(const TargetLibraryInfo &);
Modified: llvm/trunk/lib/Analysis/CFLAliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CFLAliasAnalysis.cpp?rev=273219&r1=273218&r2=273219&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CFLAliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/CFLAliasAnalysis.cpp Mon Jun 20 18:10:56 2016
@@ -64,14 +64,30 @@ CFLAAResult::CFLAAResult(CFLAAResult &&A
: AAResultBase(std::move(Arg)), TLI(Arg.TLI) {}
CFLAAResult::~CFLAAResult() {}
+/// We use ExternalRelation to describe an externally visible interaction
+/// between parameters/return value of a function.
+/// Both From and To are integer indices that represent a single parameter or
+/// return value. When the index is 0, they represent the return value. Non-zero
+/// index i represents the i-th parameter.
+struct ExternalRelation {
+ unsigned From, To;
+};
+
/// Information we have about a function and would like to keep around.
-struct CFLAAResult::FunctionInfo {
+class CFLAAResult::FunctionInfo {
StratifiedSets<Value *> Sets;
- // Lots of functions have < 4 returns. Adjust as necessary.
- SmallVector<Value *, 4> ReturnedValues;
- FunctionInfo(StratifiedSets<Value *> &&S, SmallVector<Value *, 4> &&RV)
- : Sets(std::move(S)), ReturnedValues(std::move(RV)) {}
+ // RetParamRelations is a collection of ExternalRelations.
+ SmallVector<ExternalRelation, 8> RetParamRelations;
+
+public:
+ FunctionInfo(Function &Fn, const SmallVectorImpl<Value *> &RetVals,
+ StratifiedSets<Value *> S);
+
+ const StratifiedSets<Value *> &getStratifiedSets() const { return Sets; }
+ const SmallVectorImpl<ExternalRelation> &getRetParamRelations() const {
+ return RetParamRelations;
+ }
};
/// Try to go from a Value* to a Function*. Never returns nullptr.
@@ -101,6 +117,9 @@ LLVM_CONSTEXPR StratifiedAttr AttrEscape
LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex;
LLVM_CONSTEXPR StratifiedAttr AttrGlobal = 1 << AttrGlobalIndex;
+/// The maximum number of arguments we can put into a summary.
+LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
+
/// StratifiedSets call for knowledge of "direction", so this is how we
/// represent that locally.
enum class Level { Same, Above, Below };
@@ -361,147 +380,45 @@ public:
return Fn->isDeclaration() || !Fn->hasLocalLinkage();
}
- /// Gets whether the sets at Index1 above, below, or equal to the sets at
- /// Index2. Returns None if they are not in the same set chain.
- static Optional<Level> getIndexRelation(const StratifiedSets<Value *> &Sets,
- StratifiedIndex Index1,
- StratifiedIndex Index2) {
- if (Index1 == Index2)
- return Level::Same;
-
- const auto *Current = &Sets.getLink(Index1);
- while (Current->hasBelow()) {
- if (Current->Below == Index2)
- return Level::Below;
- Current = &Sets.getLink(Current->Below);
- }
-
- Current = &Sets.getLink(Index1);
- while (Current->hasAbove()) {
- if (Current->Above == Index2)
- return Level::Above;
- Current = &Sets.getLink(Current->Above);
- }
-
- return None;
- }
-
- // Encodes the notion of a "use"
- struct Edge {
- // Which value the edge is coming from
- Value *From;
-
- // Which value the edge is pointing to
- Value *To;
-
- // Edge weight
- EdgeType Weight;
-
- // Whether we aliased any external values along the way that may be
- // invisible to the analysis
- StratifiedAttrs FromAttrs, ToAttrs;
- };
-
- bool
- tryInterproceduralAnalysis(const SmallVectorImpl<Function *> &Fns,
- Value *FuncValue,
- const iterator_range<User::op_iterator> &Args) {
- const unsigned ExpectedMaxArgs = 8;
- const unsigned MaxSupportedArgs = 50;
+ bool tryInterproceduralAnalysis(CallSite CS,
+ const SmallVectorImpl<Function *> &Fns) {
assert(Fns.size() > 0);
- // This algorithm is n^2, so an arbitrary upper-bound of 50 args was
- // selected, so it doesn't take too long in insane cases.
- if (std::distance(Args.begin(), Args.end()) > (int)MaxSupportedArgs)
+ if (CS.arg_size() > MaxSupportedArgsInSummary)
return false;
// Exit early if we'll fail anyway
for (auto *Fn : Fns) {
if (isFunctionExternal(Fn) || Fn->isVarArg())
return false;
+ // Fail if the caller does not provide enough arguments
+ assert(Fn->arg_size() <= CS.arg_size());
auto &MaybeInfo = AA.ensureCached(Fn);
if (!MaybeInfo.hasValue())
return false;
}
- SmallVector<Edge, 8> Output;
- SmallVector<Value *, ExpectedMaxArgs> Arguments(Args.begin(), Args.end());
- SmallVector<StratifiedInfo, ExpectedMaxArgs> Parameters;
for (auto *Fn : Fns) {
- auto &Info = *AA.ensureCached(Fn);
- auto &Sets = Info.Sets;
- auto &RetVals = Info.ReturnedValues;
-
- Parameters.clear();
- for (auto &Param : Fn->args()) {
- auto MaybeInfo = Sets.find(&Param);
- // Did a new parameter somehow get added to the function/slip by?
- if (!MaybeInfo.hasValue())
- return false;
- Parameters.push_back(*MaybeInfo);
- }
-
- // Adding an edge from argument -> return value for each parameter that
- // may alias the return value
- for (unsigned I = 0, E = Parameters.size(); I != E; ++I) {
- auto &ParamInfo = Parameters[I];
- auto &ArgVal = Arguments[I];
- bool AddEdge = false;
- StratifiedAttrs RetAttrs, ParamAttrs;
- for (unsigned X = 0, XE = RetVals.size(); X != XE; ++X) {
- auto MaybeInfo = Sets.find(RetVals[X]);
- if (!MaybeInfo.hasValue())
- return false;
-
- auto &RetInfo = *MaybeInfo;
- RetAttrs |= Sets.getLink(RetInfo.Index).Attrs;
- ParamAttrs |= Sets.getLink(ParamInfo.Index).Attrs;
- auto MaybeRelation =
- getIndexRelation(Sets, ParamInfo.Index, RetInfo.Index);
- if (MaybeRelation.hasValue())
- AddEdge = true;
- }
- if (AddEdge)
- Output.push_back(
- Edge{FuncValue, ArgVal, EdgeType::Assign, RetAttrs, ParamAttrs});
- }
-
- if (Parameters.size() != Arguments.size())
- return false;
+ auto &FnInfo = AA.ensureCached(Fn);
+ assert(FnInfo.hasValue());
- /// Adding edges between arguments for arguments that may end up aliasing
- /// each other. This is necessary for functions such as
- /// void foo(int** a, int** b) { *a = *b; }
- /// (Technically, the proper sets for this would be those below
- /// Arguments[I] and Arguments[X], but our algorithm will produce
- /// extremely similar, and equally correct, results either way)
- for (unsigned I = 0, E = Arguments.size(); I != E; ++I) {
- auto &MainVal = Arguments[I];
- auto &MainInfo = Parameters[I];
- auto &MainAttrs = Sets.getLink(MainInfo.Index).Attrs;
- for (unsigned X = I + 1; X != E; ++X) {
- auto &SubInfo = Parameters[X];
- auto &SubVal = Arguments[X];
- auto &SubAttrs = Sets.getLink(SubInfo.Index).Attrs;
- auto MaybeRelation =
- getIndexRelation(Sets, MainInfo.Index, SubInfo.Index);
-
- if (!MaybeRelation.hasValue())
- continue;
-
- Output.push_back(
- Edge{MainVal, SubVal, EdgeType::Assign, MainAttrs, SubAttrs});
- }
+ auto &RetParamRelations = FnInfo->getRetParamRelations();
+ for (auto &Relation : RetParamRelations) {
+ auto FromIndex = Relation.From;
+ auto ToIndex = Relation.To;
+ auto FromVal = (FromIndex == 0) ? CS.getInstruction()
+ : CS.getArgument(FromIndex - 1);
+ auto ToVal =
+ (ToIndex == 0) ? CS.getInstruction() : CS.getArgument(ToIndex - 1);
+ if (FromVal->getType()->isPointerTy() &&
+ ToVal->getType()->isPointerTy())
+ // Actual arguments must be defined before they are used at callsite.
+ // Therefore by the time we reach here, FromVal and ToVal should
+ // already exist in the graph. We can go ahead and add them directly.
+ Graph.addEdge(FromVal, ToVal, EdgeType::Assign);
}
}
- // Commit all edges in Output to CFLGraph
- for (const auto &Edge : Output) {
- addEdge(Edge.From, Edge.To, Edge.Weight);
- Graph.addAttr(Edge.From, Edge.FromAttrs);
- Graph.addAttr(Edge.To, Edge.ToAttrs);
- }
-
return true;
}
@@ -511,7 +428,7 @@ public:
// Make sure all arguments and return value are added to the graph first
for (Value *V : CS.args())
addNode(V);
- if (!Inst->getType()->isVoidTy())
+ if (Inst->getType()->isPointerTy())
addNode(Inst);
// Check if Inst is a call to a library function that allocates/deallocates
@@ -526,7 +443,7 @@ public:
// that we can tack on.
SmallVector<Function *, 4> Targets;
if (getPossibleTargets(CS, Targets))
- if (tryInterproceduralAnalysis(Targets, Inst, CS.args()))
+ if (tryInterproceduralAnalysis(CS, Targets))
return;
// Because the function is opaque, we need to note that anything
@@ -539,7 +456,7 @@ public:
Escapes.insert(V);
}
- if (!Inst->getType()->isVoidTy()) {
+ if (Inst->getType()->isPointerTy()) {
auto *Fn = CS.getCalledFunction();
if (Fn == nullptr || !Fn->doesNotAlias(0))
Graph.addAttr(Inst, AttrUnknown);
@@ -643,8 +560,10 @@ class CFLGraphBuilder {
void addInstructionToGraph(Instruction &Inst) {
// We don't want the edges of most "return" instructions, but we *do* want
// to know what can be returned.
- if (isa<ReturnInst>(&Inst))
- ReturnedValues.push_back(&Inst);
+ if (auto RetInst = dyn_cast<ReturnInst>(&Inst))
+ if (auto RetVal = RetInst->getReturnValue())
+ if (RetVal->getType()->isPointerTy())
+ ReturnedValues.push_back(RetVal);
if (!hasUsefulEdges(&Inst))
return;
@@ -671,12 +590,16 @@ public:
buildGraphFrom(Fn);
}
- const CFLGraph &getCFLGraph() { return Graph; }
- SmallVector<Value *, 4> takeReturnValues() {
- return std::move(ReturnedValues);
+ const CFLGraph &getCFLGraph() const { return Graph; }
+ const SmallVector<Value *, 4> &getReturnValues() const {
+ return ReturnedValues;
+ }
+ const SmallPtrSet<Value *, 8> &getExternalValues() const {
+ return ExternalValues;
+ }
+ const SmallPtrSet<Value *, 8> &getEscapedValues() const {
+ return EscapedValues;
}
- const SmallPtrSet<Value *, 8> &getExternalValues() { return ExternalValues; }
- const SmallPtrSet<Value *, 8> &getEscapedValues() { return EscapedValues; }
};
}
@@ -788,6 +711,96 @@ static bool canSkipAddingToSets(Value *V
return false;
}
+/// Gets whether the sets at Index1 above, below, or equal to the sets at
+/// Index2. Returns None if they are not in the same set chain.
+static Optional<Level> getIndexRelation(const StratifiedSets<Value *> &Sets,
+ StratifiedIndex Index1,
+ StratifiedIndex Index2) {
+ if (Index1 == Index2)
+ return Level::Same;
+
+ const auto *Current = &Sets.getLink(Index1);
+ while (Current->hasBelow()) {
+ if (Current->Below == Index2)
+ return Level::Below;
+ Current = &Sets.getLink(Current->Below);
+ }
+
+ Current = &Sets.getLink(Index1);
+ while (Current->hasAbove()) {
+ if (Current->Above == Index2)
+ return Level::Above;
+ Current = &Sets.getLink(Current->Above);
+ }
+
+ return None;
+}
+
+CFLAAResult::FunctionInfo::FunctionInfo(Function &Fn,
+ const SmallVectorImpl<Value *> &RetVals,
+ StratifiedSets<Value *> S)
+ : Sets(std::move(S)) {
+ LLVM_CONSTEXPR unsigned ExpectedMaxArgs = 8;
+
+ // Collect StratifiedInfo for each parameter
+ SmallVector<Optional<StratifiedInfo>, ExpectedMaxArgs> ParamInfos;
+ for (auto &Param : Fn.args()) {
+ if (Param.getType()->isPointerTy())
+ ParamInfos.push_back(Sets.find(&Param));
+ else
+ ParamInfos.push_back(None);
+ }
+ // Collect StratifiedInfo for each return value
+ SmallVector<Optional<StratifiedInfo>, 4> RetInfos;
+ RetInfos.reserve(RetVals.size());
+ for (unsigned I = 0, E = RetVals.size(); I != E; ++I)
+ RetInfos.push_back(Sets.find(RetVals[I]));
+
+ // This summary generation algorithm is n^2. An arbitrary upper-bound of 50
+ // args was selected, so it doesn't take too long in insane cases.
+ if (Fn.arg_size() <= MaxSupportedArgsInSummary) {
+ for (unsigned I = 0, E = ParamInfos.size(); I != E; ++I) {
+ auto &MainInfo = ParamInfos[I];
+ if (!MainInfo)
+ continue;
+
+ // Adding edges between arguments for arguments that may end up aliasing
+ // each other. This is necessary for functions such as
+ // void foo(int** a, int** b) { *a = *b; }
+ // (Technically, the proper sets for this would be those below
+ // Arguments[I] and Arguments[X], but our algorithm will produce
+ // extremely similar, and equally correct, results either way)
+ for (unsigned X = I + 1; X != E; ++X) {
+ auto &SubInfo = ParamInfos[X];
+ if (!SubInfo)
+ continue;
+
+ auto MaybeRelation =
+ getIndexRelation(Sets, MainInfo->Index, SubInfo->Index);
+ if (!MaybeRelation.hasValue())
+ continue;
+
+ RetParamRelations.push_back(ExternalRelation{1 + I, 1 + X});
+ }
+
+ // Adding an edge from argument -> return value for each parameter that
+ // may alias the return value
+ for (unsigned X = 0, XE = RetInfos.size(); X != XE; ++X) {
+ auto &RetInfo = RetInfos[X];
+ if (!RetInfo)
+ continue;
+
+ auto MaybeRelation =
+ getIndexRelation(Sets, MainInfo->Index, RetInfo->Index);
+ if (!MaybeRelation.hasValue())
+ continue;
+
+ RetParamRelations.push_back(ExternalRelation{1 + I, 0});
+ }
+ }
+ }
+}
+
// Builds the graph + StratifiedSets for a function.
CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
CFLGraphBuilder GraphBuilder(*this, TLI, *Fn);
@@ -848,7 +861,7 @@ CFLAAResult::FunctionInfo CFLAAResult::b
SetBuilder.addAttributesBelow(Escape, AttrUnknown);
}
- return FunctionInfo(SetBuilder.build(), GraphBuilder.takeReturnValues());
+ return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
}
void CFLAAResult::scan(Function *Fn) {
@@ -912,7 +925,7 @@ AliasResult CFLAAResult::query(const Mem
auto &MaybeInfo = ensureCached(Fn);
assert(MaybeInfo.hasValue());
- auto &Sets = MaybeInfo->Sets;
+ auto &Sets = MaybeInfo->getStratifiedSets();
auto MaybeA = Sets.find(ValA);
if (!MaybeA.hasValue())
return MayAlias;
Modified: llvm/trunk/test/Analysis/CFLAliasAnalysis/basic-interproc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/basic-interproc.ll?rev=273219&r1=273218&r2=273219&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/basic-interproc.ll (original)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/basic-interproc.ll Mon Jun 20 18:10:56 2016
@@ -1,22 +1,22 @@
-; This testcase ensures that CFL AA gives conservative answers on variables
-; that involve arguments.
+; This testcase ensures that CFL AA won't be too conservative when trying to do
+; interprocedural analysis on simple callee
-; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
-; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
-; CHECK: Function: test2
+; CHECK-LABEL: Function: noop_callee
; CHECK: MayAlias: i32* %arg1, i32* %arg2
-define void @test2(i32* %arg1, i32* %arg2) {
+define void @noop_callee(i32* %arg1, i32* %arg2) {
store i32 0, i32* %arg1
store i32 0, i32* %arg2
-
ret void
}
-
-define void @test() {
+; CHECK-LABEL: Function: test_noop
+; CHECK: NoAlias: i32* %a, i32* %b
+define void @test_noop() {
%a = alloca i32, align 4
%b = alloca i32, align 4
- call void @test2(i32* %a, i32* %b)
+ call void @noop_callee(i32* %a, i32* %b)
ret void
}
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-arg.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,25 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return one of its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; We have to xfail this since @return_arg_callee is treated as an opaque
+; function, and the anlysis couldn't prove that %b and %c are not aliases
+; XFAIL: *
+
+define i32* @return_arg_callee(i32* %arg1, i32* %arg2) {
+ ret i32* %arg1
+}
+; CHECK-LABEL: Function: test_return_arg
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %c
+; CHECK: NoAlias: i32* %b, i32* %c
+define void @test_return_arg() {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+
+ %c = call i32* @return_arg_callee(i32* %a, i32* %b)
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg-multilevel.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg-multilevel.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg-multilevel.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,50 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return the multi-level dereference of one of its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+define i32* @return_deref_arg_multilevel_callee(i32*** %arg1) {
+ %deref = load i32**, i32*** %arg1
+ %deref2 = load i32*, i32** %deref
+ ret i32* %deref2
+}
+; CHECK-LABEL: Function: test_return_deref_arg_multilevel
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %c
+; CHECK: NoAlias: i32* %b, i32* %c
+; CHECK: NoAlias: i32* %c, i32** %p
+; CHECK: NoAlias: i32* %c, i32*** %pp
+; CHECK: MayAlias: i32** %lpp, i32** %p
+; CHECK: NoAlias: i32** %lpp, i32*** %pp
+; CHECK: NoAlias: i32* %c, i32** %lpp
+; CHECK: MayAlias: i32* %a, i32* %lpp_deref
+; CHECK: NoAlias: i32* %b, i32* %lpp_deref
+; CHECK: MayAlias: i32* %lpp_deref, i32** %p
+; CHECK: NoAlias: i32* %lpp_deref, i32*** %pp
+; CHECK: MayAlias: i32* %a, i32* %lp
+; CHECK: NoAlias: i32* %b, i32* %lp
+; CHECK: NoAlias: i32* %lp, i32** %p
+; CHECK: NoAlias: i32* %lp, i32*** %pp
+; CHECK: MayAlias: i32* %c, i32* %lp
+; CHECK: NoAlias: i32* %lp, i32** %lpp
+; CHECK: MayAlias: i32* %lp, i32* %lpp_deref
+define void @test_return_deref_arg_multilevel() {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %p = alloca i32*, align 8
+ %pp = alloca i32**, align 8
+
+ store i32* %a, i32** %p
+ store i32** %p, i32*** %pp
+ %c = call i32* @return_deref_arg_multilevel_callee(i32*** %pp)
+
+ %lpp = load i32**, i32*** %pp
+ %lpp_deref = load i32*, i32** %lpp
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-deref-arg.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,33 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return the dereference of one of its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+define i32* @return_deref_arg_callee(i32** %arg1) {
+ %deref = load i32*, i32** %arg1
+ ret i32* %deref
+}
+; CHECK-LABEL: Function: test_return_deref_arg
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %a, i32* %c
+; CHECK: NoAlias: i32* %b, i32* %c
+; CHECK: MayAlias: i32* %a, i32* %lp
+; CHECK: NoAlias: i32* %b, i32* %lp
+; CHECK: NoAlias: i32* %lp, i32** %p
+; CHECK: MayAlias: i32* %c, i32* %lp
+define void @test_return_deref_arg() {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %p = alloca i32*, align 8
+
+ store i32* %a, i32** %p
+ %c = call i32* @return_deref_arg_callee(i32** %p)
+
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg-multilevel.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg-multilevel.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg-multilevel.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,52 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return the multi-level reference of one of its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+declare noalias i8* @malloc(i64)
+
+define i32*** @return_ref_arg_multilevel_callee(i32* %arg1) {
+ %ptr = call noalias i8* @malloc(i64 8)
+ %ptr_cast = bitcast i8* %ptr to i32***
+ %ptr2 = call noalias i8* @malloc(i64 8)
+ %ptr_cast2 = bitcast i8* %ptr2 to i32**
+ store i32* %arg1, i32** %ptr_cast2
+ store i32** %ptr_cast2, i32*** %ptr_cast
+ ret i32*** %ptr_cast
+}
+; CHECK-LABEL: Function: test_return_ref_arg_multilevel
+; CHECK: NoAlias: i32* %a, i32*** %b
+; CHECK: NoAlias: i32** %p, i32*** %b
+; CHECK: NoAlias: i32*** %b, i32*** %pp
+; CHECK: NoAlias: i32* %a, i32** %lb
+; CHECK: NoAlias: i32** %lb, i32** %p
+; CHECK: NoAlias: i32** %lb, i32*** %pp
+; CHECK: NoAlias: i32** %lb, i32*** %b
+; CHECK: MayAlias: i32* %a, i32* %lb_deref
+; CHECK: NoAlias: i32* %lb_deref, i32** %lpp
+; CHECK: MayAlias: i32* %lb_deref, i32* %lpp_deref
+; CHECK: NoAlias: i32* %lpp_deref, i32** %lpp
+; CHECK: MayAlias: i32* %lb_deref, i32* %lp
+; CHECK: NoAlias: i32* %lp, i32** %lpp
+; CHECK: MayAlias: i32* %lp, i32* %lpp_deref
+define void @test_return_ref_arg_multilevel() {
+ %a = alloca i32, align 4
+ %p = alloca i32*, align 8
+ %pp = alloca i32**, align 8
+
+ store i32* %a, i32** %p
+ store i32** %p, i32*** %pp
+ %b = call i32*** @return_ref_arg_multilevel_callee(i32* %a)
+
+ %lb = load i32**, i32*** %b
+ %lb_deref = load i32*, i32** %lb
+ %lpp = load i32**, i32*** %pp
+ %lpp_deref = load i32*, i32** %lpp
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-ref-arg.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,37 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return the reference of one of its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+declare noalias i8* @malloc(i64)
+
+define i32** @return_ref_arg_callee(i32* %arg1) {
+ %ptr = call noalias i8* @malloc(i64 8)
+ %ptr_cast = bitcast i8* %ptr to i32**
+ store i32* %arg1, i32** %ptr_cast
+ ret i32** %ptr_cast
+}
+; CHECK-LABEL: Function: test_return_ref_arg
+; CHECK: NoAlias: i32** %b, i32** %p
+; CHECK: MayAlias: i32* %a, i32* %lb
+; CHECK: NoAlias: i32* %lb, i32** %p
+; CHECK: NoAlias: i32* %lb, i32** %b
+; CHECK: NoAlias: i32* %lp, i32** %p
+; CHECK: NoAlias: i32* %lp, i32** %b
+; CHECK: MayAlias: i32* %lb, i32* %lp
+define void @test_return_ref_arg() {
+ %a = alloca i32, align 4
+ %p = alloca i32*, align 8
+
+ store i32* %a, i32** %p
+ %b = call i32** @return_ref_arg_callee(i32* %a)
+
+ %lb = load i32*, i32** %b
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-unknown.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-unknown.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-unknown.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-ret-unknown.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,27 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to return an unknown pointer
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+ at g = external global i32
+
+define i32* @return_unknown_callee(i32* %arg1, i32* %arg2) {
+ ret i32* @g
+}
+; CHECK-LABEL: Function: test_return_unknown
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: MayAlias: i32* %c, i32* %x
+; CHECK: NoAlias: i32* %a, i32* %c
+; CHECK: NoAlias: i32* %b, i32* %c
+define void @test_return_unknown(i32* %x) {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+
+ %c = call i32* @return_unknown_callee(i32* %a, i32* %b)
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-multilevel.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-multilevel.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-multilevel.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-multilevel.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,49 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to mutate the memory pointed to by its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+declare noalias i8* @malloc(i64)
+
+define void @store_arg_multilevel_callee(i32*** %arg1, i32* %arg2) {
+ %ptr = call noalias i8* @malloc(i64 8)
+ %ptr_cast = bitcast i8* %ptr to i32**
+ store i32* %arg2, i32** %ptr_cast
+ store i32** %ptr_cast, i32*** %arg1
+ ret void
+}
+; CHECK-LABEL: Function: test_store_arg_multilevel
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: NoAlias: i32* %a, i32** %lpp
+; CHECK: NoAlias: i32* %b, i32** %lpp
+; CHECK: MayAlias: i32** %lpp, i32** %p
+; CHECK: MayAlias: i32* %a, i32* %lpp_deref
+; CHECK: MayAlias: i32* %b, i32* %lpp_deref
+; CHECK: NoAlias: i32* %lpp_deref, i32** %p
+; CHECK: NoAlias: i32* %lpp_deref, i32*** %pp
+; CHECK: NoAlias: i32* %lpp_deref, i32** %lpp
+; CHECK: MayAlias: i32* %a, i32* %lp
+; CHECK: NoAlias: i32* %b, i32* %lp
+; CHECK: NoAlias: i32* %lp, i32*** %pp
+; CHECK: NoAlias: i32* %lp, i32** %lpp
+; CHECK: MayAlias: i32* %lp, i32* %lpp_deref
+define void @test_store_arg_multilevel() {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %p = alloca i32*, align 8
+ %pp = alloca i32**, align 8
+
+ store i32* %a, i32** %p
+ store i32** %p, i32*** %pp
+ call void @store_arg_multilevel_callee(i32*** %pp, i32* %b)
+
+ %lpp = load i32**, i32*** %pp
+ %lpp_deref = load i32*, i32** %lpp
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-unknown.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-unknown.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-unknown.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg-unknown.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,35 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to mutate the memory pointed to by its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+ at g = external global i32
+
+define void @store_arg_unknown_callee(i32** %arg1) {
+ store i32* @g, i32** %arg1
+ ret void
+}
+; CHECK-LABEL: Function: test_store_arg_unknown
+; CHECK: NoAlias: i32* %x, i32** %p
+; CHECK: NoAlias: i32* %a, i32** %p
+; CHECK: NoAlias: i32* %b, i32** %p
+; CHECK: MayAlias: i32* %lp, i32* %x
+; CHECK: MayAlias: i32* %a, i32* %lp
+; CHECK: NoAlias: i32* %b, i32* %lp
+; CHECK: MayAlias: 32* %lp, i32** %p
+define void @test_store_arg_unknown(i32* %x) {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %p = alloca i32*, align 8
+
+ store i32* %a, i32** %p
+ call void @store_arg_unknown_callee(i32** %p)
+
+ %lp = load i32*, i32** %p
+
+ ret void
+}
\ No newline at end of file
Added: llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg.ll?rev=273219&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg.ll (added)
+++ llvm/trunk/test/Analysis/CFLAliasAnalysis/interproc-store-arg.ll Mon Jun 20 18:10:56 2016
@@ -0,0 +1,37 @@
+; This testcase ensures that CFL AA answers queries soundly when callee tries
+; to mutate the memory pointed to by its parameters
+
+; RUN: opt < %s -disable-basicaa -cfl-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+; RUN: opt < %s -aa-pipeline=cfl-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; xfail for now due to buggy interproc analysis
+; XFAIL: *
+
+define void @store_arg_callee(i32** %arg1, i32* %arg2) {
+ store i32* %arg2, i32** %arg1
+ ret void
+}
+; CHECK-LABEL: Function: test_store_arg
+; CHECK: NoAlias: i32* %a, i32* %b
+; CHECK: NoAlias: i32* %a, i32** %p
+; CHECK: NoAlias: i32* %b, i32** %p
+; CHECK: MayAlias: i32* %a, i32* %lp
+; CHECK: MayAlias: i32* %b, i32* %lp
+; CHECK: NoAlias: i32* %a, i32* %lq
+; CHECK: MayAlias: i32* %b, i32* %lq
+; CHECK: NoAlias: i32* %lp, i32* %lq
+define void @test_store_arg() {
+ %a = alloca i32, align 4
+ %b = alloca i32, align 4
+ %p = alloca i32*, align 8
+ %q = alloca i32*, align 8
+
+ store i32* %a, i32** %p
+ store i32* %b, i32** %q
+ call void @store_arg_callee(i32** %p, i32* %b)
+
+ %lp = load i32*, i32** %p
+ %lq = load i32*, i32** %q
+
+ ret void
+}
\ No newline at end of file
More information about the llvm-commits
mailing list