diff options
author | Simon Cook <simon.cook@embecosm.com> | 2019-10-22 21:25:01 +0100 |
---|---|---|
committer | Simon Cook <simon.cook@embecosm.com> | 2019-10-22 21:25:01 +0100 |
commit | aed9d6d64a38d155cd09232da5640b5ade069bd9 (patch) | |
tree | 039d8d57a1065a034a383b13a5448fa7c993704a /llvm/lib | |
parent | 68f5ca4e19c16f12895a6f0b9fbabc1d86c4b6b0 (diff) | |
download | bcm5719-llvm-aed9d6d64a38d155cd09232da5640b5ade069bd9.tar.gz bcm5719-llvm-aed9d6d64a38d155cd09232da5640b5ade069bd9.zip |
[RISCV] Add support for -ffixed-xX flags
This adds support for reserving GPRs such that the compiler will not
choose a register for register allocation. The implementation follows
the same design as for AArch64; each reserved register becomes a target
feature and used for getting the reserved registers for a given
MachineFunction. The backend checks that it does not need to write to
any reserved register; if it does a relevant error is generated.
Differential Revision: https://reviews.llvm.org/D67185
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/RISCV/RISCV.td | 5 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelLowering.h | 6 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVRegisterInfo.h | 2 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVSubtarget.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/RISCV/RISCVSubtarget.h | 5 |
8 files changed, 79 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index 46530a8f74a..70d87d662f9 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -69,6 +69,11 @@ def FeatureRelax : SubtargetFeature<"relax", "EnableLinkerRelax", "true", "Enable Linker relaxation.">; +foreach i = {1-31} in + def FeatureReserveX#i : + SubtargetFeature<"reserve-x"#i, "UserReservedRegister[RISCV::X"#i#"]", + "true", "Reserve X"#i>; + //===----------------------------------------------------------------------===// // Named operands for CSR instructions. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 6b6f62e18ce..daa7b7a7ea9 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -18,6 +18,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/MC/MCDwarf.h" using namespace llvm; @@ -131,6 +132,12 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, if (StackSize == 0 && !MFI.adjustsStack()) return; + // If the stack pointer has been marked as reserved, then produce an error if + // the frame requires stack allocation + if (STI.isRegisterReservedByUser(SPReg)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), "Stack pointer required, but has been reserved."}); + uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF); // Split the SP adjustment to reduce the offsets of callee saved spill. if (FirstSPAdjustAmount) @@ -167,6 +174,10 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, // Generate new FP. if (hasFP(MF)) { + if (STI.isRegisterReservedByUser(FPReg)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), "Frame pointer required, but has been reserved."}); + adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize - RVFI->getVarArgsSaveSize(), MachineInstr::FrameSetup); diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index dc829fce901..b56d95132e0 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2247,6 +2247,16 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI, Glue = Chain.getValue(1); } + // Validate that none of the argument registers have been marked as + // reserved, if so report an error. Do the same for the return address if this + // is not a tailcall. + validateCCReservedRegs(RegsToPass, MF); + if (!IsTailCall && + MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(RISCV::X1)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return address register required, but has been reserved."}); + // If the callee is a GlobalAddress/ExternalSymbol node, turn it into a // TargetGlobalAddress/TargetExternalSymbol node so that legalize won't // split it and then direct call can be matched by PseudoCALL. @@ -2362,6 +2372,9 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL, SelectionDAG &DAG) const { + const MachineFunction &MF = DAG.getMachineFunction(); + const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>(); + // Stores the assignment of the return value to a location. SmallVector<CCValAssign, 16> RVLocs; @@ -2391,6 +2404,13 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, Register RegLo = VA.getLocReg(); assert(RegLo < RISCV::X31 && "Invalid register pair"); Register RegHi = RegLo + 1; + + if (STI.isRegisterReservedByUser(RegLo) || + STI.isRegisterReservedByUser(RegHi)) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return value register required, but has been reserved."}); + Chain = DAG.getCopyToReg(Chain, DL, RegLo, Lo, Glue); Glue = Chain.getValue(1); RetOps.push_back(DAG.getRegister(RegLo, MVT::i32)); @@ -2402,6 +2422,11 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, Val = convertValVTToLocVT(DAG, Val, VA, DL); Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Glue); + if (STI.isRegisterReservedByUser(VA.getLocReg())) + MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{ + MF.getFunction(), + "Return value register required, but has been reserved."}); + // Guarantee that all emitted copies are stuck together. Glue = Chain.getValue(1); RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); @@ -2440,6 +2465,19 @@ RISCVTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, return DAG.getNode(RISCVISD::RET_FLAG, DL, MVT::Other, RetOps); } +void RISCVTargetLowering::validateCCReservedRegs( + const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs, + MachineFunction &MF) const { + const Function &F = MF.getFunction(); + const RISCVSubtarget &STI = MF.getSubtarget<RISCVSubtarget>(); + + if (std::any_of(std::begin(Regs), std::end(Regs), [&STI](auto Reg) { + return STI.isRegisterReservedByUser(Reg.first); + })) + F.getContext().diagnose(DiagnosticInfoUnsupported{ + F, "Argument register required, but has been reserved."}); +} + const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((RISCVISD::NodeType)Opcode) { case RISCVISD::FIRST_NUMBER: diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 18fc7350bbb..0d2d14e8d67 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -210,6 +210,12 @@ private: Value *AlignedAddr, Value *CmpVal, Value *NewVal, Value *Mask, AtomicOrdering Ord) const override; + + /// Generate error diagnostics if any register used by CC has been marked + /// reserved. + void validateCCReservedRegs( + const SmallVectorImpl<std::pair<llvm::Register, llvm::SDValue>> &Regs, + MachineFunction &MF) const; }; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp index 66557687c0b..65a7e41a23d 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp @@ -69,6 +69,12 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { const TargetFrameLowering *TFI = getFrameLowering(MF); BitVector Reserved(getNumRegs()); + // Mark any registers requested to be reserved as such + for (size_t Reg = 0; Reg < getNumRegs(); Reg++) { + if (MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(Reg)) + markSuperRegs(Reserved, Reg); + } + // Use markSuperRegs to ensure any register aliases are also reserved markSuperRegs(Reserved, RISCV::X0); // zero markSuperRegs(Reserved, RISCV::X1); // ra @@ -81,6 +87,11 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const { return Reserved; } +bool RISCVRegisterInfo::isAsmClobberable(const MachineFunction &MF, + unsigned PhysReg) const { + return !MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(PhysReg); +} + bool RISCVRegisterInfo::isConstantPhysReg(unsigned PhysReg) const { return PhysReg == RISCV::X0; } diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h index 56a50fe6ddc..30b639517fd 100644 --- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.h +++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.h @@ -30,6 +30,8 @@ struct RISCVRegisterInfo : public RISCVGenRegisterInfo { const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; BitVector getReservedRegs(const MachineFunction &MF) const override; + bool isAsmClobberable(const MachineFunction &MF, + unsigned PhysReg) const override; bool isConstantPhysReg(unsigned PhysReg) const override; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp index f114c6ac192..83e7e2d52cc 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -50,6 +50,7 @@ RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies( RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS, StringRef ABIName, const TargetMachine &TM) : RISCVGenSubtargetInfo(TT, CPU, FS), + UserReservedRegister(RISCV::NUM_TARGET_REGS), FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)), InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) { CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering())); diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 7d0373a5253..605d4abcc9a 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -46,6 +46,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { unsigned XLen = 32; MVT XLenVT = MVT::i32; RISCVABI::ABI TargetABI = RISCVABI::ABI_Unknown; + BitVector UserReservedRegister; RISCVFrameLowering FrameLowering; RISCVInstrInfo InstrInfo; RISCVRegisterInfo RegInfo; @@ -93,6 +94,10 @@ public: MVT getXLenVT() const { return XLenVT; } unsigned getXLen() const { return XLen; } RISCVABI::ABI getTargetABI() const { return TargetABI; } + bool isRegisterReservedByUser(Register i) const { + assert(i < RISCV::NUM_TARGET_REGS && "Register out of range"); + return UserReservedRegister[i]; + } protected: // GlobalISel related APIs. |