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 39 using namespace llvm; 40 using namespace llvm::objcarc; 41 42 namespace { runImpl(Function & F)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 run(Function & F,FunctionAnalysisManager & AM)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