Changed SmallPtrSet.count guard + SmallPtrSet.insert to just SmallPtrSet.insert.
[oota-llvm.git] / lib / Transforms / Scalar / ObjCARC.cpp
index 27c94dc0a3ff6457216d8a74fbbd65fdfacfe06d..abd6b4185f6305f82f2a0cf747b8cb0fb8f9cb06 100644 (file)
@@ -6,53 +6,53 @@
 // License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
-//
-// This file defines ObjC ARC optimizations. ARC stands for
-// Automatic Reference Counting and is a system for managing reference counts
-// for objects in Objective C.
-//
-// The optimizations performed include elimination of redundant, partially
-// redundant, and inconsequential reference count operations, elimination of
-// redundant weak pointer operations, pattern-matching and replacement of
-// low-level operations into higher-level operations, and numerous minor
-// simplifications.
-//
-// This file also defines a simple ARC-aware AliasAnalysis.
-//
-// WARNING: This file knows about certain library functions. It recognizes them
-// by name, and hardwires knowledge of their semantics.
-//
-// WARNING: This file knows about how certain Objective-C library functions are
-// used. Naive LLVM IR transformations which would otherwise be
-// behavior-preserving may break these assumptions.
-//
+/// \file
+/// This file defines ObjC ARC optimizations. ARC stands for Automatic
+/// Reference Counting and is a system for managing reference counts for objects
+/// in Objective C.
+///
+/// The optimizations performed include elimination of redundant, partially
+/// redundant, and inconsequential reference count operations, elimination of
+/// redundant weak pointer operations, pattern-matching and replacement of
+/// low-level operations into higher-level operations, and numerous minor
+/// simplifications.
+///
+/// This file also defines a simple ARC-aware AliasAnalysis.
+///
+/// WARNING: This file knows about certain library functions. It recognizes them
+/// by name, and hardwires knowledge of their semantics.
+///
+/// WARNING: This file knows about how certain Objective-C library functions are
+/// used. Naive LLVM IR transformations which would otherwise be
+/// behavior-preserving may break these assumptions.
+///
 //===----------------------------------------------------------------------===//
 
 #define DEBUG_TYPE "objc-arc"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/CommandLine.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
-// A handy option to enable/disable all optimizations in this file.
+/// \brief A handy option to enable/disable all optimizations in this file.
 static cl::opt<bool> EnableARCOpts("enable-objc-arc-opts", cl::init(true));
 
