-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV] Select signed bitfield extract for Xqcibm #143536
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
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Sudharsan Veeravalli (svs-quic) ChangesThe Xqcibm Bit Manipulation extension has the Unlike the corresponding instructions in Full diff: https://github.com/llvm/llvm-project/pull/143536.diff 2 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index babc0d7ab27e2..be5a4dcfccb44 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -601,8 +601,16 @@ bool RISCVDAGToDAGISel::tryShrinkShlLogicImm(SDNode *Node) {
}
bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
- // Only supported with XTHeadBb/XAndesPerf at the moment.
- if (!Subtarget->hasVendorXTHeadBb() && !Subtarget->hasVendorXAndesPerf())
+ unsigned Opc;
+
+ if (Subtarget->hasVendorXTHeadBb())
+ Opc = RISCV::TH_EXT;
+ else if (Subtarget->hasVendorXAndesPerf())
+ Opc = RISCV::NDS_BFOS;
+ else if (Subtarget->hasVendorXqcibm())
+ Opc = RISCV::QC_EXT;
+ else
+ // Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
return false;
auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
@@ -615,8 +623,12 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
auto BitfieldExtract = [&](SDValue N0, unsigned Msb, unsigned Lsb,
const SDLoc &DL, MVT VT) {
- unsigned Opc =
- Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXT : RISCV::NDS_BFOS;
+ if (Opc == RISCV::QC_EXT) {
+ // QC.EXT X, width, shamt
+ // shamt is the same as Lsb
+ // width is the number of bits to extract from the Lsb
+ Msb = Msb - Lsb + 1;
+ }
return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
CurDAG->getTargetConstant(Msb, DL, VT),
CurDAG->getTargetConstant(Lsb, DL, VT));
@@ -627,7 +639,7 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
const unsigned RightShAmt = N1C->getZExtValue();
// Transform (sra (shl X, C1) C2) with C1 < C2
- // -> (TH.EXT X, msb, lsb)
+ // -> (SignedBitfieldExtract X, msb, lsb)
if (N0.getOpcode() == ISD::SHL) {
auto *N01C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
if (!N01C)
@@ -643,13 +655,13 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
const unsigned Msb = MsbPlusOne - 1;
const unsigned Lsb = RightShAmt - LeftShAmt;
- SDNode *TH_EXT = BitfieldExtract(N0, Msb, Lsb, DL, VT);
- ReplaceNode(Node, TH_EXT);
+ SDNode *Sbe = BitfieldExtract(N0, Msb, Lsb, DL, VT);
+ ReplaceNode(Node, Sbe);
return true;
}
// Transform (sra (sext_inreg X, _), C) ->
- // (TH.EXT X, msb, lsb)
+ // (SignedBitfieldExtract X, msb, lsb)
if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG) {
unsigned ExtSize =
cast<VTSDNode>(N0.getOperand(1))->getVT().getSizeInBits();
@@ -663,8 +675,8 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
// the X[Msb] bit and sign-extend it.
const unsigned Lsb = RightShAmt > Msb ? Msb : RightShAmt;
- SDNode *TH_EXT = BitfieldExtract(N0, Msb, Lsb, DL, VT);
- ReplaceNode(Node, TH_EXT);
+ SDNode *Sbe = BitfieldExtract(N0, Msb, Lsb, DL, VT);
+ ReplaceNode(Node, Sbe);
return true;
}
diff --git a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
index 920dd025d4625..cb01510058da4 100644
--- a/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
+++ b/llvm/test/CodeGen/RISCV/xqcibm-extract.ll
@@ -331,3 +331,51 @@ define i64 @extu_from_lshr_and_i64(i64 %x) {
%shifted = lshr i64 %masked, 12
ret i64 %shifted
}
+
+define i32 @ext_from_ashr_shl_i32(i32 %x) {
+; RV32I-LABEL: ext_from_ashr_shl_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 8
+; RV32I-NEXT: srai a0, a0, 24
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: ext_from_ashr_shl_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.ext a0, a0, 8, 16
+; RV32XQCIBM-NEXT: ret
+ %shl = shl i32 %x, 8
+ %ashr = ashr i32 %shl, 24
+ ret i32 %ashr
+}
+
+define i32 @ext_from_ashr_sexti8_i32(i8 %x) {
+; RV32I-LABEL: ext_from_ashr_sexti8_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 24
+; RV32I-NEXT: srai a0, a0, 29
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: ext_from_ashr_sexti8_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.ext a0, a0, 3, 5
+; RV32XQCIBM-NEXT: ret
+ %sext = sext i8 %x to i32
+ %ashr = ashr i32 %sext, 5
+ ret i32 %ashr
+}
+
+define i32 @ext_from_ashr_sexti16_i32(i16 %x) {
+; RV32I-LABEL: ext_from_ashr_sexti16_i32:
+; RV32I: # %bb.0:
+; RV32I-NEXT: slli a0, a0, 16
+; RV32I-NEXT: srai a0, a0, 31
+; RV32I-NEXT: ret
+;
+; RV32XQCIBM-LABEL: ext_from_ashr_sexti16_i32:
+; RV32XQCIBM: # %bb.0:
+; RV32XQCIBM-NEXT: qc.ext a0, a0, 1, 15
+; RV32XQCIBM-NEXT: ret
+ %sext = sext i16 %x to i32
+ %ashr = ashr i32 %sext, 24
+ ret i32 %ashr
+}
|
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. Thanks!
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.ext` 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` and `Lsb`, the `qc.ext` instruction extracts `width` bits from an offset that is determined by the `shamt`.
The Xqcibm Bit Manipulation extension has the `qc.ext` 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` and `Lsb`, the `qc.ext` instruction extracts `width` bits from an offset that is determined by the `shamt`.
The Xqcibm Bit Manipulation extension has the
qc.ext
instruction that can extract a subset of bits from the source register to the destination register.Unlike the corresponding instructions in
XTHeadbb
andXAndesPerf
which extract the bits betweenMsb
andLsb
, theqc.ext
instruction extractswidth
bits from an offset that is determined by theshamt
.