brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.9 KiB · 9f6a79e Raw
498 lines · cpp
1//===- ARCFrameLowering.cpp - ARC Frame Information -------------*- C++ -*-===//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 ARC implementation of the TargetFrameLowering class.10//11//===----------------------------------------------------------------------===//12 13#include "ARCFrameLowering.h"14#include "ARCMachineFunctionInfo.h"15#include "ARCSubtarget.h"16#include "llvm/CodeGen/MachineInstrBuilder.h"17#include "llvm/CodeGen/MachineModuleInfo.h"18#include "llvm/CodeGen/RegisterScavenging.h"19#include "llvm/CodeGen/TargetRegisterInfo.h"20#include "llvm/IR/Function.h"21#include "llvm/Support/Debug.h"22 23#define DEBUG_TYPE "arc-frame-lowering"24 25using namespace llvm;26 27static cl::opt<bool>28    UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,29                          cl::desc("Use arc callee save/restore functions"),30                          cl::init(true));31 32static const char *store_funclet_name[] = {33    "__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",34    "__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",35    "__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",36};37 38static const char *load_funclet_name[] = {39    "__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",40    "__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",41    "__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",42};43 44static void generateStackAdjustment(MachineBasicBlock &MBB,45                                    MachineBasicBlock::iterator MBBI,46                                    const ARCInstrInfo &TII, DebugLoc dl,47                                    int Amount, int StackPtr) {48  unsigned AdjOp;49  if (!Amount)50    return;51  bool Positive;52  unsigned AbsAmount;53  if (Amount < 0) {54    AbsAmount = -Amount;55    Positive = false;56  } else {57    AbsAmount = Amount;58    Positive = true;59  }60 61  LLVM_DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << ","62                    << AbsAmount << "\n");63 64  assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");65  if (isUInt<6>(AbsAmount))66    AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;67  else if (isInt<12>(AbsAmount))68    AdjOp = Positive ? ARC::ADD_rrs12 : ARC::SUB_rrs12;69  else70    AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;71 72  BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)73      .addReg(StackPtr)74      .addImm(AbsAmount);75}76 77static unsigned determineLastCalleeSave(ArrayRef<CalleeSavedInfo> CSI) {78  unsigned Last = 0;79  for (auto Reg : CSI) {80    assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&81           "Unexpected callee saved reg.");82    if (Reg.getReg() > Last)83      Last = Reg.getReg();84  }85  return Last;86}87 88void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF,89                                            BitVector &SavedRegs,90                                            RegScavenger *RS) const {91  LLVM_DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName() << "\n");92  TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);93  SavedRegs.set(ARC::BLINK);94}95 96void ARCFrameLowering::adjustStackToMatchRecords(97    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,98    bool Allocate) const {99  MachineFunction &MF = *MBB.getParent();100  int ScalarAlloc = MF.getFrameInfo().getStackSize();101 102  if (Allocate) {103    // Allocate by adjusting by the negative of what the record holder tracked104    // it tracked a positive offset in a downward growing stack.105    ScalarAlloc = -ScalarAlloc;106  }107 108  generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),109                          ScalarAlloc, ARC::SP);110}111 112/// Insert prolog code into the function.113/// For ARC, this inserts a call to a function that puts required callee saved114/// registers onto the stack, when enough callee saved registers are required.115void ARCFrameLowering::emitPrologue(MachineFunction &MF,116                                    MachineBasicBlock &MBB) const {117  LLVM_DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n");118  auto *AFI = MF.getInfo<ARCFunctionInfo>();119  MCContext &Context = MF.getContext();120  const MCRegisterInfo *MRI = Context.getRegisterInfo();121  const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();122  MachineBasicBlock::iterator MBBI = MBB.begin();123  // Debug location must be unknown since the first debug location is used124  // to determine the end of the prologue.125  DebugLoc dl;126  MachineFrameInfo &MFI = MF.getFrameInfo();127  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();128  unsigned Last = determineLastCalleeSave(CSI);129  unsigned StackSlotsUsedByFunclet = 0;130  bool SavedBlink = false;131  unsigned AlreadyAdjusted = 0;132  if (MF.getFunction().isVarArg()) {133    // Add in the varargs area here first.134    LLVM_DEBUG(dbgs() << "Varargs\n");135    unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());136    unsigned Opc = ARC::SUB_rrlimm;137    if (isUInt<6>(VarArgsBytes))138      Opc = ARC::SUB_rru6;139    else if (isInt<12>(VarArgsBytes))140      Opc = ARC::SUB_rrs12;141    BuildMI(MBB, MBBI, dl, TII->get(Opc), ARC::SP)142        .addReg(ARC::SP)143        .addImm(VarArgsBytes);144  }145  if (hasFP(MF)) {146    LLVM_DEBUG(dbgs() << "Saving FP\n");147    BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))148        .addReg(ARC::SP, RegState::Define)149        .addReg(ARC::FP)150        .addReg(ARC::SP)151        .addImm(-4);152    AlreadyAdjusted += 4;153  }154  if (UseSaveRestoreFunclet && Last > ARC::R14) {155    LLVM_DEBUG(dbgs() << "Creating store funclet.\n");156    // BL to __save_r13_to_<TRI->getRegAsmName()>157    StackSlotsUsedByFunclet = Last - ARC::R12;158    BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));159    BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))160        .addReg(ARC::SP)161        .addReg(ARC::SP)162        .addImm(4 * StackSlotsUsedByFunclet);163    BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))164        .addExternalSymbol(store_funclet_name[Last - ARC::R15])165        .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);166    AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);167    SavedBlink = true;168  }169  // If we haven't saved BLINK, but we need to...do that now.170  if (MFI.hasCalls() && !SavedBlink) {171    LLVM_DEBUG(dbgs() << "Creating save blink.\n");172    BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));173    AlreadyAdjusted += 4;174  }175  if (AFI->MaxCallStackReq > 0)176    MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);177  // We have already saved some of the stack...178  LLVM_DEBUG(dbgs() << "Adjusting stack by: "179                    << (MFI.getStackSize() - AlreadyAdjusted) << "\n");180  generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,181                          -(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);182 183  if (hasFP(MF)) {184    LLVM_DEBUG(dbgs() << "Setting FP from SP.\n");185    BuildMI(MBB, MBBI, dl,186            TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6187                                                   : ARC::ADD_rrlimm),188            ARC::FP)189        .addReg(ARC::SP)190        .addImm(MFI.getStackSize());191  }192 193  // Emit CFI records:194  // .cfi_def_cfa_offset StackSize195  // .cfi_offset fp, -StackSize196  // .cfi_offset blink, -StackSize+4197  unsigned CFIIndex = MF.addFrameInst(198      MCCFIInstruction::cfiDefCfaOffset(nullptr, MFI.getStackSize()));199  BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))200      .addCFIIndex(CFIIndex)201      .setMIFlags(MachineInstr::FrameSetup);202 203  int CurOffset = -4;204  if (hasFP(MF)) {205    CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(206        nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));207    BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))208        .addCFIIndex(CFIIndex)209        .setMIFlags(MachineInstr::FrameSetup);210    CurOffset -= 4;211  }212 213  if (MFI.hasCalls()) {214    CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(215        nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));216    BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))217        .addCFIIndex(CFIIndex)218        .setMIFlags(MachineInstr::FrameSetup);219  }220  // CFI for the rest of the registers.221  for (const auto &Entry : CSI) {222    MCRegister Reg = Entry.getReg();223    int FI = Entry.getFrameIdx();224    // Skip BLINK and FP.225    if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))226      continue;227    CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(228        nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));229    BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))230        .addCFIIndex(CFIIndex)231        .setMIFlags(MachineInstr::FrameSetup);232  }233}234 235/// Insert epilog code into the function.236/// For ARC, this inserts a call to a function that restores callee saved237/// registers onto the stack, when enough callee saved registers are required.238void ARCFrameLowering::emitEpilogue(MachineFunction &MF,239                                    MachineBasicBlock &MBB) const {240  LLVM_DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n");241  auto *AFI = MF.getInfo<ARCFunctionInfo>();242  const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();243  MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();244  MachineFrameInfo &MFI = MF.getFrameInfo();245  uint64_t StackSize = MF.getFrameInfo().getStackSize();246  bool SavedBlink = false;247  unsigned AmountAboveFunclet = 0;248  // If we have variable sized frame objects, then we have to move249  // the stack pointer to a known spot (fp - StackSize).250  // Then, replace the frame pointer by (new) [sp,StackSize-4].251  // Then, move the stack pointer the rest of the way (sp = sp + StackSize).252  if (hasFP(MF)) {253    unsigned Opc = ARC::SUB_rrlimm;254    if (isUInt<6>(StackSize))255      Opc = ARC::SUB_rru6;256    BuildMI(MBB, MBBI, DebugLoc(), TII->get(Opc), ARC::SP)257        .addReg(ARC::FP)258        .addImm(StackSize);259    AmountAboveFunclet += 4;260  }261 262  // Now, move the stack pointer to the bottom of the save area for the funclet.263  const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();264  unsigned Last = determineLastCalleeSave(CSI);265  unsigned StackSlotsUsedByFunclet = 0;266  // Now, restore the callee save registers.267  if (UseSaveRestoreFunclet && Last > ARC::R14) {268    // BL to __ld_r13_to_<TRI->getRegAsmName()>269    StackSlotsUsedByFunclet = Last - ARC::R12;270    AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);271    SavedBlink = true;272  }273 274  if (MFI.hasCalls() && !SavedBlink) {275    AmountAboveFunclet += 4;276    SavedBlink = true;277  }278 279  // Move the stack pointer up to the point of the funclet.280  if (unsigned MoveAmount = StackSize - AmountAboveFunclet) {281    unsigned Opc = ARC::ADD_rrlimm;282    if (isUInt<6>(MoveAmount))283      Opc = ARC::ADD_rru6;284    else if (isInt<12>(MoveAmount))285      Opc = ARC::ADD_rrs12;286    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP)287        .addReg(ARC::SP)288        .addImm(StackSize - AmountAboveFunclet);289  }290 291  if (StackSlotsUsedByFunclet) {292    // This part of the adjustment will always be < 64 bytes.293    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))294        .addExternalSymbol(load_funclet_name[Last - ARC::R15])295        .addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);296    unsigned Opc = ARC::ADD_rrlimm;297    if (isUInt<6>(4 * StackSlotsUsedByFunclet))298      Opc = ARC::ADD_rru6;299    else if (isInt<12>(4 * StackSlotsUsedByFunclet))300      Opc = ARC::ADD_rrs12;301    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc), ARC::SP)302        .addReg(ARC::SP)303        .addImm(4 * (StackSlotsUsedByFunclet));304  }305  // Now, pop blink if necessary.306  if (SavedBlink) {307    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));308  }309  // Now, pop fp if necessary.310  if (hasFP(MF)) {311    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))312        .addReg(ARC::FP, RegState::Define)313        .addReg(ARC::SP, RegState::Define)314        .addReg(ARC::SP)315        .addImm(4);316  }317 318  // Relieve the varargs area if necessary.319  if (MF.getFunction().isVarArg()) {320    // Add in the varargs area here first.321    LLVM_DEBUG(dbgs() << "Varargs\n");322    unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());323    unsigned Opc = ARC::ADD_rrlimm;324    if (isUInt<6>(VarArgsBytes))325      Opc = ARC::ADD_rru6;326    else if (isInt<12>(VarArgsBytes))327      Opc = ARC::ADD_rrs12;328    BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(Opc))329        .addReg(ARC::SP)330        .addReg(ARC::SP)331        .addImm(VarArgsBytes);332  }333}334 335static std::vector<CalleeSavedInfo>::iterator336getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {337  for (auto I = V.begin(), E = V.end(); I != E; ++I) {338    if (reg == I->getReg())339      return I;340  }341  return V.end();342}343 344bool ARCFrameLowering::assignCalleeSavedSpillSlots(345    MachineFunction &MF, const TargetRegisterInfo *TRI,346    std::vector<CalleeSavedInfo> &CSI) const {347  // Use this opportunity to assign the spill slots for all of the potential348  // callee save registers (blink, fp, r13->r25) that we care about the349  // placement for.  We can calculate all of that data here.350  int CurOffset = -4;351  unsigned Last = determineLastCalleeSave(CSI);352  MachineFrameInfo &MFI = MF.getFrameInfo();353  if (hasFP(MF)) {354    // Create a fixed slot at for FP355    int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);356    LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "357                      << CurOffset << "\n");358    (void)StackObj;359    CurOffset -= 4;360  }361  if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {362    // Create a fixed slot for BLINK.363    int StackObj  = MFI.CreateFixedSpillStackObject(4, CurOffset, true);364    LLVM_DEBUG(dbgs() << "Creating fixed object (" << StackObj365                      << ") for BLINK at " << CurOffset << "\n");366    (void)StackObj;367    CurOffset -= 4;368  }369 370  // Create slots for last down to r13.371  for (unsigned Which = Last; Which > ARC::R12; Which--) {372    auto RegI = getSavedReg(CSI, Which);373    if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {374      // Always create the stack slot.  If for some reason the register isn't in375      // the save list, then don't worry about it.376      int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);377      if (RegI != CSI.end())378        RegI->setFrameIdx(FI);379    } else380      MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);381    CurOffset -= 4;382  }383  for (auto &I : CSI) {384    if (I.getReg() > ARC::R12)385      continue;386    if (I.getFrameIdx() == 0) {387      I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true));388      LLVM_DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()389                        << ") for other register at " << CurOffset << "\n");390    } else {391      MFI.setObjectOffset(I.getFrameIdx(), CurOffset);392      LLVM_DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()393                        << ") for other register at " << CurOffset << "\n");394    }395    CurOffset -= 4;396  }397  return true;398}399 400bool ARCFrameLowering::spillCalleeSavedRegisters(401    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,402    ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {403  LLVM_DEBUG(dbgs() << "Spill callee saved registers: "404                    << MBB.getParent()->getName() << "\n");405  // There are routines for saving at least 3 registers (r13 to r15, etc.)406  unsigned Last = determineLastCalleeSave(CSI);407  if (UseSaveRestoreFunclet && Last > ARC::R14) {408    // Use setObjectOffset for these registers.409    // Needs to be in or before processFunctionBeforeFrameFinalized.410    // Or, do assignCalleeSaveSpillSlots?411    // Will be handled in prolog.412    return true;413  }414  return false;415}416 417bool ARCFrameLowering::restoreCalleeSavedRegisters(418    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,419    MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {420  LLVM_DEBUG(dbgs() << "Restore callee saved registers: "421                    << MBB.getParent()->getName() << "\n");422  // There are routines for saving at least 3 registers (r13 to r15, etc.)423  unsigned Last = determineLastCalleeSave(CSI);424  if (UseSaveRestoreFunclet && Last > ARC::R14) {425    // Will be handled in epilog.426    return true;427  }428  return false;429}430 431// Adjust local variables that are 4-bytes or larger to 4-byte boundary432void ARCFrameLowering::processFunctionBeforeFrameFinalized(433    MachineFunction &MF, RegScavenger *RS) const {434  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();435  LLVM_DEBUG(dbgs() << "Process function before frame finalized: "436                    << MF.getName() << "\n");437  MachineFrameInfo &MFI = MF.getFrameInfo();438  LLVM_DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");439  const TargetRegisterClass *RC = &ARC::GPR32RegClass;440  if (MFI.hasStackObjects()) {441    int RegScavFI = MFI.CreateSpillStackObject(RegInfo->getSpillSize(*RC),442                                               RegInfo->getSpillAlign(*RC));443    RS->addScavengingFrameIndex(RegScavFI);444    LLVM_DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI445                      << "\n");446  }447}448 449static void emitRegUpdate(MachineBasicBlock &MBB,450                          MachineBasicBlock::iterator &MBBI, DebugLoc dl,451                          unsigned Reg, int NumBytes, bool IsAdd,452                          const ARCInstrInfo *TII) {453  unsigned Opc;454  if (isUInt<6>(NumBytes))455    Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;456  else if (isInt<12>(NumBytes))457    Opc = IsAdd ? ARC::ADD_rrs12 : ARC::SUB_rrs12;458  else459    Opc = IsAdd ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;460 461  BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)462      .addReg(Reg, RegState::Kill)463      .addImm(NumBytes);464}465 466MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(467    MachineFunction &MF, MachineBasicBlock &MBB,468    MachineBasicBlock::iterator I) const {469  LLVM_DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n");470  const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();471  MachineInstr &Old = *I;472  DebugLoc dl = Old.getDebugLoc();473  unsigned Amt = Old.getOperand(0).getImm();474  auto *AFI = MF.getInfo<ARCFunctionInfo>();475  if (!hasFP(MF)) {476    if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)477      AFI->MaxCallStackReq = Amt;478  } else {479    if (Amt != 0) {480      assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||481              Old.getOpcode() == ARC::ADJCALLSTACKUP) &&482             "Unknown Frame Pseudo.");483      bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);484      emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);485    }486  }487  return MBB.erase(I);488}489 490bool ARCFrameLowering::hasFPImpl(const MachineFunction &MF) const {491  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();492  bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||493               MF.getFrameInfo().hasVarSizedObjects() ||494               MF.getFrameInfo().isFrameAddressTaken() ||495               RegInfo->hasStackRealignment(MF);496  return HasFP;497}498