blob: f768319f0a4dd42b52239f1ffcf80ac6dd641d71 [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,
40 const MemoryLocation &LocB) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000041 if (!EnableARCOpts)
Chandler Carruth7b560d42015-09-09 17:55:00 +000042 return AAResultBase::alias(LocA, LocB);
Michael Gottesman294e7da2013-01-28 05:51:54 +000043
44 // First, strip off no-ops, including ObjC-specific no-ops, and try making a
45 // precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000046 const Value *SA = GetRCIdentityRoot(LocA.Ptr);
47 const Value *SB = GetRCIdentityRoot(LocB.Ptr);
Michael Gottesman294e7da2013-01-28 05:51:54 +000048 AliasResult Result =
Chandler Carruth7b560d42015-09-09 17:55:00 +000049 AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
50 MemoryLocation(SB, LocB.Size, LocB.AATags));
Michael Gottesman294e7da2013-01-28 05:51:54 +000051 if (Result != MayAlias)
52 return Result;
53
54 // If that failed, climb to the underlying object, including climbing through
55 // ObjC-specific no-ops, and try making an imprecise alias query.
Chandler Carruth7b560d42015-09-09 17:55:00 +000056 const Value *UA = GetUnderlyingObjCPtr(SA, DL);
57 const Value *UB = GetUnderlyingObjCPtr(SB, DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +000058 if (UA != SA || UB != SB) {
Chandler Carruth7b560d42015-09-09 17:55:00 +000059 Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB));
Michael Gottesman294e7da2013-01-28 05:51:54 +000060 // We can't use MustAlias or PartialAlias results here because
61 // GetUnderlyingObjCPtr may return an offsetted pointer value.
62 if (Result == NoAlias)
63 return NoAlias;
64 }
65
66 // If that failed, fail. We don't need to chain here, since that's covered
67 // by the earlier precise query.
68 return MayAlias;
69}
70
Chandler Carruth7b560d42015-09-09 17:55:00 +000071bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc,
72 bool OrLocal) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000073 if (!EnableARCOpts)
Chandler Carruth7b560d42015-09-09 17:55:00 +000074 return AAResultBase::pointsToConstantMemory(Loc, OrLocal);
Michael Gottesman294e7da2013-01-28 05:51:54 +000075
76 // First, strip off no-ops, including ObjC-specific no-ops, and try making
77 // a precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000078 const Value *S = GetRCIdentityRoot(Loc.Ptr);
Chandler Carruth7b560d42015-09-09 17:55:00 +000079 if (AAResultBase::pointsToConstantMemory(
Chandler Carruthac80dc72015-06-17 07:18:54 +000080 MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
Michael Gottesman294e7da2013-01-28 05:51:54 +000081 return true;
82
83 // If that failed, climb to the underlying object, including climbing through
84 // ObjC-specific no-ops, and try making an imprecise alias query.
Chandler Carruth7b560d42015-09-09 17:55:00 +000085 const Value *U = GetUnderlyingObjCPtr(S, DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +000086 if (U != S)
Chandler Carruth7b560d42015-09-09 17:55:00 +000087 return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal);
Michael Gottesman294e7da2013-01-28 05:51:54 +000088
89 // If that failed, fail. We don't need to chain here, since that's covered
90 // by the earlier precise query.
91 return false;
92}
93
Chandler Carruth7b560d42015-09-09 17:55:00 +000094FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000095 if (!EnableARCOpts)
Chandler Carruth7b560d42015-09-09 17:55:00 +000096 return AAResultBase::getModRefBehavior(F);
Michael Gottesman294e7da2013-01-28 05:51:54 +000097
98 switch (GetFunctionClass(F)) {
Michael Gottesman6f729fa2015-02-19 19:51:32 +000099 case ARCInstKind::NoopCast:
Chandler Carruth194f59c2015-07-22 23:15:57 +0000100 return FMRB_DoesNotAccessMemory;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000101 default:
102 break;
103 }
104
Chandler Carruth7b560d42015-09-09 17:55:00 +0000105 return AAResultBase::getModRefBehavior(F);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000106}
107
Chandler Carruth363ac682019-01-07 05:42:51 +0000108ModRefInfo ObjCARCAAResult::getModRefInfo(const CallBase *Call,
Chandler Carruth7b560d42015-09-09 17:55:00 +0000109 const MemoryLocation &Loc) {
Michael Gottesman294e7da2013-01-28 05:51:54 +0000110 if (!EnableARCOpts)
Chandler Carruth363ac682019-01-07 05:42:51 +0000111 return AAResultBase::getModRefInfo(Call, Loc);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000112
Chandler Carruth363ac682019-01-07 05:42:51 +0000113 switch (GetBasicARCInstKind(Call)) {
Michael Gottesman6f729fa2015-02-19 19:51:32 +0000114 case ARCInstKind::Retain:
115 case ARCInstKind::RetainRV:
116 case ARCInstKind::Autorelease:
117 case ARCInstKind::AutoreleaseRV:
118 case ARCInstKind::NoopCast:
119 case ARCInstKind::AutoreleasepoolPush:
120 case ARCInstKind::FusedRetainAutorelease:
121 case ARCInstKind::FusedRetainAutoreleaseRV:
Michael Gottesman294e7da2013-01-28 05:51:54 +0000122 // These functions don't access any memory visible to the compiler.
123 // Note that this doesn't include objc_retainBlock, because it updates
124 // pointers when it copies block data.
Alina Sbirlea193429f2017-12-07 22:41:34 +0000125 return ModRefInfo::NoModRef;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000126 default:
127 break;
128 }
129
Chandler Carruth363ac682019-01-07 05:42:51 +0000130 return AAResultBase::getModRefInfo(Call, Loc);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000131}
132
Sean Silva36e0d012016-08-09 00:28:15 +0000133ObjCARCAAResult ObjCARCAA::run(Function &F, FunctionAnalysisManager &AM) {
Chandler Carruth12884f72016-03-02 15:56:53 +0000134 return ObjCARCAAResult(F.getParent()->getDataLayout());
Chandler Carruth7b560d42015-09-09 17:55:00 +0000135}
136
Chandler Carruth7b560d42015-09-09 17:55:00 +0000137char ObjCARCAAWrapperPass::ID = 0;
Chandler Carruth12884f72016-03-02 15:56:53 +0000138INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa",
139 "ObjC-ARC-Based Alias Analysis", false, true)
Chandler Carruth7b560d42015-09-09 17:55:00 +0000140
141ImmutablePass *llvm::createObjCARCAAWrapperPass() {
142 return new ObjCARCAAWrapperPass();
143}
144
145ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) {
146 initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry());
147}
148
149bool ObjCARCAAWrapperPass::doInitialization(Module &M) {
Chandler Carruth12884f72016-03-02 15:56:53 +0000150 Result.reset(new ObjCARCAAResult(M.getDataLayout()));
Chandler Carruth7b560d42015-09-09 17:55:00 +0000151 return false;
152}
153
154bool ObjCARCAAWrapperPass::doFinalization(Module &M) {
155 Result.reset();
156 return false;
157}
158
159void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
160 AU.setPreservesAll();
Michael Gottesman294e7da2013-01-28 05:51:54 +0000161}