Index: include/llvm/Target/TargetInstrInfo.h
===================================================================
--- include/llvm/Target/TargetInstrInfo.h
+++ include/llvm/Target/TargetInstrInfo.h
@@ -832,6 +832,16 @@
     return false;
   }
 
+  /// Get the base register and byte offset of an instruction that reads/writes
+  /// memory.  This is similar to getLdStBaseRegImmOfs, but also works on memory
+  /// instructions that have been folded into other non-memory operations, like
+  /// arithmetic.
+  virtual bool getMemOpBaseRegImmOfs(MachineInstr *MemOp, bool &IsLoadingOp,
+                                     unsigned &BaseReg, unsigned &Offset,
+                                     const TargetRegisterInfo *TRI) const {
+    return false;
+  }
+
   virtual bool enableClusterLoads() const { return false; }
 
   virtual bool shouldClusterLoads(MachineInstr *FirstLdSt,
Index: lib/Target/X86/X86InstrInfo.h
===================================================================
--- lib/Target/X86/X86InstrInfo.h
+++ lib/Target/X86/X86InstrInfo.h
@@ -254,6 +254,10 @@
                      MachineBasicBlock *&FBB,
                      SmallVectorImpl<MachineOperand> &Cond,
                      bool AllowModify) const override;
+
+  bool getMemOpBaseRegImmOfs(MachineInstr *LdSt, bool &IsLoadOp,
+                             unsigned &BaseReg, unsigned &Offset,
+                             const TargetRegisterInfo *TRI) const override;
   unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
   unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
                         MachineBasicBlock *FBB,
Index: lib/Target/X86/X86InstrInfo.cpp
===================================================================
--- lib/Target/X86/X86InstrInfo.cpp
+++ lib/Target/X86/X86InstrInfo.cpp
@@ -3961,6 +3961,51 @@
   }
 }
 
+bool X86InstrInfo::getMemOpBaseRegImmOfs(MachineInstr *MemOp, bool &IsLoadingOp,
+                                         unsigned &BaseReg, unsigned &Offset,
+                                         const TargetRegisterInfo *TRI) const {
+  unsigned MemRefBegin = -1;
+
+  switch (MemOp->getOpcode()) {
+  default:
+    return false; // cannot parse this instruction
+
+  case X86::MOV64rm:
+  case X86::MOV32rm:
+  case X86::MOV16rm:
+    IsLoadingOp = true;
+    MemRefBegin = 1;
+    break;
+
+  case X86::ADD64rm:
+  case X86::ADD32rm:
+  case X86::ADD16rm:
+    IsLoadingOp = true;
+    MemRefBegin = 2;
+    break;
+  }
+
+  BaseReg = MemOp->getOperand(MemRefBegin + X86::AddrBaseReg).getReg();
+
+  if (MemOp->getOperand(MemRefBegin + X86::AddrScaleAmt).getImm() != 1)
+    return false;
+
+  if (MemOp->getOperand(MemRefBegin + X86::AddrIndexReg).getReg() !=
+      X86::NoRegister)
+    return false;
+
+  const MachineOperand &DispMO = MemOp->getOperand(MemRefBegin + X86::AddrDisp);
+
+  // Displacement can be symbolic
+  if (!DispMO.isImm())
+    return false;
+
+  Offset = DispMO.getImm();
+
+  return (MemOp->getOperand(MemRefBegin + X86::AddrIndexReg).getReg() ==
+          X86::NoRegister);
+}
+
 static unsigned getStoreRegOpcode(unsigned SrcReg,
                                   const TargetRegisterClass *RC,
                                   bool isStackAligned,