[llvm] [PATCH] [Xtensa] Implement FrameLowering methods and stack operation lowering. (PR #92960)

Andrei Safronov via llvm-commits llvm-commits at lists.llvm.org
Thu May 30 06:53:13 PDT 2024


https://github.com/andreisfr updated https://github.com/llvm/llvm-project/pull/92960

>From 78c9f32964445e4e80aa12e86468a4fa447c5c6b Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 22 May 2024 13:33:24 +0300
Subject: [PATCH 1/5] [PATCH] [Xtensa] Implement FrameLowering methods and
 stack operations lowering.

Implement emitPrologue/emitEpilogue methods, determine/spill/restore callee
saved registers functionality with test. Also implement lowering of the
DYNAMIC_STACKALLOC/STACKSAVE/STACKRESTORE stack operations with tests.
---
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 180 +++++++++++++++++-
 llvm/lib/Target/Xtensa/XtensaFrameLowering.h  |  13 ++
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp |  49 +++++
 llvm/lib/Target/Xtensa/XtensaISelLowering.h   |   6 +
 llvm/test/CodeGen/Xtensa/call.ll              |  12 +-
 llvm/test/CodeGen/Xtensa/dynamic-alloc.ll     |  26 +++
 llvm/test/CodeGen/Xtensa/saverestore.ll       |  42 ++++
 7 files changed, 320 insertions(+), 8 deletions(-)
 create mode 100644 llvm/test/CodeGen/Xtensa/dynamic-alloc.ll
 create mode 100644 llvm/test/CodeGen/Xtensa/saverestore.ll

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index ab37c09bf8bfe..fbc6c378887b5 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -33,10 +33,158 @@ bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
 }
 
 void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
-                                       MachineBasicBlock &MBB) const {}
+                                       MachineBasicBlock &MBB) const {
+  assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+      MF.getSubtarget().getRegisterInfo());
+  const XtensaInstrInfo &TII =
+      *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  MachineBasicBlock::iterator MBBI = MBB.begin();
+  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
+  unsigned SP = Xtensa::SP;
+  unsigned FP = RegInfo->getFrameRegister(MF);
+  MachineModuleInfo &MMI = MF.getMMI();
+  const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
+
+  // First, compute final stack size.
+  uint64_t StackSize = MFI.getStackSize();
+  uint64_t PrevStackSize = StackSize;
+
+  // Round up StackSize to 16*N
+  StackSize += (16 - StackSize) & 0xf;
+
+  // No need to allocate space on the stack.
+  if (StackSize == 0 && !MFI.adjustsStack())
+    return;
+
+  // Adjust stack.
+  TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);
+
+  // emit ".cfi_def_cfa_offset StackSize"
+  unsigned CFIIndex =
+      MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));
+  BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+      .addCFIIndex(CFIIndex);
+
+  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+
+  if (CSI.size()) {
+    // Find the instruction past the last instruction that saves a
+    // callee-saved register to the stack.
+    for (unsigned i = 0; i < CSI.size(); ++i)
+      ++MBBI;
+
+    // Iterate over list of callee-saved registers and emit .cfi_offset
+    // directives.
+    for (const auto &I : CSI) {
+      int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
+      Register Reg = I.getReg();
+
+      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
+          nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
+      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+          .addCFIIndex(CFIIndex);
+    }
+  }
+
+  // if framepointer enabled, set it to point to the stack pointer.
+  if (hasFP(MF)) {
+    // Insert instruction "move $fp, $sp" at this location.
+    BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)
+        .addReg(SP)
+        .addReg(SP)
+        .setMIFlag(MachineInstr::FrameSetup);
+
+    // emit ".cfi_def_cfa_register $fp"
+    unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(
+        nullptr, MRI->getDwarfRegNum(FP, true)));
+    BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+        .addCFIIndex(CFIIndex);
+  }
+
+  if (StackSize != PrevStackSize) {
+    MFI.setStackSize(StackSize);
+
+    for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {
+      if (!MFI.isDeadObjectIndex(i)) {
+        int64_t SPOffset = MFI.getObjectOffset(i);
+
+        if (SPOffset < 0)
+          MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);
+      }
+    }
+  }
+}
 
 void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
