[LoongArch] Override `isLoadFromStackSlot/isStoreToStackSlot` to expose more optimizations
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index c89212d..345a5c3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -185,6 +185,82 @@
       .addMemOperand(MMO);
 }
 
+Register LoongArchInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
+                                                 int &FrameIndex) const {
+  TypeSize Dummy = TypeSize::getZero();
+  return isLoadFromStackSlot(MI, FrameIndex, Dummy);
+}
+
+Register LoongArchInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
+                                                 int &FrameIndex,
+                                                 TypeSize &MemBytes) const {
+  switch (MI.getOpcode()) {
+  default:
+    return 0;
+  case LoongArch::LD_W:
+  case LoongArch::FLD_S:
+    MemBytes = TypeSize::getFixed(4);
+    break;
+  case LoongArch::LD_D:
+  case LoongArch::FLD_D:
+    MemBytes = TypeSize::getFixed(8);
+    break;
+  case LoongArch::VLD:
+    MemBytes = TypeSize::getFixed(16);
+    break;
+  case LoongArch::XVLD:
+    MemBytes = TypeSize::getFixed(32);
+    break;
+  }
+
+  if ((MI.getOperand(1).isFI()) &&  // is a stack slot
+      (MI.getOperand(2).isImm()) && // the imm is zero
+      (MI.getOperand(2).getImm() == 0)) {
+    FrameIndex = MI.getOperand(1).getIndex();
+    return MI.getOperand(0).getReg();
+  }
+
+  return 0;
+}
+
+Register LoongArchInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
+                                                int &FrameIndex) const {
+  TypeSize Dummy = TypeSize::getZero();
+  return isStoreToStackSlot(MI, FrameIndex, Dummy);
+}
+
+Register LoongArchInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
+                                                int &FrameIndex,
+                                                TypeSize &MemBytes) const {
+  switch (MI.getOpcode()) {
+  default:
+    return 0;
+  case LoongArch::ST_W:
+  case LoongArch::FST_S:
+    MemBytes = TypeSize::getFixed(4);
+    break;
+  case LoongArch::ST_D:
+  case LoongArch::FST_D:
+    MemBytes = TypeSize::getFixed(8);
+    break;
+  case LoongArch::VST:
+    MemBytes = TypeSize::getFixed(16);
+    break;
+  case LoongArch::XVST:
+    MemBytes = TypeSize::getFixed(32);
+    break;
+  }
+
+  if ((MI.getOperand(1).isFI()) &&  // is a stack slot
+      (MI.getOperand(2).isImm()) && // the imm is zero
+      (MI.getOperand(2).getImm() == 0)) {
+    FrameIndex = MI.getOperand(1).getIndex();
+    return MI.getOperand(0).getReg();
+  }
+
+  return 0;
+}
+
 void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator MBBI,
                                 const DebugLoc &DL, Register DstReg,
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
index f25958a..fe73e1c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -45,6 +45,15 @@
       const TargetRegisterInfo *TRI, Register VReg,
       MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
 
+  Register isLoadFromStackSlot(const MachineInstr &MI,
+                               int &FrameIndex) const override;
+  Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex,
+                               TypeSize &MemBytes) const override;
+  Register isStoreToStackSlot(const MachineInstr &MI,
+                              int &FrameIndex) const override;
+  Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex,
+                              TypeSize &MemBytes) const override;
+
   // Materializes the given integer Val into DstReg.
   void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
               const DebugLoc &DL, Register DstReg, uint64_t Val,