From af74cbf553073b701fc570c7ef9b1446111ac9b6 Mon Sep 17 00:00:00 2001 From: Robert Lytton Date: Mon, 6 Jan 2014 14:21:00 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198614 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/XCore/CMakeLists.txt | 1 + lib/Target/XCore/XCore.h | 1 + .../XCore/XCoreFrameToArgsOffsetElim.cpp | 70 +++++++++++++++++++ lib/Target/XCore/XCoreISelLowering.cpp | 12 ++++ lib/Target/XCore/XCoreISelLowering.h | 4 ++ lib/Target/XCore/XCoreInstrInfo.td | 8 +++ lib/Target/XCore/XCoreTargetMachine.cpp | 6 ++ test/CodeGen/XCore/llvm-intrinsics.ll | 26 +++++++ 8 files changed, 128 insertions(+) create mode 100644 lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt index 72d06ebaff5..5ad07544ef8 100644 --- a/lib/Target/XCore/CMakeLists.txt +++ b/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/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h index 73c310be034..d707edc8735 100644 --- a/lib/Target/XCore/XCore.h +++ b/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/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp b/lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp new file mode 100644 index 00000000000..29e2dd0e0cd --- /dev/null +++ b/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(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/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index 65568c96543..c0edee55e43 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/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); @@ -826,6 +829,15 @@ LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const { false, 0); } +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/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index a6dd2260246..c4de86e22dc 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/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/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 5974842383c..144d4fec246 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/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/lib/Target/XCore/XCoreTargetMachine.cpp b/lib/Target/XCore/XCoreTargetMachine.cpp index 21027270911..781a87b1e91 100644 --- a/lib/Target/XCore/XCoreTargetMachine.cpp +++ b/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 X(TheXCoreTarget); diff --git a/test/CodeGen/XCore/llvm-intrinsics.ll b/test/CodeGen/XCore/llvm-intrinsics.ll index 14b299d46e8..55b77ac9e6b 100644 --- a/test/CodeGen/XCore/llvm-intrinsics.ll +++ b/test/CodeGen/XCore/llvm-intrinsics.ll @@ -44,3 +44,29 @@ entry: %1 = call i8* @llvm.returnaddress(i32 0) ret i8* %1 } + +; test FRAME_TO_ARGS_OFFSET lowering +declare i8* @llvm.eh.dwarf.cfa(i32) nounwind +define i8* @FTAO0() nounwind { +entry: +; CHECK-LABEL: FTAO0 +; CHECK: ldc r0, 0 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: add r0, r1, r0 +; CHECK-NEXT: retsp 0 + %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) + ret i8* %0 +} + +define i8* @FTAO1() nounwind { +entry: +; CHECK-LABEL: FTAO1 +; CHECK: entsp 100 +; CHECK-NEXT: ldc r0, 400 +; CHECK-NEXT: ldaw r1, sp[0] +; CHECK-NEXT: add r0, r1, r0 +; CHECK-NEXT: retsp 100 + %0 = alloca [100 x i32] + %1 = call i8* @llvm.eh.dwarf.cfa(i32 0) + ret i8* %1 +} -- 2.34.1