[llvm] Xtensa] Implement windowed call ABI. (PR #130001)

Andrei Safronov via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 18 02:17:42 PDT 2025


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

>From 20df35c34e0764cf57d7844acee5e99301d2da72 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Thu, 6 Mar 2025 10:27:25 +0300
Subject: [PATCH 1/6] [Xtensa] Implement windowed call ABI.

Implement base windowed call ABI. By defaullt use
rotation window by 8 registers.
---
 llvm/lib/Target/Xtensa/XtensaCallingConv.td   |  20 +++-
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 112 +++++++++++++++++-
 llvm/lib/Target/Xtensa/XtensaFrameLowering.h  |   1 +
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp |  47 +++++++-
 llvm/lib/Target/Xtensa/XtensaISelLowering.h   |   5 +
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    |   4 +
 llvm/lib/Target/Xtensa/XtensaInstrInfo.td     |  19 ++-
 .../Target/Xtensa/XtensaMachineFunctionInfo.h |   4 +
 llvm/lib/Target/Xtensa/XtensaOperators.td     |  11 ++
 llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp |  13 +-
 llvm/lib/Target/Xtensa/XtensaSubtarget.h      |  12 +-
 llvm/test/CodeGen/Xtensa/aligned_alloc.ll     |  32 +++++
 .../CodeGen/Xtensa/calling-conv-windowed.ll   | 103 ++++++++++++++++
 llvm/test/CodeGen/Xtensa/callw.ll             |  52 ++++++++
 14 files changed, 413 insertions(+), 22 deletions(-)
 create mode 100644 llvm/test/CodeGen/Xtensa/aligned_alloc.ll
 create mode 100644 llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
 create mode 100644 llvm/test/CodeGen/Xtensa/callw.ll

diff --git a/llvm/lib/Target/Xtensa/XtensaCallingConv.td b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
index a348b4c890b22..092c50947cee8 100644
--- a/llvm/lib/Target/Xtensa/XtensaCallingConv.td
+++ b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
@@ -9,16 +9,30 @@
 //===----------------------------------------------------------------------===//
 
 //===----------------------------------------------------------------------===//
-// Xtensa return value calling convention
+// Xtensa base calling convention
 //===----------------------------------------------------------------------===//
+// Xtensa return value
 def RetCC_Xtensa : CallingConv<[
   // First two return values go in a2, a3, a4, a5
   CCIfType<[i32], CCAssignToReg<[A2, A3, A4, A5]>>,
   CCIfType<[i64], CCAssignToRegWithShadow<[A2, A4], [A3, A5]>>
 ]>;
 
+// Callee-saved register lists
+def CSR_Xtensa : CalleeSavedRegs<(add A0, A12, A13, A14, A15)>;
+
 //===----------------------------------------------------------------------===//
-// Callee-saved register lists.
+// Xtensa windowed calling convention. Currently by default implemented
+// rotation window by 8 registers.
 //===----------------------------------------------------------------------===//
+// Xtensa return value for 8 registers window
+def RetCCW8_Xtensa : CallingConv<[
+  //First two return values go in a10, a11, a12, a13
+  CCIfType<[i32], CCAssignToReg<[A10, A11, A12, A13]>>,
+  CCIfType<[i64], CCAssignToRegWithShadow<[A10, A12], [A11, A13]>>
+]>;
 
-def CSR_Xtensa : CalleeSavedRegs<(add A0, A12, A13, A14, A15)>;
+// Callee-saved register lists for rotation window by 8 registers
+def CSRW8_Xtensa : CalleeSavedRegs<(add)> {
+  let OtherPreserved = (add A0, SP, A2, A3, A4, A5, A6, A7);
+}
\ No newline at end of file
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index d09aac613f623..338a2bc958498 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -23,9 +23,15 @@
 
 using namespace llvm;
 
+/* minimum frame = reg save area (4 words) plus static chain (1 word)
+   and the total number of words must be a multiple of 128 bits.  */
+/* Width of a word, in units (bytes).  */
+#define UNITS_PER_WORD 4
+#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
+
 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::hasFPImpl(const MachineFunction &MF) const {
@@ -43,6 +49,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
   MCRegister SP = Xtensa::SP;
   MCRegister FP = TRI->getFrameRegister(MF);
   const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
+  XtensaMachineFunctionInfo *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();
 
   // First, compute final stack size.
   uint64_t StackSize = MFI.getStackSize();
@@ -51,6 +58,83 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
   // Round up StackSize to 16*N
   StackSize += (16 - StackSize) & 0xf;
 
+  if (STI.isWinABI()) {
+    StackSize += 32;
+    uint64_t MaxAlignment = MFI.getMaxAlign().value();
+    if(MaxAlignment > 32)
+      StackSize += MaxAlignment;
+
+    if (StackSize <= 32760) {
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))
+          .addReg(SP)
+          .addImm(StackSize);
+    } else {
+      /* Use a8 as a temporary since a0-a7 may be live.  */
+      unsigned TmpReg = Xtensa::A8;
+
+      const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
+          MBB.getParent()->getSubtarget().getInstrInfo());
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))
+          .addReg(SP)
+          .addImm(MIN_FRAME_SIZE);
+      TII.loadImmediate(MBB, MBBI, &TmpReg, StackSize - MIN_FRAME_SIZE);
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), TmpReg)
+          .addReg(SP)
+          .addReg(TmpReg);
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::MOVSP), SP).addReg(TmpReg);
+    }
+
+    // Calculate how much is needed to have the correct alignment.
+    // Change offset to: alignment + difference.
+    // For example, in case of alignment of 128:
+    // diff_to_128_aligned_address = (128 - (SP & 127))
+    // new_offset = SP + diff_to_128_aligned_address
+    // This is safe to do because we increased the stack size by MaxAlignment.
+    unsigned Reg, RegMisAlign;
+    if (MaxAlignment > 32){
+      TII.loadImmediate(MBB, MBBI, &RegMisAlign, MaxAlignment - 1);
+      TII.loadImmediate(MBB, MBBI, &Reg, MaxAlignment);
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::AND))
+          .addReg(RegMisAlign, RegState::Define)
+          .addReg(FP)
+          .addReg(RegMisAlign);
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), RegMisAlign)
+          .addReg(Reg)
+          .addReg(RegMisAlign);
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ADD), SP)
+          .addReg(SP)
+          .addReg(RegMisAlign, RegState::Kill);
+    }
+
+    // Store FP register in A8, because FP may be used to pass function
+    // arguments
+    if (XtensaFI->isSaveFrameRegister()) {
+      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), Xtensa::A8)
+          .addReg(FP)
+          .addReg(FP);
+    }
+
+    // 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);
+
+      MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(
+          nullptr, MRI->getDwarfRegNum(FP, true), StackSize);
+      unsigned CFIIndex = MF.addFrameInst(Inst);
+      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
+          .addCFIIndex(CFIIndex);
+    } else {
+      // 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);
+    }
+  } else {
   // No need to allocate space on the stack.
   if (StackSize == 0 && !MFI.adjustsStack())
     return;
@@ -122,6 +206,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
     BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
         .addCFIIndex(CFIIndex);
   }
+  }
 
   if (StackSize != PrevStackSize) {
     MFI.setStackSize(StackSize);
@@ -179,10 +264,22 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
              "Unexpected callee-saved register restore instruction");
 #endif
     }
-
-    BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
+    if (STI.isWinABI()) {
+      // In most architectures, we need to explicitly restore the stack pointer
+      // before returning.
+      //
+      // For Xtensa Windowed Register option, it is not needed to explicitly
+      // restore the stack pointer. Reason being is that on function return,
+      // the window of the caller (including the old stack pointer) gets
+      // restored anyways.
+    } else {
+      BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);
+    }
   }
 
+  if (STI.isWinABI())
+    return;
+
   // Get the number of bytes from FrameInfo
   uint64_t StackSize = MFI.getStackSize();
 
