mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-01 03:33:42 +00:00
[Hexagon] Overhaul of stack object allocation
- Use static allocation for aligned stack objects. - Simplify dynamic stack object allocation. - Simplify elimination of frame-indices. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235521 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1436ff81cc
commit
5ce227e787
File diff suppressed because it is too large
Load Diff
@ -15,17 +15,22 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonInstrInfo;
|
||||
|
||||
class HexagonFrameLowering : public TargetFrameLowering {
|
||||
private:
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
void expandAlloca(MachineInstr *AI, const HexagonInstrInfo &TII,
|
||||
unsigned SP, unsigned CF) const;
|
||||
|
||||
public:
|
||||
explicit HexagonFrameLowering() : TargetFrameLowering(StackGrowsDown, 8, 0) {}
|
||||
explicit HexagonFrameLowering()
|
||||
: TargetFrameLowering(StackGrowsDown, 8, 0, 1, true) {}
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
void emitPrologue(MachineFunction &MF) const override;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
|
||||
bool targetHandlesStackFrameRounding() const override {
|
||||
return true;
|
||||
}
|
||||
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
@ -41,9 +46,37 @@ public:
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const override;
|
||||
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
|
||||
RegScavenger *RS = NULL) const override;
|
||||
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
RegScavenger *RS) const override;
|
||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const override;
|
||||
bool hasFP(const MachineFunction &MF) const override;
|
||||
bool hasTailCall(MachineBasicBlock &MBB) const;
|
||||
void adjustForCalleeSavedRegsSpillCall(MachineFunction &MF) const;
|
||||
bool replacePredRegPseudoSpillCode(MachineFunction &MF) const;
|
||||
|
||||
const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries)
|
||||
const override {
|
||||
static const SpillSlot Offsets[] = {
|
||||
{ Hexagon::R17, -4 }, { Hexagon::R16, -8 }, { Hexagon::D8, -8 },
|
||||
{ Hexagon::R19, -12 }, { Hexagon::R18, -16 }, { Hexagon::D9, -16 },
|
||||
{ Hexagon::R21, -20 }, { Hexagon::R20, -24 }, { Hexagon::D10, -24 },
|
||||
{ Hexagon::R23, -28 }, { Hexagon::R22, -32 }, { Hexagon::D11, -32 },
|
||||
{ Hexagon::R25, -36 }, { Hexagon::R24, -40 }, { Hexagon::D12, -40 },
|
||||
{ Hexagon::R27, -44 }, { Hexagon::R26, -48 }, { Hexagon::D13, -48 }
|
||||
};
|
||||
|
||||
NumEntries = array_lengthof(Offsets);
|
||||
return Offsets;
|
||||
}
|
||||
|
||||
bool assignCalleeSavedSpillSlots(MachineFunction &MF,
|
||||
const TargetRegisterInfo *TRI,
|
||||
std::vector<CalleeSavedInfo> &CSI) const override;
|
||||
|
||||
bool needsAligna(const MachineFunction &MF) const;
|
||||
MachineInstr *getAlignaInstr(MachineFunction &MF) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -13,8 +13,11 @@
|
||||
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonISelLowering.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/CodeGen/FunctionLoweringInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@ -62,6 +65,7 @@ public:
|
||||
}
|
||||
|
||||
virtual void PreprocessISelDAG() override;
|
||||
virtual void EmitFunctionEntryCode() override;
|
||||
|
||||
SDNode *Select(SDNode *N) override;
|
||||
|
||||
@ -1216,12 +1220,30 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
|
||||
|
||||
SDNode *HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
|
||||
MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const HexagonFrameLowering *HFI = HST->getFrameLowering();
|
||||
int FX = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
unsigned StkA = HFI->getStackAlignment();
|
||||
unsigned MaxA = MFI->getMaxAlignment();
|
||||
SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
|
||||
SDValue Zero = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
SDLoc DL(N);
|
||||
SDNode *R = 0;
|
||||
|
||||
SDNode *R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
|
||||
// Use TFR_FI when:
|
||||
// - the object is fixed, or
|
||||
// - there are no objects with higher-than-default alignment, or
|
||||
// - there are no dynamically allocated objects.
|
||||
// Otherwise, use TFR_FIA.
|
||||
if (FX < 0 || MaxA <= StkA || !MFI->hasVarSizedObjects()) {
|
||||
R = CurDAG->getMachineNode(Hexagon::TFR_FI, DL, MVT::i32, FI, Zero);
|
||||
} else {
|
||||
auto &HMFI = *MF->getInfo<HexagonMachineFunctionInfo>();
|
||||
unsigned AR = HMFI.getStackAlignBaseVReg();
|
||||
SDValue CH = CurDAG->getEntryNode();
|
||||
SDValue Ops[] = { CurDAG->getCopyFromReg(CH, DL, AR, MVT::i32), FI, Zero };
|
||||
R = CurDAG->getMachineNode(Hexagon::TFR_FIA, DL, MVT::i32, Ops);
|
||||
}
|
||||
|
||||
if (N->getHasDebugValue())
|
||||
CurDAG->TransferDbgValues(SDValue(N, 0), SDValue(R, 0));
|
||||
@ -1280,7 +1302,6 @@ SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
|
||||
return SelectCode(N);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonDAGToDAGISel::
|
||||
SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
|
||||
std::vector<SDValue> &OutOps) {
|
||||
@ -1352,12 +1373,32 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
|
||||
}
|
||||
}
|
||||
|
||||
void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
|
||||
auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
|
||||
auto &HFI = *HST.getFrameLowering();
|
||||
if (!HFI.needsAligna(*MF))
|
||||
return;
|
||||
|
||||
MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
MachineBasicBlock *EntryBB = MF->begin();
|
||||
unsigned AR = FuncInfo->CreateReg(MVT::i32);
|
||||
unsigned MaxA = MFI->getMaxAlignment();
|
||||
auto &HII = *HST.getInstrInfo();
|
||||
BuildMI(EntryBB, DebugLoc(), HII.get(Hexagon::ALIGNA), AR)
|
||||
.addImm(MaxA);
|
||||
MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
|
||||
}
|
||||
|
||||
// Match a frame index that can be used in an addressing mode.
|
||||
bool HexagonDAGToDAGISel::SelectAddrFI(SDValue& N, SDValue &R) {
|
||||
if (N.getOpcode() != ISD::FrameIndex)
|
||||
return false;
|
||||
FrameIndexSDNode *FX = cast<FrameIndexSDNode>(N);
|
||||
R = CurDAG->getTargetFrameIndex(FX->getIndex(), MVT::i32);
|
||||
auto &HFI = *HST->getFrameLowering();
|
||||
MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
int FX = cast<FrameIndexSDNode>(N)->getIndex();
|
||||
if (!MFI->isFixedObjectIndex(FX) && HFI.needsAligna(*MF))
|
||||
return false;
|
||||
R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -420,6 +420,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
bool doesNotReturn = CLI.DoesNotReturn;
|
||||
|
||||
bool IsStructRet = (Outs.empty()) ? false : Outs[0].Flags.isSRet();
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
|
||||
// Check for varargs.
|
||||
int NumNamedVarArgParams = -1;
|
||||
@ -444,41 +445,40 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
HexagonCCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
|
||||
*DAG.getContext(), NumNamedVarArgParams);
|
||||
|
||||
if (NumNamedVarArgParams > 0)
|
||||
if (isVarArg)
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
|
||||
else
|
||||
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
|
||||
|
||||
if (DAG.getTarget().Options.DisableTailCalls)
|
||||
isTailCall = false;
|
||||
|
||||
if(isTailCall) {
|
||||
bool StructAttrFlag =
|
||||
DAG.getMachineFunction().getFunction()->hasStructRetAttr();
|
||||
if (isTailCall) {
|
||||
bool StructAttrFlag = MF.getFunction()->hasStructRetAttr();
|
||||
isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
|
||||
isVarArg, IsStructRet,
|
||||
StructAttrFlag,
|
||||
Outs, OutVals, Ins, DAG);
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i){
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
if (VA.isMemLoc()) {
|
||||
isTailCall = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isTailCall) {
|
||||
DEBUG(dbgs () << "Eligible for Tail Call\n");
|
||||
} else {
|
||||
DEBUG(dbgs () <<
|
||||
"Argument must be passed on stack. Not eligible for Tail Call\n");
|
||||
}
|
||||
DEBUG(dbgs() << (isTailCall ? "Eligible for Tail Call\n"
|
||||
: "Argument must be passed on stack. "
|
||||
"Not eligible for Tail Call\n"));
|
||||
}
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NumBytes = CCInfo.getNextStackOffset();
|
||||
SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
|
||||
SmallVector<SDValue, 8> MemOpChains;
|
||||
|
||||
const HexagonRegisterInfo *QRI = Subtarget->getRegisterInfo();
|
||||
SDValue StackPtr =
|
||||
DAG.getCopyFromReg(Chain, dl, QRI->getStackRegister(), getPointerTy());
|
||||
auto &HRI =
|
||||
static_cast<const HexagonRegisterInfo&>(*Subtarget->getRegisterInfo());
|
||||
SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(),
|
||||
getPointerTy());
|
||||
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
@ -491,6 +491,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
default:
|
||||
// Loc info must be one of Full, SExt, ZExt, or AExt.
|
||||
llvm_unreachable("Unknown loc info!");
|
||||
case CCValAssign::BCvt:
|
||||
case CCValAssign::Full:
|
||||
break;
|
||||
case CCValAssign::SExt:
|
||||
@ -506,41 +507,37 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
|
||||
if (VA.isMemLoc()) {
|
||||
unsigned LocMemOffset = VA.getLocMemOffset();
|
||||
SDValue PtrOff = DAG.getConstant(LocMemOffset, StackPtr.getValueType());
|
||||
PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff);
|
||||
|
||||
SDValue MemAddr = DAG.getConstant(LocMemOffset, StackPtr.getValueType());
|
||||
MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
|
||||
if (Flags.isByVal()) {
|
||||
// The argument is a struct passed by value. According to LLVM, "Arg"
|
||||
// is is pointer.
|
||||
MemOpChains.push_back(CreateCopyOfByValArgument(Arg, PtrOff, Chain,
|
||||
MemOpChains.push_back(CreateCopyOfByValArgument(Arg, MemAddr, Chain,
|
||||
Flags, DAG, dl));
|
||||
} else {
|
||||
// The argument is not passed by value. "Arg" is a buildin type. It is
|
||||
// not a pointer.
|
||||
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
|
||||
MachinePointerInfo(),false, false,
|
||||
0));
|
||||
MachinePointerInfo LocPI = MachinePointerInfo::getStack(LocMemOffset);
|
||||
SDValue S = DAG.getStore(Chain, dl, Arg, MemAddr, LocPI, false,
|
||||
false, 0);
|
||||
MemOpChains.push_back(S);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Arguments that can be passed on register must be kept at RegsToPass
|
||||
// vector.
|
||||
if (VA.isRegLoc()) {
|
||||
if (VA.isRegLoc())
|
||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||
}
|
||||
}
|
||||
|
||||
// Transform all store nodes into one single node because all store
|
||||
// nodes are independent of each other.
|
||||
if (!MemOpChains.empty()) {
|
||||
if (!MemOpChains.empty())
|
||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
|
||||
}
|
||||
|
||||
if (!isTailCall)
|
||||
Chain = DAG.getCALLSEQ_START(Chain, DAG.getConstant(NumBytes,
|
||||
getPointerTy(), true),
|
||||
dl);
|
||||
if (!isTailCall) {
|
||||
SDValue C = DAG.getConstant(NumBytes, getPointerTy(), true);
|
||||
Chain = DAG.getCALLSEQ_START(Chain, C, dl);
|
||||
}
|
||||
|
||||
// Build a sequence of copy-to-reg nodes chained together with token
|
||||
// chain and flag operands which copy the outgoing args into registers.
|
||||
@ -553,10 +550,9 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
}
|
||||
|
||||
// For tail calls lower the arguments to the 'real' stack slot.
|
||||
if (isTailCall) {
|
||||
} else {
|
||||
// For tail calls lower the arguments to the 'real' stack slot.
|
||||
//
|
||||
// Force all the incoming stack arguments to be loaded from the stack
|
||||
// before any new outgoing arguments are stored to the stack, because the
|
||||
// outgoing stack slots may alias the incoming argument stack slots, and
|
||||
@ -571,7 +567,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
RegsToPass[i].second, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
InFlag =SDValue();
|
||||
InFlag = SDValue();
|
||||
}
|
||||
|
||||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
||||
@ -580,8 +576,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
if (flag_aligned_memcpy) {
|
||||
const char *MemcpyName =
|
||||
"__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes";
|
||||
Callee =
|
||||
DAG.getTargetExternalSymbol(MemcpyName, getPointerTy());
|
||||
Callee = DAG.getTargetExternalSymbol(MemcpyName, getPointerTy());
|
||||
flag_aligned_memcpy = false;
|
||||
} else if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, getPointerTy());
|
||||
@ -603,9 +598,8 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
RegsToPass[i].second.getValueType()));
|
||||
}
|
||||
|
||||
if (InFlag.getNode()) {
|
||||
if (InFlag.getNode())
|
||||
Ops.push_back(InFlag);
|
||||
}
|
||||
|
||||
if (isTailCall)
|
||||
return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, Ops);
|
||||
@ -630,7 +624,7 @@ static bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
|
||||
SDValue &Offset, bool &isInc,
|
||||
SelectionDAG &DAG) {
|
||||
if (Ptr->getOpcode() != ISD::ADD)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
|
||||
isInc = (Ptr->getOpcode() == ISD::ADD);
|
||||
@ -702,8 +696,7 @@ SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDNode *Node = Op.getNode();
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
HexagonMachineFunctionInfo *FuncInfo =
|
||||
MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
switch (Node->getOpcode()) {
|
||||
case ISD::INLINEASM: {
|
||||
unsigned NumOps = Node->getNumOperands();
|
||||
@ -711,7 +704,7 @@ SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
|
||||
--NumOps; // Ignore the flag operand.
|
||||
|
||||
for (unsigned i = InlineAsm::Op_FirstOperand; i != NumOps;) {
|
||||
if (FuncInfo->hasClobberLR())
|
||||
if (FuncInfo.hasClobberLR())
|
||||
break;
|
||||
unsigned Flags =
|
||||
cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
|
||||
@ -736,7 +729,7 @@ SDValue HexagonTargetLowering::LowerINLINEASM(SDValue Op,
|
||||
// Check it to be lr
|
||||
const HexagonRegisterInfo *QRI = Subtarget->getRegisterInfo();
|
||||
if (Reg == QRI->getRARegister()) {
|
||||
FuncInfo->setHasClobberLR(true);
|
||||
FuncInfo.setHasClobberLR(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -795,43 +788,28 @@ HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Size = Op.getOperand(1);
|
||||
SDValue Align = Op.getOperand(2);
|
||||
SDLoc dl(Op);
|
||||
|
||||
unsigned SPReg = getStackPointerRegisterToSaveRestore();
|
||||
ConstantSDNode *AlignConst = dyn_cast<ConstantSDNode>(Align);
|
||||
assert(AlignConst && "Non-constant Align in LowerDYNAMIC_STACKALLOC");
|
||||
|
||||
// Get a reference to the stack pointer.
|
||||
SDValue StackPointer = DAG.getCopyFromReg(Chain, dl, SPReg, MVT::i32);
|
||||
unsigned A = AlignConst->getSExtValue();
|
||||
auto &HST = static_cast<const HexagonSubtarget&>(DAG.getSubtarget());
|
||||
auto &HFI = *HST.getFrameLowering();
|
||||
// "Zero" means natural stack alignment.
|
||||
if (A == 0)
|
||||
A = HFI.getStackAlignment();
|
||||
|
||||
// Subtract the dynamic size from the actual stack size to
|
||||
// obtain the new stack size.
|
||||
SDValue Sub = DAG.getNode(ISD::SUB, dl, MVT::i32, StackPointer, Size);
|
||||
DEBUG({
|
||||
dbgs () << __func__ << " Align: " << A << " Size: ";
|
||||
Size.getNode()->dump(&DAG);
|
||||
dbgs() << "\n";
|
||||
});
|
||||
|
||||
//
|
||||
// For Hexagon, the outgoing memory arguments area should be on top of the
|
||||
// alloca area on the stack i.e., the outgoing memory arguments should be
|
||||
// at a lower address than the alloca area. Move the alloca area down the
|
||||
// stack by adding back the space reserved for outgoing arguments to SP
|
||||
// here.
|
||||
//
|
||||
// We do not know what the size of the outgoing args is at this point.
|
||||
// So, we add a pseudo instruction ADJDYNALLOC that will adjust the
|
||||
// stack pointer. We patch this instruction with the correct, known
|
||||
// offset in emitPrologue().
|
||||
//
|
||||
// Use a placeholder immediate (zero) for now. This will be patched up
|
||||
// by emitPrologue().
|
||||
SDValue ArgAdjust = DAG.getNode(HexagonISD::ADJDYNALLOC, dl,
|
||||
MVT::i32,
|
||||
Sub,
|
||||
DAG.getConstant(0, MVT::i32));
|
||||
|
||||
// The Sub result contains the new stack start address, so it
|
||||
// must be placed in the stack pointer register.
|
||||
const HexagonRegisterInfo *QRI = Subtarget->getRegisterInfo();
|
||||
SDValue CopyChain = DAG.getCopyToReg(Chain, dl, QRI->getStackRegister(), Sub);
|
||||
|
||||
SDValue Ops[2] = { ArgAdjust, CopyChain };
|
||||
return DAG.getMergeValues(Ops, dl);
|
||||
SDValue AC = DAG.getConstant(A, MVT::i32);
|
||||
SDVTList VTs = DAG.getVTList(MVT::i32, MVT::Other);
|
||||
return DAG.getNode(HexagonISD::ALLOCA, dl, VTs, Chain, Size, AC);
|
||||
}
|
||||
|
||||
SDValue
|
||||
@ -847,9 +825,7 @@ const {
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
||||
HexagonMachineFunctionInfo *FuncInfo =
|
||||
MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
|
||||
auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
|
||||
// Assign locations to all of the incoming arguments.
|
||||
SmallVector<CCValAssign, 16> ArgLocs;
|
||||
@ -938,7 +914,7 @@ const {
|
||||
HEXAGON_LRFP_SIZE +
|
||||
CCInfo.getNextStackOffset(),
|
||||
true);
|
||||
FuncInfo->setVarArgsFrameIndex(FrameIndex);
|
||||
FuncInfo.setVarArgsFrameIndex(FrameIndex);
|
||||
}
|
||||
|
||||
return Chain;
|
||||
@ -1795,7 +1771,7 @@ HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case HexagonISD::CONST32: return "HexagonISD::CONST32";
|
||||
case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP";
|
||||
case HexagonISD::CONST32_Int_Real: return "HexagonISD::CONST32_Int_Real";
|
||||
case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
|
||||
case HexagonISD::ALLOCA: return "HexagonISD::ALLOCA";
|
||||
case HexagonISD::CMPICC: return "HexagonISD::CMPICC";
|
||||
case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC";
|
||||
case HexagonISD::BRICC: return "HexagonISD::BRICC";
|
||||
@ -2419,20 +2395,14 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Hexagon Scheduler Hooks
|
||||
//===----------------------------------------------------------------------===//
|
||||
MachineBasicBlock *
|
||||
HexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB)
|
||||
const {
|
||||
const {
|
||||
switch (MI->getOpcode()) {
|
||||
case Hexagon::ADJDYNALLOC: {
|
||||
case Hexagon::ALLOCA: {
|
||||
MachineFunction *MF = BB->getParent();
|
||||
HexagonMachineFunctionInfo *FuncInfo =
|
||||
MF->getInfo<HexagonMachineFunctionInfo>();
|
||||
auto *FuncInfo = MF->getInfo<HexagonMachineFunctionInfo>();
|
||||
FuncInfo->addAllocaAdjustInst(MI);
|
||||
return BB;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ bool isPositiveHalfWord(SDNode *N);
|
||||
CONST32_Int_Real,
|
||||
FCONST32,
|
||||
SETCC,
|
||||
ADJDYNALLOC,
|
||||
ALLOCA,
|
||||
ARGEXTEND,
|
||||
|
||||
PIC_ADD,
|
||||
|
@ -573,6 +573,12 @@ HexagonInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
|
||||
unsigned Opc = MI->getOpcode();
|
||||
|
||||
switch (Opc) {
|
||||
case Hexagon::ALIGNA:
|
||||
BuildMI(MBB, MI, DL, get(Hexagon::A2_andir), MI->getOperand(0).getReg())
|
||||
.addReg(TRI.getFrameRegister())
|
||||
.addImm(-MI->getOperand(1).getImm());
|
||||
MBB.erase(MI);
|
||||
return true;
|
||||
case Hexagon::TFR_PdTrue: {
|
||||
unsigned Reg = MI->getOperand(0).getReg();
|
||||
BuildMI(MBB, MI, DL, get(Hexagon::C2_orn), Reg)
|
||||
|
@ -4526,10 +4526,18 @@ def Y2_barrier : SYSInst<(outs), (ins),
|
||||
// SYSTEM/SUPER -
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Generate frameindex addresses.
|
||||
// Generate frameindex addresses. The main reason for the offset operand is
|
||||
// that every instruction that is allowed to have frame index as an operand
|
||||
// will then have that operand followed by an immediate operand (the offset).
|
||||
// This simplifies the frame-index elimination code.
|
||||
//
|
||||
let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1,
|
||||
isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0 in
|
||||
def TFR_FI: ALU32_ri<(outs IntRegs:$Rd), (ins IntRegs:$fi, s32Imm:$Off), "">;
|
||||
isPseudo = 1, isCodeGenOnly = 1, hasSideEffects = 0 in {
|
||||
def TFR_FI : ALU32_ri<(outs IntRegs:$Rd),
|
||||
(ins IntRegs:$fi, s32Imm:$off), "">;
|
||||
def TFR_FIA : ALU32_ri<(outs IntRegs:$Rd),
|
||||
(ins IntRegs:$Rs, IntRegs:$fi, s32Imm:$off), "">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// CRUSER - Type.
|
||||
@ -5105,21 +5113,25 @@ def : Pat <(mulhu (i64 DoubleRegs:$src1), (i64 DoubleRegs:$src2)),
|
||||
)>;
|
||||
|
||||
// Hexagon specific ISD nodes.
|
||||
def SDTHexagonADJDYNALLOC : SDTypeProfile<1, 2, [SDTCisVT<0, i32>,
|
||||
SDTCisVT<1, i32>]>;
|
||||
def SDTHexagonARGEXTEND : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
|
||||
def SDTHexagonALLOCA : SDTypeProfile<1, 2,
|
||||
[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
def HexagonALLOCA : SDNode<"HexagonISD::ALLOCA", SDTHexagonALLOCA,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
def Hexagon_ADJDYNALLOC : SDNode<"HexagonISD::ADJDYNALLOC",
|
||||
SDTHexagonADJDYNALLOC>;
|
||||
def Hexagon_ARGEXTEND : SDNode<"HexagonISD::ARGEXTEND", SDTHexagonARGEXTEND>;
|
||||
// The reason for the custom inserter is to record all ALLOCA instructions
|
||||
// in MachineFunctionInfo.
|
||||
let Defs = [R29], isCodeGenOnly = 1, isPseudo = 1, hasSideEffects = 1,
|
||||
usesCustomInserter = 1 in
|
||||
def ALLOCA: ALU32Inst<(outs IntRegs:$Rd),
|
||||
(ins IntRegs:$Rs, u32Imm:$A), "",
|
||||
[(set (i32 IntRegs:$Rd),
|
||||
(HexagonALLOCA (i32 IntRegs:$Rs), (i32 imm:$A)))]>;
|
||||
|
||||
// Needed to tag these instructions for stack layout.
|
||||
let isCodeGenOnly = 1, usesCustomInserter = 1 in
|
||||
def ADJDYNALLOC : T_Addri<s6Imm>;
|
||||
|
||||
def: Pat<(Hexagon_ADJDYNALLOC I32:$Rs, s16ImmPred:$s16),
|
||||
(ADJDYNALLOC I32:$Rs, imm:$s16)>;
|
||||
let isCodeGenOnly = 1, isPseudo = 1, Uses = [R30], hasSideEffects = 0 in
|
||||
def ALIGNA : ALU32Inst<(outs IntRegs:$Rd), (ins u32Imm:$A), "", []>;
|
||||
|
||||
def SDTHexagonARGEXTEND : SDTypeProfile<1, 1, [SDTCisVT<0, i32>]>;
|
||||
def Hexagon_ARGEXTEND : SDNode<"HexagonISD::ARGEXTEND", SDTHexagonARGEXTEND>;
|
||||
let isCodeGenOnly = 1 in
|
||||
def ARGEXTEND : ALU32_rr <(outs IntRegs:$dst), (ins IntRegs:$src1),
|
||||
"$dst = $src1",
|
||||
|
@ -27,6 +27,7 @@ class HexagonMachineFunctionInfo : public MachineFunctionInfo {
|
||||
// returning the value of the returned struct in a register. This field
|
||||
// holds the virtual register into which the sret argument is passed.
|
||||
unsigned SRetReturnReg;
|
||||
unsigned StackAlignBaseReg;
|
||||
std::vector<MachineInstr*> AllocaAdjustInsts;
|
||||
int VarArgsFrameIndex;
|
||||
bool HasClobberLR;
|
||||
@ -35,10 +36,11 @@ class HexagonMachineFunctionInfo : public MachineFunctionInfo {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
HexagonMachineFunctionInfo() : SRetReturnReg(0), HasClobberLR(0),
|
||||
HasEHReturn(false) {}
|
||||
HexagonMachineFunctionInfo() : SRetReturnReg(0), StackAlignBaseReg(0),
|
||||
HasClobberLR(0), HasEHReturn(false) {}
|
||||
|
||||
HexagonMachineFunctionInfo(MachineFunction &MF) : SRetReturnReg(0),
|
||||
StackAlignBaseReg(0),
|
||||
HasClobberLR(0),
|
||||
HasEHReturn(false) {}
|
||||
|
||||
@ -74,6 +76,9 @@ public:
|
||||
|
||||
bool hasEHReturn() const { return HasEHReturn; };
|
||||
void setHasEHReturn(bool H = true) { HasEHReturn = H; };
|
||||
|
||||
void setStackAlignBaseVReg(unsigned R) { StackAlignBaseReg = R; }
|
||||
unsigned getStackAlignBaseVReg() const { return StackAlignBaseReg; }
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -30,7 +30,9 @@
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
@ -40,6 +42,37 @@ using namespace llvm;
|
||||
HexagonRegisterInfo::HexagonRegisterInfo()
|
||||
: HexagonGenRegisterInfo(Hexagon::R31) {}
|
||||
|
||||
|
||||
bool HexagonRegisterInfo::isEHReturnCalleeSaveReg(unsigned R) const {
|
||||
return R == Hexagon::R0 || R == Hexagon::R1 || R == Hexagon::R2 ||
|
||||
R == Hexagon::R3 || R == Hexagon::D0 || R == Hexagon::D1;
|
||||
}
|
||||
|
||||
bool HexagonRegisterInfo::isCalleeSaveReg(unsigned Reg) const {
|
||||
return Hexagon::R16 <= Reg && Reg <= Hexagon::R27;
|
||||
}
|
||||
|
||||
|
||||
const MCPhysReg *
|
||||
HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF) const {
|
||||
static const MCPhysReg CallerSavedRegsV4[] = {
|
||||
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
||||
Hexagon::R5, Hexagon::R6, Hexagon::R7, Hexagon::R8, Hexagon::R9,
|
||||
Hexagon::R10, Hexagon::R11, Hexagon::R12, Hexagon::R13, Hexagon::R14,
|
||||
Hexagon::R15, 0
|
||||
};
|
||||
|
||||
auto &HST = static_cast<const HexagonSubtarget&>(MF->getSubtarget());
|
||||
switch (HST.getHexagonArchVersion()) {
|
||||
case HexagonSubtarget::V4:
|
||||
case HexagonSubtarget::V5:
|
||||
return CallerSavedRegsV4;
|
||||
}
|
||||
llvm_unreachable(
|
||||
"Callee saved registers requested for unknown archtecture version");
|
||||
}
|
||||
|
||||
|
||||
const MCPhysReg *
|
||||
HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
static const MCPhysReg CalleeSavedRegsV3[] = {
|
||||
@ -75,173 +108,153 @@ BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
|
||||
}
|
||||
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
};
|
||||
|
||||
switch (MF->getSubtarget<HexagonSubtarget>().getHexagonArchVersion()) {
|
||||
case HexagonSubtarget::V4:
|
||||
case HexagonSubtarget::V5:
|
||||
return CalleeSavedRegClassesV3;
|
||||
}
|
||||
llvm_unreachable("Callee saved register classes requested for unknown "
|
||||
"architecture version");
|
||||
}
|
||||
|
||||
void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
int SPAdj, unsigned FIOp,
|
||||
RegScavenger *RS) const {
|
||||
//
|
||||
// Hexagon_TODO: Do we need to enforce this for Hexagon?
|
||||
assert(SPAdj == 0 && "Unexpected");
|
||||
|
||||
MachineInstr &MI = *II;
|
||||
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
||||
|
||||
// Addressable stack objects are accessed using neg. offsets from %fp.
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
const HexagonInstrInfo &TII =
|
||||
*static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
||||
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
|
||||
MachineBasicBlock &MB = *MI.getParent();
|
||||
MachineFunction &MF = *MB.getParent();
|
||||
MachineFrameInfo &MFI = *MF.getFrameInfo();
|
||||
auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
|
||||
auto &HII = *HST.getInstrInfo();
|
||||
auto &HFI = *HST.getFrameLowering();
|
||||
|
||||
unsigned FrameReg = getFrameRegister(MF);
|
||||
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
||||
if (!TFI->hasFP(MF)) {
|
||||
int FI = MI.getOperand(FIOp).getIndex();
|
||||
int Offset = MFI.getObjectOffset(FI) + MI.getOperand(FIOp+1).getImm();
|
||||
bool HasAlloca = MFI.hasVarSizedObjects();
|
||||
bool HasAlign = needsStackRealignment(MF);
|
||||
|
||||
// XXX: Fixed objects cannot be accessed through SP if there are aligned
|
||||
// objects in the local frame, or if there are dynamically allocated objects.
|
||||
// In such cases, there has to be FP available.
|
||||
if (!HFI.hasFP(MF)) {
|
||||
assert(!HasAlloca && !HasAlign && "This function must have frame pointer");
|
||||
// We will not reserve space on the stack for the lr and fp registers.
|
||||
Offset -= 2 * Hexagon_WordSize;
|
||||
Offset -= 8;
|
||||
}
|
||||
|
||||
unsigned SP = getStackRegister(), FP = getFrameRegister();
|
||||
unsigned AP = 0;
|
||||
if (MachineInstr *AI = HFI.getAlignaInstr(MF))
|
||||
AP = AI->getOperand(0).getReg();
|
||||
unsigned FrameSize = MFI.getStackSize();
|
||||
if (MI.getOpcode() == Hexagon::TFR_FI)
|
||||
MI.setDesc(TII.get(Hexagon::A2_addi));
|
||||
|
||||
if (!MFI.hasVarSizedObjects() &&
|
||||
TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
|
||||
!TII.isSpillPredRegOp(&MI)) {
|
||||
// Replace frame index with a stack pointer reference.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(getStackRegister(), false,
|
||||
false, true);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(FrameSize+Offset);
|
||||
// Special handling of dbg_value instructions and INLINEASM.
|
||||
if (MI.isDebugValue() || MI.isInlineAsm()) {
|
||||
MI.getOperand(FIOp).ChangeToRegister(SP, false /*isDef*/);
|
||||
MI.getOperand(FIOp+1).ChangeToImmediate(Offset+FrameSize);
|
||||
return;
|
||||
}
|
||||
|
||||
bool UseFP = false, UseAP = false; // Default: use SP.
|
||||
if (MFI.isFixedObjectIndex(FI) || MFI.isObjectPreAllocated(FI)) {
|
||||
UseFP = HasAlloca || HasAlign;
|
||||
} else {
|
||||
// Replace frame index with a frame pointer reference.
|
||||
if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
|
||||
|
||||
// If the offset overflows, then correct it.
|
||||
//
|
||||
// For loads, we do not need a reserved register
|
||||
// r0 = memw(r30 + #10000) to:
|
||||
//
|
||||
// r0 = add(r30, #10000)
|
||||
// r0 = memw(r0)
|
||||
if ( (MI.getOpcode() == Hexagon::L2_loadri_io) ||
|
||||
(MI.getOpcode() == Hexagon::L2_loadrd_io) ||
|
||||
(MI.getOpcode() == Hexagon::L2_loadrh_io) ||
|
||||
(MI.getOpcode() == Hexagon::L2_loadruh_io) ||
|
||||
(MI.getOpcode() == Hexagon::L2_loadrb_io) ||
|
||||
(MI.getOpcode() == Hexagon::L2_loadrub_io)) {
|
||||
unsigned dstReg = (MI.getOpcode() == Hexagon::L2_loadrd_io) ?
|
||||
getSubReg(MI.getOperand(0).getReg(), Hexagon::subreg_loreg) :
|
||||
MI.getOperand(0).getReg();
|
||||
|
||||
// Check if offset can fit in addi.
|
||||
if (!TII.isValidOffset(Hexagon::A2_addi, Offset)) {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::A2_add),
|
||||
dstReg).addReg(FrameReg).addReg(dstReg);
|
||||
} else {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::A2_addi),
|
||||
dstReg).addReg(FrameReg).addImm(Offset);
|
||||
}
|
||||
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
|
||||
MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
|
||||
} else if ((MI.getOpcode() == Hexagon::S2_storeri_io) ||
|
||||
(MI.getOpcode() == Hexagon::S2_storerd_io) ||
|
||||
(MI.getOpcode() == Hexagon::S2_storerh_io) ||
|
||||
(MI.getOpcode() == Hexagon::S2_storerb_io)) {
|
||||
// For stores, we need a reserved register. Change
|
||||
// memw(r30 + #10000) = r0 to:
|
||||
//
|
||||
// rs = add(r30, #10000);
|
||||
// memw(rs) = r0
|
||||
unsigned resReg = HEXAGON_RESERVED_REG_1;
|
||||
|
||||
// Check if offset can fit in addi.
|
||||
if (!TII.isValidOffset(Hexagon::A2_addi, Offset)) {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::A2_add),
|
||||
resReg).addReg(FrameReg).addReg(resReg);
|
||||
} else {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::A2_addi),
|
||||
resReg).addReg(FrameReg).addImm(Offset);
|
||||
}
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(resReg, false, false,true);
|
||||
MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
|
||||
} else if (TII.isMemOp(&MI)) {
|
||||
// use the constant extender if the instruction provides it
|
||||
if (TII.isConstExtended(&MI)) {
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
|
||||
MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
|
||||
TII.immediateExtend(&MI);
|
||||
} else {
|
||||
llvm_unreachable("Need to implement for memops");
|
||||
}
|
||||
} else {
|
||||
unsigned dstReg = MI.getOperand(0).getReg();
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::A2_add),
|
||||
dstReg).addReg(FrameReg).addReg(dstReg);
|
||||
// Can we delete MI??? r2 = add (r2, #0).
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(dstReg, false, false,true);
|
||||
MI.getOperand(FIOperandNum+1).ChangeToImmediate(0);
|
||||
}
|
||||
} else {
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false);
|
||||
MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
|
||||
if (HasAlloca) {
|
||||
if (HasAlign)
|
||||
UseAP = true;
|
||||
else
|
||||
UseFP = true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned Opc = MI.getOpcode();
|
||||
bool ValidSP = HII.isValidOffset(Opc, FrameSize+Offset);
|
||||
bool ValidFP = HII.isValidOffset(Opc, Offset);
|
||||
|
||||
// Calculate the actual offset in the instruction.
|
||||
int64_t RealOffset = Offset;
|
||||
if (!UseFP && !UseAP)
|
||||
RealOffset = FrameSize+Offset;
|
||||
|
||||
switch (Opc) {
|
||||
case Hexagon::TFR_FIA:
|
||||
MI.setDesc(HII.get(Hexagon::A2_addi));
|
||||
MI.getOperand(FIOp).ChangeToImmediate(RealOffset);
|
||||
MI.RemoveOperand(FIOp+1);
|
||||
return;
|
||||
case Hexagon::TFR_FI:
|
||||
// Set up the instruction for updating below.
|
||||
MI.setDesc(HII.get(Hexagon::A2_addi));
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned BP = 0;
|
||||
bool Valid = false;
|
||||
if (UseFP) {
|
||||
BP = FP;
|
||||
Valid = ValidFP;
|
||||
} else if (UseAP) {
|
||||
BP = AP;
|
||||
Valid = ValidFP;
|
||||
} else {
|
||||
BP = SP;
|
||||
Valid = ValidSP;
|
||||
}
|
||||
|
||||
if (Valid) {
|
||||
MI.getOperand(FIOp).ChangeToRegister(BP, false);
|
||||
MI.getOperand(FIOp+1).ChangeToImmediate(RealOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
const Function *F = MF.getFunction();
|
||||
dbgs() << "In function ";
|
||||
if (F) dbgs() << F->getName();
|
||||
else dbgs() << "<?>";
|
||||
dbgs() << ", BB#" << MB.getNumber() << "\n" << MI;
|
||||
#endif
|
||||
llvm_unreachable("Unhandled instruction");
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getRARegister() const {
|
||||
return Hexagon::R31;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
|
||||
&MF) const {
|
||||
const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
|
||||
if (TFI->hasFP(MF)) {
|
||||
if (TFI->hasFP(MF))
|
||||
return Hexagon::R30;
|
||||
}
|
||||
|
||||
return Hexagon::R29;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getFrameRegister() const {
|
||||
return Hexagon::R30;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getStackRegister() const {
|
||||
return Hexagon::R29;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HexagonRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
|
||||
return MF.getSubtarget().getFrameLowering()->hasFP(MF);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HexagonRegisterInfo::needsStackRealignment(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
return MFI->getMaxAlignment() > 8;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
|
||||
return Hexagon::R6;
|
||||
}
|
||||
|
||||
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "HexagonGenRegisterInfo.inc"
|
||||
|
@ -43,25 +43,29 @@ struct HexagonRegisterInfo : public HexagonGenRegisterInfo {
|
||||
/// Code Generation virtual methods...
|
||||
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
getCalleeSavedRegClasses(const MachineFunction *MF = nullptr) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
RegScavenger *RS = nullptr) const override;
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
unsigned FIOperandNum, RegScavenger *RS = nullptr) const override;
|
||||
|
||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
||||
/// frame size.
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
|
||||
/// requiresRegisterScavenging - returns true since we may need scavenging for
|
||||
/// a temporary register when generating hardware loop instructions.
|
||||
/// Returns true since we may need scavenging for a temporary register
|
||||
/// when generating hardware loop instructions.
|
||||
bool requiresRegisterScavenging(const MachineFunction &MF) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Returns true. Spill code for predicate registers might need an extra
|
||||
/// register.
|
||||
bool requiresFrameIndexScavenging(const MachineFunction &MF) const override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool needsStackRealignment(const MachineFunction &MF) const override;
|
||||
|
||||
/// Returns true if the frame pointer is valid.
|
||||
bool useFPForScavengingIndex(const MachineFunction &MF) const override;
|
||||
|
||||
bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override {
|
||||
return true;
|
||||
}
|
||||
@ -71,6 +75,12 @@ struct HexagonRegisterInfo : public HexagonGenRegisterInfo {
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const override;
|
||||
unsigned getFrameRegister() const;
|
||||
unsigned getStackRegister() const;
|
||||
|
||||
const uint16_t *getCallerSavedRegs(const MachineFunction *MF) const;
|
||||
unsigned getFirstCallerSavedNonParamReg() const;
|
||||
|
||||
bool isEHReturnCalleeSaveReg(unsigned Reg) const;
|
||||
bool isCalleeSaveReg(unsigned Reg) const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
Loading…
x
Reference in New Issue
Block a user