summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelLowering.cpp')
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelLowering.cpp91
1 files changed, 82 insertions, 9 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index dc829fce9013..5a2cffbc824c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -30,6 +30,7 @@
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/IntrinsicsRISCV.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -50,6 +51,20 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
RISCVABI::ABI ABI = Subtarget.getTargetABI();
assert(ABI != RISCVABI::ABI_Unknown && "Improperly initialised target ABI");
+ if ((ABI == RISCVABI::ABI_ILP32F || ABI == RISCVABI::ABI_LP64F) &&
+ !Subtarget.hasStdExtF()) {
+ errs() << "Hard-float 'f' ABI can't be used for a target that "
+ "doesn't support the F instruction set extension (ignoring "
+ "target-abi)\n";
+ ABI = Subtarget.is64Bit() ? RISCVABI::ABI_LP64 : RISCVABI::ABI_ILP32;
+ } else if ((ABI == RISCVABI::ABI_ILP32D || ABI == RISCVABI::ABI_LP64D) &&
+ !Subtarget.hasStdExtD()) {
+ errs() << "Hard-float 'd' ABI can't be used for a target that "
+ "doesn't support the D instruction set extension (ignoring "
+ "target-abi)\n";
+ ABI = Subtarget.is64Bit() ? RISCVABI::ABI_LP64 : RISCVABI::ABI_ILP32;
+ }
+
switch (ABI) {
default:
report_fatal_error("Don't know how to lower this ABI");
@@ -146,7 +161,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
ISD::SETGE, ISD::SETNE};
ISD::NodeType FPOpToExtend[] = {
- ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM};
+ ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FREM, ISD::FP16_TO_FP,
+ ISD::FP_TO_FP16};
if (Subtarget.hasStdExtF()) {
setOperationAction(ISD::FMINNUM, MVT::f32, Legal);
@@ -158,6 +174,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BR_CC, MVT::f32, Expand);
for (auto Op : FPOpToExtend)
setOperationAction(Op, MVT::f32, Expand);
+ setLoadExtAction(ISD::EXTLOAD, MVT::f32, MVT::f16, Expand);
+ setTruncStoreAction(MVT::f32, MVT::f16, Expand);
}
if (Subtarget.hasStdExtF() && Subtarget.is64Bit())
@@ -175,6 +193,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setTruncStoreAction(MVT::f64, MVT::f32, Expand);
for (auto Op : FPOpToExtend)
setOperationAction(Op, MVT::f64, Expand);
+ setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f16, Expand);
+ setTruncStoreAction(MVT::f64, MVT::f16, Expand);
}
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
@@ -188,6 +208,9 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64,
Subtarget.is64Bit() ? Legal : Custom);
+ setOperationAction(ISD::TRAP, MVT::Other, Legal);
+ setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);
+
if (Subtarget.hasStdExtA()) {
setMaxAtomicSizeInBitsSupported(Subtarget.getXLen());
setMinCmpXchgSizeInBits(32);
@@ -573,10 +596,7 @@ SDValue RISCVTargetLowering::lowerGlobalTLSAddress(SDValue Op,
int64_t Offset = N->getOffset();
MVT XLenVT = Subtarget.getXLenVT();
- // Non-PIC TLS lowering should always use the LocalExec model.
- TLSModel::Model Model = isPositionIndependent()
- ? getTargetMachine().getTLSModel(N->getGlobal())
- : TLSModel::LocalExec;
+ TLSModel::Model Model = getTargetMachine().getTLSModel(N->getGlobal());
SDValue Addr;
switch (Model) {
@@ -2010,10 +2030,6 @@ bool RISCVTargetLowering::isEligibleForTailCallOptimization(
auto &Caller = MF.getFunction();
auto CallerCC = Caller.getCallingConv();
- // Do not tail call opt functions with "disable-tail-calls" attribute.
- if (Caller.getFnAttribute("disable-tail-calls").getValueAsString() == "true")
- return false;
-
// Exception-handling functions need a special set of instructions to
// indicate a return to the hardware. Tail-calling another function would
// probably break this.
@@ -2247,6 +2263,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 +2388,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 +2420,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 +2438,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 +2481,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:
@@ -2848,3 +2902,22 @@ bool RISCVTargetLowering::shouldExtendTypeInLibCall(EVT Type) const {
return true;
}
+
+#define GET_REGISTER_MATCHER
+#include "RISCVGenAsmMatcher.inc"
+
+Register
+RISCVTargetLowering::getRegisterByName(const char *RegName, LLT VT,
+ const MachineFunction &MF) const {
+ Register Reg = MatchRegisterAltName(RegName);
+ if (Reg == RISCV::NoRegister)
+ Reg = MatchRegisterName(RegName);
+ if (Reg == RISCV::NoRegister)
+ report_fatal_error(
+ Twine("Invalid register name \"" + StringRef(RegName) + "\"."));
+ BitVector ReservedRegs = Subtarget.getRegisterInfo()->getReservedRegs(MF);
+ if (!ReservedRegs.test(Reg) && !Subtarget.isRegisterReservedByUser(Reg))
+ report_fatal_error(Twine("Trying to obtain non-reserved register \"" +
+ StringRef(RegName) + "\"."));
+ return Reg;
+}