forked from OSchip/llvm-project
[CFLAA] Add support for ModRef queries.
This patch makes CFLAA answer some ModRef queries. Because we don't distinguish between reading/writing when making StratifiedSets, we're unable to offer any of the readonly-related answers. Patch by Jia Chen. Differential Revision: http://reviews.llvm.org/D21858 llvm-svn: 274197
This commit is contained in:
parent
48e7cbdf41
commit
d86e38e1db
llvm
include/llvm/Analysis
lib/Analysis
test/Analysis/CFLAliasAnalysis
|
@ -73,6 +73,16 @@ public:
|
||||||
return QueryResult;
|
return QueryResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the location associated with a pointer argument of a callsite.
|
||||||
|
ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
|
||||||
|
|
||||||
|
/// Returns the behavior when calling the given call site.
|
||||||
|
FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||||
|
|
||||||
|
/// Returns the behavior when calling the given function. For use when the
|
||||||
|
/// call site is not known.
|
||||||
|
FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FunctionHandle final : public CallbackVH {
|
struct FunctionHandle final : public CallbackVH {
|
||||||
FunctionHandle(Function *Fn, CFLAAResult *Result)
|
FunctionHandle(Function *Fn, CFLAAResult *Result)
|
||||||
|
|
|
@ -1047,6 +1047,77 @@ AliasResult CFLAAResult::query(const MemoryLocation &LocA,
|
||||||
return NoAlias;
|
return NoAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ModRefInfo CFLAAResult::getArgModRefInfo(ImmutableCallSite CS,
|
||||||
|
unsigned ArgIdx) {
|
||||||
|
if (auto CalledFunc = CS.getCalledFunction()) {
|
||||||
|
auto &MaybeInfo = ensureCached(const_cast<Function *>(CalledFunc));
|
||||||
|
if (!MaybeInfo.hasValue())
|
||||||
|
return MRI_ModRef;
|
||||||
|
auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
|
||||||
|
auto &RetParamRelations = MaybeInfo->getRetParamRelations();
|
||||||
|
|
||||||
|
bool ArgAttributeIsWritten =
|
||||||
|
std::any_of(RetParamAttributes.begin(), RetParamAttributes.end(),
|
||||||
|
[ArgIdx](const ExternalAttribute &ExtAttr) {
|
||||||
|
return ExtAttr.IValue.Index == ArgIdx + 1;
|
||||||
|
});
|
||||||
|
bool ArgIsAccessed =
|
||||||
|
std::any_of(RetParamRelations.begin(), RetParamRelations.end(),
|
||||||
|
[ArgIdx](const ExternalRelation &ExtRelation) {
|
||||||
|
return ExtRelation.To.Index == ArgIdx + 1 ||
|
||||||
|
ExtRelation.From.Index == ArgIdx + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (!ArgIsAccessed && !ArgAttributeIsWritten) ? MRI_NoModRef
|
||||||
|
: MRI_ModRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MRI_ModRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionModRefBehavior CFLAAResult::getModRefBehavior(ImmutableCallSite CS) {
|
||||||
|
// If we know the callee, try analyzing it
|
||||||
|
if (auto CalledFunc = CS.getCalledFunction())
|
||||||
|
return getModRefBehavior(CalledFunc);
|
||||||
|
|
||||||
|
// Otherwise, be conservative
|
||||||
|
return FMRB_UnknownModRefBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionModRefBehavior CFLAAResult::getModRefBehavior(const Function *F) {
|
||||||
|
assert(F != nullptr);
|
||||||
|
|
||||||
|
// TODO: Remove the const_cast
|
||||||
|
auto &MaybeInfo = ensureCached(const_cast<Function *>(F));
|
||||||
|
if (!MaybeInfo.hasValue())
|
||||||
|
return FMRB_UnknownModRefBehavior;
|
||||||
|
auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
|
||||||
|
auto &RetParamRelations = MaybeInfo->getRetParamRelations();
|
||||||
|
|
||||||
|
// First, if any argument is marked Escpaed, Unknown or Global, anything may
|
||||||
|
// happen to them and thus we can't draw any conclusion.
|
||||||
|
if (!RetParamAttributes.empty())
|
||||||
|
return FMRB_UnknownModRefBehavior;
|
||||||
|
|
||||||
|
// Currently we don't (and can't) distinguish reads from writes in
|
||||||
|
// RetParamRelations. All we can say is whether there may be memory access or
|
||||||
|
// not.
|
||||||
|
if (RetParamRelations.empty())
|
||||||
|
return FMRB_DoesNotAccessMemory;
|
||||||
|
|
||||||
|
// Check if something beyond argmem gets touched.
|
||||||
|
bool AccessArgMemoryOnly =
|
||||||
|
std::all_of(RetParamRelations.begin(), RetParamRelations.end(),
|
||||||
|
[](const ExternalRelation &ExtRelation) {
|
||||||
|
// Both DerefLevels has to be 0, since we don't know which
|
||||||
|
// one is a read and which is a write.
|
||||||
|
return ExtRelation.From.DerefLevel == 0 &&
|
||||||
|
ExtRelation.To.DerefLevel == 0;
|
||||||
|
});
|
||||||
|
return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees
|
||||||
|
: FMRB_UnknownModRefBehavior;
|
||||||
|
}
|
||||||
|
|
||||||
char CFLAA::PassID;
|
char CFLAA::PassID;
|
||||||
|
|
||||||
CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> &AM) {
|
CFLAAResult CFLAA::run(Function &F, AnalysisManager<Function> &AM) {
|
||||||
|
|
|
@ -11,6 +11,8 @@ define i32* @return_arg_callee(i32* %arg1, i32* %arg2) {
|
||||||
; CHECK: NoAlias: i32* %a, i32* %b
|
; CHECK: NoAlias: i32* %a, i32* %b
|
||||||
; CHECK: MayAlias: i32* %a, i32* %c
|
; CHECK: MayAlias: i32* %a, i32* %c
|
||||||
; CHECK: NoAlias: i32* %b, i32* %c
|
; CHECK: NoAlias: i32* %b, i32* %c
|
||||||
|
|
||||||
|
; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b)
|
||||||
define void @test_return_arg() {
|
define void @test_return_arg() {
|
||||||
%a = alloca i32, align 4
|
%a = alloca i32, align 4
|
||||||
%b = alloca i32, align 4
|
%b = alloca i32, align 4
|
||||||
|
|
Loading…
Reference in New Issue