99 lines · cpp
1//===- ObjCARCExpand.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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file defines ObjC ARC optimizations. ARC stands for Automatic10/// Reference Counting and is a system for managing reference counts for objects11/// in Objective C.12///13/// This specific file deals with early optimizations which perform certain14/// cleanup operations.15///16/// WARNING: This file knows about certain library functions. It recognizes them17/// by name, and hardwires knowledge of their semantics.18///19/// WARNING: This file knows about how certain Objective-C library functions are20/// used. Naive LLVM IR transformations which would otherwise be21/// behavior-preserving may break these assumptions.22///23//===----------------------------------------------------------------------===//24 25#include "llvm/Analysis/ObjCARCAnalysisUtils.h"26#include "llvm/IR/Function.h"27#include "llvm/IR/InstIterator.h"28#include "llvm/IR/Instruction.h"29#include "llvm/IR/Instructions.h"30#include "llvm/IR/PassManager.h"31#include "llvm/IR/Value.h"32#include "llvm/Support/Casting.h"33#include "llvm/Support/Debug.h"34#include "llvm/Support/raw_ostream.h"35#include "llvm/Transforms/ObjCARC.h"36 37#define DEBUG_TYPE "objc-arc-expand"38 39using namespace llvm;40using namespace llvm::objcarc;41 42namespace {43static bool runImpl(Function &F) {44 if (!EnableARCOpts)45 return false;46 47 // If nothing in the Module uses ARC, don't do anything.48 if (!ModuleHasARC(*F.getParent()))49 return false;50 51 bool Changed = false;52 53 LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName()54 << "\n");55 56 for (Instruction &Inst : instructions(&F)) {57 LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << Inst << "\n");58 59 switch (GetBasicARCInstKind(&Inst)) {60 case ARCInstKind::Retain:61 case ARCInstKind::RetainRV:62 case ARCInstKind::Autorelease:63 case ARCInstKind::AutoreleaseRV:64 case ARCInstKind::FusedRetainAutorelease:65 case ARCInstKind::FusedRetainAutoreleaseRV: {66 // These calls return their argument verbatim, as a low-level67 // optimization. However, this makes high-level optimizations68 // harder. Undo any uses of this optimization that the front-end69 // emitted here. We'll redo them in the contract pass.70 Changed = true;71 Value *Value = cast<CallInst>(&Inst)->getArgOperand(0);72 LLVM_DEBUG(dbgs() << "ObjCARCExpand: Old = " << Inst73 << "\n"74 " New = "75 << *Value << "\n");76 Inst.replaceAllUsesWith(Value);77 break;78 }79 default:80 break;81 }82 }83 84 LLVM_DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n");85 86 return Changed;87}88 89} // namespace90 91PreservedAnalyses ObjCARCExpandPass::run(Function &F,92 FunctionAnalysisManager &AM) {93 if (!runImpl(F))94 return PreservedAnalyses::all();95 PreservedAnalyses PA;96 PA.preserveSet<CFGAnalyses>();97 return PA;98}99