llvm-6502/lib/Target/Hexagon/HexagonFrameLowering.cpp
Chandler Carruth 0b8c9a80f2 Move all of the header files which are involved in modelling the LLVM IR
into their new header subdirectory: include/llvm/IR. This matches the
directory structure of lib, and begins to correct a long standing point
of file layout clutter in LLVM.

There are still more header files to move here, but I wanted to handle
them in separate commits to make tracking what files make sense at each
layer easier.

The only really questionable files here are the target intrinsic
tablegen files. But that's a battle I'd rather not fight today.

I've updated both CMake and Makefile build systems (I think, and my
tests think, but I may have missed something).

I've also re-sorted the includes throughout the project. I'll be
committing updates to Clang, DragonEgg, and Polly momentarily.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171366 91177308-0d34-0410-b5e6-96231b3b80d8
2013-01-02 11:36:10 +00:00

334 lines
11 KiB
C++

//===-- HexagonFrameLowering.cpp - Define frame lowering ------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//
//===----------------------------------------------------------------------===//
#include "HexagonFrameLowering.h"
#include "Hexagon.h"
#include "HexagonInstrInfo.h"
#include "HexagonMachineFunctionInfo.h"
#include "HexagonRegisterInfo.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
static cl::opt<bool> DisableDeallocRet(
"disable-hexagon-dealloc-ret",
cl::Hidden,
cl::desc("Disable Dealloc Return for Hexagon target"));
/// determineFrameLayout - Determine the size of the frame and maximum call
/// frame size.
void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
MachineFrameInfo *MFI = MF.getFrameInfo();
// Get the number of bytes to allocate from the FrameInfo.
unsigned FrameSize = MFI->getStackSize();
// Get the alignments provided by the target.
unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
// Get the maximum call frame size of all the calls.
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
// that allocations will be aligned.
if (MFI->hasVarSizedObjects())
maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
// Update maximum call frame size.
MFI->setMaxCallFrameSize(maxCallFrameSize);
// Include call frame size in total.
FrameSize += maxCallFrameSize;
// Make sure the frame is aligned.
FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
// Update frame info.
MFI->setStackSize(FrameSize);
}
void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front();
MachineFrameInfo *MFI = MF.getFrameInfo();
MachineModuleInfo &MMI = MF.getMMI();
MachineBasicBlock::iterator MBBI = MBB.begin();
const HexagonRegisterInfo *QRI =
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
determineFrameLayout(MF);
// Check if frame moves are needed for EH.
bool needsFrameMoves = MMI.hasDebugInfo() ||
!MF.getFunction()->needsUnwindTableEntry();
// Get the number of bytes to allocate from the FrameInfo.
int NumBytes = (int) MFI->getStackSize();
// LLVM expects allocframe not to be the first instruction in the
// basic block.
MachineBasicBlock::iterator InsertPt = MBB.begin();
//
// ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset.
//
HexagonMachineFunctionInfo *FuncInfo =
MF.getInfo<HexagonMachineFunctionInfo>();
const std::vector<MachineInstr*>& AdjustRegs =
FuncInfo->getAllocaAdjustInsts();
for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
e = AdjustRegs.end();
i != e; ++i) {
MachineInstr* MI = *i;
assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
"Expected adjust alloca node");
MachineOperand& MO = MI->getOperand(2);
assert(MO.isImm() && "Expected immediate");
MO.setImm(MFI->getMaxCallFrameSize());
}
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
if (needsFrameMoves) {
// Advance CFA. DW_CFA_def_cfa
unsigned FPReg = QRI->getFrameRegister();
unsigned RAReg = QRI->getRARegister();
MachineLocation Dst(MachineLocation::VirtualFP);
MachineLocation Src(FPReg, -8);
Moves.push_back(MachineMove(0, Dst, Src));
// R31 = (R31 - #4)
MachineLocation LRDst(RAReg, -4);
MachineLocation LRSrc(RAReg);
Moves.push_back(MachineMove(0, LRDst, LRSrc));
// R30 = (R30 - #8)
MachineLocation SPDst(FPReg, -8);
MachineLocation SPSrc(FPReg);
Moves.push_back(MachineMove(0, SPDst, SPSrc));
}
//
// Only insert ALLOCFRAME if we need to.
//
if (hasFP(MF)) {
// Check for overflow.
// Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
const int ALLOCFRAME_MAX = 16384;
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
if (NumBytes >= ALLOCFRAME_MAX) {
// Emit allocframe(#0).
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
// Subtract offset from frame pointer.
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
HEXAGON_RESERVED_REG_1).addImm(NumBytes);
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
QRI->getStackRegister()).
addReg(QRI->getStackRegister()).
addReg(HEXAGON_RESERVED_REG_1);
} else {
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
}
}
}
// Returns true if MBB has a machine instructions that indicates a tail call
// in the block.
bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
unsigned RetOpcode = MBBI->getOpcode();
return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;
}
void HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = prior(MBB.end());
DebugLoc dl = MBBI->getDebugLoc();
//
// Only insert deallocframe if we need to.
//
if (hasFP(MF)) {
MachineBasicBlock::iterator MBBI = prior(MBB.end());
MachineBasicBlock::iterator MBBI_end = MBB.end();
//
// For Hexagon, we don't need the frame size.
//
MachineFrameInfo *MFI = MF.getFrameInfo();
int NumBytes = (int) MFI->getStackSize();
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
// Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
// versions.
if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR
&& !DisableDeallocRet) {
// Remove jumpr node.
MBB.erase(MBBI);
// Add dealloc_return.
BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4))
.addImm(NumBytes);
} else { // Add deallocframe for V2 and V3.
BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes);
}
}
}
bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
const HexagonMachineFunctionInfo *FuncInfo =
MF.getInfo<HexagonMachineFunctionInfo>();
return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
FuncInfo->hasClobberLR() );
}
static inline
unsigned uniqueSuperReg(unsigned Reg, const TargetRegisterInfo *TRI) {
MCSuperRegIterator SRI(Reg, TRI);
assert(SRI.isValid() && "Expected a superreg");
unsigned SuperReg = *SRI;
++SRI;
assert(!SRI.isValid() && "Expected exactly one superreg");
return SuperReg;
}
bool
HexagonFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
MachineFunction *MF = MBB.getParent();
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
if (CSI.empty()) {
return false;
}
// We can only schedule double loads if we spill contiguous callee-saved regs
// For instance, we cannot scheduled double-word loads if we spill r24,
// r26, and r27.
// Hexagon_TODO: We can try to double-word align odd registers for -O2 and
// above.
bool ContiguousRegs = true;
for (unsigned i = 0; i < CSI.size(); ++i) {
unsigned Reg = CSI[i].getReg();
//
// Check if we can use a double-word store.
//
unsigned SuperReg = uniqueSuperReg(Reg, TRI);
bool CanUseDblStore = false;
const TargetRegisterClass* SuperRegClass = 0;
if (ContiguousRegs && (i < CSI.size()-1)) {
unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
CanUseDblStore = (SuperRegNext == SuperReg);
}
if (CanUseDblStore) {
TII.storeRegToStackSlot(MBB, MI, SuperReg, true,
CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
MBB.addLiveIn(SuperReg);
++i;
} else {
// Cannot use a double-word store.
ContiguousRegs = false;
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
TRI);
MBB.addLiveIn(Reg);
}
}
return true;
}
bool HexagonFrameLowering::restoreCalleeSavedRegisters(
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
MachineFunction *MF = MBB.getParent();
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
if (CSI.empty()) {
return false;
}
// We can only schedule double loads if we spill contiguous callee-saved regs
// For instance, we cannot scheduled double-word loads if we spill r24,
// r26, and r27.
// Hexagon_TODO: We can try to double-word align odd registers for -O2 and
// above.
bool ContiguousRegs = true;
for (unsigned i = 0; i < CSI.size(); ++i) {
unsigned Reg = CSI[i].getReg();
//
// Check if we can use a double-word load.
//
unsigned SuperReg = uniqueSuperReg(Reg, TRI);
const TargetRegisterClass* SuperRegClass = 0;
bool CanUseDblLoad = false;
if (ContiguousRegs && (i < CSI.size()-1)) {
unsigned SuperRegNext = uniqueSuperReg(CSI[i+1].getReg(), TRI);
SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg);
CanUseDblLoad = (SuperRegNext == SuperReg);
}
if (CanUseDblLoad) {
TII.loadRegFromStackSlot(MBB, MI, SuperReg, CSI[i+1].getFrameIdx(),
SuperRegClass, TRI);
MBB.addLiveIn(SuperReg);
++i;
} else {
// Cannot use a double-word load.
ContiguousRegs = false;
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
MBB.addLiveIn(Reg);
}
}
return true;
}
int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
int FI) const {
return MF.getFrameInfo()->getObjectOffset(FI);
}