@@ -199,6 +296,9 @@ bool XtensaFrameLowering::spillCalleeSavedRegisters(
   MachineFunction *MF = MBB.getParent();
   MachineBasicBlock &EntryBlock = *(MF->begin());
 
+  if (STI.isWinABI())
+    return true;
+
   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
@@ -224,6 +324,8 @@ bool XtensaFrameLowering::spillCalleeSavedRegisters(
 bool XtensaFrameLowering::restoreCalleeSavedRegisters(
     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
+  if (STI.isWinABI())
+    return true;
   return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
 }
 
@@ -251,6 +353,10 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                                RegScavenger *RS) const {
   unsigned FP = TRI->getFrameRegister(MF);
 
+  if (STI.isWinABI()) {
+    return;
+  }
+
   TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
 
   // Mark $fp as used if function has dedicated frame pointer.
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
index 3f946e1ea730f..f0095b8774154 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.h
@@ -18,6 +18,7 @@ class XtensaInstrInfo;
 class XtensaRegisterInfo;
 
 class XtensaFrameLowering : public TargetFrameLowering {
+  const XtensaSubtarget &STI;
   const XtensaInstrInfo &TII;
   const XtensaRegisterInfo *TRI;
 
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 57f0cbbc36c24..75e8dad388d1e 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -42,6 +42,15 @@ static bool isLongCall(const char *str) {
   return true;
 }
 
+// The calling conventions in XtensaCallingConv.td are described in terms of the
+// callee's register window. This function translates registers to the
+// corresponding caller window %o register.
+static unsigned toCallerWindow(unsigned Reg) {
+  if (Reg >= Xtensa::A2 && Reg <= Xtensa::A7)
+    return Reg - Xtensa::A2 + Xtensa::A10;
+  return Reg;
+}
+
 XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &TM,
                                            const XtensaSubtarget &STI)
     : TargetLowering(TM), Subtarget(STI) {
@@ -339,7 +348,18 @@ SDValue XtensaTargetLowering::LowerFormalArguments(
 
       // Transform the arguments stored on
       // physical registers into virtual ones
-      Register Reg = MF.addLiveIn(VA.getLocReg(), &Xtensa::ARRegClass);
+      Register Reg = 0;
+      unsigned FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
+
+      // Argument passed in FrameReg in WinABI we save in A8 (in emitPrologue),
+      // so load argument from A8
+      if (Subtarget.isWinABI() && (VA.getLocReg() == FrameReg)) {
+        Reg = MF.addLiveIn(Xtensa::A8, &Xtensa::ARRegClass);
+        XtensaFI->setSaveFrameRegister();
+      } else {
+        Reg = MF.addLiveIn(VA.getLocReg(), &Xtensa::ARRegClass);
+      }
+
       SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegVT);
 
       // If this is an 8 or 16-bit value, it has been passed promoted
@@ -538,6 +558,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   SDValue Glue;
   for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
     unsigned Reg = RegsToPass[I].first;
+    if (Subtarget.isWinABI())
+      Reg = toCallerWindow(Reg);
     Chain = DAG.getCopyToReg(Chain, DL, Reg, RegsToPass[I].second, Glue);
     Glue = Chain.getValue(1);
   }
@@ -587,6 +609,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // known live into the call.
   for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
     unsigned Reg = RegsToPass[I].first;
+    if (Subtarget.isWinABI())
+      Reg = toCallerWindow(Reg);
     Ops.push_back(DAG.getRegister(Reg, RegsToPass[I].second.getValueType()));
   }
 
@@ -595,7 +619,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
     Ops.push_back(Glue);
 
   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
-  Chain = DAG.getNode(XtensaISD::CALL, DL, NodeTys, Ops);
+  Chain = DAG.getNode(Subtarget.isWinABI() ? XtensaISD::CALLW8 : XtensaISD::CALL,
+                      DL, NodeTys, Ops);
   Glue = Chain.getValue(1);
 
   // Mark the end of the call, which is glued to the call itself.
@@ -606,7 +631,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RetLocs;
   CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, *DAG.getContext());
-  RetCCInfo.AnalyzeCallResult(Ins, RetCC_Xtensa);
+  RetCCInfo.AnalyzeCallResult(Ins, Subtarget.isWinABI() ? RetCCW8_Xtensa
+                                                        : RetCC_Xtensa);
 
   // Copy all of the result registers out of their specified physreg.
   for (unsigned I = 0, E = RetLocs.size(); I != E; ++I) {
@@ -648,7 +674,8 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   SDValue Glue;
   // Quick exit for void returns
   if (RetLocs.empty())
-    return DAG.getNode(XtensaISD::RET, DL, MVT::Other, Chain);
+    return DAG.getNode(Subtarget.isWinABI() ? XtensaISD::RETW
+                                            : XtensaISD::RET, DL, MVT::Other, Chain);
 
   // Copy the result values into the output registers.
   SmallVector<SDValue, 4> RetOps;
@@ -672,7 +699,8 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   if (Glue.getNode())
     RetOps.push_back(Glue);
 
-  return DAG.getNode(XtensaISD::RET, DL, MVT::Other, RetOps);
+  return DAG.getNode(Subtarget.isWinABI() ? XtensaISD::RETW
+                                            : XtensaISD::RET, DL, MVT::Other, RetOps);
 }
 
 static unsigned getBranchOpcode(ISD::CondCode Cond) {
@@ -906,6 +934,9 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
   unsigned SPReg = Xtensa::SP;
   SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
   SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value
+  if (Subtarget.isWinABI()) {
+    NewSP = DAG.getNode(XtensaISD::MOVSP, DL, MVT::i32, NewSP);
+  }
   Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain
 
   SDValue NewVal = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32);
@@ -1230,12 +1261,18 @@ const char *XtensaTargetLowering::getTargetNodeName(unsigned Opcode) const {
     return "XtensaISD::BR_JT";
   case XtensaISD::CALL:
     return "XtensaISD::CALL";
+  case XtensaISD::CALLW8:
+    return "XtensaISD::CALLW8";
   case XtensaISD::EXTUI:
     return "XtensaISD::EXTUI";
+  case XtensaISD::MOVSP:
+    return "XtensaISD::MOVSP";
   case XtensaISD::PCREL_WRAPPER:
     return "XtensaISD::PCREL_WRAPPER";
   case XtensaISD::RET:
     return "XtensaISD::RET";
+  case XtensaISD::RETW:
+    return "XtensaISD::RETW";
   case XtensaISD::SELECT_CC:
     return "XtensaISD::SELECT_CC";
   case XtensaISD::SRCL:
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.h b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
index a959299d8ca6a..c7d4f41b1f08e 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.h
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.h
@@ -29,16 +29,21 @@ enum {
   // is the target address.  The arguments start at operand 2.
   // There is an optional glue operand at the end.
   CALL,
+  // Call with rotation window by 8 registers
+  CALLW8,
 
   // Extract unsigned immediate. Operand 0 is value, operand 1
   // is bit position of the field [0..31], operand 2 is bit size
   // of the field [1..16]
   EXTUI,
 
+  MOVSP,
+
   // Wraps a TargetGlobalAddress that should be loaded using PC-relative
   // accesses.  Operand 0 is the address.
   PCREL_WRAPPER,
   RET,
+  RETW,
 
   // Select with condition operator - This selects between a true value and
   // a false value (ops #2 and #3) based on the boolean result of comparing
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index da2883e1902ca..788dc992d1d4e 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -100,9 +100,13 @@ void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
         .addReg(Reg1, RegState::Kill);
   }
 
+  if (STI.isWinABI()) {
+    BuildMI(MBB, I, DL, get(Xtensa::MOVSP), SP).addReg(Reg, RegState::Kill);
+  } else {
   BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
       .addReg(Reg, RegState::Kill)
       .addReg(Reg, RegState::Kill);
+      }
 }
 
 void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index 1f397e3ecac35..b41c00738f763 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -709,22 +709,35 @@ let isCall = 1, Defs = [A0] in {
   }
 }
 
+// Windowed call patterns. Currently rotation
+// window by 8 is implemented.
+def : Pat<(Xtensa_callw8 (i32 tglobaladdr:$dst)),
+          (CALL8 tglobaladdr:$dst)>;
+def : Pat<(Xtensa_callw8 (i32 texternalsym:$dst)),
+          (CALL8 texternalsym:$dst)>;
+def : Pat<(Xtensa_callw8 AR:$dst),
+          (CALLX8 AR:$dst)>;
+
 def MOVSP : RRR_Inst<0x00, 0x00, 0x00, (outs AR:$t), (ins AR:$s),