-//===----------------------------------------------------------------------===//
-// Misc. Utilities
-//===----------------------------------------------------------------------===//
+/// \defgroup MiscUtils Miscellaneous utilities that are not ARC specific.
+/// @{
 
 namespace {
-  /// MapVector - An associative container with fast insertion-order
-  /// (deterministic) iteration over its elements. Plus the special
-  /// blot operation.
+  /// \brief An associative container with fast insertion-order (deterministic)
+  /// iteration over its elements. Plus the special blot operation.
   template<class KeyT, class ValueT>
   class MapVector {
-    /// Map - Map keys to indices in Vector.
+    /// Map keys to indices in Vector.
     typedef DenseMap<KeyT, size_t> MapTy;
     MapTy Map;
 
-    /// Vector - Keys and values.
     typedef std::vector<std::pair<KeyT, ValueT> > VectorTy;
+    /// Keys and values.
     VectorTy Vector;
 
   public:
@@ -110,10 +110,9 @@ namespace {
       return Vector.begin() + It->second;
     }
 
-    /// blot - This is similar to erase, but instead of removing the element
-    /// from the vector, it just zeros out the key in the vector. This leaves
-    /// iterators intact, but clients must be prepared for zeroed-out keys when
-    /// iterating.
+    /// This is similar to erase, but instead of removing the element from the
+    /// vector, it just zeros out the key in the vector. This leaves iterators
+    /// intact, but clients must be prepared for zeroed-out keys when iterating.
     void blot(const KeyT &Key) {
       typename MapTy::iterator It = Map.find(Key);
       if (It == Map.end()) return;
@@ -128,19 +127,21 @@ namespace {
   };
 }
 
-//===----------------------------------------------------------------------===//
-// ARC Utilities.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCUtilities Utility declarations/definitions specific to ARC.
+/// @{
 
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/ValueTracking.h"
-#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Support/CallSite.h"
-#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Transforms/Utils/Local.h"
 
 namespace {
-  /// InstructionClass - A simple classification for instructions.
+  /// \enum InstructionClass
+  /// \brief A simple classification for instructions.
   enum InstructionClass {
     IC_Retain,              ///< objc_retain
     IC_RetainRV,            ///< objc_retainAutoreleasedReturnValue
@@ -168,8 +169,7 @@ namespace {
   };
 }
 
-/// IsPotentialUse - Test whether the given value is possible a
-/// reference-counted pointer.
+/// \brief Test whether the given value is possible a reference-counted pointer.
 static bool IsPotentialUse(const Value *Op) {
   // Pointers to static or stack storage are not reference-counted pointers.
   if (isa<Constant>(Op) || isa<AllocaInst>(Op))
@@ -192,8 +192,8 @@ static bool IsPotentialUse(const Value *Op) {
   return true;
 }
 
-/// GetCallSiteClass - Helper for GetInstructionClass. Determines what kind
-/// of construct CS is.
+/// \brief Helper for GetInstructionClass. Determines what kind of construct CS
+/// is.
 static InstructionClass GetCallSiteClass(ImmutableCallSite CS) {
   for (ImmutableCallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
        I != E; ++I)
@@ -203,8 +203,8 @@ static InstructionClass GetCallSiteClass(ImmutableCallSite CS) {
   return CS.onlyReadsMemory() ? IC_None : IC_Call;
 }
 
-/// GetFunctionClass - Determine if F is one of the special known Functions.
-/// If it isn't, return IC_CallOrUser.
+/// \brief Determine if F is one of the special known Functions.  If it isn't,
+/// return IC_CallOrUser.
 static InstructionClass GetFunctionClass(const Function *F) {
   Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
 
@@ -276,7 +276,7 @@ static InstructionClass GetFunctionClass(const Function *F) {
   return IC_CallOrUser;
 }
 
-/// GetInstructionClass - Determine what kind of construct V is.
+/// \brief Determine what kind of construct V is.
 static InstructionClass GetInstructionClass(const Value *V) {
   if (const Instruction *I = dyn_cast<Instruction>(V)) {
     // Any instruction other than bitcast and gep with a pointer operand have a
@@ -366,9 +366,11 @@ static InstructionClass GetInstructionClass(const Value *V) {
   return IC_None;
 }
 
-/// GetBasicInstructionClass - Determine what kind of construct V is. This is
-/// similar to GetInstructionClass except that it only detects objc runtine
-/// calls. This allows it to be faster.
+/// \brief Determine which objc runtime call instruction class V belongs to.
+///
+/// This is similar to GetInstructionClass except that it only detects objc
+/// runtime calls. This allows it to be faster.
+///
 static InstructionClass GetBasicInstructionClass(const Value *V) {
   if (const CallInst *CI = dyn_cast<CallInst>(V)) {
     if (const Function *F = CI->getCalledFunction())
@@ -381,22 +383,20 @@ static InstructionClass GetBasicInstructionClass(const Value *V) {
   return isa<InvokeInst>(V) ? IC_CallOrUser : IC_User;
 }
 
-/// IsRetain - Test if the given class is objc_retain or
-/// equivalent.
+/// \brief Test if the given class is objc_retain or equivalent.
 static bool IsRetain(InstructionClass Class) {
   return Class == IC_Retain ||
          Class == IC_RetainRV;
 }
 
-/// IsAutorelease - Test if the given class is objc_autorelease or
-/// equivalent.
+/// \brief Test if the given class is objc_autorelease or equivalent.
 static bool IsAutorelease(InstructionClass Class) {
   return Class == IC_Autorelease ||
          Class == IC_AutoreleaseRV;
 }
 
-/// IsForwarding - Test if the given class represents instructions which return
-/// their argument verbatim.
+/// \brief Test if the given class represents instructions which return their
+/// argument verbatim.
 static bool IsForwarding(InstructionClass Class) {
   // objc_retainBlock technically doesn't always return its argument
   // verbatim, but it doesn't matter for our purposes here.
@@ -408,8 +408,8 @@ static bool IsForwarding(InstructionClass Class) {
          Class == IC_NoopCast;
 }
 
-/// IsNoopOnNull - Test if the given class represents instructions which do
-/// nothing if passed a null pointer.
+/// \brief Test if the given class represents instructions which do nothing if
+/// passed a null pointer.
 static bool IsNoopOnNull(InstructionClass Class) {
   return Class == IC_Retain ||
          Class == IC_RetainRV ||
@@ -419,18 +419,28 @@ static bool IsNoopOnNull(InstructionClass Class) {
          Class == IC_RetainBlock;
 }
 
-/// IsAlwaysTail - Test if the given class represents instructions which are
-/// always safe to mark with the "tail" keyword.
+/// \brief Test if the given class represents instructions which are always safe
+/// to mark with the "tail" keyword.
 static bool IsAlwaysTail(InstructionClass Class) {
   // IC_RetainBlock may be given a stack argument.
   return Class == IC_Retain ||
          Class == IC_RetainRV ||
-         Class == IC_Autorelease ||
          Class == IC_AutoreleaseRV;
 }
 
-/// IsNoThrow - Test if the given class represents instructions which are always
-/// safe to mark with the nounwind attribute..
+/// \brief Test if the given class represents instructions which are never safe
+/// to mark with the "tail" keyword.
+static bool IsNeverTail(InstructionClass Class) {
+  /// It is never safe to tail call objc_autorelease since by tail calling
+  /// objc_autorelease, we also tail call -[NSObject autorelease] which supports
+  /// fast autoreleasing causing our object to be potentially reclaimed from the
+  /// autorelease pool which violates the semantics of __autoreleasing types in
+  /// ARC.
+  return Class == IC_Autorelease;
+}
+
+/// \brief Test if the given class represents instructions which are always safe
+/// to mark with the nounwind attribute.
 static bool IsNoThrow(InstructionClass Class) {
   // objc_retainBlock is not nounwind because it calls user copy constructors
   // which could theoretically throw.
@@ -443,9 +453,12 @@ static bool IsNoThrow(InstructionClass Class) {
          Class == IC_AutoreleasepoolPop;
 }
 
-/// EraseInstruction - Erase the given instruction. Many ObjC calls return their
-/// argument verbatim, so if it's such a call and the return value has users,
-/// replace them with the argument value.
+/// \brief Erase the given instruction.
+///
+/// Many ObjC calls return their argument verbatim,
+/// so if it's such a call and the return value has users, replace them with the
+/// argument value.
+///
 static void EraseInstruction(Instruction *CI) {
   Value *OldArg = cast<CallInst>(CI)->getArgOperand(0);
 
@@ -464,9 +477,9 @@ static void EraseInstruction(Instruction *CI) {
     RecursivelyDeleteTriviallyDeadInstructions(OldArg);
 }
 
-/// GetUnderlyingObjCPtr - This is a wrapper around getUnderlyingObject which
-/// also knows how to look through objc_retain and objc_autorelease calls, which
-/// we know to return their argument verbatim.
+/// \brief This is a wrapper around getUnderlyingObject which also knows how to
+/// look through objc_retain and objc_autorelease calls, which we know to return
+/// their argument verbatim.
 static const Value *GetUnderlyingObjCPtr(const Value *V) {
   for (;;) {
     V = GetUnderlyingObject(V);
@@ -478,9 +491,9 @@ static const Value *GetUnderlyingObjCPtr(const Value *V) {
   return V;
 }
 
-/// StripPointerCastsAndObjCCalls - This is a wrapper around
-/// Value::stripPointerCasts which also knows how to look through objc_retain
-/// and objc_autorelease calls, which we know to return their argument verbatim.
+/// \brief This is a wrapper around Value::stripPointerCasts which also knows
+/// how to look through objc_retain and objc_autorelease calls, which we know to
+/// return their argument verbatim.
 static const Value *StripPointerCastsAndObjCCalls(const Value *V) {
   for (;;) {
     V = V->stripPointerCasts();
@@ -491,9 +504,9 @@ static const Value *StripPointerCastsAndObjCCalls(const Value *V) {
   return V;
 }
 
-/// StripPointerCastsAndObjCCalls - This is a wrapper around
-/// Value::stripPointerCasts which also knows how to look through objc_retain
-/// and objc_autorelease calls, which we know to return their argument verbatim.
+/// \brief This is a wrapper around Value::stripPointerCasts which also knows
+/// how to look through objc_retain and objc_autorelease calls, which we know to
+/// return their argument verbatim.
 static Value *StripPointerCastsAndObjCCalls(Value *V) {
   for (;;) {
     V = V->stripPointerCasts();
@@ -504,16 +517,15 @@ static Value *StripPointerCastsAndObjCCalls(Value *V) {
   return V;
 }
 
-/// GetObjCArg - Assuming the given instruction is one of the special calls such
-/// as objc_retain or objc_release, return the argument value, stripped of no-op
+/// \brief Assuming the given instruction is one of the special calls such as
+/// objc_retain or objc_release, return the argument value, stripped of no-op
 /// casts and forwarding calls.
 static Value *GetObjCArg(Value *Inst) {
   return StripPointerCastsAndObjCCalls(cast<CallInst>(Inst)->getArgOperand(0));
 }
 
-/// IsObjCIdentifiedObject - This is similar to AliasAnalysis'
-/// isObjCIdentifiedObject, except that it uses special knowledge of
-/// ObjC conventions...
+/// \brief This is similar to AliasAnalysis's isObjCIdentifiedObject, except
+/// that it uses special knowledge of ObjC conventions.
 static bool IsObjCIdentifiedObject(const Value *V) {
   // Assume that call results and arguments have their own "provenance".
   // Constants (including GlobalVariables) and Allocas are never
@@ -546,9 +558,8 @@ static bool IsObjCIdentifiedObject(const Value *V) {
   return false;
 }
 
-/// FindSingleUseIdentifiedObject - This is similar to
-/// StripPointerCastsAndObjCCalls but it stops as soon as it finds a value
-/// with multiple uses.
+/// \brief This is similar to StripPointerCastsAndObjCCalls but it stops as soon
+/// as it finds a value with multiple uses.
 static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
   if (Arg->hasOneUse()) {
     if (const BitCastInst *BC = dyn_cast<BitCastInst>(Arg))
@@ -580,8 +591,8 @@ static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
   return 0;
 }
 
-/// ModuleHasARC - Test if the given module looks interesting to run ARC
-/// optimization on.
+/// \brief Test if the given module looks interesting to run ARC optimization
+/// on.
 static bool ModuleHasARC(const Module &M) {
   return
     M.getNamedValue("objc_retain") ||
@@ -603,19 +614,34 @@ static bool ModuleHasARC(const Module &M) {
     M.getNamedValue("objc_unretainedPointer");
 }
 
-/// DoesObjCBlockEscape - Test whether the given pointer, which is an
-/// Objective C block pointer, does not "escape". This differs from regular
-/// escape analysis in that a use as an argument to a call is not considered
-/// an escape.
+/// \brief Test whether the given pointer, which is an Objective C block
+/// pointer, does not "escape".
+///
+/// This differs from regular escape analysis in that a use as an
+/// argument to a call is not considered an escape.
+///
 static bool DoesObjCBlockEscape(const Value *BlockPtr) {
+
+  DEBUG(dbgs() << "DoesObjCBlockEscape: Target: " << *BlockPtr << "\n");
+
   // Walk the def-use chains.
   SmallVector<const Value *, 4> Worklist;
   Worklist.push_back(BlockPtr);
+
+  // Ensure we do not visit any value twice.
+  SmallPtrSet<const Value *, 4> VisitedSet;
+
   do {
     const Value *V = Worklist.pop_back_val();
+
+    DEBUG(dbgs() << "DoesObjCBlockEscape: Visiting: " << *V << "\n");
+
     for (Value::const_use_iterator UI = V->use_begin(), UE = V->use_end();
          UI != UE; ++UI) {
       const User *UUser = *UI;
+
+      DEBUG(dbgs() << "DoesObjCBlockEscape: User: " << *UUser << "\n");
+
       // Special - Use by a call (callee or argument) is not considered
       // to be an escape.
       switch (GetBasicInstructionClass(UUser)) {
@@ -623,16 +649,26 @@ static bool DoesObjCBlockEscape(const Value *BlockPtr) {
       case IC_InitWeak:
       case IC_StoreStrong:
       case IC_Autorelease:
-      case IC_AutoreleaseRV:
+      case IC_AutoreleaseRV: {
+        DEBUG(dbgs() << "DoesObjCBlockEscape: User copies pointer arguments. "
+                        "Block Escapes!\n");
         // These special functions make copies of their pointer arguments.
         return true;
+      }
       case IC_User:
       case IC_None:
         // Use by an instruction which copies the value is an escape if the
         // result is an escape.
         if (isa<BitCastInst>(UUser) || isa<GetElementPtrInst>(UUser) ||
             isa<PHINode>(UUser) || isa<SelectInst>(UUser)) {
-          Worklist.push_back(UUser);
+
+          if (!VisitedSet.insert(UUser)) {
+            DEBUG(dbgs() << "DoesObjCBlockEscape: User copies value. Escapes "
+                            "if result escapes. Adding to list.\n");
+            Worklist.push_back(UUser);
+          } else {
+            DEBUG(dbgs() << "DoesObjCBlockEscape: Already visited node.\n");
+          }
           continue;
         }
         // Use by a load is not an escape.
@@ -648,25 +684,28 @@ static bool DoesObjCBlockEscape(const Value *BlockPtr) {
         continue;
       }
       // Otherwise, conservatively assume an escape.
+      DEBUG(dbgs() << "DoesObjCBlockEscape: Assuming block escapes.\n");
       return true;
     }
   } while (!Worklist.empty());
 
   // No escapes found.
+  DEBUG(dbgs() << "DoesObjCBlockEscape: Block does not escape.\n");
   return false;
 }
 
-//===----------------------------------------------------------------------===//
-// ARC AliasAnalysis.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCAA Extends alias analysis using ObjC specific knowledge.
+/// @{
 
-#include "llvm/Pass.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/Passes.h"
+#include "llvm/Pass.h"
 
 namespace {
-  /// ObjCARCAliasAnalysis - This is a simple alias analysis
-  /// implementation that uses knowledge of ARC constructs to answer queries.
+  /// \brief This is a simple alias analysis implementation that uses knowledge
+  /// of ARC constructs to answer queries.
   ///
   /// TODO: This class could be generalized to know about other ObjC-specific
   /// tricks. Such as knowing that ivars in the non-fragile ABI are non-aliasing
@@ -684,10 +723,9 @@ namespace {
       InitializeAliasAnalysis(this);
     }
 
-    /// getAdjustedAnalysisPointer - This method is used when a pass implements
-    /// an analysis interface through multiple inheritance.  If needed, it
-    /// should override this to adjust the this pointer as needed for the
-    /// specified pass info.
+    /// This method is used when a pass implements an analysis interface through
+    /// multiple inheritance.  If needed, it should override this to adjust the
+    /// this pointer as needed for the specified pass info.
     virtual void *getAdjustedAnalysisPointer(const void *PI) {
       if (PI == &AliasAnalysis::ID)
         return static_cast<AliasAnalysis *>(this);
@@ -831,21 +869,22 @@ ObjCARCAliasAnalysis::getModRefInfo(ImmutableCallSite CS1,
   return AliasAnalysis::getModRefInfo(CS1, CS2);
 }
 
-//===----------------------------------------------------------------------===//
-// ARC expansion.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCExpansion Early ARC Optimizations.
+/// @{
 
 #include "llvm/Support/InstIterator.h"
 #include "llvm/Transforms/Scalar.h"
 
 namespace {
-  /// ObjCARCExpand - Early ARC transformations.
+  /// \brief Early ARC transformations.
   class ObjCARCExpand : public FunctionPass {
     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
     virtual bool doInitialization(Module &M);
     virtual bool runOnFunction(Function &F);
 
-    /// Run - A flag indicating whether this optimization pass should run.
+    /// A flag indicating whether this optimization pass should run.
     bool Run;
 
   public:
@@ -883,40 +922,51 @@ bool ObjCARCExpand::runOnFunction(Function &F) {
 
   bool Changed = false;
 
+  DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() << "\n");
+
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
     Instruction *Inst = &*I;
 
+    DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << *Inst << "\n");
+
     switch (GetBasicInstructionClass(Inst)) {
     case IC_Retain:
     case IC_RetainRV:
     case IC_Autorelease:
     case IC_AutoreleaseRV:
     case IC_FusedRetainAutorelease:
-    case IC_FusedRetainAutoreleaseRV:
+    case IC_FusedRetainAutoreleaseRV: {
       // These calls return their argument verbatim, as a low-level
       // optimization. However, this makes high-level optimizations
       // harder. Undo any uses of this optimization that the front-end
       // emitted here. We'll redo them in the contract pass.
       Changed = true;
-      Inst->replaceAllUsesWith(cast<CallInst>(Inst)->getArgOperand(0));
+      Value *Value = cast<CallInst>(Inst)->getArgOperand(0);
+      DEBUG(dbgs() << "ObjCARCExpand: Old = " << *Inst << "\n"
+                      "               New = " << *Value << "\n");
+      Inst->replaceAllUsesWith(Value);
       break;
+    }
     default:
       break;
     }
   }
 
+  DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n");
+
   return Changed;
 }
 
-//===----------------------------------------------------------------------===//
-// ARC autorelease pool elimination.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCAPElim ARC Autorelease Pool Elimination.
+/// @{
 
-#include "llvm/Constants.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Constants.h"
 
 namespace {
-  /// ObjCARCAPElim - Autorelease pool elimination.
+  /// \brief Autorelease pool elimination.
   class ObjCARCAPElim : public ModulePass {
     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
     virtual bool runOnModule(Module &M);
@@ -946,8 +996,8 @@ void ObjCARCAPElim::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesCFG();
 }
 
-/// MayAutorelease - Interprocedurally determine if calls made by the
-/// given call site can possibly produce autoreleases.
+/// Interprocedurally determine if calls made by the given call site can
+/// possibly produce autoreleases.
 bool ObjCARCAPElim::MayAutorelease(ImmutableCallSite CS, unsigned Depth) {
   if (const Function *Callee = CS.getCalledFunction()) {
     if (Callee->isDeclaration() || Callee->mayBeOverridden())
@@ -986,6 +1036,10 @@ bool ObjCARCAPElim::OptimizeBB(BasicBlock *BB) {
       // zap the pair.
       if (Push && cast<CallInst>(Inst)->getArgOperand(0) == Push) {
         Changed = true;
+        DEBUG(dbgs() << "ObjCARCAPElim::OptimizeBB: Zapping push pop "
+                        "autorelease pair:\n"
+                        "                           Pop: " << *Inst << "\n"
+                     << "                           Push: " << *Push << "\n");
         Inst->eraseFromParent();
         Push->eraseFromParent();
       }
@@ -1051,9 +1105,10 @@ bool ObjCARCAPElim::runOnModule(Module &M) {
   return Changed;
 }
 
-//===----------------------------------------------------------------------===//
-// ARC optimization.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCOpt ARC Optimization.
+/// @{
 
 // TODO: On code like this:
 //
@@ -1093,10 +1148,10 @@ bool ObjCARCAPElim::runOnModule(Module &M) {
 
 // TODO: Delete release+retain pairs (rare).
 
-#include "llvm/LLVMContext.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/CFG.h"
 
 STATISTIC(NumNoops,       "Number of no-op objc calls eliminated");
 STATISTIC(NumPartialNoops, "Number of partially no-op objc calls eliminated");
@@ -1107,9 +1162,9 @@ STATISTIC(NumRRs,         "Number of retain+release paths eliminated");
 STATISTIC(NumPeeps,       "Number of calls peephole-optimized");
 
 namespace {
-  /// ProvenanceAnalysis - This is similar to BasicAliasAnalysis, and it
-  /// uses many of the same techniques, except it uses special ObjC-specific
-  /// reasoning about pointer relationships.
+  /// \brief This is similar to BasicAliasAnalysis, and it uses many of the same
+  /// techniques, except it uses special ObjC-specific reasoning about pointer
+  /// relationships.
   class ProvenanceAnalysis {
     AliasAnalysis *AA;
 
@@ -1121,9 +1176,8 @@ namespace {
     bool relatedSelect(const SelectInst *A, const Value *B);
     bool relatedPHI(const PHINode *A, const Value *B);
 
-    // Do not implement.
-    void operator=(const ProvenanceAnalysis &);
-    ProvenanceAnalysis(const ProvenanceAnalysis &);
+    void operator=(const ProvenanceAnalysis &) LLVM_DELETED_FUNCTION;
+    ProvenanceAnalysis(const ProvenanceAnalysis &) LLVM_DELETED_FUNCTION;
 
   public:
     ProvenanceAnalysis() {}
@@ -1178,8 +1232,8 @@ bool ProvenanceAnalysis::relatedPHI(const PHINode *A, const Value *B) {
   return false;
 }
 
-/// isStoredObjCPointer - Test if the value of P, or any value covered by its
-/// provenance, is ever stored within the function (not counting callees).
+/// Test if the value of P, or any value covered by its provenance, is ever
+/// stored within the function (not counting callees).
 static bool isStoredObjCPointer(const Value *P) {
   SmallPtrSet<const Value *, 8> Visited;
   SmallVector<const Value *, 8> Worklist;
@@ -1283,8 +1337,10 @@ bool ProvenanceAnalysis::related(const Value *A, const Value *B) {
 }
 
 namespace {
-  // Sequence - A sequence of states that a pointer may go through in which an
-  // objc_retain and objc_release are actually needed.
+  /// \enum Sequence
+  ///
+  /// \brief A sequence of states that a pointer may go through in which an
+  /// objc_retain and objc_release are actually needed.
   enum Sequence {
     S_None,
     S_Retain,         ///< objc_retain(x)
@@ -1325,11 +1381,11 @@ static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
 }
 
 namespace {
-  /// RRInfo - Unidirectional information about either a
+  /// \brief Unidirectional information about either a
   /// retain-decrement-use-release sequence or release-use-decrement-retain
   /// reverese sequence.
   struct RRInfo {
-    /// KnownSafe - After an objc_retain, the reference count of the referenced
+    /// After an objc_retain, the reference count of the referenced
     /// object is known to be positive. Similarly, before an objc_release, the
     /// reference count of the referenced object is known to be positive. If
     /// there are retain-release pairs in code regions where the retain count
@@ -1343,24 +1399,23 @@ namespace {
     /// KnownSafe is true when either of these conditions is satisfied.
     bool KnownSafe;
 
-    /// IsRetainBlock - True if the Calls are objc_retainBlock calls (as
-    /// opposed to objc_retain calls).
+    /// True if the Calls are objc_retainBlock calls (as opposed to objc_retain
+    /// calls).
     bool IsRetainBlock;
 
-    /// IsTailCallRelease - True of the objc_release calls are all marked
-    /// with the "tail" keyword.
+    /// True of the objc_release calls are all marked with the "tail" keyword.
     bool IsTailCallRelease;
 
-    /// ReleaseMetadata - If the Calls are objc_release calls and they all have
-    /// clang.imprecise_release tag, this is the metadata tag.
+    /// If the Calls are objc_release calls and they all have a
+    /// clang.imprecise_release tag, this is the metadata tag.
     MDNode *ReleaseMetadata;
 
-    /// Calls - For a top-down sequence, the set of objc_retains or
+    /// For a top-down sequence, the set of objc_retains or
     /// objc_retainBlocks. For bottom-up, the set of objc_releases.
     SmallPtrSet<Instruction *, 2> Calls;
 
-    /// ReverseInsertPts - The set of optimal insert positions for
-    /// moving calls in the opposite sequence.
+    /// The set of optimal insert positions for moving calls in the opposite
+    /// sequence.
     SmallPtrSet<Instruction *, 2> ReverseInsertPts;
 
     RRInfo() :
@@ -1382,23 +1437,22 @@ void RRInfo::clear() {
 }
 
 namespace {
-  /// PtrState - This class summarizes several per-pointer runtime properties
-  /// which are propogated through the flow graph.
+  /// \brief This class summarizes several per-pointer runtime properties which
+  /// are propogated through the flow graph.
   class PtrState {
-    /// KnownPositiveRefCount - True if the reference count is known to
-    /// be incremented.
+    /// True if the reference count is known to be incremented.
     bool KnownPositiveRefCount;
 
-    /// Partial - True of we've seen an opportunity for partial RR elimination,
-    /// such as pushing calls into a CFG triangle or into one side of a
-    /// CFG diamond.
+    /// True of we've seen an opportunity for partial RR elimination, such as
+    /// pushing calls into a CFG triangle or into one side of a CFG diamond.
     bool Partial;
 
-    /// Seq - The current position in the sequence.
+    /// The current position in the sequence.
     Sequence Seq : 8;
 
   public:
-    /// RRI - Unidirectional information about the current sequence.
+    /// Unidirectional information about the current sequence.
+    ///
     /// TODO: Encapsulate this better.
     RRInfo RRI;
 
@@ -1479,30 +1533,31 @@ PtrState::Merge(const PtrState &Other, bool TopDown) {
 }
 
 namespace {
-  /// BBState - Per-BasicBlock state.
+  /// \brief Per-BasicBlock state.
   class BBState {
-    /// TopDownPathCount - The number of unique control paths from the entry
-    /// which can reach this block.
+    /// The number of unique control paths from the entry which can reach this
+    /// block.
     unsigned TopDownPathCount;
 
-    /// BottomUpPathCount - The number of unique control paths to exits
-    /// from this block.
+    /// The number of unique control paths to exits from this block.
     unsigned BottomUpPathCount;
 
-    /// MapTy - A type for PerPtrTopDown and PerPtrBottomUp.
+    /// A type for PerPtrTopDown and PerPtrBottomUp.
     typedef MapVector<const Value *, PtrState> MapTy;
 
-    /// PerPtrTopDown - The top-down traversal uses this to record information
-    /// known about a pointer at the bottom of each block.
+    /// The top-down traversal uses this to record information known about a
+    /// pointer at the bottom of each block.
     MapTy PerPtrTopDown;
 
-    /// PerPtrBottomUp - The bottom-up traversal uses this to record information
-    /// known about a pointer at the top of each block.
+    /// The bottom-up traversal uses this to record information known about a
+    /// pointer at the top of each block.
     MapTy PerPtrBottomUp;
 
-    /// Preds, Succs - Effective successors and predecessors of the current
-    /// block (this ignores ignorable edges and ignored backedges).
+    /// Effective predecessors of the current block ignoring ignorable edges and
+    /// ignored backedges.
     SmallVector<BasicBlock *, 2> Preds;
+    /// Effective successors of the current block ignoring ignorable edges and
+    /// ignored backedges.
     SmallVector<BasicBlock *, 2> Succs;
 
   public:
@@ -1529,12 +1584,12 @@ namespace {
       return PerPtrBottomUp.end();
     }
 
-    /// SetAsEntry - Mark this block as being an entry block, which has one
-    /// path from the entry by definition.
+    /// Mark this block as being an entry block, which has one path from the
+    /// entry by definition.
     void SetAsEntry() { TopDownPathCount = 1; }
 
-    /// SetAsExit - Mark this block as being an exit block, which has one
-    /// path to an exit by definition.
+    /// Mark this block as being an exit block, which has one path to an exit by
+    /// definition.
     void SetAsExit()  { BottomUpPathCount = 1; }
 
     PtrState &getPtrTopDownState(const Value *Arg) {
@@ -1558,9 +1613,9 @@ namespace {
     void MergePred(const BBState &Other);
     void MergeSucc(const BBState &Other);
 
-    /// GetAllPathCount - Return the number of possible unique paths from an
-    /// entry to an exit which pass through this block. This is only valid
-    /// after both the top-down and bottom-up traversals are complete.
+    /// Return the number of possible unique paths from an entry to an exit
+    /// which pass through this block. This is only valid after both the
+    /// top-down and bottom-up traversals are complete.
     unsigned GetAllPathCount() const {
       assert(TopDownPathCount != 0);
       assert(BottomUpPathCount != 0);
@@ -1591,14 +1646,15 @@ void BBState::InitFromSucc(const BBState &Other) {
   BottomUpPathCount = Other.BottomUpPathCount;
 }
 
-/// MergePred - The top-down traversal uses this to merge information about
-/// predecessors to form the initial state for a new block.
+/// The top-down traversal uses this to merge information about predecessors to
+/// form the initial state for a new block.
 void BBState::MergePred(const BBState &Other) {
   // Other.TopDownPathCount can be 0, in which case it is either dead or a
   // loop backedge. Loop backedges are special.
   TopDownPathCount += Other.TopDownPathCount;
 
-  // Check for overflow. If we have overflow, fall back to conservative behavior.
+  // Check for overflow. If we have overflow, fall back to conservative
+  // behavior.
   if (TopDownPathCount < Other.TopDownPathCount) {
     clearTopDownPointers();
     return;
@@ -1622,14 +1678,15 @@ void BBState::MergePred(const BBState &Other) {
       MI->second.Merge(PtrState(), /*TopDown=*/true);
 }
 
-/// MergeSucc - The bottom-up traversal uses this to merge information about
-/// successors to form the initial state for a new block.
+/// The bottom-up traversal uses this to merge information about successors to
+/// form the initial state for a new block.
 void BBState::MergeSucc(const BBState &Other) {
   // Other.BottomUpPathCount can be 0, in which case it is either dead or a
   // loop backedge. Loop backedges are special.
   BottomUpPathCount += Other.BottomUpPathCount;
 
-  // Check for overflow. If we have overflow, fall back to conservative behavior.
+  // Check for overflow. If we have overflow, fall back to conservative
+  // behavior.
   if (BottomUpPathCount < Other.BottomUpPathCount) {
     clearBottomUpPointers();
     return;
@@ -1654,34 +1711,43 @@ void BBState::MergeSucc(const BBState &Other) {
 }
 
 namespace {
-  /// ObjCARCOpt - The main ARC optimization pass.
+  /// \brief The main ARC optimization pass.
   class ObjCARCOpt : public FunctionPass {
     bool Changed;
     ProvenanceAnalysis PA;
 
-    /// Run - A flag indicating whether this optimization pass should run.
+    /// A flag indicating whether this optimization pass should run.
     bool Run;
 
-    /// RetainRVCallee, etc. - Declarations for ObjC runtime
-    /// functions, for use in creating calls to them. These are initialized
-    /// lazily to avoid cluttering up the Module with unused declarations.
-    Constant *RetainRVCallee, *AutoreleaseRVCallee, *ReleaseCallee,
-             *RetainCallee, *RetainBlockCallee, *AutoreleaseCallee;
-
-    /// UsedInThisFunciton - Flags which determine whether each of the
-    /// interesting runtine functions is in fact used in the current function.
+    /// Declarations for ObjC runtime functions, for use in creating calls to
+    /// them. These are initialized lazily to avoid cluttering up the Module
+    /// with unused declarations.
+
+    /// Declaration for ObjC runtime function
+    /// objc_retainAutoreleasedReturnValue.
+    Constant *RetainRVCallee;
+    /// Declaration for ObjC runtime function objc_autoreleaseReturnValue.
+    Constant *AutoreleaseRVCallee;
+    /// Declaration for ObjC runtime function objc_release.
+    Constant *ReleaseCallee;
+    /// Declaration for ObjC runtime function objc_retain.
+    Constant *RetainCallee;
+    /// Declaration for ObjC runtime function objc_retainBlock.
+    Constant *RetainBlockCallee;
+    /// Declaration for ObjC runtime function objc_autorelease.
+    Constant *AutoreleaseCallee;
+
+    /// Flags which determine whether each of the interesting runtine functions
+    /// is in fact used in the current function.
     unsigned UsedInThisFunction;
 
-    /// ImpreciseReleaseMDKind - The Metadata Kind for clang.imprecise_release
-    /// metadata.
+    /// The Metadata Kind for clang.imprecise_release metadata.
     unsigned ImpreciseReleaseMDKind;
 
-    /// CopyOnEscapeMDKind - The Metadata Kind for clang.arc.copy_on_escape
-    /// metadata.
+    /// The Metadata Kind for clang.arc.copy_on_escape metadata.
     unsigned CopyOnEscapeMDKind;
 
-    /// NoObjCARCExceptionsMDKind - The Metadata Kind for
-    /// clang.arc.no_objc_arc_exceptions metadata.
+    /// The Metadata Kind for clang.arc.no_objc_arc_exceptions metadata.
     unsigned NoObjCARCExceptionsMDKind;
 
     Constant *getRetainRVCallee(Module *M);
@@ -1695,7 +1761,8 @@ namespace {
 
     void OptimizeRetainCall(Function &F, Instruction *Retain);
     bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV);
-    void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV);
+    void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,
+                                   InstructionClass &Class);
     void OptimizeIndividualCalls(Function &F);
 
     void CheckForCFGHazards(const BasicBlock *BB,
@@ -1789,10 +1856,12 @@ Constant *ObjCARCOpt::getRetainRVCallee(Module *M) {
     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
     Type *Params[] = { I8X };
     FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     RetainRVCallee =
       M->getOrInsertFunction("objc_retainAutoreleasedReturnValue", FTy,
-                             Attributes);
+                             Attribute);
   }
   return RetainRVCallee;
 }
@@ -1803,10 +1872,12 @@ Constant *ObjCARCOpt::getAutoreleaseRVCallee(Module *M) {
     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
     Type *Params[] = { I8X };
     FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     AutoreleaseRVCallee =
       M->getOrInsertFunction("objc_autoreleaseReturnValue", FTy,
-                             Attributes);
+                             Attribute);
   }
   return AutoreleaseRVCallee;
 }
@@ -1815,12 +1886,14 @@ Constant *ObjCARCOpt::getReleaseCallee(Module *M) {
   if (!ReleaseCallee) {
     LLVMContext &C = M->getContext();
     Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     ReleaseCallee =
       M->getOrInsertFunction(
         "objc_release",
         FunctionType::get(Type::getVoidTy(C), Params, /*isVarArg=*/false),
-        Attributes);
+        Attribute);
   }
   return ReleaseCallee;
 }
@@ -1829,12 +1902,14 @@ Constant *ObjCARCOpt::getRetainCallee(Module *M) {
   if (!RetainCallee) {
     LLVMContext &C = M->getContext();
     Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     RetainCallee =
       M->getOrInsertFunction(
         "objc_retain",
         FunctionType::get(Params[0], Params, /*isVarArg=*/false),
-        Attributes);
+        Attribute);
   }
   return RetainCallee;
 }
@@ -1849,7 +1924,7 @@ Constant *ObjCARCOpt::getRetainBlockCallee(Module *M) {
       M->getOrInsertFunction(
         "objc_retainBlock",
         FunctionType::get(Params[0], Params, /*isVarArg=*/false),
-        AttrListPtr());
+        AttributeSet());
   }
   return RetainBlockCallee;
 }
@@ -1858,18 +1933,20 @@ Constant *ObjCARCOpt::getAutoreleaseCallee(Module *M) {
   if (!AutoreleaseCallee) {
     LLVMContext &C = M->getContext();
     Type *Params[] = { PointerType::getUnqual(Type::getInt8Ty(C)) };
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     AutoreleaseCallee =
       M->getOrInsertFunction(
         "objc_autorelease",
         FunctionType::get(Params[0], Params, /*isVarArg=*/false),
-        Attributes);
+        Attribute);
   }
   return AutoreleaseCallee;
 }
 
-/// IsPotentialUse - Test whether the given value is possible a
-/// reference-counted pointer, including tests which utilize AliasAnalysis.
+/// Test whether the given value is possible a reference-counted pointer,
+/// including tests which utilize AliasAnalysis.
 static bool IsPotentialUse(const Value *Op, AliasAnalysis &AA) {
   // First make the rudimentary check.
   if (!IsPotentialUse(Op))
@@ -1888,9 +1965,8 @@ static bool IsPotentialUse(const Value *Op, AliasAnalysis &AA) {
   return true;
 }
 
-/// CanAlterRefCount - Test whether the given instruction can result in a
-/// reference count modification (positive or negative) for the pointer's
-/// object.
+/// Test whether the given instruction can result in a reference count
+/// modification (positive or negative) for the pointer's object.
 static bool
 CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
                  ProvenanceAnalysis &PA, InstructionClass Class) {
@@ -1924,8 +2000,8 @@ CanAlterRefCount(const Instruction *Inst, const Value *Ptr,
   return true;
 }
 
-/// CanUse - Test whether the given instruction can "use" the given pointer's
-/// object in a way that requires the reference count to be positive.
+/// Test whether the given instruction can "use" the given pointer's object in a
+/// way that requires the reference count to be positive.
 static bool
 CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA,
        InstructionClass Class) {
@@ -1969,8 +2045,8 @@ CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA,
   return false;
 }
 
-/// CanInterruptRV - Test whether the given instruction can autorelease
-/// any pointer or cause an autoreleasepool pop.
+/// Test whether the given instruction can autorelease any pointer or cause an
+/// autoreleasepool pop.
 static bool
 CanInterruptRV(InstructionClass Class) {
   switch (Class) {
@@ -1988,8 +2064,11 @@ CanInterruptRV(InstructionClass Class) {
 }
 
 namespace {
-  /// DependenceKind - There are several kinds of dependence-like concepts in
-  /// use here.
+  /// \enum DependenceKind
+  /// \brief Defines different dependence kinds among various ARC constructs.
+  ///
+  /// There are several kinds of dependence-like concepts in use here.
+  ///
   enum DependenceKind {
     NeedsPositiveRetainCount,
     AutoreleasePoolBoundary,
@@ -2000,8 +2079,8 @@ namespace {
   };
 }
 
-/// Depends - Test if there can be dependencies on Inst through Arg. This
-/// function only tests dependencies relevant for removing pairs of calls.
+/// Test if there can be dependencies on Inst through Arg. This function only
+/// tests dependencies relevant for removing pairs of calls.
 static bool
 Depends(DependenceKind Flavor, Instruction *Inst, const Value *Arg,
         ProvenanceAnalysis &PA) {
@@ -2086,8 +2165,9 @@ Depends(DependenceKind Flavor, Instruction *Inst, const Value *Arg,
   llvm_unreachable("Invalid dependence flavor");
 }
 
-/// FindDependencies - Walk up the CFG from StartPos (which is in StartBB) and
-/// find local and non-local dependencies on Arg.
+/// Walk up the CFG from StartPos (which is in StartBB) and find local and
+/// non-local dependencies on Arg.
+///
 /// TODO: Cache results?
 static void
 FindDependencies(DependenceKind Flavor,
@@ -2159,8 +2239,8 @@ static bool isNoopInstruction(const Instruction *I) {
           cast<GetElementPtrInst>(I)->hasAllZeroIndices());
 }
 
-/// OptimizeRetainCall - Turn objc_retain into
-/// objc_retainAutoreleasedReturnValue if the operand is a return value.
+/// Turn objc_retain into objc_retainAutoreleasedReturnValue if the operand is a
+/// return value.
 void
 ObjCARCOpt::OptimizeRetainCall(Function &F, Instruction *Retain) {
   ImmutableCallSite CS(GetObjCArg(Retain));
@@ -2178,12 +2258,22 @@ ObjCARCOpt::OptimizeRetainCall(Function &F, Instruction *Retain) {
   // Turn it to an objc_retainAutoreleasedReturnValue..
   Changed = true;
   ++NumPeeps;
+
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainCall: Transforming "
+                  "objc_retain => objc_retainAutoreleasedReturnValue"
+                  " since the operand is a return value.\n"
+                  "                                Old: "
+               << *Retain << "\n");
+
   cast<CallInst>(Retain)->setCalledFunction(getRetainRVCallee(F.getParent()));
+
+  DEBUG(dbgs() << "                                New: "
+               << *Retain << "\n");
 }
 
-/// OptimizeRetainRVCall - Turn objc_retainAutoreleasedReturnValue into
-/// objc_retain if the operand is not a return value.  Or, if it can be paired
-/// with an objc_autoreleaseReturnValue, delete the pair and return true.
+/// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is
+/// not a return value.  Or, if it can be paired with an
+/// objc_autoreleaseReturnValue, delete the pair and return true.
 bool
 ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
   // Check for the argument being from an immediately preceding call or invoke.
@@ -2216,6 +2306,11 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
         GetObjCArg(I) == Arg) {
       Changed = true;
       ++NumPeeps;
+
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainRVCall: Erasing " << *I << "\n"
+                   << "                                  Erasing " << *RetainRV
+                   << "\n");
+
       EraseInstruction(I);
       EraseInstruction(RetainRV);
       return true;
@@ -2225,14 +2320,26 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {
   // Turn it to a plain objc_retain.
   Changed = true;
   ++NumPeeps;
+
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeRetainRVCall: Transforming "
+                  "objc_retainAutoreleasedReturnValue => "
+                  "objc_retain since the operand is not a return value.\n"
+                  "                                  Old: "
+               << *RetainRV << "\n");
+
   cast<CallInst>(RetainRV)->setCalledFunction(getRetainCallee(F.getParent()));
+
+  DEBUG(dbgs() << "                                  New: "
+               << *RetainRV << "\n");
+
   return false;
 }
 
-/// OptimizeAutoreleaseRVCall - Turn objc_autoreleaseReturnValue into
-/// objc_autorelease if the result is not used as a return value.
+/// Turn objc_autoreleaseReturnValue into objc_autorelease if the result is not
+/// used as a return value.
 void
-ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV) {
+ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV,
+                                      InstructionClass &Class) {
   // Check for a return of the pointer value.
   const Value *Ptr = GetObjCArg(AutoreleaseRV);
   SmallVector<const Value *, 2> Users;
@@ -2251,12 +2358,27 @@ ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV) {
 
   Changed = true;
   ++NumPeeps;
-  cast<CallInst>(AutoreleaseRV)->
+
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeAutoreleaseRVCall: Transforming "
+                  "objc_autoreleaseReturnValue => "
+                  "objc_autorelease since its operand is not used as a return "
+                  "value.\n"
+                  "                                       Old: "
+               << *AutoreleaseRV << "\n");
+
+  CallInst *AutoreleaseRVCI = cast<CallInst>(AutoreleaseRV);
+  AutoreleaseRVCI->
     setCalledFunction(getAutoreleaseCallee(F.getParent()));
+  AutoreleaseRVCI->setTailCall(false); // Never tail call objc_autorelease.
+  Class = IC_Autorelease;
+
+  DEBUG(dbgs() << "                                       New: "
+               << *AutoreleaseRV << "\n");
+
 }
 
-/// OptimizeIndividualCalls - Visit each call, one at a time, and make
-/// simplifications without doing any additional analysis.
+/// Visit each call, one at a time, and make simplifications without doing any
+/// additional analysis.
 void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
   // Reset all the flags in preparation for recomputing them.
   UsedInThisFunction = 0;
@@ -2264,6 +2386,10 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
   // Visit all objc_* calls in F.
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
     Instruction *Inst = &*I++;
+
+    DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Visiting: " <<
+          *Inst << "\n");
+
     InstructionClass Class = GetBasicInstructionClass(Inst);
 
     switch (Class) {
@@ -2280,6 +2406,8 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
     case IC_NoopCast:
       Changed = true;
       ++NumNoops;
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Erasing no-op cast:"
+                   " " << *Inst << "\n");
       EraseInstruction(Inst);
       continue;
 
@@ -2296,7 +2424,13 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
         new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
                       Constant::getNullValue(Ty),
                       CI);
-        CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
+        llvm::Value *NewValue = UndefValue::get(CI->getType());
+        DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: A null "
+                        "pointer-to-weak-pointer is undefined behavior.\n"
+                        "                                     Old = " << *CI <<
+                        "\n                                     New = " <<
+                        *NewValue << "\n");
+        CI->replaceAllUsesWith(NewValue);
         CI->eraseFromParent();
         continue;
       }
@@ -2312,7 +2446,15 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
         new StoreInst(UndefValue::get(cast<PointerType>(Ty)->getElementType()),
                       Constant::getNullValue(Ty),
                       CI);
-        CI->replaceAllUsesWith(UndefValue::get(CI->getType()));
+
+        llvm::Value *NewValue = UndefValue::get(CI->getType());
+        DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: A null "
+                        "pointer-to-weak-pointer is undefined behavior.\n"
+                        "                                     Old = " << *CI <<
+                        "\n                                     New = " <<
+                        *NewValue << "\n");
+
+        CI->replaceAllUsesWith(NewValue);
         CI->eraseFromParent();
         continue;
       }
@@ -2326,7 +2468,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
         continue;
       break;
     case IC_AutoreleaseRV:
-      OptimizeAutoreleaseRVCall(F, Inst);
+      OptimizeAutoreleaseRVCall(F, Inst, Class);
       break;
     }
 
@@ -2346,6 +2488,14 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
                            Call->getArgOperand(0), "", Call);
         NewCall->setMetadata(ImpreciseReleaseMDKind,
                              MDNode::get(C, ArrayRef<Value *>()));
+
+        DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Replacing "
+                        "objc_autorelease(x) with objc_release(x) since x is "
+                        "otherwise unused.\n"
+                        "                                     Old: " << *Call <<
+                        "\n                                     New: " <<
+                        *NewCall << "\n");
+
         EraseInstruction(Call);
         Inst = NewCall;
         Class = IC_Release;
@@ -2356,12 +2506,27 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
     // a tail keyword.
     if (IsAlwaysTail(Class)) {
       Changed = true;
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Adding tail keyword"
+            " to function since it can never be passed stack args: " << *Inst <<
+            "\n");
       cast<CallInst>(Inst)->setTailCall();
     }
 
+    // Ensure that functions that can never have a "tail" keyword due to the
+    // semantics of ARC truly do not do so.
+    if (IsNeverTail(Class)) {
+      Changed = true;
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Removing tail "
+            "keyword from function: " << *Inst <<
+            "\n");
+      cast<CallInst>(Inst)->setTailCall(false);
+    }
+
     // Set nounwind as needed.
     if (IsNoThrow(Class)) {
       Changed = true;
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Found no throw"
+            " class. Setting nounwind on: " << *Inst << "\n");
       cast<CallInst>(Inst)->setDoesNotThrow();
     }
 
@@ -2376,6 +2541,8 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
     if (isNullOrUndef(Arg)) {
       Changed = true;
       ++NumNoops;
+      DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: ARC calls with "
+            " null are no-ops. Erasing: " << *Inst << "\n");
       EraseInstruction(Inst);
       continue;
     }
@@ -2468,21 +2635,28 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {
                 Op = new BitCastInst(Op, ParamTy, "", InsertPos);
               Clone->setArgOperand(0, Op);
               Clone->insertBefore(InsertPos);
+
+              DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Cloning "
+                           << *CInst << "\n"
+                           "                                     And inserting "
+                           "clone at " << *InsertPos << "\n");
               Worklist.push_back(std::make_pair(Clone, Incoming));
             }
           }
           // Erase the original call.
+          DEBUG(dbgs() << "Erasing: " << *CInst << "\n");
           EraseInstruction(CInst);
           continue;
         }
       }
     } while (!Worklist.empty());
   }
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeIndividualCalls: Finished List.\n");
 }
 
-/// CheckForCFGHazards - Check for critical edges, loop boundaries, irreducible
-/// control flow, or other CFG structures where moving code across the edge
-/// would result in it being executed more.
+/// Check for critical edges, loop boundaries, irreducible control flow, or
+/// other CFG structures where moving code across the edge would result in it
+/// being executed more.
 void
 ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
                                DenseMap<const BasicBlock *, BBState> &BBStates,
@@ -2504,8 +2678,13 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
       // If the terminator is an invoke marked with the
       // clang.arc.no_objc_arc_exceptions metadata, the unwind edge can be
       // ignored, for ARC purposes.
-      if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind))
+      if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind)) {
+        DEBUG(dbgs() << "ObjCARCOpt::CheckForCFGHazards: Found an invoke "
+                        "terminator marked with "
+                        "clang.arc.no_objc_arc_exceptions. Ignoring unwind "
+                        "edge.\n");
         --SE;
+      }
 
       for (; SI != SE; ++SI) {
         Sequence SuccSSeq = S_None;
@@ -2558,8 +2737,13 @@ ObjCARCOpt::CheckForCFGHazards(const BasicBlock *BB,
       // If the terminator is an invoke marked with the
       // clang.arc.no_objc_arc_exceptions metadata, the unwind edge can be
       // ignored, for ARC purposes.
-      if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind))
+      if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind)) {
+        DEBUG(dbgs() << "ObjCARCOpt::CheckForCFGHazards: Found an invoke "
+                        "terminator marked with "
+                        "clang.arc.no_objc_arc_exceptions. Ignoring unwind "
+                        "edge.\n");
         --SE;
+      }
 
       for (; SI != SE; ++SI) {
         Sequence SuccSSeq = S_None;
@@ -2626,8 +2810,11 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst,
     // Theoretically we could implement removal of nested retain+release
     // pairs by making PtrState hold a stack of states, but this is
     // simple and avoids adding overhead for the non-nested case.
-    if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease)
+    if (S.GetSeq() == S_Release || S.GetSeq() == S_MovableRelease) {
+      DEBUG(dbgs() << "ObjCARCOpt::VisitInstructionBottomUp: Found nested "
+                      "releases (i.e. a release pair)\n");
       NestingDetected = true;
+    }
 
     MDNode *ReleaseMetadata = Inst->getMetadata(ImpreciseReleaseMDKind);
     S.ResetSequenceProgress(ReleaseMetadata ? S_MovableRelease : S_Release);
@@ -2790,6 +2977,8 @@ ObjCARCOpt::VisitBottomUp(BasicBlock *BB,
     if (isa<InvokeInst>(Inst))
       continue;
 
+    DEBUG(dbgs() << "ObjCARCOpt::VisitButtonUp: Visiting " << *Inst << "\n");
+
     NestingDetected |= VisitInstructionBottomUp(Inst, BB, Retains, MyStates);
   }
 
@@ -2972,6 +3161,9 @@ ObjCARCOpt::VisitTopDown(BasicBlock *BB,
   // Visit all the instructions, top-down.
   for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
     Instruction *Inst = I;
+
+    DEBUG(dbgs() << "ObjCARCOpt::VisitTopDown: Visiting " << *Inst << "\n");
+
     NestingDetected |= VisitInstructionTopDown(Inst, Releases, MyStates);
   }
 
@@ -2985,7 +3177,7 @@ ComputePostOrders(Function &F,
                   SmallVectorImpl<BasicBlock *> &ReverseCFGPostOrder,
                   unsigned NoObjCARCExceptionsMDKind,
                   DenseMap<const BasicBlock *, BBState> &BBStates) {
-  /// Visited - The visited set, for doing DFS walks.
+  /// The visited set, for doing DFS walks.
   SmallPtrSet<BasicBlock *, 16> Visited;
 
   // Do DFS, computing the PostOrder.
@@ -3010,8 +3202,13 @@ ComputePostOrders(Function &F,
     // If the terminator is an invoke marked with the
     // clang.arc.no_objc_arc_exceptions metadata, the unwind edge can be
     // ignored, for ARC purposes.
-    if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind))
+    if (isa<InvokeInst>(TI) && TI->getMetadata(NoObjCARCExceptionsMDKind)) {
+        DEBUG(dbgs() << "ObjCARCOpt::ComputePostOrders: Found an invoke "
+                        "terminator marked with "
+                        "clang.arc.no_objc_arc_exceptions. Ignoring unwind "
+                        "edge.\n");
       --SE;
+    }
 
     while (SuccStack.back().second != SE) {
       BasicBlock *SuccBB = *SuccStack.back().second++;
@@ -3066,7 +3263,7 @@ ComputePostOrders(Function &F,
   }
 }
 
-// Visit - Visit the function both top-down and bottom-up.
+// Visit the function both top-down and bottom-up.
 bool
 ObjCARCOpt::Visit(Function &F,
                   DenseMap<const BasicBlock *, BBState> &BBStates,
@@ -3101,7 +3298,7 @@ ObjCARCOpt::Visit(Function &F,
   return TopDownNestingDetected && BottomUpNestingDetected;
 }
 
-/// MoveCalls - Move the calls in RetainsToMove and ReleasesToMove.
+/// Move the calls in RetainsToMove and ReleasesToMove.
 void ObjCARCOpt::MoveCalls(Value *Arg,
                            RRInfo &RetainsToMove,
                            RRInfo &ReleasesToMove,
@@ -3129,6 +3326,11 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
                         MDNode::get(M->getContext(), ArrayRef<Value *>()));
     else
       Call->setTailCall();
+
+    DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Inserting new Release: " << *Call
+                 << "\n"
+                    "                       At insertion point: " << *InsertPt
+                 << "\n");
   }
   for (SmallPtrSet<Instruction *, 2>::const_iterator
        PI = RetainsToMove.ReverseInsertPts.begin(),
@@ -3144,6 +3346,11 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
     Call->setDoesNotThrow();
     if (ReleasesToMove.IsTailCallRelease)
       Call->setTailCall();
+
+    DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Inserting new Retain: " << *Call
+                 << "\n"
+                    "                       At insertion point: " << *InsertPt
+                 << "\n");
   }
 
   // Delete the original retain and release calls.
@@ -3153,6 +3360,8 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
     Instruction *OrigRetain = *AI;
     Retains.blot(OrigRetain);
     DeadInsts.push_back(OrigRetain);
+    DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Deleting retain: " << *OrigRetain <<
+                    "\n");
   }
   for (SmallPtrSet<Instruction *, 2>::const_iterator
        AI = ReleasesToMove.Calls.begin(),
@@ -3160,11 +3369,13 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
     Instruction *OrigRelease = *AI;
     Releases.erase(OrigRelease);
     DeadInsts.push_back(OrigRelease);
+    DEBUG(dbgs() << "ObjCARCOpt::MoveCalls: Deleting release: " << *OrigRelease
+                 << "\n");
   }
 }
 
-/// PerformCodePlacement - Identify pairings between the retains and releases,
-/// and delete and/or move them.
+/// Identify pairings between the retains and releases, and delete and/or move
+/// them.
 bool
 ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
                                    &BBStates,
@@ -3185,6 +3396,10 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
     if (!V) continue; // blotted
 
     Instruction *Retain = cast<Instruction>(V);
+
+    DEBUG(dbgs() << "ObjCARCOpt::PerformCodePlacement: Visiting: " << *Retain
+          << "\n");
+
     Value *Arg = GetObjCArg(Retain);
 
     // If the object being released is in static or stack storage, we know it's
@@ -3373,13 +3588,17 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
   return AnyPairsCompletelyEliminated;
 }
 
-/// OptimizeWeakCalls - Weak pointer optimizations.
+/// Weak pointer optimizations.
 void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
   // First, do memdep-style RLE and S2L optimizations. We can't use memdep
   // itself because it uses AliasAnalysis and we need to do provenance
   // queries instead.
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
     Instruction *Inst = &*I++;
+
+    DEBUG(dbgs() << "ObjCARCOpt::OptimizeWeakCalls: Visiting: " << *Inst <<
+          "\n");
+
     InstructionClass Class = GetBasicInstructionClass(Inst);
     if (Class != IC_LoadWeak && Class != IC_LoadWeakRetained)
       continue;
@@ -3525,10 +3744,13 @@ void ObjCARCOpt::OptimizeWeakCalls(Function &F) {
     done:;
     }
   }
+
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeWeakCalls: Finished List.\n\n");
+
 }
 
-/// OptimizeSequences - Identify program paths which execute sequences of
-/// retains and releases which can be eliminated.
+/// Identify program paths which execute sequences of retains and releases which
+/// can be eliminated.
 bool ObjCARCOpt::OptimizeSequences(Function &F) {
   /// Releases, Retains - These are used to store the results of the main flow
   /// analysis. These use Value* as the key instead of Instruction* so that the
@@ -3537,7 +3759,7 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
   DenseMap<Value *, RRInfo> Releases;
   MapVector<Value *, RRInfo> Retains;
 
-  /// BBStates, This is used during the traversal of the function to track the
+  /// This is used during the traversal of the function to track the
   /// states for each identified object at each block.
   DenseMap<const BasicBlock *, BBState> BBStates;
 
@@ -3549,20 +3771,20 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
          NestingDetected;
 }
 
-/// OptimizeReturns - Look for this pattern:
-///
+/// Look for this pattern:
+/// \code
 ///    %call = call i8* @something(...)
 ///    %2 = call i8* @objc_retain(i8* %call)
 ///    %3 = call i8* @objc_autorelease(i8* %2)
 ///    ret i8* %3
-///
+/// \endcode
 /// And delete the retain and autorelease.
 ///
 /// Otherwise if it's just this:
-///
+/// \code
 ///    %3 = call i8* @objc_autorelease(i8* %2)
 ///    ret i8* %3
-///
+/// \endcode
 /// convert the autorelease to autoreleaseRV.
 void ObjCARCOpt::OptimizeReturns(Function &F) {
   if (!F.getReturnType()->isPointerTy())
@@ -3573,6 +3795,9 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
   for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
     BasicBlock *BB = FI;
     ReturnInst *Ret = dyn_cast<ReturnInst>(&BB->back());
+
+    DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Visiting: " << *Ret << "\n");
+
     if (!Ret) continue;
 
     const Value *Arg = StripPointerCastsAndObjCCalls(Ret->getOperand(0));
@@ -3618,7 +3843,14 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
         // Convert the autorelease to an autoreleaseRV, since it's
         // returning the value.
         if (AutoreleaseClass == IC_Autorelease) {
+          DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Converting autorelease "
+                          "=> autoreleaseRV since it's returning a value.\n"
+                          "                             In: " << *Autorelease
+                       << "\n");
           Autorelease->setCalledFunction(getAutoreleaseRVCallee(F.getParent()));
+          DEBUG(dbgs() << "                             Out: " << *Autorelease
+                       << "\n");
+          Autorelease->setTailCall(); // Always tail call autoreleaseRV.
           AutoreleaseClass = IC_AutoreleaseRV;
         }
 
@@ -3646,6 +3878,9 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
           // If so, we can zap the retain and autorelease.
           Changed = true;
           ++NumRets;
+          DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Erasing: " << *Retain
+                       << "\n                             Erasing: "
+                       << *Autorelease << "\n");
           EraseInstruction(Retain);
           EraseInstruction(Autorelease);
         }
@@ -3656,6 +3891,9 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
     DependingInstructions.clear();
     Visited.clear();
   }
+
+  DEBUG(dbgs() << "ObjCARCOpt::OptimizeReturns: Finished List.\n\n");
+
 }
 
 bool ObjCARCOpt::doInitialization(Module &M) {
@@ -3700,6 +3938,8 @@ bool ObjCARCOpt::runOnFunction(Function &F) {
 
   Changed = false;
 
+  DEBUG(dbgs() << "ObjCARCOpt: Visiting Function: " << F.getName() << "\n");
+
   PA.setAA(&getAnalysis<AliasAnalysis>());
 
   // This pass performs several distinct transformations. As a compile-time aid
@@ -3733,6 +3973,8 @@ bool ObjCARCOpt::runOnFunction(Function &F) {
                             (1 << IC_AutoreleaseRV)))
     OptimizeReturns(F);
 
+  DEBUG(dbgs() << "\n");
+
   return Changed;
 }
 
@@ -3740,44 +3982,52 @@ void ObjCARCOpt::releaseMemory() {
   PA.clear();
 }
 
-//===----------------------------------------------------------------------===//
-// ARC contraction.
-//===----------------------------------------------------------------------===//
+/// @}
+///
+/// \defgroup ARCContract ARC Contraction.
+/// @{
 
 // TODO: ObjCARCContract could insert PHI nodes when uses aren't
 // dominated by single calls.
 
-#include "llvm/Operator.h"
-#include "llvm/InlineAsm.h"
 #include "llvm/Analysis/Dominators.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Operator.h"
 
 STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed");
 
 namespace {
-  /// ObjCARCContract - Late ARC optimizations.  These change the IR in a way
-  /// that makes it difficult to be analyzed by ObjCARCOpt, so it's run late.
+  /// \brief Late ARC optimizations
+  ///
+  /// These change the IR in a way that makes it difficult to be analyzed by
+  /// ObjCARCOpt, so it's run late.
   class ObjCARCContract : public FunctionPass {
     bool Changed;
     AliasAnalysis *AA;
     DominatorTree *DT;
     ProvenanceAnalysis PA;
 
-    /// Run - A flag indicating whether this optimization pass should run.
+    /// A flag indicating whether this optimization pass should run.
     bool Run;
 
-    /// StoreStrongCallee, etc. - Declarations for ObjC runtime
-    /// functions, for use in creating calls to them. These are initialized
-    /// lazily to avoid cluttering up the Module with unused declarations.
-    Constant *StoreStrongCallee,
-             *RetainAutoreleaseCallee, *RetainAutoreleaseRVCallee;
+    /// Declarations for ObjC runtime functions, for use in creating calls to
+    /// them. These are initialized lazily to avoid cluttering up the Module
+    /// with unused declarations.
+
+    /// Declaration for objc_storeStrong().
+    Constant *StoreStrongCallee;
+    /// Declaration for objc_retainAutorelease().
+    Constant *RetainAutoreleaseCallee;
+    /// Declaration for objc_retainAutoreleaseReturnValue().
+    Constant *RetainAutoreleaseRVCallee;
 
-    /// RetainRVMarker - The inline asm string to insert between calls and
-    /// RetainRV calls to make the optimization work on targets which need it.
+    /// The inline asm string to insert between calls and RetainRV calls to make
+    /// the optimization work on targets which need it.
     const MDString *RetainRVMarker;
 
-    /// StoreStrongCalls - The set of inserted objc_storeStrong calls. If
-    /// at the end of walking the function we have found no alloca
-    /// instructions, these calls can be marked "tail".
+    /// The set of inserted objc_storeStrong calls. If at the end of walking the
+    /// function we have found no alloca instructions, these calls can be marked
+    /// "tail".
     SmallPtrSet<CallInst *, 8> StoreStrongCalls;
 
     Constant *getStoreStrongCallee(Module *M);
@@ -3831,15 +4081,16 @@ Constant *ObjCARCContract::getStoreStrongCallee(Module *M) {
     Type *I8XX = PointerType::getUnqual(I8X);
     Type *Params[] = { I8XX, I8X };
 
-    AttrListPtr Attributes = AttrListPtr()
-      .addAttr(~0u, Attribute::NoUnwind)
-      .addAttr(1, Attribute::NoCapture);
+    AttributeSet Attribute = AttributeSet()
+      .addAttr(M->getContext(), AttributeSet::FunctionIndex,
+               Attribute::get(C, Attribute::NoUnwind))
+      .addAttr(M->getContext(), 1, Attribute::get(C, Attribute::NoCapture));
 
     StoreStrongCallee =
       M->getOrInsertFunction(
         "objc_storeStrong",
         FunctionType::get(Type::getVoidTy(C), Params, /*isVarArg=*/false),
-        Attributes);
+        Attribute);
   }
   return StoreStrongCallee;
 }
@@ -3850,9 +4101,11 @@ Constant *ObjCARCContract::getRetainAutoreleaseCallee(Module *M) {
     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
     Type *Params[] = { I8X };
     FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     RetainAutoreleaseCallee =
-      M->getOrInsertFunction("objc_retainAutorelease", FTy, Attributes);
+      M->getOrInsertFunction("objc_retainAutorelease", FTy, Attribute);
   }
   return RetainAutoreleaseCallee;
 }
@@ -3863,15 +4116,17 @@ Constant *ObjCARCContract::getRetainAutoreleaseRVCallee(Module *M) {
     Type *I8X = PointerType::getUnqual(Type::getInt8Ty(C));
     Type *Params[] = { I8X };
     FunctionType *FTy = FunctionType::get(I8X, Params, /*isVarArg=*/false);
-    AttrListPtr Attributes = AttrListPtr().addAttr(~0u, Attribute::NoUnwind);
+    AttributeSet Attribute =
+      AttributeSet().addAttr(M->getContext(), AttributeSet::FunctionIndex,
+                            Attribute::get(C, Attribute::NoUnwind));
     RetainAutoreleaseRVCallee =
       M->getOrInsertFunction("objc_retainAutoreleaseReturnValue", FTy,
-                             Attributes);
+                             Attribute);
   }
   return RetainAutoreleaseRVCallee;
 }
 
