[llvm] 8423778 - [RISCV] Select signed bitfield insert for XAndesPerf (#143356)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 10 22:32:52 PDT 2025
Author: Jim Lin
Date: 2025-06-11T13:32:49+08:00
New Revision: 842377882a3f52e345668751fa6d46ba4f7268d2
URL: https://github.com/llvm/llvm-project/commit/842377882a3f52e345668751fa6d46ba4f7268d2
DIFF: https://github.com/llvm/llvm-project/commit/842377882a3f52e345668751fa6d46ba4f7268d2.diff
LOG: [RISCV] Select signed bitfield insert for XAndesPerf (#143356)
This patch is similar to #142737
The XAndesPerf extension includes signed bitfield extraction
instruction `NDS.BFOS, which can extract the bits from 0 to Len - 1,
place them starting at bit Lsb, zero-filled the bits from 0 to Lsb -1,
and sign-extend the result.
When Lsb == Msb, it is a special case where the Lsb will be set to 0
instead of being equal to the Msb.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
llvm/test/CodeGen/RISCV/rv32xandesperf.ll
llvm/test/CodeGen/RISCV/rv64xandesperf.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index d298965595b47..4539efd591c8b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -683,6 +683,59 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
return false;
}
+bool RISCVDAGToDAGISel::trySignedBitfieldInsertInSign(SDNode *Node) {
+ // Only supported with XAndesPerf at the moment.
+ if (!Subtarget->hasVendorXAndesPerf())
+ return false;
+
+ auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
+ if (!N1C)
+ return false;
+
+ SDValue N0 = Node->getOperand(0);
+ if (!N0.hasOneUse())
+ return false;
+
+ auto BitfieldInsert = [&](SDValue N0, unsigned Msb, unsigned Lsb,
+ const SDLoc &DL, MVT VT) {
+ unsigned Opc = RISCV::NDS_BFOS;
+ // If the Lsb is equal to the Msb, then the Lsb should be 0.
+ if (Lsb == Msb)
+ Lsb = 0;
+ return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
+ CurDAG->getTargetConstant(Lsb, DL, VT),
+ CurDAG->getTargetConstant(Msb, DL, VT));
+ };
+
+ SDLoc DL(Node);
+ MVT VT = Node->getSimpleValueType(0);
+ const unsigned RightShAmt = N1C->getZExtValue();
+
+ // Transform (sra (shl X, C1) C2) with C1 > C2
+ // -> (NDS.BFOS X, lsb, msb)
+ if (N0.getOpcode() == ISD::SHL) {
+ auto *N01C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
+ if (!N01C)
+ return false;
+
+ const unsigned LeftShAmt = N01C->getZExtValue();
+ // Make sure that this is a bitfield insertion (i.e., the shift-right
+ // amount should be less than the left-shift).
+ if (LeftShAmt <= RightShAmt)
+ return false;
+
+ const unsigned MsbPlusOne = VT.getSizeInBits() - RightShAmt;
+ const unsigned Msb = MsbPlusOne - 1;
+ const unsigned Lsb = LeftShAmt - RightShAmt;
+
+ SDNode *Sbi = BitfieldInsert(N0, Msb, Lsb, DL, VT);
+ ReplaceNode(Node, Sbi);
+ return true;
+ }
+
+ return false;
+}
+
bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node,
const SDLoc &DL, MVT VT,
SDValue X, unsigned Msb,
@@ -1214,6 +1267,9 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
if (trySignedBitfieldExtract(Node))
return;
+ if (trySignedBitfieldInsertInSign(Node))
+ return;
+
// Optimize (sra (sext_inreg X, i16), C) ->
// (srai (slli X, (XLen-16), (XLen-16) + C)
// And (sra (sext_inreg X, i8), C) ->
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
index abc0372d15c4f..cb63c21fd8fc9 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
@@ -77,6 +77,7 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
bool tryShrinkShlLogicImm(SDNode *Node);
bool trySignedBitfieldExtract(SDNode *Node);
+ bool trySignedBitfieldInsertInSign(SDNode *Node);
bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT,
SDValue X, unsigned Msb, unsigned Lsb);
bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT,
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index 3996420d477b2..3e7f09f3d6c22 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -154,6 +154,32 @@ define i32 @bfos_from_ashr_sexti16_i32(i16 %x) {
ret i32 %ashr
}
+; MSB = 0
+
+define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 0, 14
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 31
+ %lshr = ashr i32 %shl, 17
+ ret i32 %lshr
+}
+
+; MSB < LSB
+
+define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 18, 20
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 29
+ %lshr = ashr i32 %shl, 11
+ ret i32 %lshr
+}
+
+; sext
+
define i32 @sexti1_i32(i32 %a) {
; CHECK-LABEL: sexti1_i32:
; CHECK: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
index af7c300a92d1f..98cda42665169 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -212,6 +212,52 @@ define i64 @bfos_from_ashr_sexti16_i64(i16 %x) {
ret i64 %ashr
}
+; MSB = 0
+
+define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 0, 14
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 31
+ %lshr = ashr i32 %shl, 17
+ ret i32 %lshr
+}
+
+define i64 @bfos_from_ashr_shl_with_msb_zero_insert_i64(i64 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 0, 46
+; CHECK-NEXT: ret
+ %shl = shl i64 %x, 63
+ %lshr = ashr i64 %shl, 17
+ ret i64 %lshr
+}
+
+; MSB < LSB
+
+define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 18, 20
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 29
+ %lshr = ashr i32 %shl, 11
+ ret i32 %lshr
+}
+
+define i64 @bfos_from_ashr_shl_insert_i64(i64 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_insert_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 18, 52
+; CHECK-NEXT: ret
+ %shl = shl i64 %x, 29
+ %lshr = ashr i64 %shl, 11
+ ret i64 %lshr
+}
+
+; sext
+
define signext i32 @sexti1_i32(i32 signext %a) {
; CHECK-LABEL: sexti1_i32:
; CHECK: # %bb.0:
More information about the llvm-commits
mailing list