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/IR/Function.h"
33 #include "llvm/Pass.h"
35 #define DEBUG_TYPE "objc-arc-aa"
38 using namespace llvm::objcarc
;
40 AliasResult
ObjCARCAAResult::alias(const MemoryLocation
&LocA
,
41 const MemoryLocation
&LocB
,
42 AAQueryInfo
&AAQI
, const Instruction
*) {
44 return AAResultBase::alias(LocA
, LocB
, AAQI
, nullptr);
46 // First, strip off no-ops, including ObjC-specific no-ops, and try making a
47 // precise alias query.
48 const Value
*SA
= GetRCIdentityRoot(LocA
.Ptr
);
49 const Value
*SB
= GetRCIdentityRoot(LocB
.Ptr
);
50 AliasResult Result
= AAResultBase::alias(
51 MemoryLocation(SA
, LocA
.Size
, LocA
.AATags
),
52 MemoryLocation(SB
, LocB
.Size
, LocB
.AATags
), AAQI
, nullptr);
53 if (Result
!= AliasResult::MayAlias
)
56 // If that failed, climb to the underlying object, including climbing through
57 // ObjC-specific no-ops, and try making an imprecise alias query.
58 const Value
*UA
= GetUnderlyingObjCPtr(SA
);
59 const Value
*UB
= GetUnderlyingObjCPtr(SB
);
60 if (UA
!= SA
|| UB
!= SB
) {
61 Result
= AAResultBase::alias(MemoryLocation::getBeforeOrAfter(UA
),
62 MemoryLocation::getBeforeOrAfter(UB
), AAQI
,
64 // We can't use MustAlias or PartialAlias results here because
65 // GetUnderlyingObjCPtr may return an offsetted pointer value.
66 if (Result
== AliasResult::NoAlias
)
67 return AliasResult::NoAlias
;
70 // If that failed, fail. We don't need to chain here, since that's covered
71 // by the earlier precise query.
72 return AliasResult::MayAlias
;
75 ModRefInfo
ObjCARCAAResult::getModRefInfoMask(const MemoryLocation
&Loc
,
79 return AAResultBase::getModRefInfoMask(Loc
, AAQI
, IgnoreLocals
);
81 // First, strip off no-ops, including ObjC-specific no-ops, and try making
82 // a precise alias query.
83 const Value
*S
= GetRCIdentityRoot(Loc
.Ptr
);
84 if (isNoModRef(AAResultBase::getModRefInfoMask(
85 MemoryLocation(S
, Loc
.Size
, Loc
.AATags
), AAQI
, IgnoreLocals
)))
86 return ModRefInfo::NoModRef
;
88 // If that failed, climb to the underlying object, including climbing through
89 // ObjC-specific no-ops, and try making an imprecise alias query.
90 const Value
*U
= GetUnderlyingObjCPtr(S
);
92 return AAResultBase::getModRefInfoMask(MemoryLocation::getBeforeOrAfter(U
),
95 // If that failed, fail. We don't need to chain here, since that's covered
96 // by the earlier precise query.
97 return ModRefInfo::ModRef
;
100 MemoryEffects
ObjCARCAAResult::getMemoryEffects(const Function
*F
) {
102 return AAResultBase::getMemoryEffects(F
);
104 switch (GetFunctionClass(F
)) {
105 case ARCInstKind::NoopCast
:
106 return MemoryEffects::none();
111 return AAResultBase::getMemoryEffects(F
);
114 ModRefInfo
ObjCARCAAResult::getModRefInfo(const CallBase
*Call
,
115 const MemoryLocation
&Loc
,
118 return AAResultBase::getModRefInfo(Call
, Loc
, AAQI
);
120 switch (GetBasicARCInstKind(Call
)) {
121 case ARCInstKind::Retain
:
122 case ARCInstKind::RetainRV
:
123 case ARCInstKind::Autorelease
:
124 case ARCInstKind::AutoreleaseRV
:
125 case ARCInstKind::NoopCast
:
126 case ARCInstKind::AutoreleasepoolPush
:
127 case ARCInstKind::FusedRetainAutorelease
:
128 case ARCInstKind::FusedRetainAutoreleaseRV
:
129 // These functions don't access any memory visible to the compiler.
130 // Note that this doesn't include objc_retainBlock, because it updates
131 // pointers when it copies block data.
132 return ModRefInfo::NoModRef
;
137 return AAResultBase::getModRefInfo(Call
, Loc
, AAQI
);
140 AnalysisKey
ObjCARCAA::Key
;
142 ObjCARCAAResult
ObjCARCAA::run(Function
&F
, FunctionAnalysisManager
&AM
) {
143 return ObjCARCAAResult(F
.getDataLayout());