-                                       MachineBasicBlock &MBB) const {}
+                                       MachineBasicBlock &MBB) const {
+  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+      MF.getSubtarget().getRegisterInfo());
+  const XtensaInstrInfo &TII =
+      *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
+  DebugLoc DL = MBBI->getDebugLoc();
+  unsigned SP = Xtensa::SP;
+  unsigned FP = RegInfo->getFrameRegister(MF);
+
+  // if framepointer enabled, restore the stack pointer.
+  if (hasFP(MF)) {
+    // Find the first instruction that restores a callee-saved register.
+    MachineBasicBlock::iterator I = MBBI;
+
+    for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
+      --I;
+
+    BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
+  }
+
+  // Get the number of bytes from FrameInfo
+  uint64_t StackSize = MFI.getStackSize();
+
+  if (!StackSize)
+    return;
+
+  // Adjust stack.
+  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);
+}
+
+bool XtensaFrameLowering::spillCalleeSavedRegisters(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+  MachineFunction *MF = MBB.getParent();
+
+  MachineBasicBlock &EntryBlock = *(MF->begin());
+  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
+
+  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+    // Add the callee-saved register as live-in. Do not add if the register is
+    // A0 and return address is taken, because it will be implemented in
+    // method XtensaTargetLowering::LowerRETURNADDR.
+    // It's killed at the spill, unless the register is RA and return address
+    // is taken.
+    Register Reg = CSI[i].getReg();
+    bool IsA0AndRetAddrIsTaken =
+        (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();
+    if (!IsA0AndRetAddrIsTaken)
+      EntryBlock.addLiveIn(Reg);
+
+    // Insert the spill to the stack frame.
+    bool IsKill = !IsA0AndRetAddrIsTaken;
+    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
+    TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),
+                            RC, TRI, Register());
+  }
+
+  return true;
+}
+
+bool XtensaFrameLowering::restoreCalleeSavedRegisters(
+    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+  return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
+}
 
 // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
 MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
@@ -57,3 +205,31 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
 
   return MBB.erase(I);
 }
+
+void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
+                                               BitVector &SavedRegs,
+                                               RegScavenger *RS) const {
+  MachineFrameInfo &MFI = MF.getFrameInfo();
+  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
+      MF.getSubtarget().getRegisterInfo());
+  unsigned FP = RegInfo->getFrameRegister(MF);
+
+  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
+
+  // Mark $fp as used if function has dedicated frame pointer.
+  if (hasFP(MF))
+    SavedRegs.set(FP);
+
+  // Set scavenging frame index if necessary.
+  uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
+
+  if (isInt<12>(MaxSPOffset))
+    return;
+
+  const TargetRegisterClass &RC = Xtensa::ARRegClass;
+  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
+  unsigned Size = TRI->getSpillSize(RC);
+  Align Alignment = TRI->getSpillAlign(RC);
+  int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
+  RS->addScavengingFrameIndex(FI);
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
index 2da88ab14073a..696f9ef381f2c 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
@@ -29,6 +29,19 @@ class XtensaFrameLowering : public TargetFrameLowering {
   MachineBasicBlock::iterator
   eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator I) const override;
+
+  bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
+                                 MachineBasicBlock::iterator MI,
+                                 ArrayRef<CalleeSavedInfo> CSI,
+                                 const TargetRegisterInfo *TRI) const override;
+  bool
+  restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
+                              MachineBasicBlock::iterator MI,
+                              MutableArrayRef<CalleeSavedInfo> CSI,
+                              const TargetRegisterInfo *TRI) const override;
+
+  void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
+                            RegScavenger *RS) const override;
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 64b996b6a42e5..8aebf60e46a41 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -78,6 +78,12 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
 
   setOperationAction(ISD::ConstantPool, PtrVT, Custom);
 
+  // Implement custom stack allocations
+  setOperationAction(ISD::DYNAMIC_STACKALLOC, PtrVT, Custom);
+  // Implement custom stack save and restore
+  setOperationAction(ISD::STACKSAVE, MVT::Other, Custom);
+  setOperationAction(ISD::STACKRESTORE, MVT::Other, Custom);
+
   // Compute derived properties from the register classes
   computeRegisterProperties(STI.getRegisterInfo());
 }
@@ -534,6 +540,43 @@ SDValue XtensaTargetLowering::LowerConstantPool(ConstantPoolSDNode *CP,
   return getAddrPCRel(Result, DAG);
 }
 
+SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op,
+                                             SelectionDAG &DAG) const {
+  unsigned SP = Xtensa::SP;
+  return DAG.getCopyFromReg(Op.getOperand(0), SDLoc(Op), SP, Op.getValueType());
+}
+
+SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op,
+                                                SelectionDAG &DAG) const {
+  unsigned SP = Xtensa::SP;
+  return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), SP, Op.getOperand(1));
+}
+
+SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
+                                                      SelectionDAG &DAG) const {
+  SDValue Chain = Op.getOperand(0); // Legalize the chain.
+  SDValue Size = Op.getOperand(1);  // Legalize the size.
+  EVT VT = Size->getValueType(0);
+  SDLoc DL(Op);
+
+  // Round up Size to 32
+  SDValue SizeTmp =
+      DAG.getNode(ISD::ADD, DL, VT, Size, DAG.getConstant(31, DL, MVT::i32));
+  SDValue SizeRoundUp = DAG.getNode(ISD::AND, DL, VT, SizeTmp,
+                                    DAG.getConstant(~31, DL, MVT::i32));
+
+  unsigned SPReg = Xtensa::SP;
+  SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
+  SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value
+  Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain
+
+  SDValue NewVal = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32);
+  Chain = NewVal.getValue(1);
+
+  SDValue Ops[2] = {NewVal, Chain};
+  return DAG.getMergeValues(Ops, DL);
+}
+
 SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
                                              SelectionDAG &DAG) const {
   switch (Op.getOpcode()) {
@@ -541,6 +584,12 @@ SDValue XtensaTargetLowering::LowerOperation(SDValue Op,
     return LowerImmediate(Op, DAG);
   case ISD::ConstantPool:
     return LowerConstantPool(cast<ConstantPoolSDNode>(Op), DAG);
+  case ISD::STACKSAVE:
+    return LowerSTACKSAVE(Op, DAG);
+  case ISD::STACKRESTORE:
+    return LowerSTACKRESTORE(Op, DAG);
+  case ISD::DYNAMIC_STACKALLOC:
+    return LowerDYNAMIC_STACKALLOC(Op, DAG);
   default:
     report_fatal_error("Unexpected node to lower");
   }
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index 077559e2d6129..6f6ec391430a9 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -75,6 +75,12 @@ class XtensaTargetLowering : public TargetLowering {
 
   SDValue LowerConstantPool(ConstantPoolSDNode *CP, SelectionDAG &DAG) const;
 
+  SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
+
+  SDValue LowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const;
+
+  SDValue LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const;
+
   SDValue getAddrPCRel(SDValue Op, SelectionDAG &DAG) const;
 
   CCAssignFn *CCAssignFnForCall(CallingConv::ID CC, bool IsVarArg) const;
diff --git a/llvm/test/CodeGen/Xtensa/call.ll b/llvm/test/CodeGen/Xtensa/call.ll
index 24c7c4f558e13..921f89a81b2e4 100644
--- a/llvm/test/CodeGen/Xtensa/call.ll
+++ b/llvm/test/CodeGen/Xtensa/call.ll
@@ -5,11 +5,11 @@ declare i32 @external_function(i32)
 define i32 @test_call_external(i32 %a) nounwind {
 ; CHECK-LABEL: test_call_external:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:  s32i  a0, a1, 0
+; CHECK:       s32i  a0, a1, 0
 ; CHECK-NEXT:  l32r  a8, .LCPI0_0
 ; CHECK-NEXT:  callx0  a8
 ; CHECK-NEXT:  l32i  a0, a1, 0
-; CHECK-NEXT:  ret
+; CHECK:       ret
   %1 = call i32 @external_function(i32 %a)
   ret i32 %1
 }
@@ -26,11 +26,11 @@ define i32 @defined_function(i32 %a) nounwind {
 define i32 @test_call_defined(i32 %a) nounwind {
 ; CHECK-LABEL: test_call_defined:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:  s32i  a0, a1, 0
+; CHECK:       s32i  a0, a1, 0
 ; CHECK-NEXT:  l32r  a8, .LCPI2_0
 ; CHECK-NEXT:  callx0  a8
 ; CHECK-NEXT:  l32i  a0, a1, 0
-; CHECK-NEXT:  ret
+; CHECK:       ret
   %1 = call i32 @defined_function(i32 %a) nounwind
   ret i32 %1
 }
@@ -38,12 +38,12 @@ define i32 @test_call_defined(i32 %a) nounwind {
 define i32 @test_call_indirect(ptr %a, i32 %b) nounwind {
 ; CHECK-LABEL: test_call_indirect:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:  s32i  a0, a1, 0
+; CHECK:       s32i  a0, a1, 0
 ; CHECK-NEXT:  or  a8, a2, a2
 ; CHECK-NEXT:  or  a2, a3, a3
 ; CHECK-NEXT:  callx0  a8
 ; CHECK-NEXT:  l32i  a0, a1, 0
-; CHECK-NEXT:  ret
+; CHECK:       ret
   %1 = call i32 %a(i32 %b)
   ret i32 %1
 }
diff --git a/llvm/test/CodeGen/Xtensa/dynamic-alloc.ll b/llvm/test/CodeGen/Xtensa/dynamic-alloc.ll
new file mode 100644
index 0000000000000..2b28f3559d775
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/dynamic-alloc.ll
@@ -0,0 +1,26 @@
+; RUN: llc -mtriple=xtensa -disable-block-placement -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s
+
+define ptr @test_simple_alloca(i32 %numelts) {
+; CHECK-LABEL: test_simple_alloca
+; CHECK:       addi  a8, a1, -16
+; CHECK:       or  a1, a8, a8
+; CHECK:       s32i  a15, a1, 0
+; CHECK:       or a15, a1, a1
+; CHECK:       addi  a8, a2, 3
+; CHECK-NEXT:  movi  a9, -4
+; CHECK-NEXT:  and  a8, a8, a9
+; CHECK-NEXT:  addi  a8, a8, 31
+; CHECK-NEXT:  movi  a9, -32
+; CHECK-NEXT:  and  a8, a8, a9
+; CHECK-NEXT:  sub  a1, a1, a8
+; CHECK-NEXT:  or  a2, a1, a1
+; CHECK-NEXT:  or  a1, a15, a15
+; CHECK-NEXT:  l32i  a15, a1, 0
+; CHECK-NEXT:  addi  a8, a1, 16
+; CHECK-NEXT:  or  a1, a8, a8
+; CHECK-NEXT:  ret
+
+  %addr = alloca i8, i32 %numelts
+  ret ptr %addr
+}
diff --git a/llvm/test/CodeGen/Xtensa/saverestore.ll b/llvm/test/CodeGen/Xtensa/saverestore.ll
new file mode 100644
index 0000000000000..69c8b16ab601d
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/saverestore.ll
@@ -0,0 +1,42 @@
+; RUN: llc --mtriple=xtensa < %s | FileCheck %s
+
+declare ptr @llvm.stacksave()
+
+declare void @llvm.stackrestore(ptr)
+
+declare void @use_addr(ptr)
+
+define void @test_saverestore(i64 %n) {
+; CHECK:       # %bb.0:
+; CHECK-NEXT:  addi a8, a1, -16
+; CHECK-NEXT:  or a1, a8, a8
+; CHECK:       s32i a0, a1, 8
+; CHECK-NEXT:  s32i a12, a1, 4
+; CHECK-NEXT:  s32i a15, a1, 0
+; CHECK:       or a15, a1, a1
+; CHECK:       addi a8, a2, 3
+; CHECK-NEXT:  movi a9, -4
+; CHECK-NEXT:  and a8, a8, a9
+; CHECK-NEXT:  addi a8, a8, 31
+; CHECK-NEXT:  movi a9, -32
+; CHECK-NEXT:  and a8, a8, a9
+; CHECK-NEXT:  or a12, a1, a1
+; CHECK-NEXT:  sub a1, a1, a8
+; CHECK-NEXT:  or a2, a1, a1
+; CHECK-NEXT:  l32r a8, .LCPI0_0
+; CHECK-NEXT:  callx0 a8
+; CHECK-NEXT:  or a1, a12, a12
+; CHECK-NEXT:  or a1, a15, a15
+; CHECK-NEXT:  l32i a15, a1, 0
+; CHECK-NEXT:  l32i a12, a1, 4
+; CHECK-NEXT:  l32i a0, a1, 8
+; CHECK-NEXT:  addi a8, a1, 16
+; CHECK-NEXT:  or a1, a8, a8
+; CHECK-NEXT:  ret
+
+  %sp = call ptr @llvm.stacksave.p0()
+  %addr = alloca i8, i64 %n
+  call void @use_addr(ptr %addr)
+  call void @llvm.stackrestore.p0(ptr %sp)
+  ret void
+}

>From c84f7f10d71a36f75b356f541707dbb1df1fd1c5 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 28 May 2024 02:37:00 +0300
Subject: [PATCH 2/5] [PATCH] [Xtensa] Minor fixes in FrameLowering and
 ISelLowering.

Remove redundant code from XtensaFrameLowering and
XtensaISelLowering, add comments.
---
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 41 ++++++++-----------
 llvm/lib/Target/Xtensa/XtensaFrameLowering.h  |  8 +++-
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp |  8 ++--
 llvm/lib/Target/Xtensa/XtensaSubtarget.cpp    |  2 +-
 4 files changed, 29 insertions(+), 30 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index fbc6c378887b5..26d3a0bead1d1 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -22,9 +22,10 @@
 
 using namespace llvm;
 
-XtensaFrameLowering::XtensaFrameLowering()
+XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
-                          Align(4)) {}
+                          Align(4)),
+      STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
 
 bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -36,14 +37,10 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
                                        MachineBasicBlock &MBB) const {
   assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
-      MF.getSubtarget().getRegisterInfo());
-  const XtensaInstrInfo &TII =
-      *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
   MachineBasicBlock::iterator MBBI = MBB.begin();
   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
-  unsigned SP = Xtensa::SP;
-  unsigned FP = RegInfo->getFrameRegister(MF);
+  MCRegister SP = Xtensa::SP;
+  MCRegister FP = TRI->getFrameRegister(MF);
   MachineModuleInfo &MMI = MF.getMMI();
   const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo();
 
@@ -121,20 +118,21 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
                                        MachineBasicBlock &MBB) const {
   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
-      MF.getSubtarget().getRegisterInfo());
-  const XtensaInstrInfo &TII =
-      *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
   DebugLoc DL = MBBI->getDebugLoc();
-  unsigned SP = Xtensa::SP;
-  unsigned FP = RegInfo->getFrameRegister(MF);
+  MCRegister SP = Xtensa::SP;
+  MCRegister FP = TRI->getFrameRegister(MF);
 
   // if framepointer enabled, restore the stack pointer.
   if (hasFP(MF)) {
-    // Find the first instruction that restores a callee-saved register.
+    // We should place restore stack pointer instruction just before
+    // sequence of instructions which restores callee-saved registers.
+    // This sequence is placed at the end of the basic block,
+    // so we should find first instruction of the sequence.
     MachineBasicBlock::iterator I = MBBI;
 
-    for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++i)
+    // Find the first instruction at the end that restores a callee-saved
+    // register.
+    for (auto &Info : MFI.getCalleeSavedInfo())
       --I;
 
     BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
@@ -154,9 +152,7 @@ bool XtensaFrameLowering::spillCalleeSavedRegisters(
     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
     ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
   MachineFunction *MF = MBB.getParent();
-
   MachineBasicBlock &EntryBlock = *(MF->begin());
-  const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
 
   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
     // Add the callee-saved register as live-in. Do not add if the register is
@@ -199,8 +195,7 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
     if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)
       Amount = -Amount;
 
-    unsigned SP = Xtensa::SP;
-    TII.adjustStackPtr(SP, Amount, MBB, I);
+    TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);
   }
 
   return MBB.erase(I);
