[llvm] c216ce0 - [LoongArch] Fix handling of the chain of CSRWR and CSRXCHG nodes

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 16 19:56:07 PDT 2023


Author: Weining Lu
Date: 2023-06-17T10:49:18+08:00
New Revision: c216ce0ef84063f57c7324df21b71cd5c78cfa81

URL: https://github.com/llvm/llvm-project/commit/c216ce0ef84063f57c7324df21b71cd5c78cfa81
DIFF: https://github.com/llvm/llvm-project/commit/c216ce0ef84063f57c7324df21b71cd5c78cfa81.diff

LOG: [LoongArch] Fix handling of the chain of CSRWR and CSRXCHG nodes

`LoongArchISD::CSRWR` has two results. The first is the result of
`loongarch.csrwr.[wd]` intrinsic and the second is the chain. But
currently the chain is not processed correctly when creating this
node, resulting in the `csrwr` instruction being optimized out when
the result is not used by anyone [1]. `LoongArchISD::CSRXCHG` has
the same issue.

This patch addresses this issue.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/asm/loongarch.h?h=v6.4-rc6#n219

Reviewed By: hev

Differential Revision: https://reviews.llvm.org/D153120

Added: 
    

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchISelLowering.h
    llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
    llvm/test/CodeGen/LoongArch/intrinsic.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index d750d64b6b8b5..5361856fc9f62 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -644,24 +644,18 @@ LoongArchTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
     unsigned Imm = cast<ConstantSDNode>(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<ConstantSDNode>(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 @@ void LoongArchTargetLowering::ReplaceNodeResults(
                                                      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 @@ void LoongArchTargetLowering::ReplaceNodeResults(
                                                      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/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 03e2b30a587fb..dab8944c50a78 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -80,7 +80,22 @@ enum NodeType : unsigned {
   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/test/CodeGen/LoongArch/intrinsic-la64.ll b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
index ceb3213ea94ee..8b251be99647c 100644
--- a/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
+++ b/llvm/test/CodeGen/LoongArch/intrinsic-la64.ll
@@ -122,10 +122,10 @@ entry:
 }
 
 ;; 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 @@ entry:
 }
 
 ;; 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
index 8d7c0946011f9..930e89b96d1b1 100644
--- a/llvm/test/CodeGen/LoongArch/intrinsic.ll
+++ b/llvm/test/CodeGen/LoongArch/intrinsic.ll
@@ -100,10 +100,10 @@ entry:
 }
 
 ;; 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 @@ entry:
 }
 
 ;; 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)


        


More information about the llvm-commits mailing list