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-exception 6// 7//===----------------------------------------------------------------------===// 8/// \file 9/// This file defines ObjC ARC optimizations. ARC stands for Automatic 10/// Reference Counting and is a system for managing reference counts for objects 11/// in Objective C. 12/// 13/// This specific file deals with early optimizations which perform certain 14/// cleanup operations. 15/// 16/// WARNING: This file knows about certain library functions. It recognizes them 17/// by name, and hardwires knowledge of their semantics. 18/// 19/// WARNING: This file knows about how certain Objective-C library functions are 20/// used. Naive LLVM IR transformations which would otherwise be 21/// 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-level 67 // optimization. However, this makes high-level optimizations 68 // harder. Undo any uses of this optimization that the front-end 69 // 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 = " << Inst 73 << "\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} // namespace 90 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