-
Notifications
You must be signed in to change notification settings - Fork 13.7k
[RISCV] Select unsigned bitfield extract for Xqcibm #143354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Sudharsan Veeravalli (svs-quic) ChangesThe Xqcibm Bit Manipulation extension has the Unlike the corresponding instructions in XTHeadbb and XAndesPerf which extract the bits between Full diff: https://github.com/llvm/llvm-project/pull/143354.diff 2 Files Affected:
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
+}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
The Xqcibm Bit Manipulation extension has the
qc.extu
instruction that can extract a subset of bits from the source register to the destination register.Unlike the corresponding instructions in XTHeadbb and XAndesPerf which extract the bits between
Msb
andLsb
, theqc.extu
instruction extractswidth
bits from an offset that is determined by theshamt
.