16504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//===- ObjCARCExpand.cpp - ObjC ARC Optimization --------------------------===//
26504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//
36504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//                     The LLVM Compiler Infrastructure
46504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//
56504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman// This file is distributed under the University of Illinois Open Source
66504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman// License. See LICENSE.TXT for details.
76504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//
86504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//===----------------------------------------------------------------------===//
96504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// \file
106504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// This file defines ObjC ARC optimizations. ARC stands for Automatic
116504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// Reference Counting and is a system for managing reference counts for objects
126504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// in Objective C.
136504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman///
146504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// This specific file deals with early optimizations which perform certain
156504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// cleanup operations.
166504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman///
176504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// WARNING: This file knows about certain library functions. It recognizes them
186504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// by name, and hardwires knowledge of their semantics.
196504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman///
206504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// WARNING: This file knows about how certain Objective-C library functions are
216504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// used. Naive LLVM IR transformations which would otherwise be
226504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman/// behavior-preserving may break these assumptions.
236504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman///
246504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman//===----------------------------------------------------------------------===//
256504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
266504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman#include "ObjCARC.h"
27074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/ADT/StringRef.h"
28074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/IR/Function.h"
2936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/IR/InstIterator.h"
30074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/IR/Instruction.h"
31074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/IR/Instructions.h"
32074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/IR/Value.h"
33074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/Pass.h"
34074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/PassAnalysisSupport.h"
35074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/PassRegistry.h"
36074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/PassSupport.h"
37074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/Support/Casting.h"
38074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/Support/Debug.h"
39074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman#include "llvm/Support/raw_ostream.h"
40074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman
41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "objc-arc-expand"
42dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
43074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesmannamespace llvm {
44074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman  class Module;
45074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman}
46074ddd6f014b8b3488e53d22a961874230afb0d5Michael Gottesman
476504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanusing namespace llvm;
486504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanusing namespace llvm::objcarc;
496504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
506504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmannamespace {
516504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  /// \brief Early ARC transformations.
526504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  class ObjCARCExpand : public FunctionPass {
5336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override;
5436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool doInitialization(Module &M) override;
5536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override;
566504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
576504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    /// A flag indicating whether this optimization pass should run.
586504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    bool Run;
596504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
606504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  public:
616504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    static char ID;
626504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    ObjCARCExpand() : FunctionPass(ID) {
636504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      initializeObjCARCExpandPass(*PassRegistry::getPassRegistry());
646504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    }
656504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  };
666504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman}
676504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
686504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanchar ObjCARCExpand::ID = 0;
696504255a2257c53df8ab191c1db4517139f5dc8cMichael GottesmanINITIALIZE_PASS(ObjCARCExpand,
706504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman                "objc-arc-expand", "ObjC ARC expansion", false, false)
716504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
726504255a2257c53df8ab191c1db4517139f5dc8cMichael GottesmanPass *llvm::createObjCARCExpandPass() {
736504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  return new ObjCARCExpand();
746504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman}
756504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
766504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanvoid ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const {
776504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  AU.setPreservesCFG();
786504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman}
796504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
806504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanbool ObjCARCExpand::doInitialization(Module &M) {
816504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  Run = ModuleHasARC(M);
826504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  return false;
836504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman}
846504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
856504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesmanbool ObjCARCExpand::runOnFunction(Function &F) {
866504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  if (!EnableARCOpts)
876504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    return false;
886504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
896504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  // If nothing in the Module uses ARC, don't do anything.
906504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  if (!Run)
916504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    return false;
926504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
936504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  bool Changed = false;
946504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
956504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() << "\n");
966504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
976504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
986504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    Instruction *Inst = &*I;
996504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
1006504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << *Inst << "\n");
1016504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
1026504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    switch (GetBasicInstructionClass(Inst)) {
1036504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_Retain:
1046504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_RetainRV:
1056504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_Autorelease:
1066504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_AutoreleaseRV:
1076504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_FusedRetainAutorelease:
1086504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    case IC_FusedRetainAutoreleaseRV: {
1096504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      // These calls return their argument verbatim, as a low-level
1106504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      // optimization. However, this makes high-level optimizations
1116504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      // harder. Undo any uses of this optimization that the front-end
1126504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      // emitted here. We'll redo them in the contract pass.
1136504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      Changed = true;
1146504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      Value *Value = cast<CallInst>(Inst)->getArgOperand(0);
1156504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      DEBUG(dbgs() << "ObjCARCExpand: Old = " << *Inst << "\n"
1166504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman                      "               New = " << *Value << "\n");
1176504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      Inst->replaceAllUsesWith(Value);
1186504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      break;
1196504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    }
1206504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    default:
1216504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman      break;
1226504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman    }
1236504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  }
1246504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
1256504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n");
1266504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman
1276504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman  return Changed;
1286504255a2257c53df8ab191c1db4517139f5dc8cMichael Gottesman}
129