aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/BasicAliasAnalysis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/BasicAliasAnalysis.cpp')
-rw-r--r--llvm/lib/Analysis/BasicAliasAnalysis.cpp104
1 files changed, 48 insertions, 56 deletions
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index b41c00a..4d1a95a 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -847,15 +847,15 @@ MemoryEffects BasicAAResult::getMemoryEffects(const Function *F) {
ModRefInfo BasicAAResult::getArgModRefInfo(const CallBase *Call,
unsigned ArgIdx) {
- if (Call->paramHasAttr(ArgIdx, Attribute::WriteOnly))
+ if (Call->doesNotAccessMemory(ArgIdx))
+ return ModRefInfo::NoModRef;
+
+ if (Call->onlyWritesMemory(ArgIdx))
return ModRefInfo::Mod;
- if (Call->paramHasAttr(ArgIdx, Attribute::ReadOnly))
+ if (Call->onlyReadsMemory(ArgIdx))
return ModRefInfo::Ref;
- if (Call->paramHasAttr(ArgIdx, Attribute::ReadNone))
- return ModRefInfo::NoModRef;
-
return ModRefInfo::ModRef;
}
@@ -921,66 +921,58 @@ ModRefInfo BasicAAResult::getModRefInfo(const CallBase *Call,
if (!AI->isStaticAlloca() && isIntrinsicCall(Call, Intrinsic::stackrestore))
return ModRefInfo::Mod;
- // A call can access a locally allocated object either because it is passed as
- // an argument to the call, or because it has escaped prior to the call.
- //
- // Make sure the object has not escaped here, and then check that none of the
- // call arguments alias the object below.
+ // We can completely ignore inaccessible memory here, because MemoryLocations
+ // can only reference accessible memory.
+ auto ME = AAQI.AAR.getMemoryEffects(Call, AAQI)
+ .getWithoutLoc(IRMemLocation::InaccessibleMem);
+ if (ME.doesNotAccessMemory())
+ return ModRefInfo::NoModRef;
+
+ ModRefInfo ArgMR = ME.getModRef(IRMemLocation::ArgMem);
+ ModRefInfo OtherMR = ME.getWithoutLoc(IRMemLocation::ArgMem).getModRef();
+
+ // An identified function-local object that does not escape can only be
+ // accessed via call arguments. Reduce OtherMR (which includes accesses to
+ // escaped memory) based on that.
//
// We model calls that can return twice (setjmp) as clobbering non-escaping
// objects, to model any accesses that may occur prior to the second return.
// As an exception, ignore allocas, as setjmp is not required to preserve
// non-volatile stores for them.
- if (!isa<Constant>(Object) && Call != Object &&
- AAQI.CA->isNotCapturedBefore(Object, Call, /*OrAt*/ false) &&
- (isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice))) {
-
- // Optimistically assume that call doesn't touch Object and check this
- // assumption in the following loop.
- ModRefInfo Result = ModRefInfo::NoModRef;
-
- unsigned OperandNo = 0;
- for (auto CI = Call->data_operands_begin(), CE = Call->data_operands_end();
- CI != CE; ++CI, ++OperandNo) {
- if (!(*CI)->getType()->isPointerTy())
- continue;
-
- // Call doesn't access memory through this operand, so we don't care
- // if it aliases with Object.
- if (Call->doesNotAccessMemory(OperandNo))
- continue;
-
- // If this is a no-capture pointer argument, see if we can tell that it
- // is impossible to alias the pointer we're checking.
- AliasResult AR =
- AAQI.AAR.alias(MemoryLocation::getBeforeOrAfter(*CI),
- MemoryLocation::getBeforeOrAfter(Object), AAQI);
- // Operand doesn't alias 'Object', continue looking for other aliases
- if (AR == AliasResult::NoAlias)
+ if (isModOrRefSet(OtherMR) && !isa<Constant>(Object) && Call != Object &&
+ AAQI.CA->isNotCapturedBefore(Object, Call, /*OrAt=*/false) &&
+ (isa<AllocaInst>(Object) || !Call->hasFnAttr(Attribute::ReturnsTwice)))
+ OtherMR = ModRefInfo::NoModRef;
+
+ // Refine the modref info for argument memory. We only bother to do this
+ // if ArgMR is not a subset of OtherMR, otherwise this won't have an impact
+ // on the final result.
+ if ((ArgMR | OtherMR) != OtherMR) {
+ ModRefInfo NewArgMR = ModRefInfo::NoModRef;
+ for (const Use &U : Call->data_ops()) {
+ const Value *Arg = U;
+ if (!Arg->getType()->isPointerTy())
continue;
- // Operand aliases 'Object', but call doesn't modify it. Strengthen
- // initial assumption and keep looking in case if there are more aliases.
- if (Call->onlyReadsMemory(OperandNo)) {
- Result |= ModRefInfo::Ref;
- continue;
- }
- // Operand aliases 'Object' but call only writes into it.
- if (Call->onlyWritesMemory(OperandNo)) {
- Result |= ModRefInfo::Mod;
- continue;
- }
- // This operand aliases 'Object' and call reads and writes into it.
- // Setting ModRef will not yield an early return below, MustAlias is not
- // used further.
- Result = ModRefInfo::ModRef;
- break;
+ unsigned ArgIdx = Call->getDataOperandNo(&U);
+ MemoryLocation ArgLoc =
+ Call->isArgOperand(&U)
+ ? MemoryLocation::getForArgument(Call, ArgIdx, TLI)
+ : MemoryLocation::getBeforeOrAfter(Arg);
+ AliasResult ArgAlias = AAQI.AAR.alias(ArgLoc, Loc, AAQI, Call);
+ if (ArgAlias != AliasResult::NoAlias)
+ NewArgMR |= ArgMR & AAQI.AAR.getArgModRefInfo(Call, ArgIdx);
+
+ // Exit early if we cannot improve over the original ArgMR.
+ if (NewArgMR == ArgMR)
+ break;
}
-
- // Early return if we improved mod ref information
- if (!isModAndRefSet(Result))
- return Result;
+ ArgMR = NewArgMR;
}
+ ModRefInfo Result = ArgMR | OtherMR;
+ if (!isModAndRefSet(Result))
+ return Result;
+
// If the call is malloc/calloc like, we can assume that it doesn't
// modify any IR visible value. This is only valid because we assume these
// routines do not read values visible in the IR. TODO: Consider special