-/// ContractAutorelease - Merge an autorelease with a retain into a fused call.
+/// Merge an autorelease with a retain into a fused call.
 bool
 ObjCARCContract::ContractAutorelease(Function &F, Instruction *Autorelease,
                                      InstructionClass Class,
@@ -3910,19 +4165,27 @@ ObjCARCContract::ContractAutorelease(Function &F, Instruction *Autorelease,
   Changed = true;
   ++NumPeeps;
 
+  DEBUG(dbgs() << "ObjCARCContract::ContractAutorelease: Fusing "
+                  "retain/autorelease. Erasing: " << *Autorelease << "\n"
+                  "                                      Old Retain: "
+               << *Retain << "\n");
+
   if (Class == IC_AutoreleaseRV)
     Retain->setCalledFunction(getRetainAutoreleaseRVCallee(F.getParent()));
   else
     Retain->setCalledFunction(getRetainAutoreleaseCallee(F.getParent()));
 
+  DEBUG(dbgs() << "                                      New Retain: "
+               << *Retain << "\n");
+
   EraseInstruction(Autorelease);
   return true;
 }
 
-/// ContractRelease - Attempt to merge an objc_release with a store, load, and
-/// objc_retain to form an objc_storeStrong. This can be a little tricky because
-/// the instructions don't always appear in order, and there may be unrelated
-/// intervening instructions.
+/// Attempt to merge an objc_release with a store, load, and objc_retain to form
+/// an objc_storeStrong. This can be a little tricky because the instructions
+/// don't always appear in order, and there may be unrelated intervening
+/// instructions.
 void ObjCARCContract::ContractRelease(Instruction *Release,
                                       inst_iterator &Iter) {
   LoadInst *Load = dyn_cast<LoadInst>(GetObjCArg(Release));
@@ -4065,6 +4328,8 @@ bool ObjCARCContract::runOnFunction(Function &F) {
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {
     Instruction *Inst = &*I++;
 
+    DEBUG(dbgs() << "ObjCARCContract: Visiting: " << *Inst << "\n");
+
     // Only these library routines return their argument. In particular,
     // objc_retainBlock does not necessarily return its argument.
     InstructionClass Class = GetBasicInstructionClass(Inst);
@@ -4102,6 +4367,8 @@ bool ObjCARCContract::runOnFunction(Function &F) {
       } while (isNoopInstruction(BBI));
 
       if (&*BBI == GetObjCArg(Inst)) {
+        DEBUG(dbgs() << "ObjCARCContract: Adding inline asm marker for "
+                        "retainAutoreleasedReturnValue optimization.\n");
         Changed = true;
         InlineAsm *IA =
           InlineAsm::get(FunctionType::get(Type::getVoidTy(Inst->getContext()),
@@ -4121,6 +4388,10 @@ bool ObjCARCContract::runOnFunction(Function &F) {
           ConstantPointerNull::get(cast<PointerType>(CI->getType()));
         Changed = true;
         new StoreInst(Null, CI->getArgOperand(0), CI);
+
+        DEBUG(dbgs() << "OBJCARCContract: Old = " << *CI << "\n"
+                     << "                 New = " << *Null << "\n");
+
         CI->replaceAllUsesWith(Null);
         CI->eraseFromParent();
       }
@@ -4140,6 +4411,8 @@ bool ObjCARCContract::runOnFunction(Function &F) {
       continue;
     }
 
+    DEBUG(dbgs() << "ObjCARCContract: Finished List.\n\n");
+
     // Don't use GetObjCArg because we don't want to look through bitcasts
     // and such; to do the replacement, the argument must have type i8*.
     const Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
@@ -4216,3 +4489,6 @@ bool ObjCARCContract::runOnFunction(Function &F) {
 
   return Changed;
 }
+
+/// @}
+///