@@ -210,9 +205,7 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                                BitVector &SavedRegs,
                                                RegScavenger *RS) const {
   MachineFrameInfo &MFI = MF.getFrameInfo();
-  const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>(
-      MF.getSubtarget().getRegisterInfo());
-  unsigned FP = RegInfo->getFrameRegister(MF);
+  unsigned FP = TRI->getFrameRegister(MF);
 
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 
@@ -227,9 +220,9 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
     return;
 
   const TargetRegisterClass &RC = Xtensa::ARRegClass;
-  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
   unsigned Size = TRI->getSpillSize(RC);
   Align Alignment = TRI->getSpillAlign(RC);
   int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false);
+
   RS->addScavengingFrameIndex(FI);
 }
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
index 696f9ef381f2c..2e705f6294ebf 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
@@ -14,10 +14,16 @@
 namespace llvm {
 class XtensaTargetMachine;
 class XtensaSubtarget;
+class XtensaInstrInfo;
+class XtensaRegisterInfo;
 
 class XtensaFrameLowering : public TargetFrameLowering {
+  const XtensaSubtarget &STI;
+  const XtensaInstrInfo &TII;
+  const XtensaRegisterInfo *TRI;
+
 public:
-  XtensaFrameLowering();
+  XtensaFrameLowering(const XtensaSubtarget &STI);
 
   bool hasFP(const MachineFunction &MF) const override;
 
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 8aebf60e46a41..6c3258b4bb46c 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -542,14 +542,14 @@ SDValue XtensaTargetLowering::LowerConstantPool(ConstantPoolSDNode *CP,
 
 SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op,
                                              SelectionDAG &DAG) const {
-  unsigned SP = Xtensa::SP;
-  return DAG.getCopyFromReg(Op.getOperand(0), SDLoc(Op), SP, Op.getValueType());
+  return DAG.getCopyFromReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP,
+                            Op.getValueType());
 }
 
 SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op,
                                                 SelectionDAG &DAG) const {
-  unsigned SP = Xtensa::SP;
-  return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), SP, Op.getOperand(1));
+  return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP,
+                          Op.getOperand(1));
 }
 
 SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp b/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp
