1 //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// This file defines a simple ARC-aware AliasAnalysis using special knowledge
10 /// of Objective C to enhance other optimization passes which rely on the Alias
11 /// Analysis infrastructure.
13 /// WARNING: This file knows about certain library functions. It recognizes them
14 /// by name, and hardwires knowledge of their semantics.
16 /// WARNING: This file knows about how certain Objective-C library functions are
17 /// used. Naive LLVM IR transformations which would otherwise be
18 /// behavior-preserving may break these assumptions.
20 /// TODO: Theoretically we could check for dependencies between objc_* calls
21 /// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
23 /// TODO: The calls here to AAResultBase member functions are all effectively
24 /// no-ops that just return a conservative result. The original intent was to
25 /// chain to another analysis for a recursive query, but this was lost in a
26 /// refactor. These should instead be rephrased in terms of queries to AAQI.AAR.
28 //===----------------------------------------------------------------------===//
30 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
31 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
32 #include "llvm/Analysis/Passes.h"
33 #include "llvm/IR/Function.h"
34 #include "llvm/InitializePasses.h"
35 #include "llvm/Pass.h"
37 #define DEBUG_TYPE "objc-arc-aa"
40 using namespace llvm::objcarc
;
42 AliasResult
ObjCARCAAResult::alias(const MemoryLocation
&LocA
,
43 const MemoryLocation
&LocB
,
44 AAQueryInfo
&AAQI
, const Instruction
*) {
46 return AAResultBase::alias(LocA
, LocB
, AAQI
, nullptr);
48 // First, strip off no-ops, including ObjC-specific no-ops, and try making a
49 // precise alias query.
50 const Value
*SA
= GetRCIdentityRoot(LocA
.Ptr
);
51 const Value
*SB
= GetRCIdentityRoot(LocB
.Ptr
);
52 AliasResult Result
= AAResultBase::alias(
53 MemoryLocation(SA
, LocA
.Size
, LocA
.AATags
),
54 MemoryLocation(SB
, LocB
.Size
, LocB
.AATags
), AAQI
, nullptr);
55 if (Result
!= AliasResult::MayAlias
)
58 // If that failed, climb to the underlying object, including climbing through
59 // ObjC-specific no-ops, and try making an imprecise alias query.
60 const Value
*UA
= GetUnderlyingObjCPtr(SA
);
61 const Value
*UB
= GetUnderlyingObjCPtr(SB
);
62 if (UA
!= SA
|| UB
!= SB
) {
63 Result
= AAResultBase::alias(MemoryLocation::getBeforeOrAfter(UA
),
64 MemoryLocation::getBeforeOrAfter(UB
), AAQI
,
66 // We can't use MustAlias or PartialAlias results here because
67 // GetUnderlyingObjCPtr may return an offsetted pointer value.
68 if (Result
== AliasResult::NoAlias
)
69 return AliasResult::NoAlias
;
72 // If that failed, fail. We don't need to chain here, since that's covered
73 // by the earlier precise query.
74 return AliasResult::MayAlias
;
77 ModRefInfo
ObjCARCAAResult::getModRefInfoMask(const MemoryLocation
&Loc
,
81 return AAResultBase::getModRefInfoMask(Loc
, AAQI
, IgnoreLocals
);
83 // First, strip off no-ops, including ObjC-specific no-ops, and try making
84 // a precise alias query.
85 const Value
*S
= GetRCIdentityRoot(Loc
.Ptr
);
86 if (isNoModRef(AAResultBase::getModRefInfoMask(
87 MemoryLocation(S
, Loc
.Size
, Loc
.AATags
), AAQI
, IgnoreLocals
)))
88 return ModRefInfo::NoModRef
;
90 // If that failed, climb to the underlying object, including climbing through
91 // ObjC-specific no-ops, and try making an imprecise alias query.
92 const Value
*U
= GetUnderlyingObjCPtr(S
);
94 return AAResultBase::getModRefInfoMask(MemoryLocation::getBeforeOrAfter(U
),
97 // If that failed, fail. We don't need to chain here, since that's covered
98 // by the earlier precise query.
99 return ModRefInfo::ModRef
;
102 MemoryEffects
ObjCARCAAResult::getMemoryEffects(const Function
*F
) {
104 return AAResultBase::getMemoryEffects(F
);
106 switch (GetFunctionClass(F
)) {
107 case ARCInstKind::NoopCast
:
108 return MemoryEffects::none();
113 return AAResultBase::getMemoryEffects(F
);
116 ModRefInfo
ObjCARCAAResult::getModRefInfo(const CallBase
*Call
,
117 const MemoryLocation
&Loc
,
120 return AAResultBase::getModRefInfo(Call
, Loc
, AAQI
);
122 switch (GetBasicARCInstKind(Call
)) {
123 case ARCInstKind::Retain
:
124 case ARCInstKind::RetainRV
:
125 case ARCInstKind::Autorelease
:
126 case ARCInstKind::AutoreleaseRV
:
127 case ARCInstKind::NoopCast
:
128 case ARCInstKind::AutoreleasepoolPush
:
129 case ARCInstKind::FusedRetainAutorelease
:
130 case ARCInstKind::FusedRetainAutoreleaseRV
:
131 // These functions don't access any memory visible to the compiler.
132 // Note that this doesn't include objc_retainBlock, because it updates
133 // pointers when it copies block data.
134 return ModRefInfo::NoModRef
;
139 return AAResultBase::getModRefInfo(Call
, Loc
, AAQI
);
142 AnalysisKey
ObjCARCAA::Key
;
144 ObjCARCAAResult
ObjCARCAA::run(Function
&F
, FunctionAnalysisManager
&AM
) {
145 return ObjCARCAAResult(F
.getParent()->getDataLayout());