[BasicAA] Handle assumes with operand bundles
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 23 Mar 2021 20:18:30 +0000 (21:18 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 23 Mar 2021 20:21:19 +0000 (21:21 +0100)
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.

llvm/lib/Analysis/BasicAliasAnalysis.cpp
llvm/test/Analysis/BasicAA/assume.ll

index 86362f7..65117d8 100644 (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)) {
index 4b26883..bc6be3e 100644 (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 }