Home | History | Annotate | Download | only in SystemZ
      1 //=====- SystemZFrameLowering.cpp - SystemZ Frame Information ------*- C++ -*-====//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains the SystemZ implementation of TargetFrameLowering class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "SystemZFrameLowering.h"
     15 #include "SystemZInstrBuilder.h"
     16 #include "SystemZInstrInfo.h"
     17 #include "SystemZMachineFunctionInfo.h"
     18 #include "llvm/Function.h"
     19 #include "llvm/CodeGen/MachineFrameInfo.h"
     20 #include "llvm/CodeGen/MachineFunction.h"
     21 #include "llvm/CodeGen/MachineInstrBuilder.h"
     22 #include "llvm/CodeGen/MachineModuleInfo.h"
     23 #include "llvm/CodeGen/MachineRegisterInfo.h"
     24 #include "llvm/Target/TargetData.h"
     25 #include "llvm/Target/TargetOptions.h"
     26 #include "llvm/Support/CommandLine.h"
     27 
     28 using namespace llvm;
     29 
     30 SystemZFrameLowering::SystemZFrameLowering(const SystemZSubtarget &sti)
     31   : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 8, -160), STI(sti) {
     32   // Fill the spill offsets map
     33   static const unsigned SpillOffsTab[][2] = {
     34     { SystemZ::R2D,  0x10 },
     35     { SystemZ::R3D,  0x18 },
     36     { SystemZ::R4D,  0x20 },
     37     { SystemZ::R5D,  0x28 },
     38     { SystemZ::R6D,  0x30 },
     39     { SystemZ::R7D,  0x38 },
     40     { SystemZ::R8D,  0x40 },
     41     { SystemZ::R9D,  0x48 },
     42     { SystemZ::R10D, 0x50 },
     43     { SystemZ::R11D, 0x58 },
     44     { SystemZ::R12D, 0x60 },
     45     { SystemZ::R13D, 0x68 },
     46     { SystemZ::R14D, 0x70 },
     47     { SystemZ::R15D, 0x78 }
     48   };
     49 
     50   RegSpillOffsets.grow(SystemZ::NUM_TARGET_REGS);
     51 
     52   for (unsigned i = 0, e = array_lengthof(SpillOffsTab); i != e; ++i)
     53     RegSpillOffsets[SpillOffsTab[i][0]] = SpillOffsTab[i][1];
     54 }
     55 
     56 /// needsFP - Return true if the specified function should have a dedicated
     57 /// frame pointer register.  This is true if the function has variable sized
     58 /// allocas or if frame pointer elimination is disabled.
     59 bool SystemZFrameLowering::hasFP(const MachineFunction &MF) const {
     60   const MachineFrameInfo *MFI = MF.getFrameInfo();
     61   return DisableFramePointerElim(MF) || MFI->hasVarSizedObjects();
     62 }
     63 
     64 /// emitSPUpdate - Emit a series of instructions to increment / decrement the
     65 /// stack pointer by a constant value.
     66 static
     67 void emitSPUpdate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI,
     68                   int64_t NumBytes, const TargetInstrInfo &TII) {
     69   unsigned Opc; uint64_t Chunk;
     70   bool isSub = NumBytes < 0;
     71   uint64_t Offset = isSub ? -NumBytes : NumBytes;
     72 
     73   if (Offset >= (1LL << 15) - 1) {
     74     Opc = SystemZ::ADD64ri32;
     75     Chunk = (1LL << 31) - 1;
     76   } else {
     77     Opc = SystemZ::ADD64ri16;
     78     Chunk = (1LL << 15) - 1;
     79   }
     80 
     81   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
     82 
     83   while (Offset) {
     84     uint64_t ThisVal = (Offset > Chunk) ? Chunk : Offset;
     85     MachineInstr *MI =
     86       BuildMI(MBB, MBBI, DL, TII.get(Opc), SystemZ::R15D)
     87       .addReg(SystemZ::R15D).addImm(isSub ? -ThisVal : ThisVal);
     88     // The PSW implicit def is dead.
     89     MI->getOperand(3).setIsDead();
     90     Offset -= ThisVal;
     91   }
     92 }
     93 
     94 void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const {
     95   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
     96   MachineFrameInfo *MFI = MF.getFrameInfo();
     97   const SystemZInstrInfo &TII =
     98     *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
     99   SystemZMachineFunctionInfo *SystemZMFI =
    100     MF.getInfo<SystemZMachineFunctionInfo>();
    101   MachineBasicBlock::iterator MBBI = MBB.begin();
    102   DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
    103 
    104   // Get the number of bytes to allocate from the FrameInfo.
    105   // Note that area for callee-saved stuff is already allocated, thus we need to
    106   // 'undo' the stack movement.
    107   uint64_t StackSize = MFI->getStackSize();
    108   StackSize -= SystemZMFI->getCalleeSavedFrameSize();
    109 
    110   uint64_t NumBytes = StackSize - getOffsetOfLocalArea();
    111 
    112   // Skip the callee-saved push instructions.
    113   while (MBBI != MBB.end() &&
    114          (MBBI->getOpcode() == SystemZ::MOV64mr ||
    115           MBBI->getOpcode() == SystemZ::MOV64mrm))
    116     ++MBBI;
    117 
    118   if (MBBI != MBB.end())
    119     DL = MBBI->getDebugLoc();
    120 
    121   // adjust stack pointer: R15 -= numbytes
    122   if (StackSize || MFI->hasCalls()) {
    123     assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
    124            "Invalid stack frame calculation!");
    125     emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, TII);
    126   }
    127 
    128   if (hasFP(MF)) {
    129     // Update R11 with the new base value...
    130     BuildMI(MBB, MBBI, DL, TII.get(SystemZ::MOV64rr), SystemZ::R11D)
    131       .addReg(SystemZ::R15D);
    132 
    133     // Mark the FramePtr as live-in in every block except the entry.
    134     for (MachineFunction::iterator I = llvm::next(MF.begin()), E = MF.end();
    135          I != E; ++I)
    136       I->addLiveIn(SystemZ::R11D);
    137 
    138   }
    139 }
    140 
    141 void SystemZFrameLowering::emitEpilogue(MachineFunction &MF,
    142                                     MachineBasicBlock &MBB) const {
    143   const MachineFrameInfo *MFI = MF.getFrameInfo();
    144   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
    145   const SystemZInstrInfo &TII =
    146     *static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo());
    147   SystemZMachineFunctionInfo *SystemZMFI =
    148     MF.getInfo<SystemZMachineFunctionInfo>();
    149   unsigned RetOpcode = MBBI->getOpcode();
    150 
    151   switch (RetOpcode) {
    152   case SystemZ::RET: break;  // These are ok
    153   default:
    154     assert(0 && "Can only insert epilog into returning blocks");
    155   }
    156 
    157   // Get the number of bytes to allocate from the FrameInfo
    158   // Note that area for callee-saved stuff is already allocated, thus we need to
    159   // 'undo' the stack movement.
    160   uint64_t StackSize =
    161     MFI->getStackSize() - SystemZMFI->getCalleeSavedFrameSize();
    162   uint64_t NumBytes = StackSize - getOffsetOfLocalArea();
    163 
    164   // Skip the final terminator instruction.
    165   while (MBBI != MBB.begin()) {
    166     MachineBasicBlock::iterator PI = prior(MBBI);
    167     --MBBI;
    168     if (!PI->getDesc().isTerminator())
    169       break;
    170   }
    171 
    172   // During callee-saved restores emission stack frame was not yet finialized
    173   // (and thus - the stack size was unknown). Tune the offset having full stack
    174   // size in hands.
    175   if (StackSize || MFI->hasCalls()) {
    176     assert((MBBI->getOpcode() == SystemZ::MOV64rmm ||
    177             MBBI->getOpcode() == SystemZ::MOV64rm) &&
    178            "Expected to see callee-save register restore code");
    179     assert(MF.getRegInfo().isPhysRegUsed(SystemZ::R15D) &&
    180            "Invalid stack frame calculation!");
    181 
    182     unsigned i = 0;
    183     MachineInstr &MI = *MBBI;
    184     while (!MI.getOperand(i).isImm()) {
    185       ++i;
    186       assert(i < MI.getNumOperands() && "Unexpected restore code!");
    187     }
    188 
    189     uint64_t Offset = NumBytes + MI.getOperand(i).getImm();
    190     // If Offset does not fit into 20-bit signed displacement field we need to
    191     // emit some additional code...
    192     if (Offset > 524287) {
    193       // Fold the displacement into load instruction as much as possible.
    194       NumBytes = Offset - 524287;
    195       Offset = 524287;
    196       emitSPUpdate(MBB, MBBI, NumBytes, TII);
    197     }
    198 
    199     MI.getOperand(i).ChangeToImmediate(Offset);
    200   }
    201 }
    202 
    203 int SystemZFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
    204                                           int FI) const {
    205   const MachineFrameInfo *MFI = MF.getFrameInfo();
    206   const SystemZMachineFunctionInfo *SystemZMFI =
    207     MF.getInfo<SystemZMachineFunctionInfo>();
    208   int Offset = MFI->getObjectOffset(FI) + MFI->getOffsetAdjustment();
    209   uint64_t StackSize = MFI->getStackSize();
    210 
    211   // Fixed objects are really located in the "previous" frame.
    212   if (FI < 0)
    213     StackSize -= SystemZMFI->getCalleeSavedFrameSize();
    214 
    215   Offset += StackSize - getOffsetOfLocalArea();
    216 
    217   // Skip the register save area if we generated the stack frame.
    218   if (StackSize || MFI->hasCalls())
    219     Offset -= getOffsetOfLocalArea();
    220 
    221   return Offset;
    222 }
    223 
    224 bool
    225 SystemZFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
    226                                             MachineBasicBlock::iterator MI,
    227                                         const std::vector<CalleeSavedInfo> &CSI,
    228                                           const TargetRegisterInfo *TRI) const {
    229   if (CSI.empty())
    230     return false;
    231 
    232   DebugLoc DL;
    233   if (MI != MBB.end()) DL = MI->getDebugLoc();
    234 
    235   MachineFunction &MF = *MBB.getParent();
    236   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
    237   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
    238   unsigned CalleeFrameSize = 0;
    239 
    240   // Scan the callee-saved and find the bounds of register spill area.
    241   unsigned LowReg = 0, HighReg = 0, StartOffset = -1U, EndOffset = 0;
    242   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    243     unsigned Reg = CSI[i].getReg();
    244     if (!SystemZ::FP64RegClass.contains(Reg)) {
    245       unsigned Offset = RegSpillOffsets[Reg];
    246       CalleeFrameSize += 8;
    247       if (StartOffset > Offset) {
    248         LowReg = Reg; StartOffset = Offset;
    249       }
    250       if (EndOffset < Offset) {
    251         HighReg = Reg; EndOffset = RegSpillOffsets[Reg];
    252       }
    253     }
    254   }
    255 
    256   // Save information for epilogue inserter.
    257   MFI->setCalleeSavedFrameSize(CalleeFrameSize);
    258   MFI->setLowReg(LowReg); MFI->setHighReg(HighReg);
    259 
    260   // Save GPRs
    261   if (StartOffset) {
    262     // Build a store instruction. Use STORE MULTIPLE instruction if there are many
    263     // registers to store, otherwise - just STORE.
    264     MachineInstrBuilder MIB =
    265       BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
    266                                     SystemZ::MOV64mr : SystemZ::MOV64mrm)));
    267 
    268     // Add store operands.
    269     MIB.addReg(SystemZ::R15D).addImm(StartOffset);
    270     if (LowReg == HighReg)
    271       MIB.addReg(0);
    272     MIB.addReg(LowReg, RegState::Kill);
    273     if (LowReg != HighReg)
    274       MIB.addReg(HighReg, RegState::Kill);
    275 
    276     // Do a second scan adding regs as being killed by instruction
    277     for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    278       unsigned Reg = CSI[i].getReg();
    279       // Add the callee-saved register as live-in. It's killed at the spill.
    280       MBB.addLiveIn(Reg);
    281       if (Reg != LowReg && Reg != HighReg)
    282         MIB.addReg(Reg, RegState::ImplicitKill);
    283     }
    284   }
    285 
    286   // Save FPRs
    287   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    288     unsigned Reg = CSI[i].getReg();
    289     if (SystemZ::FP64RegClass.contains(Reg)) {
    290       MBB.addLiveIn(Reg);
    291       TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(),
    292                               &SystemZ::FP64RegClass, TRI);
    293     }
    294   }
    295 
    296   return true;
    297 }
    298 
    299 bool
    300 SystemZFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
    301                                               MachineBasicBlock::iterator MI,
    302                                         const std::vector<CalleeSavedInfo> &CSI,
    303                                           const TargetRegisterInfo *TRI) const {
    304   if (CSI.empty())
    305     return false;
    306 
    307   DebugLoc DL;
    308   if (MI != MBB.end()) DL = MI->getDebugLoc();
    309 
    310   MachineFunction &MF = *MBB.getParent();
    311   const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
    312   SystemZMachineFunctionInfo *MFI = MF.getInfo<SystemZMachineFunctionInfo>();
    313 
    314   // Restore FP registers
    315   for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    316     unsigned Reg = CSI[i].getReg();
    317     if (SystemZ::FP64RegClass.contains(Reg))
    318       TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(),
    319                                &SystemZ::FP64RegClass, TRI);
    320   }
    321 
    322   // Restore GP registers
    323   unsigned LowReg = MFI->getLowReg(), HighReg = MFI->getHighReg();
    324   unsigned StartOffset = RegSpillOffsets[LowReg];
    325 
    326   if (StartOffset) {
    327     // Build a load instruction. Use LOAD MULTIPLE instruction if there are many
    328     // registers to load, otherwise - just LOAD.
    329     MachineInstrBuilder MIB =
    330       BuildMI(MBB, MI, DL, TII.get((LowReg == HighReg ?
    331                                     SystemZ::MOV64rm : SystemZ::MOV64rmm)));
    332     // Add store operands.
    333     MIB.addReg(LowReg, RegState::Define);
    334     if (LowReg != HighReg)
    335       MIB.addReg(HighReg, RegState::Define);
    336 
    337     MIB.addReg(hasFP(MF) ? SystemZ::R11D : SystemZ::R15D);
    338     MIB.addImm(StartOffset);
    339     if (LowReg == HighReg)
    340       MIB.addReg(0);
    341 
    342     // Do a second scan adding regs as being defined by instruction
    343     for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
    344       unsigned Reg = CSI[i].getReg();
    345       if (Reg != LowReg && Reg != HighReg)
    346         MIB.addReg(Reg, RegState::ImplicitDefine);
    347     }
    348   }
    349 
    350   return true;
    351 }
    352 
    353 void
    354 SystemZFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
    355                                                        RegScavenger *RS) const {
    356   // Determine whether R15/R14 will ever be clobbered inside the function. And
    357   // if yes - mark it as 'callee' saved.
    358   MachineFrameInfo *FFI = MF.getFrameInfo();
    359   MachineRegisterInfo &MRI = MF.getRegInfo();
    360 
    361   // Check whether high FPRs are ever used, if yes - we need to save R15 as
    362   // well.
    363   static const unsigned HighFPRs[] = {
    364     SystemZ::F8L,  SystemZ::F9L,  SystemZ::F10L, SystemZ::F11L,
    365     SystemZ::F12L, SystemZ::F13L, SystemZ::F14L, SystemZ::F15L,
    366     SystemZ::F8S,  SystemZ::F9S,  SystemZ::F10S, SystemZ::F11S,
    367     SystemZ::F12S, SystemZ::F13S, SystemZ::F14S, SystemZ::F15S,
    368   };
    369 
    370   bool HighFPRsUsed = false;
    371   for (unsigned i = 0, e = array_lengthof(HighFPRs); i != e; ++i)
    372     HighFPRsUsed |= MRI.isPhysRegUsed(HighFPRs[i]);
    373 
    374   if (FFI->hasCalls())
    375     /* FIXME: function is varargs */
    376     /* FIXME: function grabs RA */
    377     /* FIXME: function calls eh_return */
    378     MRI.setPhysRegUsed(SystemZ::R14D);
    379 
    380   if (HighFPRsUsed ||
    381       FFI->hasCalls() ||
    382       FFI->getObjectIndexEnd() != 0 || // Contains automatic variables
    383       FFI->hasVarSizedObjects() // Function calls dynamic alloca's
    384       /* FIXME: function is varargs */)
    385     MRI.setPhysRegUsed(SystemZ::R15D);
    386 }
    387