-                    "movsp\t$t, $s", []>, Requires<[HasWindowed]> {
+                    "movsp\t$t, $s",
+                    [(set AR:$t, (Xtensa_movsp AR:$s))]>,
+                    Requires<[HasWindowed]> {
   let r = 0x01;
 }
 
 let isReturn = 1, isTerminator = 1,
     isBarrier = 1, Uses = [A0] in {
   def RETW_N : RRRN_Inst<0x0D, (outs), (ins),
-                        "retw.n", []>, Requires<[HasWindowed, HasDensity]> {
+                        "retw.n", [(Xtensa_retw)]>,
+                        Requires<[HasWindowed, HasDensity]> {
     let r = 0x0F;
     let s = 0;
     let t = 1;
   }
 
   def RETW : CALLX_Inst<0x00, 0x00, 0x00, (outs), (ins),
-                       "retw", []>, Requires<[HasWindowed]> {
+                       "retw", [(Xtensa_retw)]>,
+                       Requires<[HasWindowed]> {
     let m = 0x2;
     let n = 0x1;
     let s = 0;
diff --git a/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
index c430562091ba7..bc051d9ca14fa 100644
--- a/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaMachineFunctionInfo.h
@@ -27,6 +27,7 @@ class XtensaMachineFunctionInfo : public MachineFunctionInfo {
   unsigned VarArgsFirstGPR;
   int VarArgsOnStackFrameIndex;
   int VarArgsInRegsFrameIndex;
+  bool SaveFrameRegister = false;
 
 public:
   explicit XtensaMachineFunctionInfo(const Function &F,
@@ -50,6 +51,9 @@ class XtensaMachineFunctionInfo : public MachineFunctionInfo {
   // Get and set the frame index of the first stack vararg.
   int getVarArgsInRegsFrameIndex() const { return VarArgsInRegsFrameIndex; }
   void setVarArgsInRegsFrameIndex(int FI) { VarArgsInRegsFrameIndex = FI; }
+
+  bool isSaveFrameRegister() const { return SaveFrameRegister; }
+  void setSaveFrameRegister() { SaveFrameRegister = true; }
 };
 
 } // namespace llvm
diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index 3dd73b44f336a..1fe5c3f64b607 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -31,15 +31,23 @@ def SDT_XtensaSRC                 : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCi
 def SDT_XtensaEXTUI               : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
                                                          SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
 
+def SDT_XtensaMOVSP               : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisVT<0, i32>]>;
+
 //===----------------------------------------------------------------------===//
 // Node definitions
 //===----------------------------------------------------------------------===//
 def Xtensa_call: SDNode<"XtensaISD::CALL", SDT_XtensaCall,
                        [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
 
+def Xtensa_callw8: SDNode<"XtensaISD::CALLW8", SDT_XtensaCall,
+                        [SDNPHasChain, SDNPOutGlue, SDNPOptInGlue, SDNPVariadic]>;
+
 def Xtensa_ret: SDNode<"XtensaISD::RET", SDTNone,
                        [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
 
+def Xtensa_retw: SDNode<"XtensaISD::RETW", SDTNone,
+                       [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
 def Xtensa_pcrel_wrapper: SDNode<"XtensaISD::PCREL_WRAPPER", SDT_XtensaWrapPtr, []>;
 
 def Xtensa_callseq_start: SDNode<"ISD::CALLSEQ_START", SDT_XtensaCallSeqStart,
@@ -59,3 +67,6 @@ def Xtensa_srcl: SDNode<"XtensaISD::SRCL", SDT_XtensaSRC>;
 def Xtensa_srcr: SDNode<"XtensaISD::SRCR", SDT_XtensaSRC>;
 
 def Xtensa_extui: SDNode<"XtensaISD::EXTUI", SDT_XtensaEXTUI>;
+
+def Xtensa_movsp: SDNode<"XtensaISD::MOVSP", SDT_XtensaMOVSP,
+                        [SDNPInGlue]>;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
index 4a8bafc540df0..cd8bfa0d4d164 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
@@ -34,13 +34,19 @@ XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI)
 
 const uint16_t *
 XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
-  return CSR_Xtensa_SaveList;
+  if (Subtarget.isWinABI())
+    return CSRW8_Xtensa_SaveList;
+  else
+    return CSR_Xtensa_SaveList;
 }
 
 const uint32_t *
 XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
                                          CallingConv::ID) const {
-  return CSR_Xtensa_RegMask;
+  if (Subtarget.isWinABI())
+    return CSRW8_Xtensa_RegMask;
+  else
+    return CSR_Xtensa_RegMask;
 }
 
 BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
@@ -129,5 +135,6 @@ bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
 
 Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
-  return TFI->hasFP(MF) ? Xtensa::A15 : Xtensa::SP;
+  return TFI->hasFP(MF) ? (Subtarget.isWinABI() ? Xtensa::A7 : Xtensa::A15)
+                        : Xtensa::SP;
 }
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index 770f73905b337..b537a72bfe407 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -30,17 +30,17 @@ class StringRef;
 
 class XtensaSubtarget : public XtensaGenSubtargetInfo {
 private:
+// Bool members corresponding to the SubtargetFeatures defined in tablegen
+#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
+  bool ATTRIBUTE = DEFAULT;
+#include "XtensaGenSubtargetInfo.inc"
+
   const Triple &TargetTriple;
   XtensaInstrInfo InstrInfo;
   XtensaTargetLowering TLInfo;
   SelectionDAGTargetInfo TSInfo;
   XtensaFrameLowering FrameLowering;
 
-// Bool members corresponding to the SubtargetFeatures defined in tablegen
-#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
-  bool ATTRIBUTE = DEFAULT;
-#include "XtensaGenSubtargetInfo.inc"
-
   XtensaSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
 
 public:
@@ -72,6 +72,8 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
 
   bool hasBoolean() const { return HasBoolean; }
 
+  bool isWinABI() const { return hasWindowed(); }
+
   // Automatically generated by tblgen.
   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
 };
diff --git a/llvm/test/CodeGen/Xtensa/aligned_alloc.ll b/llvm/test/CodeGen/Xtensa/aligned_alloc.ll
new file mode 100644
index 0000000000000..ebb24d9272ddc
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/aligned_alloc.ll
@@ -0,0 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -O0 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=XTENSA
+
+define i8 @loadi8_128(i8 %a) {
+; XTENSA-LABEL: loadi8_128:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    addi a8, a1, -128
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    .cfi_def_cfa_offset 128
+; XTENSA-NEXT:    s32i a0, a1, 124 # 4-byte Folded Spill
+; XTENSA-NEXT:    .cfi_offset a0, -4
+; XTENSA-NEXT:    addi a2, a1, 0
+; XTENSA-NEXT:    movi a3, 0
+; XTENSA-NEXT:    movi a4, 64
+; XTENSA-NEXT:    l32r a8, .LCPI0_0
+; XTENSA-NEXT:    callx0 a8
+; XTENSA-NEXT:    l8ui a2, a1, 0
+; XTENSA-NEXT:    l32i a0, a1, 124 # 4-byte Folded Reload
+; XTENSA-NEXT:    movi a8, 128
+; XTENSA-NEXT:    add a8, a1, a8
+; XTENSA-NEXT:    or a1, a8, a8
+; XTENSA-NEXT:    ret
+    %aligned = alloca i8, align 128
+    call void @llvm.memset.p0.i64(ptr noundef nonnull align 64 dereferenceable(64) %aligned, i8 0, i64 64, i1 false)
+    %1 = load i8, ptr %aligned, align 128
+    ret i8 %1
+}
+
+; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
diff --git a/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll b/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
new file mode 100644
index 0000000000000..27855b1cdf481
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
@@ -0,0 +1,103 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=xtensa -O1 -mattr=+windowed -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s -check-prefix=XTENSA
+
+; Check placement of first 6 arguments in registers and 7th argument on stack
+define dso_local i32 @test1(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, i32 noundef %4, i32 noundef %5, ptr nocapture noundef readonly byval(i32) align 4 %6) {
+; XTENSA-LABEL: test1:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a8, a7, a2
+; XTENSA-NEXT:    l32i a9, a1, 32
+; XTENSA-NEXT:    add a2, a8, a9
+; XTENSA-NEXT:    retw
+  %8 = load i32, ptr %6, align 4
+  %9 = add nsw i32 %5, %0
+  %10 = add nsw i32 %9, %8
+  ret i32 %10
+}
+
+; Check placement of second i64 argument in registers
+define dso_local i32 @test2(i32 noundef %0, i64 noundef %1, i32 noundef %2) {
+; XTENSA-LABEL: test2:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a8, a6, a2
+; XTENSA-NEXT:    add a2, a8, a4
+; XTENSA-NEXT:    retw
+  %4 = trunc i64 %1 to i32
+  %5 = add nsw i32 %2, %0
+  %6 = add nsw i32 %5, %4
+  ret i32 %6
+}
+
+; Check placement of first argument typeof i8 in register
+define dso_local i32 @test3(i8 noundef signext %0, i64 noundef %1, i32 noundef %2) {
+; XTENSA-LABEL: test3:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a8, a2, a6
+; XTENSA-NEXT:    add a2, a8, a4
+; XTENSA-NEXT:    retw
+  %4 = trunc i64 %1 to i32
+  %5 = sext i8 %0 to i32
+  %6 = add nsw i32 %5, %2
+  %7 = add nsw i32 %6, %4
+  ret i32 %7
+}
+
+; Check placement of 4th argument typeof i64 on stack
+define dso_local i32 @test4(i8 noundef signext %0, i64 noundef %1, i32 noundef %2, ptr nocapture noundef readonly byval(i64) align 8 %3) {
+; XTENSA-LABEL: test4:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a8, a2, a6
+; XTENSA-NEXT:    add a8, a8, a4
+; XTENSA-NEXT:    l32i a9, a1, 32
+; XTENSA-NEXT:    add a2, a8, a9
+; XTENSA-NEXT:    retw
+  %5 = load i64, ptr %3, align 8
+  %6 = trunc i64 %1 to i32
+  %7 = trunc i64 %5 to i32
+  %8 = sext i8 %0 to i32
+  %9 = add nsw i32 %8, %2
+  %10 = add nsw i32 %9, %6
+  %11 = add nsw i32 %10, %7
+  ret i32 %11
+}
+
+; Check placement of 128 bit structure on registers
+define dso_local i32 @test5([4 x i32] %0, i32 noundef %1) {
+; XTENSA-LABEL: test5:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a2, a2, a6
+; XTENSA-NEXT:    retw
+  %3 = extractvalue [4 x i32] %0, 0
+  %4 = add nsw i32 %3, %1
+  ret i32 %4
+}
+
+; Check placement of 128 bit structure on stack
+define dso_local i32 @test6(i32 noundef %0, [4 x i32] %1) {
+; XTENSA-LABEL: test6:
+; XTENSA:         .cfi_startproc
+; XTENSA-NEXT:  # %bb.0:
+; XTENSA-NEXT:    entry a1, 32
+; XTENSA-NEXT:    .cfi_def_cfa_offset 32
+; XTENSA-NEXT:    add a2, a3, a2
+; XTENSA-NEXT:    retw
+  %3 = extractvalue [4 x i32] %1, 0
+  %4 = add nsw i32 %3, %0
+  ret i32 %4
+}
diff --git a/llvm/test/CodeGen/Xtensa/callw.ll b/llvm/test/CodeGen/Xtensa/callw.ll
new file mode 100644
index 0000000000000..21549bcf22678
--- /dev/null
+++ b/llvm/test/CodeGen/Xtensa/callw.ll
@@ -0,0 +1,52 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=xtensa -mattr=+windowed < %s | FileCheck %s
+
+declare i32 @external_function(i32)
+
+define i32 @test_call_external(i32 %a) nounwind {
+; CHECK-LABEL: test_call_external:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    entry a1, 32
+; CHECK-NEXT:    l32r a8, .LCPI0_0
+; CHECK-NEXT:    or a10, a2, a2
+; CHECK-NEXT:    callx8 a8
+; CHECK-NEXT:    or a2, a10, a10
+; CHECK-NEXT:    retw
+  %1 = call i32 @external_function(i32 %a)
+  ret i32 %1
+}
+
+define i32 @defined_function(i32 %a) nounwind {
+; CHECK-LABEL: defined_function:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    entry a1, 32
+; CHECK-NEXT:    addi a2, a2, 1
+; CHECK-NEXT:    retw
+  %1 = add i32 %a, 1
+  ret i32 %1
+}
+
+define i32 @test_call_defined(i32 %a) nounwind {
+; CHECK-LABEL: test_call_defined:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    entry a1, 32
+; CHECK-NEXT:    l32r a8, .LCPI2_0
+; CHECK-NEXT:    or a10, a2, a2
+; CHECK-NEXT:    callx8 a8
+; CHECK-NEXT:    or a2, a10, a10
+; CHECK-NEXT:    retw
+  %1 = call i32 @defined_function(i32 %a) nounwind
+  ret i32 %1
+}
+
+define i32 @test_call_indirect(ptr %a, i32 %b) nounwind {
+; CHECK-LABEL: test_call_indirect:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    entry a1, 32
+; CHECK-NEXT:    or a10, a3, a3
+; CHECK-NEXT:    callx8 a2
+; CHECK-NEXT:    or a2, a10, a10
+; CHECK-NEXT:    retw
+  %1 = call i32 %a(i32 %b)
+  ret i32 %1
+}

>From 637c28726bebc95af652327abc82627934b3f178 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 12 Mar 2025 02:59:04 +0300
Subject: [PATCH 2/6] [Xtensa] Fix windowed call ABI.

Fixed windowed call ABI test. Code formatting and other minor fixes.
---
 llvm/lib/Target/Xtensa/XtensaCallingConv.td   |   2 +-
 .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 147 +++++++++---------
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp |  31 ++--
 llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp    |  18 +--
 llvm/lib/Target/Xtensa/XtensaInstrInfo.h      |   4 +-
 llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp |  17 +-
 llvm/lib/Target/Xtensa/XtensaSubtarget.h      |   2 +-
 .../CodeGen/Xtensa/calling-conv-windowed.ll   |  66 ++++----
 8 files changed, 143 insertions(+), 144 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaCallingConv.td b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
index 092c50947cee8..2c48f8f86cafb 100644
--- a/llvm/lib/Target/Xtensa/XtensaCallingConv.td
+++ b/llvm/lib/Target/Xtensa/XtensaCallingConv.td
@@ -35,4 +35,4 @@ def RetCCW8_Xtensa : CallingConv<[
 // Callee-saved register lists for rotation window by 8 registers
 def CSRW8_Xtensa : CalleeSavedRegs<(add)> {
   let OtherPreserved = (add A0, SP, A2, A3, A4, A5, A6, A7);
-}
\ No newline at end of file
+}
diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 338a2bc958498..44a240386511a 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -23,9 +23,9 @@
 
 using namespace llvm;
 
-/* minimum frame = reg save area (4 words) plus static chain (1 word)
-   and the total number of words must be a multiple of 128 bits.  */
-/* Width of a word, in units (bytes).  */
+// Minimum frame = reg save area (4 words) plus static chain (1 word)
+// and the total number of words must be a multiple of 128 bits.
+// Width of a word, in units (bytes).
 #define UNITS_PER_WORD 4
 #define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
 
@@ -58,7 +58,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
   // Round up StackSize to 16*N
   StackSize += (16 - StackSize) & 0xf;
 
-  if (STI.isWinABI()) {
+  if (STI.isWindowedABI()) {
     StackSize += 32;
     uint64_t MaxAlignment = MFI.getMaxAlign().value();
     if(MaxAlignment > 32)
@@ -69,8 +69,8 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
           .addReg(SP)
           .addImm(StackSize);
     } else {
-      /* Use a8 as a temporary since a0-a7 may be live.  */
-      unsigned TmpReg = Xtensa::A8;
+      // Use a8 as a temporary since a0-a7 may be live.
+      MCRegister TmpReg = Xtensa::A8;
 
       const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
           MBB.getParent()->getSubtarget().getInstrInfo());
@@ -90,7 +90,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
     // diff_to_128_aligned_address = (128 - (SP & 127))
     // new_offset = SP + diff_to_128_aligned_address
     // This is safe to do because we increased the stack size by MaxAlignment.
-    unsigned Reg, RegMisAlign;
+    MCRegister Reg, RegMisAlign;
     if (MaxAlignment > 32){
       TII.loadImmediate(MBB, MBBI, &RegMisAlign, MaxAlignment - 1);
       TII.loadImmediate(MBB, MBBI, &Reg, MaxAlignment);
@@ -135,79 +135,80 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
           .addCFIIndex(CFIIndex);
     }
   } else {
-  // No need to allocate space on the stack.
-  if (StackSize == 0 && !MFI.adjustsStack())
-    return;
+    // 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.empty()) {
-    // Find the instruction past the last instruction that saves a
-    // 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, e = CSI.size(); i < e; ++i) {
+    // 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.empty()) {
+      // Find the instruction past the last instruction that saves a
+      // 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, e = CSI.size(); i < e; ++i) {
 #ifndef NDEBUG
-      const CalleeSavedInfo &Info = CSI[i];
-      int FI = Info.getFrameIdx();
-      int StoreFI = 0;
+        const CalleeSavedInfo &Info = CSI[i];
+        int FI = Info.getFrameIdx();
+        int StoreFI = 0;
+
+        // 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.asMCReg() &&
+                        Info.getReg() == Reg.asMCReg();
+        } else {
+          Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
+          IsStoreInst = Reg.asMCReg() == Info.getReg() && StoreFI == FI;
+        }
+        assert(IsStoreInst &&
+               "Unexpected callee-saved register store instruction");
+#endif
+        ++MBBI;
+      }
 
-      // 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.asMCReg() &&
-                      Info.getReg() == Reg.asMCReg();
-      } else {
-        Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);
-        IsStoreInst = Reg.asMCReg() == Info.getReg() && StoreFI == FI;
+      // Iterate over list of callee-saved registers and emit .cfi_offset
+      // directives.
+      for (const auto &I : CSI) {
+        int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
+        MCRegister 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);
       }
-      assert(IsStoreInst &&
-             "Unexpected callee-saved register store instruction");
-#endif
-      ++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());
-      MCRegister Reg = I.getReg();
+    // 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);
 
