[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