blob: 811033e7314774dca477e2d44ca46d1b508b709e [file] [log] [blame]
Michael Gottesman6eb95dc2013-07-10 18:49:00 +00001//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===//
Michael Gottesman294e7da2013-01-28 05:51:54 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Michael Gottesman294e7da2013-01-28 05:51:54 +00006//
7//===----------------------------------------------------------------------===//
8/// \file
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.
12///
13/// WARNING: This file knows about certain library functions. It recognizes them
14/// by name, and hardwires knowledge of their semantics.
15///
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.
19///
Chandler Carruth7b560d42015-09-09 17:55:00 +000020/// TODO: Theoretically we could check for dependencies between objc_* calls
21/// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
22///
Michael Gottesman294e7da2013-01-28 05:51:54 +000023//===----------------------------------------------------------------------===//
24
Chandler Carruth0f792182015-08-20 08:06:03 +000025#include "llvm/Analysis/ObjCARCAliasAnalysis.h"
26#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
Chandler Carruthb4ebdf32015-08-14 03:55:36 +000027#include "llvm/IR/Function.h"
Michael Gottesman294e7da2013-01-28 05:51:54 +000028#include "llvm/IR/Instruction.h"
Chandler Carruthb4ebdf32015-08-14 03:55:36 +000029#include "llvm/IR/Value.h"
Michael Gottesman294e7da2013-01-28 05:51:54 +000030#include "llvm/InitializePasses.h"
31#include "llvm/PassAnalysisSupport.h"
32#include "llvm/PassSupport.h"
33
Chandler Carruth964daaa2014-04-22 02:55:47 +000034#define DEBUG_TYPE "objc-arc-aa"
35
Michael Gottesman294e7da2013-01-28 05:51:54 +000036using namespace llvm;
37using namespace llvm::objcarc;
38
Chandler Carruth7b560d42015-09-09 17:55:00 +000039AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA,
Alina Sbirleabfc779e2019-03-22 17:22:19 +000040 const MemoryLocation &LocB,
41 AAQueryInfo &AAQI) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000042 if (!EnableARCOpts)
Alina Sbirleabfc779e2019-03-22 17:22:19 +000043 return AAResultBase::alias(LocA, LocB, AAQI);
Michael Gottesman294e7da2013-01-28 05:51:54 +000044
45 // First, strip off no-ops, including ObjC-specific no-ops, and try making a
46 // precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000047 const Value *SA = GetRCIdentityRoot(LocA.Ptr);
48 const Value *SB = GetRCIdentityRoot(LocB.Ptr);
Michael Gottesman294e7da2013-01-28 05:51:54 +000049 AliasResult Result =
Chandler Carruth7b560d42015-09-09 17:55:00 +000050 AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
Alina Sbirleabfc779e2019-03-22 17:22:19 +000051 MemoryLocation(SB, LocB.Size, LocB.AATags), AAQI);
Michael Gottesman294e7da2013-01-28 05:51:54 +000052 if (Result != MayAlias)
53 return Result;
54
55 // If that failed, climb to the underlying object, including climbing through
56 // ObjC-specific no-ops, and try making an imprecise alias query.
Chandler Carruth7b560d42015-09-09 17:55:00 +000057 const Value *UA = GetUnderlyingObjCPtr(SA, DL);
58 const Value *UB = GetUnderlyingObjCPtr(SB, DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +000059 if (UA != SA || UB != SB) {
Alina Sbirleabfc779e2019-03-22 17:22:19 +000060 Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB), AAQI);
Michael Gottesman294e7da2013-01-28 05:51:54 +000061 // We can't use MustAlias or PartialAlias results here because
62 // GetUnderlyingObjCPtr may return an offsetted pointer value.
63 if (Result == NoAlias)
64 return NoAlias;
65 }
66
67 // If that failed, fail. We don't need to chain here, since that's covered
68 // by the earlier precise query.
69 return MayAlias;
70}
71
Chandler Carruth7b560d42015-09-09 17:55:00 +000072bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
Alina Sbirleabfc779e2019-03-22 17:22:19 +000073 AAQueryInfo &AAQI, bool OrLocal) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000074 if (!EnableARCOpts)
Alina Sbirleabfc779e2019-03-22 17:22:19 +000075 return AAResultBase::pointsToConstantMemory(Loc, AAQI, OrLocal);
Michael Gottesman294e7da2013-01-28 05:51:54 +000076
77 // First, strip off no-ops, including ObjC-specific no-ops, and try making
78 // a precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000079 const Value *S = GetRCIdentityRoot(Loc.Ptr);
Chandler Carruth7b560d42015-09-09 17:55:00 +000080 if (AAResultBase::pointsToConstantMemory(
Alina Sbirleabfc779e2019-03-22 17:22:19 +000081 MemoryLocation(S, Loc.Size, Loc.AATags), AAQI, OrLocal))
Michael Gottesman294e7da2013-01-28 05:51:54 +000082 return true;
83
84 // If that failed, climb to the underlying object, including climbing through
85 // ObjC-specific no-ops, and try making an imprecise alias query.
Chandler Carruth7b560d42015-09-09 17:55:00 +000086 const Value *U = GetUnderlyingObjCPtr(S, DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +000087 if (U != S)
Alina Sbirleabfc779e2019-03-22 17:22:19 +000088 return AAResultBase::pointsToConstantMemory(MemoryLocation(U), AAQI,
89 OrLocal);
Michael Gottesman294e7da2013-01-28 05:51:54 +000090
91 // If that failed, fail. We don't need to chain here, since that's covered
92 // by the earlier precise query.
93 return false;
94}
95
Chandler Carruth7b560d42015-09-09 17:55:00 +000096FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000097 if (!EnableARCOpts)
Chandler Carruth7b560d42015-09-09 17:55:00 +000098 return AAResultBase::getModRefBehavior(F);
Michael Gottesman294e7da2013-01-28 05:51:54 +000099
100 switch (GetFunctionClass(F)) {
Michael Gottesman6f729fa2015-02-19 19:51:32 +0000101 case ARCInstKind::NoopCast:
Chandler Carruth194f59c2015-07-22 23:15:57 +0000102 return FMRB_DoesNotAccessMemory;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000103 default:
104 break;
105 }
106
Chandler Carruth7b560d42015-09-09 17:55:00 +0000107 return AAResultBase::getModRefBehavior(F);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000108}
109
Chandler Carruth363ac682019-01-07 05:42:51 +0000110ModRefInfo ObjCARCAAResult::getModRefInfo(const CallBase *Call,
Alina Sbirleabfc779e2019-03-22 17:22:19 +0000111 const MemoryLocation &Loc,
112 AAQueryInfo &AAQI) {
Michael Gottesman294e7da2013-01-28 05:51:54 +0000113 if (!EnableARCOpts)
Alina Sbirleabfc779e2019-03-22 17:22:19 +0000114 return AAResultBase::getModRefInfo(Call, Loc, AAQI);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000115
Chandler Carruth363ac682019-01-07 05:42:51 +0000116 switch (GetBasicARCInstKind(Call)) {
Michael Gottesman6f729fa2015-02-19 19:51:32 +0000117 case ARCInstKind::Retain:
118 case ARCInstKind::RetainRV:
119 case ARCInstKind::Autorelease:
120 case ARCInstKind::AutoreleaseRV:
121 case ARCInstKind::NoopCast:
122 case ARCInstKind::AutoreleasepoolPush:
123 case ARCInstKind::FusedRetainAutorelease:
124 case ARCInstKind::FusedRetainAutoreleaseRV:
Michael Gottesman294e7da2013-01-28 05:51:54 +0000125 // These functions don't access any memory visible to the compiler.
126 // Note that this doesn't include objc_retainBlock, because it updates
127 // pointers when it copies block data.
Alina Sbirlea193429f2017-12-07 22:41:34 +0000128 return ModRefInfo::NoModRef;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000129 default:
130 break;
131 }
132
Alina Sbirleabfc779e2019-03-22 17:22:19 +0000133 return AAResultBase::getModRefInfo(Call, Loc, AAQI);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000134}
135
Sean Silva36e0d012016-08-09 00:28:15 +0000136ObjCARCAAResult ObjCARCAA::run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth12884f72016-03-02 15:56:53 +0000137 return ObjCARCAAResult(F.getParent()->getDataLayout());
Chandler Carruth7b560d42015-09-09 17:55:00 +0000138}
139
Chandler Carruth7b560d42015-09-09 17:55:00 +0000140char ObjCARCAAWrapperPass::ID = 0;
Chandler Carruth12884f72016-03-02 15:56:53 +0000141INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa",
142 "ObjC-ARC-Based Alias Analysis", false, true)
Chandler Carruth7b560d42015-09-09 17:55:00 +0000143
144ImmutablePass *llvm::createObjCARCAAWrapperPass() {
145 return new ObjCARCAAWrapperPass();
146}
147
148ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
149 initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
150}
151
152bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
Chandler Carruth12884f72016-03-02 15:56:53 +0000153 Result.reset(new ObjCARCAAResult(M.getDataLayout()));
Chandler Carruth7b560d42015-09-09 17:55:00 +0000154 return false;
155}
156
157bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
158 Result.reset();
159 return false;
160}
161
162void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
163 AU.setPreservesAll();
Michael Gottesman294e7da2013-01-28 05:51:54 +0000164}