Skip to content

Commit 10f944d

Browse files
committed
[BasicAA] Improve escape source analysis for return-only captures
This fixes an issue where improving inference from a general capture to a return-only capture can make alias analysis results worse. The problem is that if there are return-only captures, the call can no longer treated as a plain escape source, as the call result may alias one of the return-only-capture arguments, even if they don't escape. Fix this by having isEscapeSource() return the relevant arguments and explicitly check that these aren't aliased. Fixes #131168.
1 parent 761c4d7 commit 10f944d

File tree

7 files changed

+32
-19
lines changed

7 files changed

+32
-19
lines changed

llvm/include/llvm/Analysis/AliasAnalysis.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -888,9 +888,9 @@ bool isIdentifiedFunctionLocal(const Value *V);
888888
/// can be inbounds w.r.t the actual underlying object.
889889
bool isBaseOfObject(const Value *V);
890890

891-
/// Returns true if the pointer is one which would have been considered an
892-
/// escape by isNonEscapingLocalObject.
893-
bool isEscapeSource(const Value *V);
891+
/// Returns true if the pointer cannot alias a non-escaping local object,
892+
/// except via the values returned in the MayAlias argument.
893+
bool isEscapeSource(const Value *V, SmallVectorImpl<Value *> &MayAlias);
894894

895895
/// Return true if Object memory is not visible after an unwind, in the sense
896896
/// that program semantics cannot depend on Object containing any particular

llvm/include/llvm/IR/InstrTypes.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1692,10 +1692,11 @@ class CallBase : public Instruction {
16921692
return capturesNothing(getCaptureInfo(OpNo));
16931693
}
16941694

1695-
/// Returns whether the call has an argument that has an attribute like
1695+
/// Collects call arguments that have an attribute like
16961696
/// captures(ret: address, provenance), where the return capture components
16971697
/// are not a subset of the other capture components.
1698-
bool hasArgumentWithAdditionalReturnCaptureComponents() const;
1698+
void getArgumentsWithAdditionalReturnCaptureComponents(
1699+
SmallVectorImpl<Value *> &Args) const;
16991700

17001701
/// Determine whether this argument is passed by value.
17011702
bool isByValArgument(unsigned ArgNo) const {

llvm/lib/Analysis/AliasAnalysis.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -840,15 +840,16 @@ bool llvm::isBaseOfObject(const Value *V) {
840840
return (isa<AllocaInst>(V) || isa<GlobalVariable>(V));
841841
}
842842

843-
bool llvm::isEscapeSource(const Value *V) {
843+
bool llvm::isEscapeSource(const Value *V, SmallVectorImpl<Value *> &MayAlias) {
844844
if (auto *CB = dyn_cast<CallBase>(V)) {
845845
if (isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(CB, true))
846846
return false;
847847

848848
// The return value of a function with a captures(ret: address, provenance)
849-
// attribute is not necessarily an escape source. The return value may
850-
// alias with a non-escaping object.
851-
return !CB->hasArgumentWithAdditionalReturnCaptureComponents();
849+
// attribute may alias with the corresponding argument. If it doesn't, then
850+
// it is an escape source.
851+
CB->getArgumentsWithAdditionalReturnCaptureComponents(MayAlias);
852+
return true;
852853
}
853854

854855
// The load case works because isNonEscapingLocalObject considers all

llvm/lib/Analysis/BasicAliasAnalysis.cpp

+15-5
Original file line numberDiff line numberDiff line change
@@ -1606,11 +1606,21 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
16061606
// temporary store the nocapture argument's value in a temporary memory
16071607
// location if that memory location doesn't escape. Or it may pass a
16081608
// nocapture value to other functions as long as they don't capture it.
1609-
if (isEscapeSource(O1) && AAQI.CA->isNotCapturedBefore(
1610-
O2, dyn_cast<Instruction>(O1), /*OrAt*/ true))
1611-
return AliasResult::NoAlias;
1612-
if (isEscapeSource(O2) && AAQI.CA->isNotCapturedBefore(
1613-
O1, dyn_cast<Instruction>(O2), /*OrAt*/ true))
1609+
auto EscapeSourceDoesNotAliasNonEscapingLocalObject =
1610+
[&](const Value *O1, const Value *O2) {
1611+
SmallVector<Value *> MayAlias;
1612+
if (!isEscapeSource(O1, MayAlias) ||
1613+
!AAQI.CA->isNotCapturedBefore(O2, dyn_cast<Instruction>(O1),
1614+
/*OrAt=*/true))
1615+
return false;
1616+
for (Value *V : MayAlias)
1617+
if (AAQI.AAR.alias(MemoryLocation::getBeforeOrAfter(O2),
1618+
MemoryLocation::getBeforeOrAfter(V), AAQI))
1619+
return false;
1620+
return true;
1621+
};
1622+
if (EscapeSourceDoesNotAliasNonEscapingLocalObject(O1, O2) ||
1623+
EscapeSourceDoesNotAliasNonEscapingLocalObject(O2, O1))
16141624
return AliasResult::NoAlias;
16151625
}
16161626

llvm/lib/IR/Instructions.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,8 @@ CaptureInfo CallBase::getCaptureInfo(unsigned OpNo) const {
713713
return OBU.isDeoptOperandBundle() ? CaptureInfo::none() : CaptureInfo::all();
714714
}
715715

716-
bool CallBase::hasArgumentWithAdditionalReturnCaptureComponents() const {
716+
void CallBase::getArgumentsWithAdditionalReturnCaptureComponents(
717+
SmallVectorImpl<Value *> &Args) const {
717718
for (unsigned I = 0, E = arg_size(); I < E; ++I) {
718719
if (!getArgOperand(I)->getType()->isPointerTy())
719720
continue;
@@ -722,9 +723,8 @@ bool CallBase::hasArgumentWithAdditionalReturnCaptureComponents() const {
722723
if (auto *Fn = dyn_cast<Function>(getCalledOperand()))
723724
CI &= Fn->getAttributes().getParamAttrs(I).getCaptureInfo();
724725
if (capturesAnything(CI.getRetComponents() & ~CI.getOtherComponents()))
725-
return true;
726+
Args.push_back(getArgOperand(I));
726727
}
727-
return false;
728728
}
729729

730730
//===----------------------------------------------------------------------===//

llvm/lib/Transforms/Utils/InlineFunction.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1273,7 +1273,8 @@ static void AddAliasScopeMetadata(CallBase &CB, ValueToValueMapTy &VMap,
12731273
UsesAliasingPtr = true;
12741274
}
12751275

1276-
if (isEscapeSource(V)) {
1276+
SmallVector<Value *> MayAlias;
1277+
if (isEscapeSource(V, MayAlias) && MayAlias.empty()) {
12771278
// An escape source can only alias with a noalias argument if it has
12781279
// been captured beforehand.
12791280
RequiresNoCaptureBefore = true;

llvm/test/Analysis/BasicAA/captures.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ declare ptr @capture_ret(ptr, ptr)
4545

4646
; CHECK-LABEL: capture_ret_only
4747
; CHECK: MayAlias: i8* %a, i8* %ret
48-
; CHECK: MayAlias: i8* %b, i8* %ret
48+
; CHECK: NoAlias: i8* %b, i8* %ret
4949
define void @capture_ret_only(ptr noalias %a, ptr noalias %b) {
5050
%ret = call ptr @capture_ret(ptr captures(ret: address, provenance) %a, ptr captures(none) %b)
5151
load i8, ptr %ret

0 commit comments

Comments
 (0)