index 10ab92d2a2d38..d6b1b4bc15463 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.cpp
@@ -41,4 +41,4 @@ XtensaSubtarget::XtensaSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
                                  const TargetMachine &TM)
     : XtensaGenSubtargetInfo(TT, CPU, /*TuneCPU=*/CPU, FS), TargetTriple(TT),
       InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this),
-      TSInfo(), FrameLowering() {}
+      TSInfo(), FrameLowering(*this) {}

>From cfe1305eafbc28875980b0597e0cc8dee54db1ca Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 29 May 2024 02:20:29 +0300
Subject: [PATCH 3/5] [PATCH] [Xtensa] Check save/restore instructions in
 emitPrologue and emitEpilogue.

Check whether store/restore instruciton for callee-saved registers
are placed correctly in emitProlgue and emitEpilogue. Also move
frame index scavenging from determineCalleeSaves function to
processFunctionBeforeFrameFinalized function.
---
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 88 +++++++++++++++++--
 llvm/lib/Target/Xtensa/XtensaFrameLowering.h  |  3 +
 2 files changed, 86 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 26d3a0bead1d1..fab7719d7533a 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -33,6 +33,70 @@ bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
          MFI.hasVarSizedObjects();
 }
 
+#ifndef NDEBUG
+/* Check whether instruction I stores some callee-saved register from CSI
+ */
+static bool checkStoreInstruction(MachineBasicBlock::iterator I,
+                                  const std::vector<CalleeSavedInfo> &CSI) {
+  bool IsStoreInstruction = false;
+
+  if (I->getOpcode() == TargetOpcode::COPY) {
+    Register DstReg = I->getOperand(0).getReg();
+    Register Reg = I->getOperand(1).getReg();
+    for (const auto &Info : CSI) {
+      if (Info.isSpilledToReg()) {
+        IsStoreInstruction =
+            (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
+      }
+      if (IsStoreInstruction)
+        break;
+    }
+  } else if (I->getOpcode() == Xtensa::S32I) {
+    Register Reg = I->getOperand(0).getReg();
+    for (const auto &Info : CSI) {
+      if (!Info.isSpilledToReg()) {
+        IsStoreInstruction = (Info.getReg() == Reg);
+      }
+      if (IsStoreInstruction)
+        break;
+    }
+  }
+
+  return IsStoreInstruction;
+}
+
+/* Check whether instruction I restores some callee-saved register from CSI
+ */
+static bool checkRestoreInstruction(MachineBasicBlock::iterator I,
+                                    const std::vector<CalleeSavedInfo> &CSI) {
+  bool IsRestoreInstruction = false;
+
+  if (I->getOpcode() == TargetOpcode::COPY) {
+    Register Reg = I->getOperand(0).getReg();
+    Register DstReg = I->getOperand(1).getReg();
+    for (const auto &Info : CSI) {
+      if (Info.isSpilledToReg()) {
+        IsRestoreInstruction =
+            (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
+      }
+      if (IsRestoreInstruction)
+        break;
+    }
+  } else if (I->getOpcode() == Xtensa::L32I) {
+    Register Reg = I->getOperand(0).getReg();
+    for (const auto &Info : CSI) {
+      if (!Info.isSpilledToReg()) {
+        IsRestoreInstruction = (Info.getReg() == Reg);
+      }
+      if (IsRestoreInstruction)
+        break;
+    }
+  }
+
+  return IsRestoreInstruction;
+}
+#endif
+
 void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
                                        MachineBasicBlock &MBB) const {
   assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
@@ -66,11 +130,17 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
 
   const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
 
-  if (CSI.size()) {
+  if (!CSI.empty()) {
     // Find the instruction past the last instruction that saves a
-    // callee-saved register to the stack.
-    for (unsigned i = 0; i < CSI.size(); ++i)
+    // callee-saved register to the stack. The callee-saved store
+    // instructions are placed at the begin of basic block, so
+    //  iterate over instruction sequence and check that
+    // save instructions are placed correctly.
+    for (unsigned i = 0; i < CSI.size(); ++i) {
+      assert(checkStoreInstruction(MBBI, CSI) &&
+             "Unexpected callee-saved register store instruction");
       ++MBBI;
+    }
 
     // Iterate over list of callee-saved registers and emit .cfi_offset
     // directives.
@@ -130,10 +200,15 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
     // so we should find first instruction of the sequence.
     MachineBasicBlock::iterator I = MBBI;
 
+    const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+
     // Find the first instruction at the end that restores a callee-saved
     // register.
-    for (auto &Info : MFI.getCalleeSavedInfo())
+    for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
       --I;
+      assert(checkRestoreInstruction(I, CSI) &&
+             "Unexpected callee-saved register restore instruction");
+    }
 
     BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
   }
@@ -204,7 +279,6 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
 void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                                BitVector &SavedRegs,
                                                RegScavenger *RS) const {
-  MachineFrameInfo &MFI = MF.getFrameInfo();
   unsigned FP = TRI->getFrameRegister(MF);
 
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
@@ -212,8 +286,12 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
   // Mark $fp as used if function has dedicated frame pointer.
   if (hasFP(MF))
     SavedRegs.set(FP);
+}
 
+void XtensaFrameLowering::processFunctionBeforeFrameFinalized(
+    MachineFunction &MF, RegScavenger *RS) const {
   // Set scavenging frame index if necessary.
+  MachineFrameInfo &MFI = MF.getFrameInfo();
   uint64_t MaxSPOffset = MFI.estimateStackSize(MF);
 
   if (isInt<12>(MaxSPOffset))
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
index 2e705f6294ebf..31c496d2b89de 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
@@ -48,6 +48,9 @@ class XtensaFrameLowering : public TargetFrameLowering {
 
   void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
                             RegScavenger *RS) const override;
+
+  void processFunctionBeforeFrameFinalized(MachineFunction &MF,
+                                           RegScavenger *RS) const override;
 };
 
 } // namespace llvm

