xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 Andric static 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 Andric PreservedAnalyses 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