diff --git a/llvm/include/llvm/IR/Use.h b/llvm/include/llvm/IR/Use.h
--- a/llvm/include/llvm/IR/Use.h
+++ b/llvm/include/llvm/IR/Use.h
@@ -91,7 +91,7 @@
 private:
   /// Destructor - Only for zap()
   ~Use() {
-    if (Val)
+    if (Val.getPointer())
       removeFromList();
   }
 
@@ -100,11 +100,22 @@
   /// Constructor
   Use(PrevPtrTag tag) { Prev.setInt(tag); }
 
+#ifndef NDEBUG
+  bool checkDroppable() const;
+#endif
+  void setDroppable(bool NewVal = true) { Val.setInt(NewVal); }
+
 public:
   friend class Value;
+  friend class User;
+
+  bool isDroppable() const {
+    assert(checkDroppable() && "the use should be marked droppable");
+    return Val.getInt();
+  }
 
-  operator Value *() const { return Val; }
-  Value *get() const { return Val; }
+  operator Value *() const { return Val.getPointer(); }
+  Value *get() const { return Val.getPointer(); }
 
   /// Returns the User that contains this Use.
   ///
@@ -117,8 +128,8 @@
   inline Value *operator=(Value *RHS);
   inline const Use &operator=(const Use &RHS);
 
-  Value *operator->() { return Val; }
-  const Value *operator->() const { return Val; }
+  Value *operator->() { return Val.getPointer(); }
+  const Value *operator->() const { return Val.getPointer(); }
 
   Use *getNext() const { return Next; }
 
@@ -138,7 +149,7 @@
 private:
   const Use *getImpliedUser() const LLVM_READONLY;
 
-  Value *Val = nullptr;
+  PointerIntPair<Value *, 1> Val = {nullptr, 0};
   Use *Next = nullptr;
   PointerIntPair<Use **, 2, PrevPtrTag, PrevPointerTraits> Prev;
 
diff --git a/llvm/include/llvm/IR/User.h b/llvm/include/llvm/IR/User.h
--- a/llvm/include/llvm/IR/User.h
+++ b/llvm/include/llvm/IR/User.h
@@ -223,6 +223,10 @@
   /// from happening.
   bool isDroppable() const;
 
+  /// This will mark every use as droppable if the user is droppable.
+  /// This should be called from 
+  void maybeMarkUsesAsDroppable();
+
   // ---------------------------------------------------------------------------
   // Operand Iterator interface...
   //
diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h
--- a/llvm/include/llvm/IR/Value.h
+++ b/llvm/include/llvm/IR/Value.h
@@ -449,7 +449,17 @@
   ///
   /// This is specialized because it is a common request and does not require
   /// traversing the whole use list.
-  Use *getSingleUndroppableUse();
+  Use *getSingleUndroppableUse() {
+    Use *Result = nullptr;
+    for (Use &U : uses()) {
+      if (!U.isDroppable()) {
+        if (Result)
+          return nullptr;
+        Result = &U;
+      }
+    }
+    return Result;
+  }
 
   /// Return true if there this value.
   ///
@@ -756,8 +766,9 @@
 }
 
 void Use::set(Value *V) {
-  if (Val) removeFromList();
-  Val = V;
+  if (Val.getPointer())
+    removeFromList();
+  Val.setPointer(V);
   if (V) V->addUse(*this);
 }
 
@@ -767,7 +778,7 @@
 }
 
 const Use &Use::operator=(const Use &RHS) {
-  set(RHS.Val);
+  set(RHS.Val.getPointer());
   return *this;
 }
 
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -460,6 +460,7 @@
   assert(It + 1 == op_end() && "Should add up!");
 
   setName(NameStr);