-      unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
-          nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));
+      // 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 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);
 
@@ -264,7 +265,7 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
              "Unexpected callee-saved register restore instruction");
 #endif
     }
-    if (STI.isWinABI()) {
+    if (STI.isWindowedABI()) {
       // In most architectures, we need to explicitly restore the stack pointer
       // before returning.
       //
@@ -277,7 +278,7 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,
     }
   }
 
-  if (STI.isWinABI())
+  if (STI.isWindowedABI())
     return;
 
   // Get the number of bytes from FrameInfo
@@ -296,7 +297,7 @@ bool XtensaFrameLowering::spillCalleeSavedRegisters(
   MachineFunction *MF = MBB.getParent();
   MachineBasicBlock &EntryBlock = *(MF->begin());
 
-  if (STI.isWinABI())
+  if (STI.isWindowedABI())
     return true;
 
   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
@@ -324,7 +325,7 @@ bool XtensaFrameLowering::spillCalleeSavedRegisters(
 bool XtensaFrameLowering::restoreCalleeSavedRegisters(
     MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
     MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {
-  if (STI.isWinABI())
+  if (STI.isWindowedABI())
     return true;
   return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);
 }
@@ -353,7 +354,7 @@ void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                                RegScavenger *RS) const {
   unsigned FP = TRI->getFrameRegister(MF);
 
-  if (STI.isWinABI()) {
+  if (STI.isWindowedABI()) {
     return;
   }
 
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 75e8dad388d1e..c4aa513d9ca40 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -349,11 +349,11 @@ SDValue XtensaTargetLowering::LowerFormalArguments(
       // Transform the arguments stored on
       // physical registers into virtual ones
       Register Reg = 0;
-      unsigned FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
+      MCRegister FrameReg = Subtarget.getRegisterInfo()->getFrameRegister(MF);
 
-      // Argument passed in FrameReg in WinABI we save in A8 (in emitPrologue),
-      // so load argument from A8
-      if (Subtarget.isWinABI() && (VA.getLocReg() == FrameReg)) {
+      // Argument passed in FrameReg in Windowed ABI we save in A8 (in
+      // emitPrologue), so load argument from A8
+      if (Subtarget.isWindowedABI() && (VA.getLocReg() == FrameReg)) {
         Reg = MF.addLiveIn(Xtensa::A8, &Xtensa::ARRegClass);
         XtensaFI->setSaveFrameRegister();
       } else {
@@ -558,7 +558,7 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   SDValue Glue;
   for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
     unsigned Reg = RegsToPass[I].first;
-    if (Subtarget.isWinABI())
+    if (Subtarget.isWindowedABI())
       Reg = toCallerWindow(Reg);
     Chain = DAG.getCopyToReg(Chain, DL, Reg, RegsToPass[I].second, Glue);
     Glue = Chain.getValue(1);
@@ -609,7 +609,7 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // known live into the call.
   for (unsigned I = 0, E = RegsToPass.size(); I != E; ++I) {
     unsigned Reg = RegsToPass[I].first;
-    if (Subtarget.isWinABI())
+    if (Subtarget.isWindowedABI())
       Reg = toCallerWindow(Reg);
     Ops.push_back(DAG.getRegister(Reg, RegsToPass[I].second.getValueType()));
   }
@@ -619,7 +619,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
     Ops.push_back(Glue);
 
   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
-  Chain = DAG.getNode(Subtarget.isWinABI() ? XtensaISD::CALLW8 : XtensaISD::CALL,
+  Chain = DAG.getNode(Subtarget.isWindowedABI() ? XtensaISD::CALLW8
+                                                : XtensaISD::CALL,
                       DL, NodeTys, Ops);
   Glue = Chain.getValue(1);
 
@@ -631,8 +632,8 @@ XtensaTargetLowering::LowerCall(CallLoweringInfo &CLI,
   // Assign locations to each value returned by this call.
   SmallVector<CCValAssign, 16> RetLocs;
   CCState RetCCInfo(CallConv, IsVarArg, MF, RetLocs, *DAG.getContext());
-  RetCCInfo.AnalyzeCallResult(Ins, Subtarget.isWinABI() ? RetCCW8_Xtensa
-                                                        : RetCC_Xtensa);
+  RetCCInfo.AnalyzeCallResult(Ins, Subtarget.isWindowedABI() ? RetCCW8_Xtensa
+                                                             : RetCC_Xtensa);
 
   // Copy all of the result registers out of their specified physreg.
   for (unsigned I = 0, E = RetLocs.size(); I != E; ++I) {
@@ -674,8 +675,9 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   SDValue Glue;
   // Quick exit for void returns
   if (RetLocs.empty())
-    return DAG.getNode(Subtarget.isWinABI() ? XtensaISD::RETW
-                                            : XtensaISD::RET, DL, MVT::Other, Chain);
+    return DAG.getNode(Subtarget.isWindowedABI() ? XtensaISD::RETW
+                                                 : XtensaISD::RET,
+                       DL, MVT::Other, Chain);
 
   // Copy the result values into the output registers.
   SmallVector<SDValue, 4> RetOps;
@@ -699,8 +701,9 @@ XtensaTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
   if (Glue.getNode())
     RetOps.push_back(Glue);
 
-  return DAG.getNode(Subtarget.isWinABI() ? XtensaISD::RETW
-                                            : XtensaISD::RET, DL, MVT::Other, RetOps);
+  return DAG.getNode(Subtarget.isWindowedABI() ? XtensaISD::RETW
+                                               : XtensaISD::RET,
+                     DL, MVT::Other, RetOps);
 }
 
 static unsigned getBranchOpcode(ISD::CondCode Cond) {
@@ -934,7 +937,7 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
   unsigned SPReg = Xtensa::SP;
   SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
   SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value
-  if (Subtarget.isWinABI()) {
+  if (Subtarget.isWindowedABI()) {
     NewSP = DAG.getNode(XtensaISD::MOVSP, DL, MVT::i32, NewSP);
   }
   Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
index 788dc992d1d4e..005532b864c41 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
@@ -76,7 +76,7 @@ Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
 }
 
 /// Adjust SP by Amount bytes.
-void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
+void XtensaInstrInfo::adjustStackPtr(MCRegister SP, int64_t Amount,
                                      MachineBasicBlock &MBB,
                                      MachineBasicBlock::iterator I) const {
   DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
@@ -88,25 +88,25 @@ void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
   const TargetRegisterClass *RC = &Xtensa::ARRegClass;
 
   // create virtual reg to store immediate
-  unsigned Reg = RegInfo.createVirtualRegister(RC);
+  MCRegister Reg = RegInfo.createVirtualRegister(RC);
 
   if (isInt<8>(Amount)) { // addi sp, sp, amount
     BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount);
   } else { // Expand immediate that doesn't fit in 8-bit.
-    unsigned Reg1;
+    MCRegister Reg1;
     loadImmediate(MBB, I, &Reg1, Amount);
     BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg)
         .addReg(SP)
         .addReg(Reg1, RegState::Kill);
   }
 
-  if (STI.isWinABI()) {
+  if (STI.isWindowedABI()) {
     BuildMI(MBB, I, DL, get(Xtensa::MOVSP), SP).addReg(Reg, RegState::Kill);
   } else {
-  BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
-      .addReg(Reg, RegState::Kill)
-      .addReg(Reg, RegState::Kill);
-      }
+    BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
+        .addReg(Reg, RegState::Kill)
+        .addReg(Reg, RegState::Kill);
+  }
 }
 
 void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
@@ -160,7 +160,7 @@ void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
 
 void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
                                     MachineBasicBlock::iterator MBBI,
-                                    unsigned *Reg, int64_t Value) const {
+                                    MCRegister *Reg, int64_t Value) const {
   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
   MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
   const TargetRegisterClass *RC = &Xtensa::ARRegClass;
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
index 9bb2114427146..1808cb36d8a9b 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.h
@@ -35,7 +35,7 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
 public:
   XtensaInstrInfo(const XtensaSubtarget &STI);
 
-  void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
+  void adjustStackPtr(MCRegister SP, int64_t Amount, MachineBasicBlock &MBB,
                       MachineBasicBlock::iterator I) const;
 
   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
@@ -73,7 +73,7 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
   // Emit code before MBBI in MI to move immediate value Value into
   // physical register Reg.
   void loadImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
-                     unsigned *Reg, int64_t Value) const;
+                     MCRegister *Reg, int64_t Value) const;
 
   bool
   reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
diff --git a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
index cd8bfa0d4d164..74633050861c2 100644
--- a/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp
@@ -34,19 +34,14 @@ XtensaRegisterInfo::XtensaRegisterInfo(const XtensaSubtarget &STI)
 
 const uint16_t *
 XtensaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
-  if (Subtarget.isWinABI())
-    return CSRW8_Xtensa_SaveList;
-  else
-    return CSR_Xtensa_SaveList;
+  return Subtarget.isWindowedABI() ? CSRW8_Xtensa_SaveList
+                                   : CSR_Xtensa_SaveList;
 }
 
 const uint32_t *
 XtensaRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
                                          CallingConv::ID) const {
-  if (Subtarget.isWinABI())
-    return CSRW8_Xtensa_RegMask;
-  else
-    return CSR_Xtensa_RegMask;
+  return Subtarget.isWindowedABI() ? CSRW8_Xtensa_RegMask : CSR_Xtensa_RegMask;
 }
 
 BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
@@ -88,7 +83,7 @@ bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   //  4. Locations for eh data registers.
   // Everything else is referenced relative to whatever register
   // getFrameRegister() returns.
-  unsigned FrameReg;
+  MCRegister FrameReg;
   if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI))
     FrameReg = Xtensa::SP;
   else
@@ -113,7 +108,7 @@ bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
     MachineBasicBlock &MBB = *MI.getParent();
     DebugLoc DL = II->getDebugLoc();
     unsigned ADD = Xtensa::ADD;
-    unsigned Reg;
+    MCRegister Reg;
     const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
         MBB.getParent()->getSubtarget().getInstrInfo());
 
