[llvm] [RISCV] Select signed bitfield insert for XAndesPerf (PR #143356)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 9 19:25:52 PDT 2025


https://github.com/tclin914 updated https://github.com/llvm/llvm-project/pull/143356

>From adbca923156b3189b965fbeec120678105f16b80 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Mon, 9 Jun 2025 15:54:35 +0800
Subject: [PATCH 1/3] [RISCV] Pre-commit

---
 llvm/test/CodeGen/RISCV/rv32xandesperf.ll | 28 +++++++++++++
 llvm/test/CodeGen/RISCV/rv64xandesperf.ll | 50 +++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index 3996420d477b2..f76f16a72f54f 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -154,6 +154,34 @@ 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:    slli a0, a0, 31
+; CHECK-NEXT:    srai a0, a0, 17
+; 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:    slli a0, a0, 29
+; CHECK-NEXT:    srai a0, a0, 11
+; 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..8ee16a009335f 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -212,6 +212,56 @@ 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:    slli a0, a0, 63
+; CHECK-NEXT:    srai a0, a0, 49
+; 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:    slli a0, a0, 63
+; CHECK-NEXT:    srai a0, a0, 17
+; 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:    slli a0, a0, 61
+; CHECK-NEXT:    srai a0, a0, 43
+; 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:    slli a0, a0, 29
+; CHECK-NEXT:    srai a0, a0, 11
+; 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:

>From fbf78164d9bf72820f4c4e3c42119cd9047167e4 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Mon, 9 Jun 2025 15:55:50 +0800
Subject: [PATCH 2/3] [RISCV] Select signed bitfield insert for XAndesPerf

---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 56 +++++++++++++++++++++
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h   |  1 +
 llvm/test/CodeGen/RISCV/rv32xandesperf.ll   |  6 +--
 llvm/test/CodeGen/RISCV/rv64xandesperf.ll   | 12 ++---
 4 files changed, 63 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 494d6ed03292a..1bed4051c09e6 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -671,6 +671,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, 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, SDLoc DL,
                                                    MVT VT, SDValue X,
                                                    unsigned Msb, unsigned Lsb) {
@@ -1191,6 +1244,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 f199c2031b9a9..80deac2be12fc 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, SDLoc DL, MVT VT, SDValue X,
                                   unsigned Msb, unsigned Lsb);
   bool tryUnsignedBitfieldInsertInZero(SDNode *Node, SDLoc DL, MVT VT,
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index f76f16a72f54f..3e7f09f3d6c22 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -159,8 +159,7 @@ define i32 @bfos_from_ashr_sexti16_i32(i16 %x) {
 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:    slli a0, a0, 31
-; CHECK-NEXT:    srai a0, a0, 17
+; CHECK-NEXT:    nds.bfos a0, a0, 0, 14
 ; CHECK-NEXT:    ret
   %shl = shl i32 %x, 31
   %lshr = ashr i32 %shl, 17
@@ -172,8 +171,7 @@ define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
 define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
 ; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 29
-; CHECK-NEXT:    srai a0, a0, 11
+; CHECK-NEXT:    nds.bfos a0, a0, 18, 20
 ; CHECK-NEXT:    ret
   %shl = shl i32 %x, 29
   %lshr = ashr i32 %shl, 11
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
index 8ee16a009335f..98cda42665169 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -217,8 +217,7 @@ define i64 @bfos_from_ashr_sexti16_i64(i16 %x) {
 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:    slli a0, a0, 63
-; CHECK-NEXT:    srai a0, a0, 49
+; CHECK-NEXT:    nds.bfos a0, a0, 0, 14
 ; CHECK-NEXT:    ret
   %shl = shl i32 %x, 31
   %lshr = ashr i32 %shl, 17
@@ -228,8 +227,7 @@ define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
 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:    slli a0, a0, 63
-; CHECK-NEXT:    srai a0, a0, 17
+; CHECK-NEXT:    nds.bfos a0, a0, 0, 46
 ; CHECK-NEXT:    ret
   %shl = shl i64 %x, 63
   %lshr = ashr i64 %shl, 17
@@ -241,8 +239,7 @@ define i64 @bfos_from_ashr_shl_with_msb_zero_insert_i64(i64 %x) {
 define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
 ; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 61
-; CHECK-NEXT:    srai a0, a0, 43
+; CHECK-NEXT:    nds.bfos a0, a0, 18, 20
 ; CHECK-NEXT:    ret
   %shl = shl i32 %x, 29
   %lshr = ashr i32 %shl, 11
@@ -252,8 +249,7 @@ define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
 define i64 @bfos_from_ashr_shl_insert_i64(i64 %x) {
 ; CHECK-LABEL: bfos_from_ashr_shl_insert_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 29
-; CHECK-NEXT:    srai a0, a0, 11
+; CHECK-NEXT:    nds.bfos a0, a0, 18, 52
 ; CHECK-NEXT:    ret
   %shl = shl i64 %x, 29
   %lshr = ashr i64 %shl, 11

>From c0168fca14f9b6f292d34b30ff0c7981b0e67c59 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Tue, 10 Jun 2025 09:07:46 +0800
Subject: [PATCH 3/3] SDLoc passed by const reference

---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 1bed4051c09e6..edbf6b776c42c 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -684,8 +684,8 @@ bool RISCVDAGToDAGISel::trySignedBitfieldInsertInSign(SDNode *Node) {
   if (!N0.hasOneUse())
     return false;
 
-  auto BitfieldInsert = [&](SDValue N0, unsigned Msb, unsigned Lsb, SDLoc DL,
-                            MVT VT) {
+  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)



More information about the llvm-commits mailing list