mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-04 01:26:41 +00:00
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
This commit is contained in:
parent
12ad7cd730
commit
af74cbf553
@ -24,6 +24,7 @@ add_llvm_target(XCoreCodeGen
|
||||
XCoreTargetObjectFile.cpp
|
||||
XCoreTargetTransformInfo.cpp
|
||||
XCoreSelectionDAGInfo.cpp
|
||||
XCoreFrameToArgsOffsetElim.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(Disassembler)
|
||||
|
@ -27,6 +27,7 @@ namespace llvm {
|
||||
|
||||
void initializeXCoreLowerThreadLocalPass(PassRegistry &p);
|
||||
|
||||
FunctionPass *createXCoreFrameToArgsOffsetEliminationPass();
|
||||
FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM,
|
||||
CodeGenOpt::Level OptLevel);
|
||||
ModulePass *createXCoreLowerThreadLocalPass();
|
||||
|
70
lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp
Normal file
70
lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp
Normal file
@ -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;
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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))]>;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user