+  maybeMarkUsesAsDroppable();
 }
 
 void CallInst::init(FunctionType *FTy, Value *Func, const Twine &NameStr) {
@@ -470,6 +471,7 @@
   assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
 
   setName(NameStr);
+  maybeMarkUsesAsDroppable();
 }
 
 CallInst::CallInst(FunctionType *Ty, Value *Func, const Twine &Name,
diff --git a/llvm/lib/IR/Use.cpp b/llvm/lib/IR/Use.cpp
--- a/llvm/lib/IR/Use.cpp
+++ b/llvm/lib/IR/Use.cpp
@@ -17,23 +17,23 @@
   if (Val == RHS.Val)
     return;
 
-  if (Val)
+  if (Val.getPointer())
     removeFromList();
 
-  Value *OldVal = Val;
-  if (RHS.Val) {
+  Value *OldVal = Val.getPointer();
+  if (RHS.Val.getPointer()) {
     RHS.removeFromList();
-    Val = RHS.Val;
-    Val->addUse(*this);
+    Val.setPointer(RHS.Val.getPointer());
+    Val.getPointer()->addUse(*this);
   } else {
-    Val = nullptr;
+    Val.setPointer(nullptr);
   }
 
   if (OldVal) {
-    RHS.Val = OldVal;
-    RHS.Val->addUse(RHS);
+    RHS.Val.setPointer(OldVal);
+    RHS.Val.getPointer()->addUse(RHS);
   } else {
-    RHS.Val = nullptr;
+    RHS.Val.setPointer(nullptr);
   }
 }
 
@@ -48,6 +48,12 @@
   return this - getUser()->op_begin();
 }
 
+#ifndef NDEBUG
+bool Use::checkDroppable() const {
+  return Val.getInt() == getUser()->isDroppable();
+}
+#endif
+
 // Sets up the waymarking algorithm's tags for a series of Uses. See the
 // algorithm details here:
 //
diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp
--- a/llvm/lib/IR/User.cpp
+++ b/llvm/lib/IR/User.cpp
@@ -109,9 +109,18 @@
 bool User::isDroppable() const {
   if (const auto *Intr = dyn_cast<IntrinsicInst>(this))
     return Intr->getIntrinsicID() == Intrinsic::assume;
+  /// If you are changing this definition you may need to add calls to
+  /// maybeMarkUsesAsDroppable in some subclasses
   return false;
 }
 
+void User::maybeMarkUsesAsDroppable() {
+  if (!isDroppable())
+    return;
+  for (unsigned i = 0; i < getNumOperands(); i++)
+    getOperandUse(i).setDroppable();
+}
+
 //===----------------------------------------------------------------------===//
 //                         User operator new Implementations
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -141,33 +141,21 @@
   return hasNItemsOrMore(use_begin(), use_end(), N);
 }
 
-static bool isUnDroppableUser(const User *U) { return !U->isDroppable(); }
-
-Use *Value::getSingleUndroppableUse() {
-  Use *Result = nullptr;
-  for (Use &U : uses()) {
-    if (!U.getUser()->isDroppable()) {
-      if (Result)
-        return nullptr;
-      Result = &U;
-    }
-  }
-  return Result;
-}
+static bool isUnDroppableUse(const Use& U) { return !U.isDroppable(); }
 
 bool Value::hasNUndroppableUses(unsigned int N) const {
-  return hasNItems(user_begin(), user_end(), N, isUnDroppableUser);
+  return hasNItems(use_begin(), use_end(), N, isUnDroppableUse);
 }
 
 bool Value::hasNUndroppableUsesOrMore(unsigned int N) const {
-  return hasNItemsOrMore(user_begin(), user_end(), N, isUnDroppableUser);
+  return hasNItemsOrMore(use_begin(), use_end(), N, isUnDroppableUse);
 }
 
 void Value::dropDroppableUses(
     llvm::function_ref<bool(const Use *)> ShouldDrop) {
   SmallVector<Use *, 8> ToBeEdited;
   for (Use &U : uses())
-    if (U.getUser()->isDroppable() && ShouldDrop(&U))
+    if (U.isDroppable() && ShouldDrop(&U))
       ToBeEdited.push_back(&U);
   for (Use *U : ToBeEdited) {
     U->removeFromList();
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -4428,8 +4428,7 @@
   /// See CaptureTracker::shouldExplore(...).
   bool shouldExplore(const Use *U) override {
     // Check liveness and ignore droppable users.
-    return !U->getUser()->isDroppable() &&
-           !A.isAssumedDead(*U, &NoCaptureAA, &IsDeadAA);
+    return !U->isDroppable() && !A.isAssumedDead(*U, &NoCaptureAA, &IsDeadAA);
   }
 
   /// Update the state according to \p CapturedInMem, \p CapturedInInt, and
@@ -7452,7 +7451,7 @@
       LLVM_DEBUG(dbgs() << "[Attributor] Dead use, skip!\n");
       continue;
     }
-    if (U->getUser()->isDroppable()) {
+    if (U->isDroppable()) {
       LLVM_DEBUG(dbgs() << "[Attributor] Droppable user, skip!\n");
       continue;
     }