mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Make ModRefBehavior a lattice. Use this to clean up AliasAnalysis
chaining and simplify FunctionAttrs' GetModRefBehavior logic. llvm-svn: 118660
This commit is contained in:
parent
993d07638e
commit
1571dfc883
@ -175,6 +175,9 @@ public:
|
||||
///
|
||||
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
|
||||
|
||||
/// These values define additional bits used to define the
|
||||
/// ModRefBehavior values.
|
||||
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
|
||||
|
||||
/// ModRefBehavior - Summary of how a function affects memory in the program.
|
||||
/// Loads from constant globals are not considered memory accesses for this
|
||||
@ -187,20 +190,20 @@ public:
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readnone' attribute.
|
||||
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
|
||||
DoesNotAccessMemory,
|
||||
DoesNotAccessMemory = Nowhere | NoModRef,
|
||||
|
||||
/// AccessesArgumentsReadonly - This function loads through function
|
||||
/// arguments and does not perform any non-local stores or volatile
|
||||
/// loads.
|
||||
///
|
||||
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
|
||||
AccessesArgumentsReadonly,
|
||||
AccessesArgumentsReadonly = ArgumentPointees | Ref,
|
||||
|
||||
/// AccessesArguments - This function accesses function arguments in well
|
||||
/// known (possibly volatile) ways, but does not access any other memory.
|
||||
///
|
||||
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
|
||||
AccessesArguments,
|
||||
AccessesArguments = ArgumentPointees | ModRef,
|
||||
|
||||
/// OnlyReadsMemory - This function does not perform any non-local stores or
|
||||
/// volatile loads, but may read from any memory location.
|
||||
@ -208,11 +211,11 @@ public:
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readonly' attribute.
|
||||
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
|
||||
OnlyReadsMemory,
|
||||
OnlyReadsMemory = Anywhere | Ref,
|
||||
|
||||
/// UnknownModRefBehavior - This indicates that the function could not be
|
||||
/// classified into one of the behaviors above.
|
||||
UnknownModRefBehavior
|
||||
UnknownModRefBehavior = Anywhere | ModRef
|
||||
};
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
@ -270,12 +273,9 @@ public:
|
||||
/// true. For use when the call site is not known.
|
||||
///
|
||||
static bool onlyReadsMemory(ModRefBehavior MRB) {
|
||||
return MRB == DoesNotAccessMemory ||
|
||||
MRB == AccessesArgumentsReadonly ||
|
||||
MRB == OnlyReadsMemory;
|
||||
return !(MRB & Mod);
|
||||
}
|
||||
|
||||
|
||||
/// getModRefInfo - Return information about whether or not an instruction may
|
||||
/// read or write the specified memory location. An instruction
|
||||
/// that doesn't read or write memory may be trivially LICM'd for example.
|
||||
|
@ -179,7 +179,7 @@ AliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
|
||||
// Otherwise, fall back to the next AA in the chain. But we can merge
|
||||
// in any result we've managed to compute.
|
||||
return std::min(AA->getModRefBehavior(CS), Min);
|
||||
return ModRefBehavior(AA->getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
AliasAnalysis::ModRefBehavior
|
||||
|
@ -595,7 +595,7 @@ BasicAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
Min = OnlyReadsMemory;
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return std::min(AliasAnalysis::getModRefBehavior(CS), Min);
|
||||
return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given function.
|
||||
@ -613,12 +613,14 @@ BasicAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
#undef GET_INTRINSIC_MODREF_BEHAVIOR
|
||||
}
|
||||
|
||||
ModRefBehavior Min = UnknownModRefBehavior;
|
||||
|
||||
// If the function declares it only reads memory, go with that.
|
||||
if (F->onlyReadsMemory())
|
||||
return OnlyReadsMemory;
|
||||
Min = OnlyReadsMemory;
|
||||
|
||||
// Otherwise be conservative.
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
|
||||
}
|
||||
|
||||
/// getModRefInfo - Check to see if the specified callsite can clobber the
|
||||
@ -671,6 +673,8 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
return NoModRef;
|
||||
}
|
||||
|
||||
ModRefResult Min = ModRef;
|
||||
|
||||
// Finally, handle specific knowledge of intrinsics.
|
||||
const IntrinsicInst *II = dyn_cast<IntrinsicInst>(CS.getInstruction());
|
||||
if (II != 0)
|
||||
@ -686,7 +690,7 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
if (isNoAlias(Location(Dest, Len), Loc)) {
|
||||
if (isNoAlias(Location(Src, Len), Loc))
|
||||
return NoModRef;
|
||||
return Ref;
|
||||
Min = Ref;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -745,7 +749,7 @@ BasicAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
|
||||
}
|
||||
|
||||
// The AliasAnalysis base class has some smarts, lets use them.
|
||||
return AliasAnalysis::getModRefInfo(CS, Loc);
|
||||
return ModRefResult(AliasAnalysis::getModRefInfo(CS, Loc) & Min);
|
||||
}
|
||||
|
||||
/// aliasGEP - Provide a bunch of ad-hoc rules to disambiguate a GEP instruction
|
||||
|
@ -120,28 +120,33 @@ namespace {
|
||||
/// called from the specified call site. The call site may be null in which
|
||||
/// case the most generic behavior of this function should be returned.
|
||||
ModRefBehavior getModRefBehavior(const Function *F) {
|
||||
ModRefBehavior Min = UnknownModRefBehavior;
|
||||
|
||||
if (FunctionRecord *FR = getFunctionInfo(F)) {
|
||||
if (FR->FunctionEffect == 0)
|
||||
return DoesNotAccessMemory;
|
||||
Min = DoesNotAccessMemory;
|
||||
else if ((FR->FunctionEffect & Mod) == 0)
|
||||
return OnlyReadsMemory;
|
||||
Min = OnlyReadsMemory;
|
||||
}
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
|
||||
return ModRefBehavior(AliasAnalysis::getModRefBehavior(F) & Min);
|
||||
}
|
||||
|
||||
/// getModRefBehavior - Return the behavior of the specified function if
|
||||
/// called from the specified call site. The call site may be null in which
|
||||
/// case the most generic behavior of this function should be returned.
|
||||
ModRefBehavior getModRefBehavior(ImmutableCallSite CS) {
|
||||
const Function* F = CS.getCalledFunction();
|
||||
if (!F) return AliasAnalysis::getModRefBehavior(CS);
|
||||
if (FunctionRecord *FR = getFunctionInfo(F)) {
|
||||
if (FR->FunctionEffect == 0)
|
||||
return DoesNotAccessMemory;
|
||||
else if ((FR->FunctionEffect & Mod) == 0)
|
||||
return OnlyReadsMemory;
|
||||
}
|
||||
return AliasAnalysis::getModRefBehavior(CS);
|
||||
ModRefBehavior Min = UnknownModRefBehavior;
|
||||
|
||||
if (const Function* F = CS.getCalledFunction())
|
||||
if (FunctionRecord *FR = getFunctionInfo(F)) {
|
||||
if (FR->FunctionEffect == 0)
|
||||
Min = DoesNotAccessMemory;
|
||||
else if ((FR->FunctionEffect & Mod) == 0)
|
||||
Min = OnlyReadsMemory;
|
||||
}
|
||||
|
||||
return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
virtual void deleteValue(Value *V);
|
||||
|
@ -256,11 +256,12 @@ TypeBasedAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
||||
if (TBAANode(M).TypeIsImmutable())
|
||||
Min = OnlyReadsMemory;
|
||||
|
||||
return std::min(AliasAnalysis::getModRefBehavior(CS), Min);
|
||||
return ModRefBehavior(AliasAnalysis::getModRefBehavior(CS) & Min);
|
||||
}
|
||||
|
||||
AliasAnalysis::ModRefBehavior
|
||||
TypeBasedAliasAnalysis::getModRefBehavior(const Function *F) {
|
||||
// Functions don't have metadata. Just chain to the next implementation.
|
||||
return AliasAnalysis::getModRefBehavior(F);
|
||||
}
|
||||
|
||||
|
@ -128,54 +128,41 @@ bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
|
||||
// Ignore calls to functions in the same SCC.
|
||||
if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction()))
|
||||
continue;
|
||||
switch (AA->getModRefBehavior(CS)) {
|
||||
case AliasAnalysis::DoesNotAccessMemory:
|
||||
// Ignore calls that don't access memory.
|
||||
continue;
|
||||
case AliasAnalysis::OnlyReadsMemory:
|
||||
// Handle calls that only read from memory.
|
||||
ReadsMemory = true;
|
||||
continue;
|
||||
case AliasAnalysis::AccessesArguments:
|
||||
// Check whether all pointer arguments point to local memory, and
|
||||
// ignore calls that only access local memory.
|
||||
for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
|
||||
CI != CE; ++CI) {
|
||||
Value *Arg = *CI;
|
||||
if (Arg->getType()->isPointerTy()) {
|
||||
AliasAnalysis::Location Loc(Arg,
|
||||
AliasAnalysis::UnknownSize,
|
||||
I->getMetadata(LLVMContext::MD_tbaa));
|
||||
if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true))
|
||||
// Writes memory. Just give up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Only reads and writes local memory.
|
||||
continue;
|
||||
case AliasAnalysis::AccessesArgumentsReadonly:
|
||||
// Check whether all pointer arguments point to local memory, and
|
||||
// ignore calls that only access local memory.
|
||||
for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
|
||||
CI != CE; ++CI) {
|
||||
Value *Arg = *CI;
|
||||
if (Arg->getType()->isPointerTy()) {
|
||||
AliasAnalysis::Location Loc(Arg,
|
||||
AliasAnalysis::UnknownSize,
|
||||
I->getMetadata(LLVMContext::MD_tbaa));
|
||||
if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) {
|
||||
// Reads non-local memory.
|
||||
ReadsMemory = true;
|
||||
break;
|
||||
AliasAnalysis::ModRefBehavior MRB = AA->getModRefBehavior(CS);
|
||||
// If the call doesn't access arbitrary memory, we may be able to
|
||||
// figure out something.
|
||||
if (!(MRB & AliasAnalysis::Anywhere &
|
||||
~AliasAnalysis::ArgumentPointees)) {
|
||||
// If the call accesses argument pointees, check each argument.
|
||||
if (MRB & AliasAnalysis::AccessesArguments)
|
||||
// Check whether all pointer arguments point to local memory, and
|
||||
// ignore calls that only access local memory.
|
||||
for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end();
|
||||
CI != CE; ++CI) {
|
||||
Value *Arg = *CI;
|
||||
if (Arg->getType()->isPointerTy()) {
|
||||
AliasAnalysis::Location Loc(Arg,
|
||||
AliasAnalysis::UnknownSize,
|
||||
I->getMetadata(LLVMContext::MD_tbaa));
|
||||
if (!AA->pointsToConstantMemory(Loc, /*OrLocal=*/true)) {
|
||||
if (MRB & AliasAnalysis::Mod)
|
||||
// Writes non-local memory. Give up.
|
||||
return false;
|
||||
if (MRB & AliasAnalysis::Ref)
|
||||
// Ok, it reads non-local memory.
|
||||
ReadsMemory = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only reads memory.
|
||||
continue;
|
||||
default:
|
||||
// Otherwise, be conservative.
|
||||
break;
|
||||
}
|
||||
// The call could access any memory. If that includes writes, give up.
|
||||
if (MRB & AliasAnalysis::Mod)
|
||||
return false;
|
||||
// If it reads, note it.
|
||||
if (MRB & AliasAnalysis::Ref)
|
||||
ReadsMemory = true;
|
||||
continue;
|
||||
} else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
|
||||
// Ignore non-volatile loads from local memory.
|
||||
if (!LI->isVolatile()) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt < %s -functionattrs -S | grep readnone | count 4
|
||||
; RUN: opt < %s -basicaa -functionattrs -S | grep readnone | count 4
|
||||
@x = global i32 0
|
||||
|
||||
declare i32 @e() readnone
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: opt < %s -functionattrs -S | grep readonly | count 2
|
||||
; RUN: opt < %s -basicaa -functionattrs -S | grep readonly | count 2
|
||||
|
||||
define i32 @f() {
|
||||
entry:
|
||||
|
Loading…
Reference in New Issue
Block a user