10b57cec5SDimitry Andric //===- ObjCARCExpand.cpp - ObjC ARC Optimization --------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// This file defines ObjC ARC optimizations. ARC stands for Automatic 100b57cec5SDimitry Andric /// Reference Counting and is a system for managing reference counts for objects 110b57cec5SDimitry Andric /// in Objective C. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric /// This specific file deals with early optimizations which perform certain 140b57cec5SDimitry Andric /// cleanup operations. 150b57cec5SDimitry Andric /// 160b57cec5SDimitry Andric /// WARNING: This file knows about certain library functions. It recognizes them 170b57cec5SDimitry Andric /// by name, and hardwires knowledge of their semantics. 180b57cec5SDimitry Andric /// 190b57cec5SDimitry Andric /// WARNING: This file knows about how certain Objective-C library functions are 200b57cec5SDimitry Andric /// used. Naive LLVM IR transformations which would otherwise be 210b57cec5SDimitry Andric /// behavior-preserving may break these assumptions. 220b57cec5SDimitry Andric /// 230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 240b57cec5SDimitry Andric 25*81ad6265SDimitry Andric #include "llvm/Analysis/ObjCARCAnalysisUtils.h" 260b57cec5SDimitry Andric #include "llvm/IR/Function.h" 270b57cec5SDimitry Andric #include "llvm/IR/InstIterator.h" 280b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 290b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 30e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 310b57cec5SDimitry Andric #include "llvm/IR/Value.h" 320b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 330b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 340b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 35e8d8bef9SDimitry Andric #include "llvm/Transforms/ObjCARC.h" 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #define DEBUG_TYPE "objc-arc-expand" 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric using namespace llvm; 400b57cec5SDimitry Andric using namespace llvm::objcarc; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric namespace { runImpl(Function & F)43e8d8bef9SDimitry Andricstatic bool runImpl(Function &F) { 440b57cec5SDimitry Andric if (!EnableARCOpts) 450b57cec5SDimitry Andric return false; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric // If nothing in the Module uses ARC, don't do anything. 48e8d8bef9SDimitry Andric if (!ModuleHasARC(*F.getParent())) 490b57cec5SDimitry Andric return false; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric bool Changed = false; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() 540b57cec5SDimitry Andric << "\n"); 550b57cec5SDimitry Andric 56349cc55cSDimitry Andric for (Instruction &Inst : instructions(&F)) { 57349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << Inst << "\n"); 580b57cec5SDimitry Andric 59349cc55cSDimitry Andric switch (GetBasicARCInstKind(&Inst)) { 600b57cec5SDimitry Andric case ARCInstKind::Retain: 610b57cec5SDimitry Andric case ARCInstKind::RetainRV: 620b57cec5SDimitry Andric case ARCInstKind::Autorelease: 630b57cec5SDimitry Andric case ARCInstKind::AutoreleaseRV: 640b57cec5SDimitry Andric case ARCInstKind::FusedRetainAutorelease: 650b57cec5SDimitry Andric case ARCInstKind::FusedRetainAutoreleaseRV: { 660b57cec5SDimitry Andric // These calls return their argument verbatim, as a low-level 670b57cec5SDimitry Andric // optimization. However, this makes high-level optimizations 680b57cec5SDimitry Andric // harder. Undo any uses of this optimization that the front-end 690b57cec5SDimitry Andric // emitted here. We'll redo them in the contract pass. 700b57cec5SDimitry Andric Changed = true; 71349cc55cSDimitry Andric Value *Value = cast<CallInst>(&Inst)->getArgOperand(0); 72349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "ObjCARCExpand: Old = " << Inst 730b57cec5SDimitry Andric << "\n" 740b57cec5SDimitry Andric " New = " 750b57cec5SDimitry Andric << *Value << "\n"); 76349cc55cSDimitry Andric Inst.replaceAllUsesWith(Value); 770b57cec5SDimitry Andric break; 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric default: 800b57cec5SDimitry Andric break; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n"); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric return Changed; 870b57cec5SDimitry Andric } 88e8d8bef9SDimitry Andric 89e8d8bef9SDimitry Andric } // namespace 90e8d8bef9SDimitry Andric run(Function & F,FunctionAnalysisManager & AM)91e8d8bef9SDimitry AndricPreservedAnalyses ObjCARCExpandPass::run(Function &F, 92e8d8bef9SDimitry Andric FunctionAnalysisManager &AM) { 93e8d8bef9SDimitry Andric if (!runImpl(F)) 94e8d8bef9SDimitry Andric return PreservedAnalyses::all(); 95e8d8bef9SDimitry Andric PreservedAnalyses PA; 96e8d8bef9SDimitry Andric PA.preserveSet<CFGAnalyses>(); 97e8d8bef9SDimitry Andric return PA; 98e8d8bef9SDimitry Andric } 99