Added generic function to get subreg idx from offset and size
diff --git a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
index 2e97629..11f63c6 100644
--- a/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetRegisterInfo.h
@@ -240,6 +240,10 @@
   /// access sub-registers at different offsets), return -1.
   unsigned getSubRegIdxOffset(unsigned Idx) const;
 
+  /// Find a SubReg index for the given bit size and bit offset.
+  /// Returns 0(no-op sub-register) if no matching index exists.
+  unsigned getSubRegIdxFromOffsetSize(unsigned Offset, unsigned Size) const;
+
   /// Return a bitmask representing the parts of a register that are covered by
   /// SubIdx \see LaneBitmask.
   ///
@@ -249,9 +253,6 @@
     return SubRegIndexLaneMasks[SubIdx];
   }
 
-  /// Try to find a matching subreg from the given lanemask.
-  unsigned getSubRegIdxFromLaneMask(LaneBitmask LaneMask) const;
-
   /// Try to find one or more subregister indexes to cover \p LaneMask.
   ///
   /// If this is possible, returns true and appends the best matching set of
diff --git a/llvm/lib/CodeGen/TargetRegisterInfo.cpp b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
index 7c522f0..2a49e7e 100644
--- a/llvm/lib/CodeGen/TargetRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/TargetRegisterInfo.cpp
@@ -495,16 +495,6 @@
   return getRegSizeInBits(*RC);
 }
 
-unsigned
-TargetRegisterInfo::getSubRegIdxFromLaneMask(LaneBitmask LaneMask) const {
-  for (unsigned Idx = 1, E = getNumSubRegIndices(); Idx < E; ++Idx) {
-    if (getSubRegIndexLaneMask(Idx) == LaneMask)
-      return Idx;
-  }
-
-  return 0 /*NoSubRegister*/;
-}
-
 bool TargetRegisterInfo::getCoveringSubRegIndexes(
     const TargetRegisterClass *RC, LaneBitmask LaneMask,
     SmallVectorImpl<unsigned> &NeededIndexes) const {
@@ -613,6 +603,18 @@
   return SubRegIdxRanges[HwMode * getNumSubRegIndices() + Idx].Offset;
 }
 
+unsigned TargetRegisterInfo::getSubRegIdxFromOffsetSize(unsigned Offset,
+                                                        unsigned Size) const {
+  unsigned NumIdx = getNumSubRegIndices();
+  unsigned Base = HwMode * NumIdx;
+  for (unsigned Idx = 1; Idx < NumIdx; Idx++) {
+    if (SubRegIdxRanges[Base + Idx].Offset == Offset &&
+        SubRegIdxRanges[Base + Idx].Size == Size)
+      return Idx;
+  }
+  return 0;
+}
+
 Register
 TargetRegisterInfo::lookThruCopyLike(Register SrcReg,
                                      const MachineRegisterInfo *MRI) const {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp b/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
index 0c6d23e..9f66d09 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURewriteAGPRCopyMFMA.cpp
@@ -454,27 +454,18 @@
 AMDGPURewriteAGPRCopyMFMAImpl::getSubRegFromReload(MachineInstr &MI,
                                                    Register Reg) const {
   unsigned NumRegs = TRI.getRegSizeInBits(*MRI.getRegClass(Reg)) / 32;
-  unsigned SubReg = AMDGPU::NoSubRegister;
+  unsigned NumSpilledRegs = TII.getNumSubRegsForSpillOp(MI);
   // SubReg accesses for the tuple registers are of interest here.
+  // Skip if the entire tuple is reloaded.
   // Note: We don't support 16-bit subreg reloads. If that assumption is
   // changed in the future, this function should be revised.
-  if (NumRegs == 1)
-    return SubReg;
+  if (NumRegs == 1 || NumRegs == NumSpilledRegs)
+    return AMDGPU::NoSubRegister;
 
-  unsigned NumSpilledRegs = TII.getNumSubRegsForSpillOp(MI);
-  // Skip if the entire tuple is reloaded.
-  if (NumRegs == NumSpilledRegs)
-    return SubReg;
-
-  // Construct the covering lanes for the reloaded portion.
-  unsigned SubRegIdx =
-      TII.getNamedOperand(MI, AMDGPU::OpName::offset)->getImm() / 4;
-  // Subreg lane masks are maintained in terms of regunits and each 32-bit
-  // register consists of two regunits.
-  uint64_t Lanes = (1ULL << NumSpilledRegs * 2) - 1;
-  LaneBitmask CoveringLanes = LaneBitmask(Lanes << SubRegIdx * 2);
-  SubReg = TRI.getSubRegIdxFromLaneMask(CoveringLanes);
-  return SubReg;
+  unsigned StackSlotBitOffset =
+      TII.getNamedOperand(MI, AMDGPU::OpName::offset)->getImm() * 8;
+  return TRI.getSubRegIdxFromOffsetSize(StackSlotBitOffset,
+                                        NumSpilledRegs * 32);
 }
 
 void AMDGPURewriteAGPRCopyMFMAImpl::replaceSpillWithCopyToVReg(