brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.1 KiB · 1c0dc66 Raw
391 lines · cpp
1//===- XtensaFrameLowering.cpp - Xtensa Frame Information -----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Xtensa implementation of TargetFrameLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "XtensaFrameLowering.h"14#include "XtensaInstrInfo.h"15#include "XtensaMachineFunctionInfo.h"16#include "XtensaSubtarget.h"17#include "llvm/CodeGen/MachineFrameInfo.h"18#include "llvm/CodeGen/MachineInstrBuilder.h"19#include "llvm/CodeGen/MachineModuleInfo.h"20#include "llvm/CodeGen/MachineRegisterInfo.h"21#include "llvm/CodeGen/RegisterScavenging.h"22#include "llvm/IR/Function.h"23 24using namespace llvm;25 26// Minimum frame = reg save area (4 words) plus static chain (1 word)27// and the total number of words must be a multiple of 128 bits.28// Width of a word, in units (bytes).29#define UNITS_PER_WORD 430#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)31 32XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI)33    : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0,34                          Align(4)),35      STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}36 37bool XtensaFrameLowering::hasFPImpl(const MachineFunction &MF) const {38  const MachineFrameInfo &MFI = MF.getFrameInfo();39  return MF.getTarget().Options.DisableFramePointerElim(MF) ||40         MFI.hasVarSizedObjects();41}42 43void XtensaFrameLowering::emitPrologue(MachineFunction &MF,44                                       MachineBasicBlock &MBB) const {45  assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented");46  MachineFrameInfo &MFI = MF.getFrameInfo();47  MachineBasicBlock::iterator MBBI = MBB.begin();48  DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();49  MCRegister SP = Xtensa::SP;50  MCRegister FP = TRI->getFrameRegister(MF);51  const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();52  XtensaMachineFunctionInfo *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();53 54  // First, compute final stack size.55  uint64_t StackSize = MFI.getStackSize();56  uint64_t PrevStackSize = StackSize;57 58  // Round up StackSize to 16*N59  StackSize += (16 - StackSize) & 0xf;60 61  if (STI.isWindowedABI()) {62    StackSize += 32;63    uint64_t MaxAlignment = MFI.getMaxAlign().value();64    if (MaxAlignment > 32)65      StackSize += MaxAlignment;66 67    if (StackSize <= 32760) {68      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))69          .addReg(SP)70          .addImm(StackSize);71    } else {72      // Use a8 as a temporary since a0-a7 may be live.73      MCRegister TmpReg = Xtensa::A8;74 75      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ENTRY))76          .addReg(SP)77          .addImm(MIN_FRAME_SIZE);78      TII.loadImmediate(MBB, MBBI, &TmpReg, StackSize - MIN_FRAME_SIZE);79      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), TmpReg)80          .addReg(SP)81          .addReg(TmpReg);82      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::MOVSP), SP).addReg(TmpReg);83    }84 85    // Calculate how much is needed to have the correct alignment.86    // Change offset to: alignment + difference.87    // For example, in case of alignment of 128:88    // diff_to_128_aligned_address = (128 - (SP & 127))89    // new_offset = SP + diff_to_128_aligned_address90    // This is safe to do because we increased the stack size by MaxAlignment.91    MCRegister Reg, RegMisAlign;92    if (MaxAlignment > 32) {93      TII.loadImmediate(MBB, MBBI, &RegMisAlign, MaxAlignment - 1);94      TII.loadImmediate(MBB, MBBI, &Reg, MaxAlignment);95      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::AND))96          .addReg(RegMisAlign, RegState::Define)97          .addReg(FP)98          .addReg(RegMisAlign);99      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::SUB), RegMisAlign)100          .addReg(Reg)101          .addReg(RegMisAlign);102      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::ADD), SP)103          .addReg(SP)104          .addReg(RegMisAlign, RegState::Kill);105    }106 107    // Store FP register in A8, because FP may be used to pass function108    // arguments109    if (XtensaFI->isSaveFrameRegister()) {110      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), Xtensa::A8)111          .addReg(FP)112          .addReg(FP);113    }114 115    // if framepointer enabled, set it to point to the stack pointer.116    if (hasFP(MF)) {117      // Insert instruction "move $fp, $sp" at this location.118      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)119          .addReg(SP)120          .addReg(SP)121          .setMIFlag(MachineInstr::FrameSetup);122 123      MCCFIInstruction Inst = MCCFIInstruction::cfiDefCfa(124          nullptr, MRI->getDwarfRegNum(FP, true), StackSize);125      unsigned CFIIndex = MF.addFrameInst(Inst);126      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))127          .addCFIIndex(CFIIndex);128    } else {129      // emit ".cfi_def_cfa_offset StackSize"130      unsigned CFIIndex = MF.addFrameInst(131          MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));132      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))133          .addCFIIndex(CFIIndex);134    }135  } else {136    // No need to allocate space on the stack.137    if (StackSize == 0 && !MFI.adjustsStack())138      return;139 140    // Adjust stack.141    TII.adjustStackPtr(SP, -StackSize, MBB, MBBI);142 143    // emit ".cfi_def_cfa_offset StackSize"144    unsigned CFIIndex =145        MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize));146    BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))147        .addCFIIndex(CFIIndex);148 149    const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();150 151    if (!CSI.empty()) {152      // Find the instruction past the last instruction that saves a153      // callee-saved register to the stack. The callee-saved store154      // instructions are placed at the begin of basic block, so155      //  iterate over instruction sequence and check that156      // save instructions are placed correctly.157      for (unsigned i = 0, e = CSI.size(); i < e; ++i) {158#ifndef NDEBUG159        const CalleeSavedInfo &Info = CSI[i];160        int FI = Info.getFrameIdx();161        int StoreFI = 0;162 163        // Checking that the instruction is exactly as expected164        bool IsStoreInst = false;165        if (MBBI->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {166          Register DstReg = MBBI->getOperand(0).getReg();167          Register Reg = MBBI->getOperand(1).getReg();168          IsStoreInst = Info.getDstReg() == DstReg.asMCReg() &&169                        Info.getReg() == Reg.asMCReg();170        } else {171          Register Reg = TII.isStoreToStackSlot(*MBBI, StoreFI);172          IsStoreInst = Reg.asMCReg() == Info.getReg() && StoreFI == FI;173        }174        assert(IsStoreInst &&175               "Unexpected callee-saved register store instruction");176#endif177        ++MBBI;178      }179 180      // Iterate over list of callee-saved registers and emit .cfi_offset181      // directives.182      for (const auto &I : CSI) {183        int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());184        MCRegister Reg = I.getReg();185 186        unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(187            nullptr, MRI->getDwarfRegNum(Reg, 1), Offset));188        BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))189            .addCFIIndex(CFIIndex);190      }191    }192 193    // if framepointer enabled, set it to point to the stack pointer.194    if (hasFP(MF)) {195      // Insert instruction "move $fp, $sp" at this location.196      BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP)197          .addReg(SP)198          .addReg(SP)199          .setMIFlag(MachineInstr::FrameSetup);200 201      // emit ".cfi_def_cfa_register $fp"202      unsigned CFIIndex =203          MF.addFrameInst(MCCFIInstruction::createDefCfaRegister(204              nullptr, MRI->getDwarfRegNum(FP, true)));205      BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))206          .addCFIIndex(CFIIndex);207    }208  }209 210  if (StackSize != PrevStackSize) {211    MFI.setStackSize(StackSize);212 213    for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) {214      if (!MFI.isDeadObjectIndex(i)) {215        int64_t SPOffset = MFI.getObjectOffset(i);216 217        if (SPOffset < 0)218          MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize);219      }220    }221  }222}223 224void XtensaFrameLowering::emitEpilogue(MachineFunction &MF,225                                       MachineBasicBlock &MBB) const {226  MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();227  MachineFrameInfo &MFI = MF.getFrameInfo();228  DebugLoc DL = MBBI->getDebugLoc();229  MCRegister SP = Xtensa::SP;230  MCRegister FP = TRI->getFrameRegister(MF);231 232  // if framepointer enabled, restore the stack pointer.233  if (hasFP(MF)) {234    // We should place restore stack pointer instruction just before235    // sequence of instructions which restores callee-saved registers.236    // This sequence is placed at the end of the basic block,237    // so we should find first instruction of the sequence.238    MachineBasicBlock::iterator I = MBBI;239 240    const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();241 242    // Find the first instruction at the end that restores a callee-saved243    // register.244    for (unsigned i = 0, e = CSI.size(); i < e; ++i) {245      --I;246#ifndef NDEBUG247      const CalleeSavedInfo &Info = CSI[i];248      int FI = Info.getFrameIdx();249      int LoadFI = 0;250 251      // Checking that the instruction is exactly as expected252      bool IsRestoreInst = false;253      if (I->getOpcode() == TargetOpcode::COPY && Info.isSpilledToReg()) {254        Register Reg = I->getOperand(0).getReg();255        Register DstReg = I->getOperand(1).getReg();256        IsRestoreInst = Info.getDstReg() == DstReg.asMCReg() &&257                        Info.getReg() == Reg.asMCReg();258      } else {259        Register Reg = TII.isLoadFromStackSlot(*I, LoadFI);260        IsRestoreInst = Info.getReg() == Reg.asMCReg() && LoadFI == FI;261      }262      assert(IsRestoreInst &&263             "Unexpected callee-saved register restore instruction");264#endif265    }266    if (STI.isWindowedABI()) {267      // In most architectures, we need to explicitly restore the stack pointer268      // before returning.269      //270      // For Xtensa Windowed Register option, it is not needed to explicitly271      // restore the stack pointer. Reason being is that on function return,272      // the window of the caller (including the old stack pointer) gets273      // restored anyways.274    } else {275      BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP);276    }277  }278 279  if (STI.isWindowedABI())280    return;281 282  // Get the number of bytes from FrameInfo283  uint64_t StackSize = MFI.getStackSize();284 285  if (!StackSize)286    return;287 288  // Adjust stack.289  TII.adjustStackPtr(SP, StackSize, MBB, MBBI);290}291 292bool XtensaFrameLowering::spillCalleeSavedRegisters(293    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,294    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {295  MachineFunction *MF = MBB.getParent();296  MachineBasicBlock &EntryBlock = *(MF->begin());297 298  if (STI.isWindowedABI())299    return true;300 301  for (unsigned i = 0, e = CSI.size(); i != e; ++i) {302    // Add the callee-saved register as live-in. Do not add if the register is303    // A0 and return address is taken, because it will be implemented in304    // method XtensaTargetLowering::LowerRETURNADDR.305    // It's killed at the spill, unless the register is RA and return address306    // is taken.307    MCRegister Reg = CSI[i].getReg();308    bool IsA0AndRetAddrIsTaken =309        (Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken();310    if (!IsA0AndRetAddrIsTaken)311      EntryBlock.addLiveIn(Reg);312 313    // Insert the spill to the stack frame.314    bool IsKill = !IsA0AndRetAddrIsTaken;315    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);316    TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(),317                            RC, Register());318  }319 320  return true;321}322 323bool XtensaFrameLowering::restoreCalleeSavedRegisters(324    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,325    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {326  if (STI.isWindowedABI())327    return true;328  return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI);329}330 331// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions332MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr(333    MachineFunction &MF, MachineBasicBlock &MBB,334    MachineBasicBlock::iterator I) const {335  if (!hasReservedCallFrame(MF)) {336    int64_t Amount = I->getOperand(0).getImm();337 338    if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN)339      Amount = -Amount;340 341    TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I);342  }343 344  return MBB.erase(I);345}346 347void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF,348                                               BitVector &SavedRegs,349                                               RegScavenger *RS) const {350  MCRegister FP = TRI->getFrameRegister(MF);351 352  if (STI.isWindowedABI()) {353    return;354  }355 356  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);357 358  // Mark $fp as used if function has dedicated frame pointer.359  if (hasFP(MF))360    SavedRegs.set(FP);361}362 363void XtensaFrameLowering::processFunctionBeforeFrameFinalized(364    MachineFunction &MF, RegScavenger *RS) const {365  // Set scavenging frame index if necessary.366  MachineFrameInfo &MFI = MF.getFrameInfo();367  uint64_t MaxSPOffset = MFI.estimateStackSize(MF);368  auto *XtensaFI = MF.getInfo<XtensaMachineFunctionInfo>();369  unsigned ScavSlotsNum = 0;370 371  if (!isInt<12>(MaxSPOffset))372    ScavSlotsNum = 1;373 374  // Far branches over 18-bit offset require a spill slot for scratch register.375  bool IsLargeFunction = !isInt<18>(MF.estimateFunctionSizeInBytes());376  if (IsLargeFunction)377    ScavSlotsNum = std::max(ScavSlotsNum, 1u);378 379  const TargetRegisterClass &RC = Xtensa::ARRegClass;380  unsigned Size = TRI->getSpillSize(RC);381  Align Alignment = TRI->getSpillAlign(RC);382  for (unsigned I = 0; I < ScavSlotsNum; I++) {383    int FI = MFI.CreateSpillStackObject(Size, Alignment);384    RS->addScavengingFrameIndex(FI);385 386    if (IsLargeFunction &&387        XtensaFI->getBranchRelaxationScratchFrameIndex() == -1)388      XtensaFI->setBranchRelaxationScratchFrameIndex(FI);389  }390}391