mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-07 12:18:32 +00:00
The RCIdentity root ("Reference Count Identity Root") of a value V is a
dominating value U for which retaining or releasing U is equivalent to
retaining or releasing V. In other words, ARC operations on V are
equivalent to ARC operations on U.
This is a useful property to ascertain since we can use this in the ARC
optimizer to make it easier to match up ARC operations by always mapping
ARC operations to RCIdentityRoots instead of pointers themselves. Then
we perform pairing of retains, releases which are applied to the same
RCIdentityRoot.
In general, the two ways that we see RCIdentical values in ObjC are via:
1. PointerCasts
2. Forwarding Calls that return their argument verbatim.
As such in ObjC, two RCIdentical pointers must always point to the same
memory location.
Previously this concept was implicit in the code and various methods
that dealt with this concept were given functional names that did not
conform to any name in the "ARC" model. This often times resulted in
code that was hard for the non-ARC acquanted to understand resulting in
unhappiness and confusion.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@229796 91177308-0d34-0410-b5e6-96231b3b80d8
164 lines
5.4 KiB
C++
164 lines
5.4 KiB
C++
//===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
/// This file defines a simple ARC-aware AliasAnalysis using special knowledge
|
|
/// of Objective C to enhance other optimization passes which rely on the Alias
|
|
/// Analysis infrastructure.
|
|
///
|
|
/// WARNING: This file knows about certain library functions. It recognizes them
|
|
/// by name, and hardwires knowledge of their semantics.
|
|
///
|
|
/// WARNING: This file knows about how certain Objective-C library functions are
|
|
/// used. Naive LLVM IR transformations which would otherwise be
|
|
/// behavior-preserving may break these assumptions.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "ObjCARC.h"
|
|
#include "ObjCARCAliasAnalysis.h"
|
|
#include "llvm/IR/Instruction.h"
|
|
#include "llvm/InitializePasses.h"
|
|
#include "llvm/PassAnalysisSupport.h"
|
|
#include "llvm/PassSupport.h"
|
|
|
|
#define DEBUG_TYPE "objc-arc-aa"
|
|
|
|
namespace llvm {
|
|
class Function;
|
|
class Value;
|
|
}
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::objcarc;
|
|
|
|
// Register this pass...
|
|
char ObjCARCAliasAnalysis::ID = 0;
|
|
INITIALIZE_AG_PASS(ObjCARCAliasAnalysis, AliasAnalysis, "objc-arc-aa",
|
|
"ObjC-ARC-Based Alias Analysis", false, true, false)
|
|
|
|
ImmutablePass *llvm::createObjCARCAliasAnalysisPass() {
|
|
return new ObjCARCAliasAnalysis();
|
|
}
|
|
|
|
void
|
|
ObjCARCAliasAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.setPreservesAll();
|
|
AliasAnalysis::getAnalysisUsage(AU);
|
|
}
|
|
|
|
AliasAnalysis::AliasResult
|
|
ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) {
|
|
if (!EnableARCOpts)
|
|
return AliasAnalysis::alias(LocA, LocB);
|
|
|
|
// First, strip off no-ops, including ObjC-specific no-ops, and try making a
|
|
// precise alias query.
|
|
const Value *SA = GetRCIdentityRoot(LocA.Ptr);
|
|
const Value *SB = GetRCIdentityRoot(LocB.Ptr);
|
|
AliasResult Result =
|
|
AliasAnalysis::alias(Location(SA, LocA.Size, LocA.AATags),
|
|
Location(SB, LocB.Size, LocB.AATags));
|
|
if (Result != MayAlias)
|
|
return Result;
|
|
|
|
// If that failed, climb to the underlying object, including climbing through
|
|
// ObjC-specific no-ops, and try making an imprecise alias query.
|
|
const Value *UA = GetUnderlyingObjCPtr(SA);
|
|
const Value *UB = GetUnderlyingObjCPtr(SB);
|
|
if (UA != SA || UB != SB) {
|
|
Result = AliasAnalysis::alias(Location(UA), Location(UB));
|
|
// We can't use MustAlias or PartialAlias results here because
|
|
// GetUnderlyingObjCPtr may return an offsetted pointer value.
|
|
if (Result == NoAlias)
|
|
return NoAlias;
|
|
}
|
|
|
|
// If that failed, fail. We don't need to chain here, since that's covered
|
|
// by the earlier precise query.
|
|
return MayAlias;
|
|
}
|
|
|
|
bool
|
|
ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc,
|
|
bool OrLocal) {
|
|
if (!EnableARCOpts)
|
|
return AliasAnalysis::pointsToConstantMemory(Loc, OrLocal);
|
|
|
|
// First, strip off no-ops, including ObjC-specific no-ops, and try making
|
|
// a precise alias query.
|
|
const Value *S = GetRCIdentityRoot(Loc.Ptr);
|
|
if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.AATags),
|
|
OrLocal))
|
|
return true;
|
|
|
|
// If that failed, climb to the underlying object, including climbing through
|
|
// ObjC-specific no-ops, and try making an imprecise alias query.
|
|
const Value *U = GetUnderlyingObjCPtr(S);
|
|
if (U != S)
|
|
return AliasAnalysis::pointsToConstantMemory(Location(U), OrLocal);
|
|
|
|
// If that failed, fail. We don't need to chain here, since that's covered
|
|
// by the earlier precise query.
|
|
return false;
|
|
}
|
|
|
|
AliasAnalysis::ModRefBehavior
|
|
ObjCARCAliasAnalysis::getModRefBehavior(ImmutableCallSite CS) {
|
|
// We have nothing to do. Just chain to the next AliasAnalysis.
|
|
return AliasAnalysis::getModRefBehavior(CS);
|
|
}
|
|
|
|
AliasAnalysis::ModRefBehavior
|
|
ObjCARCAliasAnalysis::getModRefBehavior(const Function *F) {
|
|
if (!EnableARCOpts)
|
|
return AliasAnalysis::getModRefBehavior(F);
|
|
|
|
switch (GetFunctionClass(F)) {
|
|
case IC_NoopCast:
|
|
return DoesNotAccessMemory;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return AliasAnalysis::getModRefBehavior(F);
|
|
}
|
|
|
|
AliasAnalysis::ModRefResult
|
|
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS, const Location &Loc) {
|
|
if (!EnableARCOpts)
|
|
return AliasAnalysis::getModRefInfo(CS, Loc);
|
|
|
|
switch (GetBasicInstructionClass(CS.getInstruction())) {
|
|
case IC_Retain:
|
|
case IC_RetainRV:
|
|
case IC_Autorelease:
|
|
case IC_AutoreleaseRV:
|
|
case IC_NoopCast:
|
|
case IC_AutoreleasepoolPush:
|
|
case IC_FusedRetainAutorelease:
|
|
case IC_FusedRetainAutoreleaseRV:
|
|
// These functions don't access any memory visible to the compiler.
|
|
// Note that this doesn't include objc_retainBlock, because it updates
|
|
// pointers when it copies block data.
|
|
return NoModRef;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return AliasAnalysis::getModRefInfo(CS, Loc);
|
|
}
|
|
|
|
AliasAnalysis::ModRefResult
|
|
ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
|
|
ImmutableCallSite CS2) {
|
|
// TODO: Theoretically we could check for dependencies between objc_* calls
|
|
// and OnlyAccessesArgumentPointees calls or other well-behaved calls.
|
|
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
|
}
|