Index: include/llvm/IR/Statepoint.h
===================================================================
--- include/llvm/IR/Statepoint.h
+++ include/llvm/IR/Statepoint.h
@@ -24,13 +24,20 @@
 
 namespace llvm {
 
+class GCRelocateOperands;
+class ImmutableStatepoint;
+
 bool isStatepoint(const ImmutableCallSite &CS);
 bool isStatepoint(const Instruction *inst);
 bool isStatepoint(const Instruction &inst);
+bool isStatepoint(const Value *inst);
+bool isStatepoint(const Value &inst);
 
+bool isGCRelocate(const Value *inst);
 bool isGCRelocate(const Instruction *inst);
 bool isGCRelocate(const ImmutableCallSite &CS);
 
+bool isGCResult(const Value *inst);
 bool isGCResult(const Instruction *inst);
 bool isGCResult(const ImmutableCallSite &CS);
 
@@ -127,6 +134,11 @@
     return iterator_range<arg_iterator>(gc_args_begin(), gc_args_end());
   }
 
+  /// Get list of all gc reloactes linked to this statepoint
+  /// May contain several relocations for the same base/derived pair.
+  /// For example this could happen due to relocations on exceptional
+  /// path of invoke.
+  std::vector<GCRelocateOperands> getRelocates(ImmutableStatepoint &IS);
 
 #ifndef NDEBUG
   /// Asserts if this statepoint is malformed.  Common cases for failure
@@ -187,9 +199,35 @@
     assert(isGCRelocate(CS));
   }
 
+  bool isTiedToInvoke() const {
+    const Value *Token = RelocateCS.getArgument(0);
+
+    return isa<ExtractValueInst>(Token) ||
+      isa<InvokeInst>(Token);
+  }
+
+  /// Get enclosed relocate intrinsic
+  ImmutableCallSite getUnderlyingCallSite() {
+    return RelocateCS;
+  }
+
   /// The statepoint with which this gc.relocate is associated.
   const Instruction *statepoint() {
-    return cast<Instruction>(RelocateCS.getArgument(0));
+    const Value *token = RelocateCS.getArgument(0);
+
+    if (!isa<ExtractValueInst>(token)) {
+      return cast<Instruction>(token);
+    }
+
+    // This relocate is on exceptional path of an invoke statepoint
+    const BasicBlock *invokeBB =
+      cast<Instruction>(token)->getParent()->getUniquePredecessor();
+
+    assert(invokeBB && "safepoints should have unique landingpads");
+    assert(invokeBB->getTerminator() && "safepoint block should be well formed");
+    assert(isStatepoint(invokeBB->getTerminator()));
+
+    return invokeBB->getTerminator();
   }
   /// The index into the associate statepoint's argument list
   /// which contains the base pointer of the pointer whose
@@ -211,5 +249,47 @@
     return *(CS.arg_begin() + derivedPtrIndex());
   }
 };
+
+template <typename InstructionTy, typename ValueTy, typename CallSiteTy>
+std::vector<GCRelocateOperands>
+  StatepointBase<InstructionTy, ValueTy, CallSiteTy>::
+    getRelocates(ImmutableStatepoint &IS) {
+
+  std::vector<GCRelocateOperands> res;
+
+  ImmutableCallSite StatepointCS = IS.getCallSite();
+
+  // Search for relocated pointers.  Note that working backwards from the
+  // gc_relocates ensures that we only get pairs which are actually relocated
+  // and used after the statepoint.
+  for (const User *U : StatepointCS.getInstruction()->users()) {
+    if (isGCRelocate(U)) {
+      res.push_back(GCRelocateOperands(U));
+    }
+  }
+
+  // Scan thorough exceptional relocations if it is invoke statepoint
+  if (StatepointCS.isInvoke()) {
+    LandingPadInst *landingpad =
+      cast<InvokeInst>(StatepointCS.getInstruction())->getLandingPadInst();
+
+    // Search for extract value from landingpad instruction to which
+    // gc relocates will be attached
+    for (const User *landingpadUser : landingpad->users()) {
+      if (!isa<ExtractValueInst>(landingpadUser)) {
+        continue;
+      }
+
+      // gc relocates should be attached to this extract value
+      for (const User *U : landingpadUser->users()) {
+        if (isGCRelocate(U)) {
+          res.push_back(GCRelocateOperands(U));
+        }
+      }
+    }
+  }
+  return res;
+}
+
 }
 #endif
Index: lib/IR/Statepoint.cpp
===================================================================
--- lib/IR/Statepoint.cpp
+++ lib/IR/Statepoint.cpp
@@ -23,21 +23,27 @@
   const Function *F = CS.getCalledFunction();
   return (F && F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint);
 }
-bool llvm::isStatepoint(const Instruction *inst) {
+bool llvm::isStatepoint(const Value *inst) {
   if (isa<InvokeInst>(inst) || isa<CallInst>(inst)) {
     ImmutableCallSite CS(inst);
     return isStatepoint(CS);
   }
   return false;
 }
-bool llvm::isStatepoint(const Instruction &inst) {
+bool llvm::isStatepoint(const Value &inst) {
   return isStatepoint(&inst);
 }
+bool llvm::isStatepoint(const Instruction *inst) {
+  return isStatepoint(static_cast<const Value*>(inst));
+}
+bool llvm::isStatepoint(const Instruction &inst) {
+  return isStatepoint(static_cast<const Value*>(&inst));
+}
 
 bool llvm::isGCRelocate(const ImmutableCallSite &CS) {
   return isGCRelocate(CS.getInstruction());
 }
-bool llvm::isGCRelocate(const Instruction *inst) {
+bool llvm::isGCRelocate(const Value *inst) {
   if (const CallInst *call = dyn_cast<CallInst>(inst)) {
     if (const Function *F = call->getCalledFunction()) {
       return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
@@ -45,11 +51,14 @@
   }
   return false;
 }
+bool llvm::isGCRelocate(const Instruction *inst) {
+  return isGCRelocate(static_cast<const Value*>(inst));
+}
 
 bool llvm::isGCResult(const ImmutableCallSite &CS) {
   return isGCResult(CS.getInstruction());
 }
-bool llvm::isGCResult(const Instruction *inst) {
+bool llvm::isGCResult(const Value *inst) {
   if (const CallInst *call = dyn_cast<CallInst>(inst)) {
     if (Function *F = call->getCalledFunction()) {
       return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int ||
@@ -60,3 +69,6 @@
   }
   return false;
 }
+bool llvm::isGCResult(const Instruction *inst) {
+  return isGCResult(static_cast<const Value*>(inst));
+}