@@ -135,6 +130,6 @@ bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
 
 Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
   const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
-  return TFI->hasFP(MF) ? (Subtarget.isWinABI() ? Xtensa::A7 : Xtensa::A15)
+  return TFI->hasFP(MF) ? (Subtarget.isWindowedABI() ? Xtensa::A7 : Xtensa::A15)
                         : Xtensa::SP;
 }
diff --git a/llvm/lib/Target/Xtensa/XtensaSubtarget.h b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
index b537a72bfe407..05c0c07e93a96 100644
--- a/llvm/lib/Target/Xtensa/XtensaSubtarget.h
+++ b/llvm/lib/Target/Xtensa/XtensaSubtarget.h
@@ -72,7 +72,7 @@ class XtensaSubtarget : public XtensaGenSubtargetInfo {
 
   bool hasBoolean() const { return HasBoolean; }
 
-  bool isWinABI() const { return hasWindowed(); }
+  bool isWindowedABI() const { return hasWindowed(); }
 
   // Automatically generated by tblgen.
   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
diff --git a/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll b/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
index 27855b1cdf481..2b6b018019c52 100644
--- a/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
+++ b/llvm/test/CodeGen/Xtensa/calling-conv-windowed.ll
@@ -3,7 +3,7 @@
 ; RUN:   | FileCheck %s -check-prefix=XTENSA
 
 ; Check placement of first 6 arguments in registers and 7th argument on stack
-define dso_local i32 @test1(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32 noundef %3, i32 noundef %4, i32 noundef %5, ptr nocapture noundef readonly byval(i32) align 4 %6) {
+define dso_local i32 @test1(i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e, i32 noundef %f, ptr nocapture noundef readonly byval(i32) align 4 %p) {
 ; XTENSA-LABEL: test1:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -13,14 +13,14 @@ define dso_local i32 @test1(i32 noundef %0, i32 noundef %1, i32 noundef %2, i32
 ; XTENSA-NEXT:    l32i a9, a1, 32
 ; XTENSA-NEXT:    add a2, a8, a9
 ; XTENSA-NEXT:    retw
-  %8 = load i32, ptr %6, align 4
-  %9 = add nsw i32 %5, %0
-  %10 = add nsw i32 %9, %8
-  ret i32 %10
+  %l = load i32, ptr %p, align 4
+  %sum = add nsw i32 %f, %a
+  %1 = add nsw i32 %sum, %l
+  ret i32 %1
 }
 
 ; Check placement of second i64 argument in registers
-define dso_local i32 @test2(i32 noundef %0, i64 noundef %1, i32 noundef %2) {
+define dso_local i32 @test2(i32 noundef %a, i64 noundef %b, i32 noundef %c) {
 ; XTENSA-LABEL: test2:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -29,14 +29,14 @@ define dso_local i32 @test2(i32 noundef %0, i64 noundef %1, i32 noundef %2) {
 ; XTENSA-NEXT:    add a8, a6, a2
 ; XTENSA-NEXT:    add a2, a8, a4
 ; XTENSA-NEXT:    retw
-  %4 = trunc i64 %1 to i32
-  %5 = add nsw i32 %2, %0
-  %6 = add nsw i32 %5, %4
-  ret i32 %6
+  %tr = trunc i64 %b to i32
+  %sum = add nsw i32 %c, %a
+  %1 = add nsw i32 %sum, %tr
+  ret i32 %1
 }
 
 ; Check placement of first argument typeof i8 in register
-define dso_local i32 @test3(i8 noundef signext %0, i64 noundef %1, i32 noundef %2) {
+define dso_local i32 @test3(i8 noundef signext %a, i64 noundef %b, i32 noundef %c) {
 ; XTENSA-LABEL: test3:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -45,15 +45,15 @@ define dso_local i32 @test3(i8 noundef signext %0, i64 noundef %1, i32 noundef %
 ; XTENSA-NEXT:    add a8, a2, a6
 ; XTENSA-NEXT:    add a2, a8, a4
 ; XTENSA-NEXT:    retw
-  %4 = trunc i64 %1 to i32
-  %5 = sext i8 %0 to i32
-  %6 = add nsw i32 %5, %2
-  %7 = add nsw i32 %6, %4
-  ret i32 %7
+  %tr = trunc i64 %b to i32
+  %se = sext i8 %a to i32
+  %sum = add nsw i32 %se, %c
+  %1 = add nsw i32 %sum, %tr
+  ret i32 %1
 }
 
 ; Check placement of 4th argument typeof i64 on stack
-define dso_local i32 @test4(i8 noundef signext %0, i64 noundef %1, i32 noundef %2, ptr nocapture noundef readonly byval(i64) align 8 %3) {
+define dso_local i32 @test4(i8 noundef signext %a, i64 noundef %b, i32 noundef %c, ptr nocapture noundef readonly byval(i64) align 8 %p) {
 ; XTENSA-LABEL: test4:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -64,18 +64,18 @@ define dso_local i32 @test4(i8 noundef signext %0, i64 noundef %1, i32 noundef %
 ; XTENSA-NEXT:    l32i a9, a1, 32
 ; XTENSA-NEXT:    add a2, a8, a9
 ; XTENSA-NEXT:    retw
-  %5 = load i64, ptr %3, align 8
-  %6 = trunc i64 %1 to i32
-  %7 = trunc i64 %5 to i32
-  %8 = sext i8 %0 to i32
-  %9 = add nsw i32 %8, %2
-  %10 = add nsw i32 %9, %6
-  %11 = add nsw i32 %10, %7
-  ret i32 %11
+  %l = load i64, ptr %p, align 8
+  %tr1 = trunc i64 %b to i32
+  %tr2 = trunc i64 %l to i32
+  %se = sext i8 %a to i32
+  %sum1 = add nsw i32 %se, %c
+  %sum2 = add nsw i32 %sum1, %tr1
+  %1 = add nsw i32 %sum2, %tr2
+  ret i32 %1
 }
 
 ; Check placement of 128 bit structure on registers
-define dso_local i32 @test5([4 x i32] %0, i32 noundef %1) {
+define dso_local i32 @test5([4 x i32] %a, i32 noundef %b) {
 ; XTENSA-LABEL: test5:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -83,13 +83,13 @@ define dso_local i32 @test5([4 x i32] %0, i32 noundef %1) {
 ; XTENSA-NEXT:    .cfi_def_cfa_offset 32
 ; XTENSA-NEXT:    add a2, a2, a6
 ; XTENSA-NEXT:    retw
-  %3 = extractvalue [4 x i32] %0, 0
-  %4 = add nsw i32 %3, %1
-  ret i32 %4
+  %ev = extractvalue [4 x i32] %a, 0
+  %1 = add nsw i32 %ev, %b
+  ret i32 %1
 }
 
 ; Check placement of 128 bit structure on stack
-define dso_local i32 @test6(i32 noundef %0, [4 x i32] %1) {
+define dso_local i32 @test6(i32 noundef %a, [4 x i32] %b) {
 ; XTENSA-LABEL: test6:
 ; XTENSA:         .cfi_startproc
 ; XTENSA-NEXT:  # %bb.0:
@@ -97,7 +97,7 @@ define dso_local i32 @test6(i32 noundef %0, [4 x i32] %1) {
 ; XTENSA-NEXT:    .cfi_def_cfa_offset 32
 ; XTENSA-NEXT:    add a2, a3, a2
 ; XTENSA-NEXT:    retw
-  %3 = extractvalue [4 x i32] %1, 0
-  %4 = add nsw i32 %3, %0
-  ret i32 %4
+  %ev = extractvalue [4 x i32] %b, 0
+  %1 = add nsw i32 %ev, %a
+  ret i32 %1
 }

>From ef88051434b4ff211e24a234e255fd56d35c770a Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 12 Mar 2025 12:24:45 +0300
Subject: [PATCH 3/6] [Xtensa] Minor code formatting.

---
 llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 44a240386511a..33c57e504b363 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -31,8 +31,8 @@ using namespace llvm;
 
 XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)
     : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,
-                          Align(4)), STI(STI),
-      TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
+                          Align(4)),
+      STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
 
 bool XtensaFrameLowering::hasFPImpl(const MachineFunction &MF) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
@@ -61,7 +61,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
   if (STI.isWindowedABI()) {
     StackSize += 32;
     uint64_t MaxAlignment = MFI.getMaxAlign().value();
-    if(MaxAlignment > 32)
+    if (MaxAlignment > 32)
       StackSize += MaxAlignment;
 
     if (StackSize <= 32760) {
@@ -91,7 +91,7 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
     // new_offset = SP + diff_to_128_aligned_address
     // This is safe to do because we increased the stack size by MaxAlignment.
     MCRegister Reg, RegMisAlign;
-    if (MaxAlignment > 32){
+    if (MaxAlignment > 32) {
       TII.loadImmediate(MBB, MBBI, &RegMisAlign, MaxAlignment - 1);
       TII.loadImmediate(MBB, MBBI, &Reg, MaxAlignment);
       BuildMI(MBB, MBBI, DL, TII.get(Xtensa::AND))

>From 1293a26788b7c6a1a60a1f0cb2145e4a1350e543 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Wed, 12 Mar 2025 12:51:03 +0300
Subject: [PATCH 4/6] [Xtensa] Fix XtensaFrameLowering implementation.

---
 llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 33c57e504b363..3ff30f05ad780 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -72,8 +72,6 @@ void XtensaFrameLowering::emitPrologue(MachineFunction &MF,
       // Use a8 as a temporary since a0-a7 may be live.
       MCRegister TmpReg = Xtensa::A8;
 
-      const XtensaInstrInfo &TII = *static_cast<const XtensaInstrInfo *>(
-          MBB.getParent()->getSubtarget().getInstrInfo());
       BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))
           .addReg(SP)
           .addImm(MIN_FRAME_SIZE);
@@ -334,9 +332,6 @@ bool XtensaFrameLowering::restoreCalleeSavedRegisters(
 MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
     MachineFunction &MF, MachineBasicBlock &MBB,
     MachineBasicBlock::iterator I) const {
-  const XtensaInstrInfo &TII =
-      *static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo());
-
   if (!hasReservedCallFrame(MF)) {
     int64_t Amount = I->getOperand(0).getImm();
 

>From 5d43d83375cc08690622af53c1b77e33abb796bb Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Sat, 15 Mar 2025 16:56:20 +0300
Subject: [PATCH 5/6] [Xtensa] Implement Windowed ABI for STACKRESTORE.

---
 llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp |  2 +-
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp  | 14 ++++++++++----
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
index 3ff30f05ad780..cf9a2a052978d 100644
--- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp
@@ -347,7 +347,7 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(
 void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,
                                                BitVector &SavedRegs,
                                                RegScavenger *RS) const {
-  unsigned FP = TRI->getFrameRegister(MF);
+  MCRegister FP = TRI->getFrameRegister(MF);
 
   if (STI.isWindowedABI()) {
     return;
diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index c4aa513d9ca40..93cb7a679be06 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -895,8 +895,14 @@ SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op,
 
 SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op,
                                                 SelectionDAG &DAG) const {
-  return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP,
-                          Op.getOperand(1));
+  if (Subtarget.isWindowedABI()) {
+    SDValue NewSP =
+        DAG.getNode(XtensaISD::MOVSP, SDLoc(Op), MVT::i32, Op.getOperand(1));
+    return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP, NewSP);
+  } else {
+    return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP,
+                            Op.getOperand(1));
+  }
 }
 
 SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op,
@@ -915,7 +921,7 @@ SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op,
   EVT VT = Op.getValueType();
   SDLoc DL(Op);
 
-  Register FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF);
+  MCRegister FrameRegister = Subtarget.getRegisterInfo()->getFrameRegister(MF);
   SDValue FrameAddr =
       DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameRegister, VT);
   return FrameAddr;
@@ -934,7 +940,7 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
   SDValue SizeRoundUp = DAG.getNode(ISD::AND, DL, VT, SizeTmp,
                                     DAG.getSignedConstant(~31, DL, MVT::i32));
 
-  unsigned SPReg = Xtensa::SP;
+  MCRegister SPReg = Xtensa::SP;
   SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
   SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value
   if (Subtarget.isWindowedABI()) {

>From 5bbdb8a67ae4cf978cd45297b85090bea1f0b8f4 Mon Sep 17 00:00:00 2001
From: Andrei Safronov <safronov at espressif.com>
Date: Tue, 18 Mar 2025 11:56:50 +0300
Subject: [PATCH 6/6] [Xtensa] Add test for STACKRESTORE. Fix SP update.

Implemented MOVSP_P pseudo operation for SP register update in
STACKRESTORE and DYNAMIC_STACKALLOC lowerinng.
---
 llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 30 +++++--
 llvm/lib/Target/Xtensa/XtensaInstrInfo.td     | 11 ++-
 llvm/lib/Target/Xtensa/XtensaOperators.td     |  4 +-
 llvm/test/CodeGen/Xtensa/saverestore.ll       | 84 +++++++++++++------
 4 files changed, 89 insertions(+), 40 deletions(-)

diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
index 93cb7a679be06..93837ca321e08 100644
--- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
+++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp
@@ -895,14 +895,16 @@ SDValue XtensaTargetLowering::LowerSTACKSAVE(SDValue Op,
 
 SDValue XtensaTargetLowering::LowerSTACKRESTORE(SDValue Op,
                                                 SelectionDAG &DAG) const {
+  SDValue Chain = Op.getOperand(0);
+  SDValue NewSP = Op.getOperand(1);
+
   if (Subtarget.isWindowedABI()) {
-    SDValue NewSP =
-        DAG.getNode(XtensaISD::MOVSP, SDLoc(Op), MVT::i32, Op.getOperand(1));
-    return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP, NewSP);
-  } else {
-    return DAG.getCopyToReg(Op.getOperand(0), SDLoc(Op), Xtensa::SP,
-                            Op.getOperand(1));
+    return DAG.getNode(XtensaISD::MOVSP, SDLoc(Op), MVT::Other, Chain,
+                       DAG.getRegister(Xtensa::SP, NewSP.getValueType()),
+                       NewSP);
   }
+
+  return DAG.getCopyToReg(Chain, SDLoc(Op), Xtensa::SP, NewSP);
 }
 
 SDValue XtensaTargetLowering::LowerFRAMEADDR(SDValue Op,
@@ -944,9 +946,11 @@ SDValue XtensaTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
   SDValue SP = DAG.getCopyFromReg(Chain, DL, SPReg, VT);
   SDValue NewSP = DAG.getNode(ISD::SUB, DL, VT, SP, SizeRoundUp); // Value
   if (Subtarget.isWindowedABI()) {
-    NewSP = DAG.getNode(XtensaISD::MOVSP, DL, MVT::i32, NewSP);
+    Chain = DAG.getNode(XtensaISD::MOVSP, SDLoc(Op), MVT::Other, SP.getValue(1),
+                        DAG.getRegister(SPReg, NewSP.getValueType()), NewSP);
+  } else {
+    Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain
   }
-  Chain = DAG.getCopyToReg(SP.getValue(1), DL, SPReg, NewSP); // Output chain
 
   SDValue NewVal = DAG.getCopyFromReg(Chain, DL, SPReg, MVT::i32);
   Chain = NewVal.getValue(1);
@@ -1385,6 +1389,16 @@ MachineBasicBlock *XtensaTargetLowering::EmitInstrWithCustomInserter(
     }
     return MBB;
   }
+  case Xtensa::MOVSP_P: {
+    MachineOperand SP = MI.getOperand(0);
+    MachineOperand NewSP = MI.getOperand(1);
+
+    BuildMI(*MBB, MI, DL, TII.get(Xtensa::MOVSP), SP.getReg())
+        .addReg(NewSP.getReg());
+    MI.eraseFromParent();
+
+    return MBB;
+  }
   default:
     llvm_unreachable("Unexpected instr type to insert");
   }
diff --git a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
index b41c00738f763..631cf4bd73a6c 100644
--- a/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
+++ b/llvm/lib/Target/Xtensa/XtensaInstrInfo.td
@@ -719,12 +719,17 @@ def : Pat<(Xtensa_callw8 AR:$dst),
           (CALLX8 AR:$dst)>;
 
 def MOVSP : RRR_Inst<0x00, 0x00, 0x00, (outs AR:$t), (ins AR:$s),
-                    "movsp\t$t, $s",
-                    [(set AR:$t, (Xtensa_movsp AR:$s))]>,
-                    Requires<[HasWindowed]> {
+                    "movsp\t$t, $s", []>, Requires<[HasWindowed]> {
   let r = 0x01;
 }
 
+// Use this pseudo operation instead of getCopyToReg function to
+// update SP register.
+let usesCustomInserter = 1, Predicates = [HasWindowed] in {
+  def MOVSP_P : Pseudo<(outs), (ins AR:$t, AR:$s),
+                      "!movsp_p\t$t, $s", [(Xtensa_movsp AR:$t, AR:$s)]>;
+}
+
 let isReturn = 1, isTerminator = 1,
     isBarrier = 1, Uses = [A0] in {
   def RETW_N : RRRN_Inst<0x0D, (outs), (ins),
diff --git a/llvm/lib/Target/Xtensa/XtensaOperators.td b/llvm/lib/Target/Xtensa/XtensaOperators.td
index 1fe5c3f64b607..1e92d90d191e2 100644
--- a/llvm/lib/Target/Xtensa/XtensaOperators.td
+++ b/llvm/lib/Target/Xtensa/XtensaOperators.td
@@ -31,7 +31,7 @@ def SDT_XtensaSRC                 : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCi
 def SDT_XtensaEXTUI               : SDTypeProfile<1, 3, [SDTCisVT<0, i32>, SDTCisVT<1, i32>,
                                                          SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
 
-def SDT_XtensaMOVSP               : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisVT<0, i32>]>;
+def SDT_XtensaMOVSP               : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>, SDTCisVT<0, i32>]>;
 
 //===----------------------------------------------------------------------===//
 // Node definitions
@@ -69,4 +69,4 @@ def Xtensa_srcr: SDNode<"XtensaISD::SRCR", SDT_XtensaSRC>;
 def Xtensa_extui: SDNode<"XtensaISD::EXTUI", SDT_XtensaEXTUI>;
 
 def Xtensa_movsp: SDNode<"XtensaISD::MOVSP", SDT_XtensaMOVSP,
-                        [SDNPInGlue]>;
+                        [SDNPHasChain, SDNPSideEffect, SDNPInGlue]>;
diff --git a/llvm/test/CodeGen/Xtensa/saverestore.ll b/llvm/test/CodeGen/Xtensa/saverestore.ll
index 69c8b16ab601d..82c0dab1a680a 100644
--- a/llvm/test/CodeGen/Xtensa/saverestore.ll
+++ b/llvm/test/CodeGen/Xtensa/saverestore.ll
@@ -1,4 +1,6 @@
-; RUN: llc --mtriple=xtensa < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=xtensa < %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc --mtriple=xtensa --mattr=+windowed < %s | FileCheck -check-prefixes=CHECK-WINDOWED %s
 
 declare ptr @llvm.stacksave()
 
@@ -7,32 +9,60 @@ 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
+; CHECK-LABEL: test_saverestore:
+; CHECK:         .cfi_startproc
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    addi a8, a1, -16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    s32i a0, a1, 8 # 4-byte Folded Spill
+; CHECK-NEXT:    s32i a12, a1, 4 # 4-byte Folded Spill
+; CHECK-NEXT:    s32i a15, a1, 0 # 4-byte Folded Spill
+; CHECK-NEXT:    .cfi_offset a0, -4
+; CHECK-NEXT:    .cfi_offset a12, -8
+; CHECK-NEXT:    .cfi_offset a15, -12
+; CHECK-NEXT:    or a15, a1, a1
+; CHECK-NEXT:    .cfi_def_cfa_register a15
+; CHECK-NEXT:    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 # 4-byte Folded Reload
+; CHECK-NEXT:    l32i a12, a1, 4 # 4-byte Folded Reload
+; CHECK-NEXT:    l32i a0, a1, 8 # 4-byte Folded Reload
+; CHECK-NEXT:    addi a8, a1, 16
+; CHECK-NEXT:    or a1, a8, a8
+; CHECK-NEXT:    ret
+;
+; CHECK-WINDOWED-LABEL: test_saverestore:
+; CHECK-WINDOWED:         .cfi_startproc
+; CHECK-WINDOWED-NEXT:  # %bb.0:
+; CHECK-WINDOWED-NEXT:    entry a1, 32
+; CHECK-WINDOWED-NEXT:    or a7, a1, a1
+; CHECK-WINDOWED-NEXT:    .cfi_def_cfa a7, 32
+; CHECK-WINDOWED-NEXT:    addi a8, a2, 3
+; CHECK-WINDOWED-NEXT:    movi a9, -4
+; CHECK-WINDOWED-NEXT:    and a8, a8, a9
+; CHECK-WINDOWED-NEXT:    addi a8, a8, 31
+; CHECK-WINDOWED-NEXT:    movi a9, -32
+; CHECK-WINDOWED-NEXT:    and a8, a8, a9
+; CHECK-WINDOWED-NEXT:    or a6, a1, a1
+; CHECK-WINDOWED-NEXT:    sub a8, a1, a8
+; CHECK-WINDOWED-NEXT:    movsp a1, a8
+; CHECK-WINDOWED-NEXT:    or a10, a1, a1
+; CHECK-WINDOWED-NEXT:    l32r a8, .LCPI0_0
+; CHECK-WINDOWED-NEXT:    callx8 a8
+; CHECK-WINDOWED-NEXT:    movsp a1, a6
+; CHECK-WINDOWED-NEXT:    retw
 
   %sp = call ptr @llvm.stacksave.p0()
   %addr = alloca i8, i64 %n



More information about the llvm-commits mailing list