>From 7df895e0e215522d26807b7bf5f212327114434e Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 30 May 2024 11:17:57 +0300
Subject: [PATCH 4/5] [PATCH] [Xtensa] Simplify calle-saved register checking.

---
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 102 ++++++------------
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    |  24 +++++
 llvm/lib/Target/Xtensa/XtensaInstrInfo.h      |   6 ++
 3 files changed, 64 insertions(+), 68 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index fab7719d7533a..3445e64851fbd 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -33,70 +33,6 @@ bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const {
          MFI.hasVarSizedObjects();
 }
 
-#ifndef NDEBUG
-/* Check whether instruction I stores some callee-saved register from CSI
- */
-static bool checkStoreInstruction(MachineBasicBlock::iterator I,
-                                  const std::vector<CalleeSavedInfo> &CSI) {
-  bool IsStoreInstruction = false;
-
-  if (I->getOpcode() == TargetOpcode::COPY) {
-    Register DstReg = I->getOperand(0).getReg();
-    Register Reg = I->getOperand(1).getReg();
-    for (const auto &Info : CSI) {
-      if (Info.isSpilledToReg()) {
-        IsStoreInstruction =
-            (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
-      }
-      if (IsStoreInstruction)
-        break;
-    }
-  } else if (I->getOpcode() == Xtensa::S32I) {
-    Register Reg = I->getOperand(0).getReg();
-    for (const auto &Info : CSI) {
-      if (!Info.isSpilledToReg()) {
-        IsStoreInstruction = (Info.getReg() == Reg);
-      }
-      if (IsStoreInstruction)
-        break;
-    }
-  }
-
-  return IsStoreInstruction;
-}
-
-/* Check whether instruction I restores some callee-saved register from CSI
- */
-static bool checkRestoreInstruction(MachineBasicBlock::iterator I,
-                                    const std::vector<CalleeSavedInfo> &CSI) {
-  bool IsRestoreInstruction = false;
-
-  if (I->getOpcode() == TargetOpcode::COPY) {
-    Register Reg = I->getOperand(0).getReg();
-    Register DstReg = I->getOperand(1).getReg();
-    for (const auto &Info : CSI) {
-      if (Info.isSpilledToReg()) {
-        IsRestoreInstruction =
-            (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
-      }
-      if (IsRestoreInstruction)
-        break;
-    }
-  } else if (I->getOpcode() == Xtensa::L32I) {
-    Register Reg = I->getOperand(0).getReg();
-    for (const auto &Info : CSI) {
-      if (!Info.isSpilledToReg()) {
-        IsRestoreInstruction = (Info.getReg() == Reg);
-      }
-      if (IsRestoreInstruction)
-        break;
-    }
-  }
-
-  return IsRestoreInstruction;
-}
-#endif
-
 void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
                                        MachineBasicBlock &MBB) const {
   assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");
@@ -136,9 +72,24 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
     // instructions are placed at the begin of basic block, so
     //  iterate over instruction sequence and check that
     // save instructions are placed correctly.
-    for (unsigned i = 0; i < CSI.size(); ++i) {
-      assert(checkStoreInstruction(MBBI, CSI) &&
+    for (const auto &Info : CSI) {
+      int FI = Info.getFrameIdx();
+      int StoreFI = 0;
+
+#ifndef NDEBUG
+      // Checking that the instruction is exactly as expected
+      bool IsStoreInst = false;
+      if ((MBBI->getOpcode() == TargetOpcode::COPY) && Info.isSpilledToReg()) {
+        Register DstReg = MBBI->getOperand(0).getReg();
+        Register Reg = MBBI->getOperand(1).getReg();
+        IsStoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
+      } else {
+        Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
+        IsStoreInst = (Reg == Info.getReg()) && (StoreFI == FI);
+      }
+      assert(IsStoreInst &&
              "Unexpected callee-saved register store instruction");
+#endif
       ++MBBI;
     }
 
@@ -204,10 +155,25 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
 
     // Find the first instruction at the end that restores a callee-saved
     // register.
-    for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
+    for (const auto &Info : CSI) {
+      int FI = Info.getFrameIdx();
+      int LoadFI = 0;
+
       --I;
-      assert(checkRestoreInstruction(I, CSI) &&
+#ifndef NDEBUG
+      // Checking that the instruction is exactly as expected
+      bool IsRestoreInstr = false;
+      if (I->getOpcode() == TargetOpcode::COPY) {
+        Register Reg = I->getOperand(0).getReg();
+        Register DstReg = I->getOperand(1).getReg();
+        IsRestoreInstr = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
+      } else {
+        Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);
+        IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI);
+      }
+      assert(IsRestoreInstr &&
              "Unexpected callee-saved register restore instruction");
+#endif
     }
 
     BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 26d8727ce1d3b..506ef8431abe4 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -48,6 +48,30 @@ XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI)
     : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP),
       RI(STI), STI(STI) {}
 
+Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
+                                              int &FrameIndex) const {
+  if (MI.getOpcode() == Xtensa::L32I) {
+    if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+        MI.getOperand(2).getImm() == 0) {
+      FrameIndex = MI.getOperand(1).getIndex();
+      return MI.getOperand(0).getReg();
+    }
+  }
+  return 0;
+}
+
+Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
+                                             int &FrameIndex) const {
+  if (MI.getOpcode() == Xtensa::S32I) {
+    if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
+        MI.getOperand(2).getImm() == 0) {
+      FrameIndex = MI.getOperand(1).getIndex();
+      return MI.getOperand(0).getReg();
+    }
+  }
+  return 0;
+}
+
 /// Adjust SP by Amount bytes.
 void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
                                      MachineBasicBlock &MBB,
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
index 1acd314e2720a..37f157f832464 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
@@ -41,6 +41,12 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
   // Return the XtensaRegisterInfo, which this class owns.
   const XtensaRegisterInfo &getRegisterInfo() const { return RI; }
 
