[llvm] [RISCV] Select unsigned bitfield extract for Xqcibm (PR #143354)
Sudharsan Veeravalli via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 9 19:31:00 PDT 2025
https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/143354
>From a0323373fc089bc5efdb6e0ae10a4aa4b6a291cb Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Mon, 9 Jun 2025 13:55:26 +0530
Subject: [PATCH 1/3] [RISCV] Select unsigned bitfield extract for Xqcibm
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 20 +++-
llvm/test/CodeGen/RISCV/xqcibm-extract.ll | 100 ++++++++++++++++++++
2 files changed, 116 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 494d6ed03292a..24f652da52422 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -674,12 +674,24 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL,
MVT VT, SDValue X,
unsigned Msb, unsigned Lsb) {
- // Only supported with XTHeadBb/XAndesPerf at the moment.
- if (!Subtarget->hasVendorXTHeadBb() && !Subtarget->hasVendorXAndesPerf())
+ bool IsXTheadBb = Subtarget->hasVendorXTHeadBb();
+ bool IsXAndesPerf = Subtarget->hasVendorXAndesPerf();
+ bool IsXqcibm = Subtarget->hasVendorXqcibm();
+
+ // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
+ if (!IsXTheadBb && !IsXAndesPerf && !IsXqcibm)
return false;
- unsigned Opc =
- Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXTU : RISCV::NDS_BFOZ;
+ if (IsXqcibm) {
+ // QC.EXTU X, width, shamt
+ // shamt is the same as Lsb
+ // width is the number of bits to extract from the Lsb
+ Msb = Msb - Lsb + 1;
+ }
+
+ unsigned Opc = IsXTheadBb ? RISCV::TH_EXTU
+ : IsXAndesPerf ? RISCV::NDS_BFOZ
+ : RISCV::QC_EXTU;
SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
CurDAG->getTargetConstant(Msb, DL, VT),
diff --git a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
index 3f5b949585fa3..920dd025d4625 100644
--- a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
+++ b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
@@ -231,3 +231,103 @@ define i64 @sexti32_i64_2(i32 %a) {
%1 = sext i32 %a to i64
ret i64 %1
}
+
+define i32 @extu_from_and_i32(i32 %x) {
+; RV32I-LABEL: extu_from_and_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 20
+; RV32I-NEXT: srli a0, a0, 20
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_and_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 0
+; RV32XQCIBM-NEXT: ret
+ %a = and i32 %x, 4095
+ ret i32 %a
+}
+
+define i64 @extu_from_and_i64(i64 %x) {
+; RV32I-LABEL: extu_from_and_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 20
+; RV32I-NEXT: srli a0, a0, 20
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_and_i64:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 0
+; RV32XQCIBM-NEXT: li a1, 0
+; RV32XQCIBM-NEXT: ret
+ %a = and i64 %x, 4095
+ ret i64 %a
+}
+
+define i32 @extu_from_and_lshr_i32(i32 %x) {
+; RV32I-LABEL: extu_from_and_lshr_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 6
+; RV32I-NEXT: srli a0, a0, 29
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_and_lshr_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a0, 3, 23
+; RV32XQCIBM-NEXT: ret
+ %shifted = lshr i32 %x, 23
+ %masked = and i32 %shifted, 7
+ ret i32 %masked
+}
+
+define i64 @extu_from_and_lshr_i64(i64 %x) {
+; RV32I-LABEL: extu_from_and_lshr_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a1, 6
+; RV32I-NEXT: srli a0, a0, 20
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_and_lshr_i64:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a1, 12, 14
+; RV32XQCIBM-NEXT: li a1, 0
+; RV32XQCIBM-NEXT: ret
+ %shifted = lshr i64 %x, 46
+ %masked = and i64 %shifted, 4095
+ ret i64 %masked
+}
+
+define i32 @extu_from_lshr_and_i32(i32 %x) {
+; RV32I-LABEL: extu_from_lshr_and_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 8
+; RV32I-NEXT: srli a0, a0, 20
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_lshr_and_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 12
+; RV32XQCIBM-NEXT: ret
+ %masked = and i32 %x, 16773120
+ %shifted = lshr i32 %masked, 12
+ ret i32 %shifted
+}
+
+define i64 @extu_from_lshr_and_i64(i64 %x) {
+; RV32I-LABEL: extu_from_lshr_and_i64:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 8
+; RV32I-NEXT: srli a0, a0, 20
+; RV32I-NEXT: li a1, 0
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: extu_from_lshr_and_i64:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 12
+; RV32XQCIBM-NEXT: li a1, 0
+; RV32XQCIBM-NEXT: ret
+ %masked = and i64 %x, 16773120
+ %shifted = lshr i64 %masked, 12
+ ret i64 %shifted
+}
>From 4bd9c20c410a0bd4326bdcb3e5cae99f58a32e6b Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Mon, 9 Jun 2025 15:46:54 +0530
Subject: [PATCH 2/3] Refactor tryUnsignedBitfieldExtract
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 24 ++++++++++-----------
1 file changed, 11 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 24f652da52422..decee34898151 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -674,24 +674,22 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL,
MVT VT, SDValue X,
unsigned Msb, unsigned Lsb) {
- bool IsXTheadBb = Subtarget->hasVendorXTHeadBb();
- bool IsXAndesPerf = Subtarget->hasVendorXAndesPerf();
- bool IsXqcibm = Subtarget->hasVendorXqcibm();
-
- // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
- if (!IsXTheadBb && !IsXAndesPerf && !IsXqcibm)
- return false;
-
- if (IsXqcibm) {
+ unsigned Opc;
+
+ if (Subtarget->hasVendorXTHeadBb())
+ Opc = RISCV::TH_EXTU;
+ else if (Subtarget->hasVendorXAndesPerf())
+ Opc = RISCV::NDS_BFOZ;
+ else if (Subtarget->hasVendorXqcibm()) {
+ Opc = RISCV::QC_EXTU;
// QC.EXTU X, width, shamt
// shamt is the same as Lsb
// width is the number of bits to extract from the Lsb
Msb = Msb - Lsb + 1;
}
-
- unsigned Opc = IsXTheadBb ? RISCV::TH_EXTU
- : IsXAndesPerf ? RISCV::NDS_BFOZ
- : RISCV::QC_EXTU;
+ // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
+ else
+ return false;
SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
CurDAG->getTargetConstant(Msb, DL, VT),
>From da524c3df4e7423bf6877bed6ba7604ed80a4f0e Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Mon, 9 Jun 2025 20:59:40 +0530
Subject: [PATCH 3/3] Curly Braces
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index decee34898151..053b147888b8a 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -676,20 +676,20 @@ bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL,
unsigned Msb, unsigned Lsb) {
unsigned Opc;
- if (Subtarget->hasVendorXTHeadBb())
+ if (Subtarget->hasVendorXTHeadBb()) {
Opc = RISCV::TH_EXTU;
- else if (Subtarget->hasVendorXAndesPerf())
+ } else if (Subtarget->hasVendorXAndesPerf()) {
Opc = RISCV::NDS_BFOZ;
- else if (Subtarget->hasVendorXqcibm()) {
+ } else if (Subtarget->hasVendorXqcibm()) {
Opc = RISCV::QC_EXTU;
// QC.EXTU X, width, shamt
// shamt is the same as Lsb
// width is the number of bits to extract from the Lsb
Msb = Msb - Lsb + 1;
- }
- // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
- else
+ } else {
+ // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
return false;
+ }
SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
CurDAG->getTargetConstant(Msb, DL, VT),
More information about the llvm-commits
mailing list