[BasicAA] Handle assumes with operand bundles

This fixes a regression reported on D99022: If a call has operand
bundles, then the inaccessiblememonly attribute on the function
will be ignored, as operand bundles can affect modref behavior in
the general case. However, for assume operand bundles in particular
this is not the case.

Adjust getModRefBehavior() to always report inaccessiblememonly
for assumes, regardless of presence of operand bundles.
This commit is contained in:
Nikita Popov 2021-03-23 21:18:30 +01:00
parent b1389f6683
commit 931b6066ac
2 changed files with 14 additions and 9 deletions

View File

@ -672,12 +672,22 @@ bool BasicAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
return Worklist.empty();
}
static bool isIntrinsicCall(const CallBase *Call, Intrinsic::ID IID) {
const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call);
return II && II->getIntrinsicID() == IID;
}
/// Returns the behavior when calling the given call site.
FunctionModRefBehavior BasicAAResult::getModRefBehavior(const CallBase *Call) {
if (Call->doesNotAccessMemory())
// Can't do better than this.
return FMRB_DoesNotAccessMemory;
// The assume intrinsic can have operand bundles, but still only accesses
// inaccessible memory in that case (to maintain control dependencies).
if (isIntrinsicCall(Call, Intrinsic::assume))
return FMRB_OnlyAccessesInaccessibleMem;
FunctionModRefBehavior Min = FMRB_UnknownModRefBehavior;
// If the callsite knows it only reads memory, don't return worse
@ -771,11 +781,6 @@ ModRefInfo BasicAAResult::getArgModRefInfo(const CallBase *Call,
return AAResultBase::getArgModRefInfo(Call, ArgIdx);
}
static bool isIntrinsicCall(const CallBase *Call, Intrinsic::ID IID) {
const IntrinsicInst *II = dyn_cast<IntrinsicInst>(Call);
return II && II->getIntrinsicID() == IID;
}
#ifndef NDEBUG
static const Function *getParent(const Value *V) {
if (const Instruction *inst = dyn_cast<Instruction>(V)) {

View File

@ -29,12 +29,12 @@ define void @test2(i8* %P, i8* %Q) nounwind ssp {
; CHECK-LABEL: Function: test2:
; CHECK: MayAlias: i8* %P, i8* %Q
; CHECK: Both ModRef: Ptr: i8* %P <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
; CHECK: Both ModRef: Ptr: i8* %Q <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
; CHECK: NoModRef: Ptr: i8* %P <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
; CHECK: NoModRef: Ptr: i8* %Q <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
; CHECK: Both ModRef: Ptr: i8* %P <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
; CHECK: Both ModRef: Ptr: i8* %Q <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
; CHECK: Both ModRef: tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ] <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
; CHECK: Both ModRef: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
; CHECK: NoModRef: tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ] <-> tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false)
; CHECK: NoModRef: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %P, i8* %Q, i64 12, i1 false) <-> tail call void @llvm.assume(i1 true) [ "nonnull"(i8* %P) ]
}
attributes #0 = { nounwind }