1 //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===// 2 // 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 6 // 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 /// 20 /// TODO: Theoretically we could check for dependencies between objc_* calls 21 /// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls. 22 /// 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. 27 /// 28 //===----------------------------------------------------------------------===// 29 30 #include "llvm/Analysis/ObjCARCAliasAnalysis.h" 31 #include "llvm/Analysis/ObjCARCAnalysisUtils.h" 32 #include "llvm/IR/Function.h" 33 #include "llvm/Pass.h" 34 35 #define DEBUG_TYPE "objc-arc-aa" 36 37 using namespace llvm; 38 using namespace llvm::objcarc; 39 40 AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA, 41 const MemoryLocation &LocB, 42 AAQueryInfo &AAQI, const Instruction *) { 43 if (!EnableARCOpts) 44 return AAResultBase::alias(LocA, LocB, AAQI, nullptr); 45 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) 54 return Result; 55 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, 63 nullptr); 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; 68 } 69 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; 73 } 74 75 ModRefInfo ObjCARCAAResult::getModRefInfoMask(const MemoryLocation &Loc, 76 AAQueryInfo &AAQI, 77 bool IgnoreLocals) { 78 if (!EnableARCOpts) 79 return AAResultBase::getModRefInfoMask(Loc, AAQI, IgnoreLocals); 80 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; 87 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); 91 if (U != S) 92 return AAResultBase::getModRefInfoMask(MemoryLocation::getBeforeOrAfter(U), 93 AAQI, IgnoreLocals); 94 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; 98 } 99 100 MemoryEffects ObjCARCAAResult::getMemoryEffects(const Function *F) { 101 if (!EnableARCOpts) 102 return AAResultBase::getMemoryEffects(F); 103 104 switch (GetFunctionClass(F)) { 105 case ARCInstKind::NoopCast: 106 return MemoryEffects::none(); 107 default: 108 break; 109 } 110 111 return AAResultBase::getMemoryEffects(F); 112 } 113 114 ModRefInfo ObjCARCAAResult::getModRefInfo(const CallBase *Call, 115 const MemoryLocation &Loc, 116 AAQueryInfo &AAQI) { 117 if (!EnableARCOpts) 118 return AAResultBase::getModRefInfo(Call, Loc, AAQI); 119 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; 133 default: 134 break; 135 } 136 137 return AAResultBase::getModRefInfo(Call, Loc, AAQI); 138 } 139 140 AnalysisKey ObjCARCAA::Key; 141 142 ObjCARCAAResult ObjCARCAA::run(Function &F, FunctionAnalysisManager &AM) { 143 return ObjCARCAAResult(F.getDataLayout()); 144 } 145