diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h @@ -192,6 +192,7 @@ SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerWRITE_REGISTER(SDValue Op, SelectionDAG &DAG) const; bool isFPImmLegal(const APFloat &Imm, EVT VT, bool ForCodeSize) const override; diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -93,6 +93,8 @@ setOperationAction(ISD::CTLZ, MVT::i32, Custom); setOperationAction(ISD::INTRINSIC_VOID, MVT::i32, Custom); setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i32, Custom); + setOperationAction(ISD::READ_REGISTER, MVT::i32, Custom); + setOperationAction(ISD::WRITE_REGISTER, MVT::i32, Custom); if (Subtarget.hasBasicF() && !Subtarget.hasBasicD()) setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); if (Subtarget.hasBasicF()) @@ -118,6 +120,8 @@ } else { setOperationAction(ISD::BITREVERSE, MVT::i32, Legal); setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom); + setOperationAction(ISD::READ_REGISTER, MVT::i64, Custom); + setOperationAction(ISD::WRITE_REGISTER, MVT::i64, Custom); } static const ISD::CondCode FPCCToExpand[] = { @@ -244,10 +248,30 @@ return lowerFRAMEADDR(Op, DAG); case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG); + case ISD::WRITE_REGISTER: + return lowerWRITE_REGISTER(Op, DAG); } return SDValue(); } +SDValue LoongArchTargetLowering::lowerWRITE_REGISTER(SDValue Op, + SelectionDAG &DAG) const { + + if (Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i32) { + DAG.getContext()->emitError( + "On LA64, only 64-bit registers can be written."); + return Op.getOperand(0); + } + + if (!Subtarget.is64Bit() && Op.getOperand(2).getValueType() == MVT::i64) { + DAG.getContext()->emitError( + "On LA32, only 32-bit registers can be written."); + return Op.getOperand(0); + } + + return Op; +} + SDValue LoongArchTargetLowering::lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { if (!isa(Op.getOperand(0))) { @@ -927,6 +951,17 @@ } break; } + case ISD::READ_REGISTER: { + if (Subtarget.is64Bit()) + DAG.getContext()->emitError( + "On LA64, only 64-bit registers can be read."); + else + DAG.getContext()->emitError( + "On LA32, only 32-bit registers can be read."); + Results.push_back(DAG.getUNDEF(N->getValueType(0))); + Results.push_back(N->getOperand(0)); + break; + } } } diff --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la32.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: not llc < %s --mtriple=loongarch32 2>&1 | FileCheck %s + +define i64 @read_sp() nounwind { +entry: +; CHECK: On LA32, only 32-bit registers can be read. + %a1 = call i64 @llvm.read_register.i64(metadata !0) + ret i64 %a1 +} + +define void @write_sp(i64 %val) nounwind { +entry: +; CHECK: On LA32, only 32-bit registers can be written. + call void @llvm.write_register.i64(metadata !0, i64 %val) + ret void +} + +declare i64 @llvm.read_register.i64(metadata) nounwind +declare void @llvm.write_register.i64(metadata, i64) nounwind + +!0 = !{!"$sp\00"} diff --git a/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/LoongArch/get-reg-error-la64.ll @@ -0,0 +1,21 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: not llc < %s --mtriple=loongarch64 2>&1 | FileCheck %s + +define i32 @read_sp() nounwind { +entry: +; CHECK: On LA64, only 64-bit registers can be read. + %a1 = call i32 @llvm.read_register.i32(metadata !0) + ret i32 %a1 +} + +define void @write_sp(i32 %val) nounwind { +entry: +; CHECK: On LA64, only 64-bit registers can be written. + call void @llvm.write_register.i32(metadata !0, i32 %val) + ret void +} + +declare i32 @llvm.read_register.i32(metadata) nounwind +declare void @llvm.write_register.i32(metadata, i32) nounwind + +!0 = !{!"$sp\00"}