blob: 7de4b7f8b9de40ec7a0a809c6c53c90f670d0083 [file] [log] [blame]
Michael Gottesman6eb95dc2013-07-10 18:49:00 +00001//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===//
Michael Gottesman294e7da2013-01-28 05:51:54 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9/// \file
10/// This file defines a simple ARC-aware AliasAnalysis using special knowledge
11/// of Objective C to enhance other optimization passes which rely on the Alias
12/// Analysis infrastructure.
13///
14/// WARNING: This file knows about certain library functions. It recognizes them
15/// by name, and hardwires knowledge of their semantics.
16///
17/// WARNING: This file knows about how certain Objective-C library functions are
18/// used. Naive LLVM IR transformations which would otherwise be
19/// behavior-preserving may break these assumptions.
20///
21//===----------------------------------------------------------------------===//
22
Michael Gottesman294e7da2013-01-28 05:51:54 +000023#include "ObjCARC.h"
24#include "ObjCARCAliasAnalysis.h"
Chandler Carruthb4ebdf32015-08-14 03:55:36 +000025#include "llvm/IR/Function.h"
Michael Gottesman294e7da2013-01-28 05:51:54 +000026#include "llvm/IR/Instruction.h"
Chandler Carruthb4ebdf32015-08-14 03:55:36 +000027#include "llvm/IR/Value.h"
Michael Gottesman294e7da2013-01-28 05:51:54 +000028#include "llvm/InitializePasses.h"
29#include "llvm/PassAnalysisSupport.h"
30#include "llvm/PassSupport.h"
31
Chandler Carruth964daaa2014-04-22 02:55:47 +000032#define DEBUG_TYPE "objc-arc-aa"
33
Michael Gottesman294e7da2013-01-28 05:51:54 +000034using namespace llvm;
35using namespace llvm::objcarc;
36
37// Register this pass...
38char ObjCARCAliasAnalysis::ID = 0;
39INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
40 "ObjC-ARC-Based Alias Analysis", false, true, false)
41
42ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
43 return new ObjCARCAliasAnalysis();
44}
45
Mehdi Amini46a43552015-03-04 18:43:29 +000046bool ObjCARCAliasAnalysis::doInitialization(Module &M) {
47 InitializeAliasAnalysis(this, &M.getDataLayout());
48 return true;
49}
50
Chandler Carruthd541e732015-08-14 03:57:00 +000051void ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
Michael Gottesman294e7da2013-01-28 05:51:54 +000052 AU.setPreservesAll();
53 AliasAnalysis::getAnalysisUsage(AU);
54}
55
Chandler Carruthc3f49eb2015-06-22 02:16:51 +000056AliasResult ObjCARCAliasAnalysis::alias(const MemoryLocation &LocA,
57 const MemoryLocation &LocB) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000058 if (!EnableARCOpts)
59 return AliasAnalysis::alias(LocA, LocB);
60
61 // First, strip off no-ops, including ObjC-specific no-ops, and try making a
62 // precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000063 const Value *SA = GetRCIdentityRoot(LocA.Ptr);
64 const Value *SB = GetRCIdentityRoot(LocB.Ptr);
Michael Gottesman294e7da2013-01-28 05:51:54 +000065 AliasResult Result =
Chandler Carruthac80dc72015-06-17 07:18:54 +000066 AliasAnalysis::alias(MemoryLocation(SA, LocA.Size, LocA.AATags),
67 MemoryLocation(SB, LocB.Size, LocB.AATags));
Michael Gottesman294e7da2013-01-28 05:51:54 +000068 if (Result != MayAlias)
69 return Result;
70
71 // If that failed, climb to the underlying object, including climbing through
72 // ObjC-specific no-ops, and try making an imprecise alias query.
Mehdi Aminia28d91d2015-03-10 02:37:25 +000073 const Value *UA = GetUnderlyingObjCPtr(SA, *DL);
74 const Value *UB = GetUnderlyingObjCPtr(SB, *DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +000075 if (UA != SA || UB != SB) {
Chandler Carruthac80dc72015-06-17 07:18:54 +000076 Result = AliasAnalysis::alias(MemoryLocation(UA), MemoryLocation(UB));
Michael Gottesman294e7da2013-01-28 05:51:54 +000077 // We can't use MustAlias or PartialAlias results here because
78 // GetUnderlyingObjCPtr may return an offsetted pointer value.
79 if (Result == NoAlias)
80 return NoAlias;
81 }
82
83 // If that failed, fail. We don't need to chain here, since that's covered
84 // by the earlier precise query.
85 return MayAlias;
86}
87
Chandler Carruthac80dc72015-06-17 07:18:54 +000088bool ObjCARCAliasAnalysis::pointsToConstantMemory(const MemoryLocation &Loc,
89 bool OrLocal) {
Michael Gottesman294e7da2013-01-28 05:51:54 +000090 if (!EnableARCOpts)
91 return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
92
93 // First, strip off no-ops, including ObjC-specific no-ops, and try making
94 // a precise alias query.
Michael Gottesmane5ad66f2015-02-19 00:42:38 +000095 const Value *S = GetRCIdentityRoot(Loc.Ptr);
Chandler Carruthac80dc72015-06-17 07:18:54 +000096 if (AliasAnalysis::pointsToConstantMemory(
97 MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal))
Michael Gottesman294e7da2013-01-28 05:51:54 +000098 return true;
99
100 // If that failed, climb to the underlying object, including climbing through
101 // ObjC-specific no-ops, and try making an imprecise alias query.
Mehdi Aminia28d91d2015-03-10 02:37:25 +0000102 const Value *U = GetUnderlyingObjCPtr(S, *DL);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000103 if (U != S)
Chandler Carruthac80dc72015-06-17 07:18:54 +0000104 return AliasAnalysis::pointsToConstantMemory(MemoryLocation(U), OrLocal);
Michael Gottesman294e7da2013-01-28 05:51:54 +0000105
106 // If that failed, fail. We don't need to chain here, since that's covered
107 // by the earlier precise query.
108 return false;
109}
110
Chandler Carruth194f59c2015-07-22 23:15:57 +0000111FunctionModRefBehavior
Michael Gottesman294e7da2013-01-28 05:51:54 +0000112ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
113 // We have nothing to do. Just chain to the next AliasAnalysis.
114 return AliasAnalysis::getModRefBehavior(CS);
115}
116
Chandler Carruth194f59c2015-07-22 23:15:57 +0000117FunctionModRefBehavior
Michael Gottesman294e7da2013-01-28 05:51:54 +0000118ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
119 if (!EnableARCOpts)
120 return AliasAnalysis::getModRefBehavior(F);
121
122 switch (GetFunctionClass(F)) {
Michael Gottesman6f729fa2015-02-19 19:51:32 +0000123 case ARCInstKind::NoopCast:
Chandler Carruth194f59c2015-07-22 23:15:57 +0000124 return FMRB_DoesNotAccessMemory;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000125 default:
126 break;
127 }
128
129 return AliasAnalysis::getModRefBehavior(F);
130}
131
Chandler Carruth194f59c2015-07-22 23:15:57 +0000132ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS,
133 const MemoryLocation &Loc) {
Michael Gottesman294e7da2013-01-28 05:51:54 +0000134 if (!EnableARCOpts)
135 return AliasAnalysis::getModRefInfo(CS, Loc);
136
Michael Gottesman6f729fa2015-02-19 19:51:32 +0000137 switch (GetBasicARCInstKind(CS.getInstruction())) {
138 case ARCInstKind::Retain:
139 case ARCInstKind::RetainRV:
140 case ARCInstKind::Autorelease:
141 case ARCInstKind::AutoreleaseRV:
142 case ARCInstKind::NoopCast:
143 case ARCInstKind::AutoreleasepoolPush:
144 case ARCInstKind::FusedRetainAutorelease:
145 case ARCInstKind::FusedRetainAutoreleaseRV:
Michael Gottesman294e7da2013-01-28 05:51:54 +0000146 // These functions don't access any memory visible to the compiler.
147 // Note that this doesn't include objc_retainBlock, because it updates
148 // pointers when it copies block data.
Chandler Carruth194f59c2015-07-22 23:15:57 +0000149 return MRI_NoModRef;
Michael Gottesman294e7da2013-01-28 05:51:54 +0000150 default:
151 break;
152 }
153
154 return AliasAnalysis::getModRefInfo(CS, Loc);
155}
156
Chandler Carruth194f59c2015-07-22 23:15:57 +0000157ModRefInfo ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
158 ImmutableCallSite CS2) {
Michael Gottesman294e7da2013-01-28 05:51:54 +0000159 // TODO: Theoretically we could check for dependencies between objc_* calls
Chandler Carruth194f59c2015-07-22 23:15:57 +0000160 // and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls.
Michael Gottesman294e7da2013-01-28 05:51:54 +0000161 return AliasAnalysis::getModRefInfo(CS1, CS2);
162}