+  Register isLoadFromStackSlot(const MachineInstr &MI,
+                               int &FrameIndex) const override;
+
+  Register isStoreToStackSlot(const MachineInstr &MI,
+                              int &FrameIndex) const override;
+
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
                    const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
                    bool KillSrc) const override;

>From 039f075469b02ea3eb57ee1347d84259d4e22390 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 30 May 2024 16:51:24 +0300
Subject: [PATCH 5/5] [PATCH] [Xtensa] Minor changes in callee-saved registers
 checks

---
 llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp | 2 +-
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp     | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 3445e64851fbd..9f97f3aaed31d 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -163,7 +163,7 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
 #ifndef NDEBUG
       // Checking that the instruction is exactly as expected
       bool IsRestoreInstr = false;
-      if (I->getOpcode() == TargetOpcode::COPY) {
+      if ((I->getOpcode() == TargetOpcode::COPY) && Info.isSpilledToReg()) {
         Register Reg = I->getOperand(0).getReg();
         Register DstReg = I->getOperand(1).getReg();
         IsRestoreInstr = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg);
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 506ef8431abe4..27e198508c792 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -57,7 +57,7 @@ Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
       return MI.getOperand(0).getReg();
     }
   }
-  return 0;
+  return Register();
 }
 
 Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
@@ -69,7 +69,7 @@ Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
       return MI.getOperand(0).getReg();
     }
   }
-  return 0;
+  return Register();
 }
 
 /// Adjust SP by Amount bytes.



More information about the llvm-commits mailing list