Home | History | Annotate | Download | only in CellSPU
      1 //===-- SPUTargetMachine.cpp - Define TargetMachine for Cell SPU ----------===//
      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 // Top-level implementation for the Cell SPU target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "SPU.h"
     15 #include "SPUFrameLowering.h"
     16 #include "SPUInstrBuilder.h"
     17 #include "SPUInstrInfo.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/CodeGen/RegisterScavenging.h"
     25 #include "llvm/Target/TargetData.h"
     26 #include "llvm/Target/TargetOptions.h"
     27 #include "llvm/Support/CommandLine.h"
     28 using namespace llvm;
     29 
     30 //===----------------------------------------------------------------------===//
     31 // SPUFrameLowering:
     32 //===----------------------------------------------------------------------===//
     33 
     34 SPUFrameLowering::SPUFrameLowering(const SPUSubtarget &sti)
     35   : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 16, 0),
     36     Subtarget(sti) {
     37   LR[0].first = SPU::R0;
     38   LR[0].second = 16;
     39 }
     40 
     41 
     42 //--------------------------------------------------------------------------
     43 // hasFP - Return true if the specified function actually has a dedicated frame
     44 // pointer register.  This is true if the function needs a frame pointer and has
     45 // a non-zero stack size.
     46 bool SPUFrameLowering::hasFP(const MachineFunction &MF) const {
     47   const MachineFrameInfo *MFI = MF.getFrameInfo();
     48 
     49   return MFI->getStackSize() &&
     50     (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects());
     51 }
     52 
     53 
     54 /// determineFrameLayout - Determine the size of the frame and maximum call
     55 /// frame size.
     56 void SPUFrameLowering::determineFrameLayout(MachineFunction &MF) const {
     57   MachineFrameInfo *MFI = MF.getFrameInfo();
     58 
     59   // Get the number of bytes to allocate from the FrameInfo
     60   unsigned FrameSize = MFI->getStackSize();
     61 
     62   // Get the alignments provided by the target, and the maximum alignment
     63   // (if any) of the fixed frame objects.
     64   unsigned TargetAlign = getStackAlignment();
     65   unsigned Align = std::max(TargetAlign, MFI->getMaxAlignment());
     66   assert(isPowerOf2_32(Align) && "Alignment is not power of 2");
     67   unsigned AlignMask = Align - 1;
     68 
     69   // Get the maximum call frame size of all the calls.
     70   unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
     71 
     72   // If we have dynamic alloca then maxCallFrameSize needs to be aligned so
     73   // that allocations will be aligned.
     74   if (MFI->hasVarSizedObjects())
     75     maxCallFrameSize = (maxCallFrameSize + AlignMask) & ~AlignMask;
     76 
     77   // Update maximum call frame size.
     78   MFI->setMaxCallFrameSize(maxCallFrameSize);
     79 
     80   // Include call frame size in total.
     81   FrameSize += maxCallFrameSize;
     82 
     83   // Make sure the frame is aligned.
     84   FrameSize = (FrameSize + AlignMask) & ~AlignMask;
     85 
     86   // Update frame info.
     87   MFI->setStackSize(FrameSize);
     88 }
     89 
     90 void SPUFrameLowering::emitPrologue(MachineFunction &MF) const {
     91   MachineBasicBlock &MBB = MF.front();   // Prolog goes in entry BB
     92   MachineBasicBlock::iterator MBBI = MBB.begin();
     93   MachineFrameInfo *MFI = MF.getFrameInfo();
     94   const SPUInstrInfo &TII =
     95     *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
     96   MachineModuleInfo &MMI = MF.getMMI();
     97   DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
     98 
     99   // Prepare for debug frame info.
    100   bool hasDebugInfo = MMI.hasDebugInfo();
    101   MCSymbol *FrameLabel = 0;
    102 
    103   // Move MBBI back to the beginning of the function.
    104   MBBI = MBB.begin();
    105 
    106   // Work out frame sizes.
    107   determineFrameLayout(MF);
    108   int FrameSize = MFI->getStackSize();
    109 
    110   assert((FrameSize & 0xf) == 0
    111          && "SPURegisterInfo::emitPrologue: FrameSize not aligned");
    112 
    113   // the "empty" frame size is 16 - just the register scavenger spill slot
    114   if (FrameSize > 16 || MFI->adjustsStack()) {
    115     FrameSize = -(FrameSize + SPUFrameLowering::minStackSize());
    116     if (hasDebugInfo) {
    117       // Mark effective beginning of when frame pointer becomes valid.
    118       FrameLabel = MMI.getContext().CreateTempSymbol();
    119       BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(FrameLabel);
    120     }
    121 
    122     // Adjust stack pointer, spilling $lr -> 16($sp) and $sp -> -FrameSize($sp)
    123     // for the ABI
    124     BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R0).addImm(16)
    125       .addReg(SPU::R1);
    126     if (isInt<10>(FrameSize)) {
    127       // Spill $sp to adjusted $sp
    128       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr32), SPU::R1).addImm(FrameSize)
    129         .addReg(SPU::R1);
    130       // Adjust $sp by required amout
    131       BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1).addReg(SPU::R1)
    132         .addImm(FrameSize);
    133     } else if (isInt<16>(FrameSize)) {
    134       // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
    135       // $r2 to adjust $sp:
    136       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
    137         .addImm(-16)
    138         .addReg(SPU::R1);
    139       BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
    140         .addImm(FrameSize);
    141       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQXr32), SPU::R1)
    142         .addReg(SPU::R2)
    143         .addReg(SPU::R1);
    144       BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
    145         .addReg(SPU::R1)
    146         .addReg(SPU::R2);
    147       BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2)
    148         .addReg(SPU::R2)
    149         .addImm(16);
    150       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
    151         .addReg(SPU::R2)
    152         .addReg(SPU::R1);
    153     } else {
    154       report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
    155     }
    156 
    157     if (hasDebugInfo) {
    158       std::vector<MachineMove> &Moves = MMI.getFrameMoves();
    159 
    160       // Show update of SP.
    161       MachineLocation SPDst(MachineLocation::VirtualFP);
    162       MachineLocation SPSrc(MachineLocation::VirtualFP, -FrameSize);
    163       Moves.push_back(MachineMove(FrameLabel, SPDst, SPSrc));
    164 
    165       // Add callee saved registers to move list.
    166       const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
    167       for (unsigned I = 0, E = CSI.size(); I != E; ++I) {
    168         int Offset = MFI->getObjectOffset(CSI[I].getFrameIdx());
    169         unsigned Reg = CSI[I].getReg();
    170         if (Reg == SPU::R0) continue;
    171         MachineLocation CSDst(MachineLocation::VirtualFP, Offset);
    172         MachineLocation CSSrc(Reg);
    173         Moves.push_back(MachineMove(FrameLabel, CSDst, CSSrc));
    174       }
    175 
    176       // Mark effective beginning of when frame pointer is ready.
    177       MCSymbol *ReadyLabel = MMI.getContext().CreateTempSymbol();
    178       BuildMI(MBB, MBBI, dl, TII.get(SPU::PROLOG_LABEL)).addSym(ReadyLabel);
    179 
    180       MachineLocation FPDst(SPU::R1);
    181       MachineLocation FPSrc(MachineLocation::VirtualFP);
    182       Moves.push_back(MachineMove(ReadyLabel, FPDst, FPSrc));
    183     }
    184   }
    185 }
    186 
    187 void SPUFrameLowering::emitEpilogue(MachineFunction &MF,
    188                                 MachineBasicBlock &MBB) const {
    189   MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
    190   const SPUInstrInfo &TII =
    191     *static_cast<const SPUInstrInfo*>(MF.getTarget().getInstrInfo());
    192   const MachineFrameInfo *MFI = MF.getFrameInfo();
    193   int FrameSize = MFI->getStackSize();
    194   int LinkSlotOffset = SPUFrameLowering::stackSlotSize();
    195   DebugLoc dl = MBBI->getDebugLoc();
    196 
    197   assert(MBBI->getOpcode() == SPU::RET &&
    198          "Can only insert epilog into returning blocks");
    199   assert((FrameSize & 0xf) == 0 && "FrameSize not aligned");
    200 
    201   // the "empty" frame size is 16 - just the register scavenger spill slot
    202   if (FrameSize > 16 || MFI->adjustsStack()) {
    203     FrameSize = FrameSize + SPUFrameLowering::minStackSize();
    204     if (isInt<10>(FrameSize + LinkSlotOffset)) {
    205       // Reload $lr, adjust $sp by required amount
    206       // Note: We do this to slightly improve dual issue -- not by much, but it
    207       // is an opportunity for dual issue.
    208       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
    209         .addImm(FrameSize + LinkSlotOffset)
    210         .addReg(SPU::R1);
    211       BuildMI(MBB, MBBI, dl, TII.get(SPU::AIr32), SPU::R1)
    212         .addReg(SPU::R1)
    213         .addImm(FrameSize);
    214     } else if (FrameSize <= (1 << 16) - 1 && FrameSize >= -(1 << 16)) {
    215       // Frame size can be loaded into ILr32n, so temporarily spill $r2 and use
    216       // $r2 to adjust $sp:
    217       BuildMI(MBB, MBBI, dl, TII.get(SPU::STQDr128), SPU::R2)
    218         .addImm(16)
    219         .addReg(SPU::R1);
    220       BuildMI(MBB, MBBI, dl, TII.get(SPU::ILr32), SPU::R2)
    221         .addImm(FrameSize);
    222       BuildMI(MBB, MBBI, dl, TII.get(SPU::Ar32), SPU::R1)
    223         .addReg(SPU::R1)
    224         .addReg(SPU::R2);
    225       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQDr128), SPU::R0)
    226         .addImm(16)
    227         .addReg(SPU::R1);
    228       BuildMI(MBB, MBBI, dl, TII.get(SPU::SFIr32), SPU::R2).
    229         addReg(SPU::R2)
    230         .addImm(16);
    231       BuildMI(MBB, MBBI, dl, TII.get(SPU::LQXr128), SPU::R2)
    232         .addReg(SPU::R2)
    233         .addReg(SPU::R1);
    234     } else {
    235       report_fatal_error("Unhandled frame size: " + Twine(FrameSize));
    236     }
    237   }
    238 }
    239 
    240 void SPUFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
    241                                                         RegScavenger *RS) const{
    242   // Mark LR and SP unused, since the prolog spills them to stack and
    243   // we don't want anyone else to spill them for us.
    244   //
    245   // Also, unless R2 is really used someday, don't spill it automatically.
    246   MF.getRegInfo().setPhysRegUnused(SPU::R0);
    247   MF.getRegInfo().setPhysRegUnused(SPU::R1);
    248   MF.getRegInfo().setPhysRegUnused(SPU::R2);
    249 
    250   MachineFrameInfo *MFI = MF.getFrameInfo();
    251   const TargetRegisterClass *RC = &SPU::R32CRegClass;
    252   RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
    253                                                      RC->getAlignment(),
    254                                                      false));
    255 }
    256