From 78c9f32964445e4e80aa12e86468a4fa447c5c6b Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Wed, 22 May 2024 13:33:24 +0300 Subject: [PATCH 1/6] [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( + MF.getSubtarget().getRegisterInfo()); + const XtensaInstrInfo &TII = + *static_cast(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 &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( + MF.getSubtarget().getRegisterInfo()); + const XtensaInstrInfo &TII = + *static_cast(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 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 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( + 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 CSI, + const TargetRegisterInfo *TRI) const override; + bool + restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + MutableArrayRef 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(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 Date: Tue, 28 May 2024 02:37:00 +0300 Subject: [PATCH 2/6] [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( - MF.getSubtarget().getRegisterInfo()); - const XtensaInstrInfo &TII = - *static_cast(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( - MF.getSubtarget().getRegisterInfo()); - const XtensaInstrInfo &TII = - *static_cast(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 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( - 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 Date: Wed, 29 May 2024 02:20:29 +0300 Subject: [PATCH 3/6] [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 &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 &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 &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 &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 Date: Thu, 30 May 2024 11:17:57 +0300 Subject: [PATCH 4/6] [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 &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 &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 Date: Thu, 30 May 2024 16:51:24 +0300 Subject: [PATCH 5/6] [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. From 7a15a9927cc1fe841663470fe0797faec120d30d Mon Sep 17 00:00:00 2001 From: Andrei Safronov Date: Thu, 30 May 2024 19:20:29 +0300 Subject: [PATCH 6/6] [PATCH] [Xtensa] Fix compile warnings anf variable name typo. --- .../lib/Target/Xtensa/XtensaFrameLowering.cpp | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp index 9f97f3aaed31d..71b1bb674ca78 100644 --- a/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaFrameLowering.cpp @@ -72,14 +72,15 @@ 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 (const auto &Info : CSI) { + for (unsigned i = 0, e = CSI.size(); i < e; ++i) { +#ifndef NDEBUG + const CalleeSavedInfo &Info = CSI[i]; 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()) { + 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); @@ -155,23 +156,24 @@ void XtensaFrameLowering::emitEpilogue(MachineFunction &MF, // Find the first instruction at the end that restores a callee-saved // register. - for (const auto &Info : CSI) { + for (unsigned i = 0, e = CSI.size(); i < e; ++i) { + --I; +#ifndef NDEBUG + const CalleeSavedInfo &Info = CSI[i]; int FI = Info.getFrameIdx(); int LoadFI = 0; - --I; -#ifndef NDEBUG // Checking that the instruction is exactly as expected - bool IsRestoreInstr = false; - if ((I->getOpcode() == TargetOpcode::COPY) && Info.isSpilledToReg()) { + bool IsRestoreInst = false; + 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); + IsRestoreInst = (Info.getDstReg() == DstReg) && (Info.getReg() == Reg); } else { Register Reg = TII.isLoadFromStackSlot(*I, LoadFI); IsRestoreInst = (Info.getReg() == Reg) && (LoadFI == FI); } - assert(IsRestoreInstr && + assert(IsRestoreInst && "Unexpected callee-saved register restore instruction"); #endif }