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 @@ -80,7 +80,22 @@ CRCC_W_D_W, CSRRD, + + // Write new value to CSR and return old value. + // Operand 0: A chain pointer. + // Operand 1: The new value to write. + // Operand 2: The address of the required CSR. + // Result 0: The old value of the CSR. + // Result 1: The new chain pointer. CSRWR, + + // Similar to CSRWR but with a write mask. + // Operand 0: A chain pointer. + // Operand 1: The new value to write. + // Operand 2: The write mask. + // Operand 3: The address of the required CSR. + // Result 0: The old value of the CSR. + // Result 1: The new chain pointer. CSRXCHG, // IOCSR access operations 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 @@ -644,24 +644,18 @@ unsigned Imm = cast(Op.getOperand(3))->getZExtValue(); return !isUInt<14>(Imm) ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG) - : DAG.getMergeValues( - {DAG.getNode(LoongArchISD::CSRWR, DL, GRLenVT, Chain, - Op.getOperand(2), - DAG.getConstant(Imm, DL, GRLenVT)), - Chain}, - DL); + : DAG.getNode(LoongArchISD::CSRWR, DL, {GRLenVT, MVT::Other}, + {Chain, Op.getOperand(2), + DAG.getConstant(Imm, DL, GRLenVT)}); } case Intrinsic::loongarch_csrxchg_w: case Intrinsic::loongarch_csrxchg_d: { unsigned Imm = cast(Op.getOperand(4))->getZExtValue(); return !isUInt<14>(Imm) ? emitIntrinsicWithChainErrorMessage(Op, ErrorMsgOOR, DAG) - : DAG.getMergeValues( - {DAG.getNode(LoongArchISD::CSRXCHG, DL, GRLenVT, Chain, - Op.getOperand(2), Op.getOperand(3), - DAG.getConstant(Imm, DL, GRLenVT)), - Chain}, - DL); + : DAG.getNode(LoongArchISD::CSRXCHG, DL, {GRLenVT, MVT::Other}, + {Chain, Op.getOperand(2), Op.getOperand(3), + DAG.getConstant(Imm, DL, GRLenVT)}); } case Intrinsic::loongarch_iocsrrd_d: { return DAG.getMergeValues( @@ -1199,12 +1193,13 @@ ErrorMsgOOR); return; } - Results.push_back(DAG.getNode( - ISD::TRUNCATE, DL, VT, - DAG.getNode(LoongArchISD::CSRWR, DL, GRLenVT, Chain, - DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), - DAG.getConstant(Imm, DL, GRLenVT)))); - Results.push_back(Chain); + SDValue CSRWRResults = + DAG.getNode(LoongArchISD::CSRWR, DL, {GRLenVT, MVT::Other}, + {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), + DAG.getConstant(Imm, DL, GRLenVT)}); + Results.push_back( + DAG.getNode(ISD::TRUNCATE, DL, VT, CSRWRResults.getValue(0))); + Results.push_back(CSRWRResults.getValue(1)); break; } case Intrinsic::loongarch_csrxchg_w: { @@ -1214,14 +1209,14 @@ ErrorMsgOOR); return; } - Results.push_back(DAG.getNode( - ISD::TRUNCATE, DL, VT, - DAG.getNode( - LoongArchISD::CSRXCHG, DL, GRLenVT, Chain, - DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), - DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3)), - DAG.getConstant(Imm, DL, GRLenVT)))); - Results.push_back(Chain); + SDValue CSRXCHGResults = DAG.getNode( + LoongArchISD::CSRXCHG, DL, {GRLenVT, MVT::Other}, + {Chain, DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, Op2), + DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i64, N->getOperand(3)), + DAG.getConstant(Imm, DL, GRLenVT)}); + Results.push_back( + DAG.getNode(ISD::TRUNCATE, DL, VT, CSRXCHGResults.getValue(0))); + Results.push_back(CSRXCHGResults.getValue(1)); break; } #define IOCSRRD_CASE(NAME, NODE) \ diff --git a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll --- a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll @@ -122,10 +122,10 @@ } ;; Check that csrwr is emitted even if the return value of the intrinsic is not used. -;; FIXME: currently csrwr is not emitted. define void @csrwr_d_noret(i64 %a) { ; CHECK-LABEL: csrwr_d_noret: ; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrwr $a0, 1 ; CHECK-NEXT: ret entry: %0 = tail call i64 @llvm.loongarch.csrwr.d(i64 %a, i32 1) @@ -143,10 +143,10 @@ } ;; Check that csrxchg is emitted even if the return value of the intrinsic is not used. -;; FIXME: currently csrxchg is not emitted. define void @csrxchg_d_noret(i64 %a, i64 %b) { ; CHECK-LABEL: csrxchg_d_noret: ; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrxchg $a0, $a1, 1 ; CHECK-NEXT: ret entry: %0 = tail call i64 @llvm.loongarch.csrxchg.d(i64 %a, i64 %b, i32 1) diff --git a/llvm/test/CodeGen/LoongArch/intrinsic.ll b/llvm/test/CodeGen/LoongArch/intrinsic.ll --- a/llvm/test/CodeGen/LoongArch/intrinsic.ll +++ b/llvm/test/CodeGen/LoongArch/intrinsic.ll @@ -100,10 +100,10 @@ } ;; Check that csrwr is emitted even if the return value of the intrinsic is not used. -;; FIXME: currently csrwr is not emitted. define void @csrwr_w_noret(i32 signext %a) { ; CHECK-LABEL: csrwr_w_noret: ; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrwr $a0, 1 ; CHECK-NEXT: ret entry: %0 = tail call i32 @llvm.loongarch.csrwr.w(i32 %a, i32 1) @@ -121,10 +121,10 @@ } ;; Check that csrxchg is emitted even if the return value of the intrinsic is not used. -;; FIXME: currently csrxchg is not emitted. define void @csrxchg_w_noret(i32 signext %a, i32 signext %b) { ; CHECK-LABEL: csrxchg_w_noret: ; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrxchg $a0, $a1, 1 ; CHECK-NEXT: ret entry: %0 = tail call i32 @llvm.loongarch.csrxchg.w(i32 %a, i32 %b, i32 1)