[llvm] 94c2416 - [RISCV] Select signed bitfield extract for Xqcibm (#143536)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 10 09:00:59 PDT 2025
Author: Sudharsan Veeravalli
Date: 2025-06-10T21:30:56+05:30
New Revision: 94c241614f491c0cd832614bde6130e315e53467
URL: https://github.com/llvm/llvm-project/commit/94c241614f491c0cd832614bde6130e315e53467
DIFF: https://github.com/llvm/llvm-project/commit/94c241614f491c0cd832614bde6130e315e53467.diff
LOG: [RISCV] Select signed bitfield extract for Xqcibm (#143536)
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`.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/test/CodeGen/RISCV/xqcibm-extract.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 9ed67e74d440c..d298965595b47 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
+}
More information about the llvm-commits
mailing list