diff options
author | Robert Lytton <robert@xmos.com> | 2014-01-06 14:21:00 +0000 |
---|---|---|
committer | Robert Lytton <robert@xmos.com> | 2014-01-06 14:21:00 +0000 |
commit | 5da175214bffc33e394bf7531a8de49a2649b58c (patch) | |
tree | 986a373871e464bff4a316dbe475a7e338aeb088 /llvm/lib | |
parent | dec798751a0a7dc36b559fae920ab916bbe10137 (diff) | |
download | bcm5719-llvm-5da175214bffc33e394bf7531a8de49a2649b58c.tar.gz bcm5719-llvm-5da175214bffc33e394bf7531a8de49a2649b58c.zip |
XCore target: Lower FRAME_TO_ARGS_OFFSET
This requires a knowledge of the stack size which is not known until
the frame is complete, hence the need for the XCoreFTAOElim pass
which lowers the XCoreISD::FRAME_TO_ARGS_OFFSET instrution into its
final form.
llvm-svn: 198614
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/XCore/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCore.h | 1 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp | 70 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreISelLowering.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreISelLowering.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreInstrInfo.td | 8 | ||||
-rw-r--r-- | llvm/lib/Target/XCore/XCoreTargetMachine.cpp | 6 |
7 files changed, 102 insertions, 0 deletions
diff --git a/llvm/lib/Target/XCore/CMakeLists.txt b/llvm/lib/Target/XCore/CMakeLists.txt index 72d06ebaff5..5ad07544ef8 100644 --- a/llvm/lib/Target/XCore/CMakeLists.txt +++ b/llvm/lib/Target/XCore/CMakeLists.txt @@ -24,6 +24,7 @@ add_llvm_target(XCoreCodeGen XCoreTargetObjectFile.cpp XCoreTargetTransformInfo.cpp XCoreSelectionDAGInfo.cpp + XCoreFrameToArgsOffsetElim.cpp ) add_subdirectory(Disassembler) diff --git a/llvm/lib/Target/XCore/XCore.h b/llvm/lib/Target/XCore/XCore.h index 73c310be034..d707edc8735 100644 --- a/llvm/lib/Target/XCore/XCore.h +++ b/llvm/lib/Target/XCore/XCore.h @@ -27,6 +27,7 @@ namespace llvm { void initializeXCoreLowerThreadLocalPass(PassRegistry &p); + FunctionPass *createXCoreFrameToArgsOffsetEliminationPass(); FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM, CodeGenOpt::Level OptLevel); ModulePass *createXCoreLowerThreadLocalPass(); diff --git a/llvm/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp b/llvm/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp new file mode 100644 index 00000000000..29e2dd0e0cd --- /dev/null +++ b/llvm/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp @@ -0,0 +1,70 @@ +//===-- XCoreFrameToArgsOffsetElim.cpp ----------------------------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Replace Pseudo FRAME_TO_ARGS_OFFSET with the appropriate real offset. +// +//===----------------------------------------------------------------------===// + +#include "XCore.h" +#include "XCoreInstrInfo.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" +using namespace llvm; + +namespace { + struct XCoreFTAOElim : public MachineFunctionPass { + static char ID; + XCoreFTAOElim() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &Fn); + + virtual const char *getPassName() const { + return "XCore FRAME_TO_ARGS_OFFSET Elimination"; + } + }; + char XCoreFTAOElim::ID = 0; +} + +/// createXCoreFrameToArgsOffsetEliminationPass - returns an instance of the +/// Frame to args offset elimination pass +FunctionPass *llvm::createXCoreFrameToArgsOffsetEliminationPass() { + return new XCoreFTAOElim(); +} + +static inline bool isImmU6(unsigned val) { + return val < (1 << 6); +} + +static inline bool isImmU16(unsigned val) { + return val < (1 << 16); +} + +bool XCoreFTAOElim::runOnMachineFunction(MachineFunction &MF) { + const XCoreInstrInfo &TII = + *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo()); + unsigned StackSize = MF.getFrameInfo()->getStackSize(); + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) { + MachineBasicBlock &MBB = *MFI; + for (MachineBasicBlock::iterator MBBI = MBB.begin(), EE = MBB.end(); + MBBI != EE; ++MBBI) { + if (MBBI->getOpcode() == XCore::FRAME_TO_ARGS_OFFSET) { + MachineInstr *OldInst = MBBI; + unsigned Reg = OldInst->getOperand(0).getReg(); + MBBI = TII.loadImmediate(MBB, MBBI, Reg, StackSize); + OldInst->eraseFromParent(); + } + } + } + return true; +} diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp index 65568c96543..c0edee55e43 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -60,6 +60,7 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::CRC8 : return "XCoreISD::CRC8"; case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; + case XCoreISD::FRAME_TO_ARGS_OFFSET : return "XCoreISD::FRAME_TO_ARGS_OFFSET"; case XCoreISD::MEMBARRIER : return "XCoreISD::MEMBARRIER"; default : return NULL; } @@ -153,6 +154,7 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) // Exception handling setExceptionPointerRegister(XCore::R0); setExceptionSelectorRegister(XCore::R1); + setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); // Atomic operations setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); @@ -213,6 +215,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); + case ISD::FRAME_TO_ARGS_OFFSET: return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); @@ -827,6 +830,15 @@ LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { } SDValue XCoreTargetLowering:: +LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const { + // This node represents offset from frame pointer to first on-stack argument. + // This is needed for correct stack adjustment during unwind. + // However, we don't know the offset until after the frame has be finalised. + // This is done during the XCoreFTAOElim pass. + return DAG.getNode(XCoreISD::FRAME_TO_ARGS_OFFSET, SDLoc(Op), MVT::i32); +} + +SDValue XCoreTargetLowering:: LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const { return Op.getOperand(0); } diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.h b/llvm/lib/Target/XCore/XCoreISelLowering.h index a6dd2260246..c4de86e22dc 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.h +++ b/llvm/lib/Target/XCore/XCoreISelLowering.h @@ -72,6 +72,9 @@ namespace llvm { // Jumptable branch using long branches for each entry. BR_JT32, + // Offset from frame pointer to the first (possible) on-stack argument + FRAME_TO_ARGS_OFFSET, + // Memory barrier. MEMBARRIER }; @@ -158,6 +161,7 @@ namespace llvm { SDValue LowerUMUL_LOHI(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSMUL_LOHI(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const; SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; diff --git a/llvm/lib/Target/XCore/XCoreInstrInfo.td b/llvm/lib/Target/XCore/XCoreInstrInfo.td index 5974842383c..144d4fec246 100644 --- a/llvm/lib/Target/XCore/XCoreInstrInfo.td +++ b/llvm/lib/Target/XCore/XCoreInstrInfo.td @@ -56,6 +56,9 @@ def dprelwrapper : SDNode<"XCoreISD::DPRelativeWrapper", SDT_XCoreAddress, def cprelwrapper : SDNode<"XCoreISD::CPRelativeWrapper", SDT_XCoreAddress, []>; +def frametoargsoffset : SDNode<"XCoreISD::FRAME_TO_ARGS_OFFSET", SDTIntLeaf, + []>; + def SDT_XCoreStwsp : SDTypeProfile<0, 2, [SDTCisInt<1>]>; def XCoreStwsp : SDNode<"XCoreISD::STWSP", SDT_XCoreStwsp, [SDNPHasChain, SDNPMayStore]>; @@ -326,6 +329,11 @@ def ADJCALLSTACKUP : PseudoInstXCore<(outs), (ins i32imm:$amt1, i32imm:$amt2), [(callseq_end timm:$amt1, timm:$amt2)]>; } +let isReMaterializable = 1 in +def FRAME_TO_ARGS_OFFSET : PseudoInstXCore<(outs GRRegs:$dst), (ins), + "# FRAME_TO_ARGS_OFFSET $dst", + [(set GRRegs:$dst, (frametoargsoffset))]>; + def LDWFI : PseudoInstXCore<(outs GRRegs:$dst), (ins MEMii:$addr), "# LDWFI $dst, $addr", [(set GRRegs:$dst, (load ADDRspii:$addr))]>; diff --git a/llvm/lib/Target/XCore/XCoreTargetMachine.cpp b/llvm/lib/Target/XCore/XCoreTargetMachine.cpp index 21027270911..781a87b1e91 100644 --- a/llvm/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/llvm/lib/Target/XCore/XCoreTargetMachine.cpp @@ -48,6 +48,7 @@ public: virtual bool addPreISel(); virtual bool addInstSelector(); + virtual bool addPreEmitPass(); }; } // namespace @@ -65,6 +66,11 @@ bool XCorePassConfig::addInstSelector() { return false; } +bool XCorePassConfig::addPreEmitPass() { + addPass(createXCoreFrameToArgsOffsetEliminationPass()); + return false; +} + // Force static initialization. extern "C" void LLVMInitializeXCoreTarget() { RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget); |