[llvm] [RISCV] Select unsigned bitfield extracts for XAndesPerf (PR #141398)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Mon May 26 22:04:05 PDT 2025


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

>From d1d3a3231e2b03f9446a2ce4a8f9d02045be20b6 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Sun, 25 May 2025 14:44:44 +0800
Subject: [PATCH 1/3] [RISCV] Pre-commit

---
 llvm/test/CodeGen/RISCV/rv32xandesperf.ll | 73 +++++++++++++++++++++++
 llvm/test/CodeGen/RISCV/rv64xandesperf.ll | 64 ++++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index efe5b4a306fee..a60251f095cda 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -2,6 +2,79 @@
 ; RUN: llc -O0 -mtriple=riscv32 -mattr=+xandesperf -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s
 
+define i32 @bfoz_from_and_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_and_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 20
+; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    ret
+  %a = and i32 %x, 4095
+  ret i32 %a
+}
+
+define i64 @bfoz_from_and_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_and_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $x11 killed $x10
+; CHECK-NEXT:    slli a0, a0, 20
+; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    ret
+  %a = and i64 %x, 4095
+  ret i64 %a
+}
+
+define i32 @bfoz_from_and_lshr_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_and_lshr_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 6
+; CHECK-NEXT:    srli a0, a0, 29
+; CHECK-NEXT:    ret
+  %shifted = lshr i32 %x, 23
+  %masked = and i32 %shifted, 7
+  ret i32 %masked
+}
+
+define i64 @bfoz_from_and_lshr_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_and_lshr_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $x12 killed $x11
+; CHECK-NEXT:    slli a0, a1, 6
+; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    ret
+  %shifted = lshr i64 %x, 46
+  %masked = and i64 %shifted, 4095
+  ret i64 %masked
+}
+
+define i32 @bfoz_from_lshr_and_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_lshr_and_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 8
+; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    ret
+  %masked = and i32 %x, 16773120
+  %shifted = lshr i32 %masked, 12
+  ret i32 %shifted
+}
+
+define i64 @bfoz_from_lshr_and_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_lshr_and_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    # kill: def $x12 killed $x11
+; CHECK-NEXT:    # kill: def $x12 killed $x10
+; CHECK-NEXT:    andi a1, a1, 15
+; CHECK-NEXT:    srli a0, a0, 24
+; CHECK-NEXT:    slli a1, a1, 8
+; CHECK-NEXT:    or a0, a0, a1
+; CHECK-NEXT:    li a1, 0
+; CHECK-NEXT:    ret
+  %masked = and i64 %x, 68702699520
+  %shifted = lshr i64 %masked, 24
+  ret i64 %shifted
+}
+
 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 9cc95ce886133..360a7ba43cd67 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -2,6 +2,70 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+xandesperf -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s
 
+define i32 @bfoz_from_and_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_and_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 52
+; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    ret
+  %a = and i32 %x, 4095
+  ret i32 %a
+}
+
+define i64 @bfoz_from_and_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_and_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 52
+; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    ret
+  %a = and i64 %x, 4095
+  ret i64 %a
+}
+
+define i32 @bfoz_from_and_lshr_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_and_lshr_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 38
+; CHECK-NEXT:    srli a0, a0, 61
+; CHECK-NEXT:    ret
+  %shifted = lshr i32 %x, 23
+  %masked = and i32 %shifted, 7
+  ret i32 %masked
+}
+
+define i64 @bfoz_from_and_lshr_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_and_lshr_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 6
+; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    ret
+  %shifted = lshr i64 %x, 46
+  %masked = and i64 %shifted, 4095
+  ret i64 %masked
+}
+
+define i32 @bfoz_from_lshr_and_i32(i32 %x) {
+; CHECK-LABEL: bfoz_from_lshr_and_i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 40
+; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    ret
+  %masked = and i32 %x, 16773120
+  %shifted = lshr i32 %masked, 12
+  ret i32 %shifted
+}
+
+define i64 @bfoz_from_lshr_and_i64(i64 %x) {
+; CHECK-LABEL: bfoz_from_lshr_and_i64:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    slli a0, a0, 28
+; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    ret
+  %masked = and i64 %x, 68702699520
+  %shifted = lshr i64 %masked, 24
+  ret i64 %shifted
+}
+
 define signext i32 @sexti1_i32(i32 signext %a) {
 ; CHECK-LABEL: sexti1_i32:
 ; CHECK:       # %bb.0:

>From 06cf15dd27968fffee18917a3e882cb1c634d383 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Sun, 25 May 2025 14:47:59 +0800
Subject: [PATCH 2/3] [RISCV] Select unsigned bitfiled extracts for XAndesPerf

The XAndesPerf extension includes unsigned bitfield extraction instruction
`NDS.BFOZ`, which can extract the bits from LSB to MSB, places them starting
at bit 0, and zero-extends the result.
---
 llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 15 +++++++++------
 llvm/test/CodeGen/RISCV/rv32xandesperf.ll   | 15 +++++----------
 llvm/test/CodeGen/RISCV/rv64xandesperf.ll   | 18 ++++++------------
 3 files changed, 20 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 18af1545d5a34..306da41a9c8e4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -672,14 +672,17 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
 bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL,
                                                    MVT VT, SDValue X,
                                                    unsigned Msb, unsigned Lsb) {
-  // Only supported with XTHeadBb at the moment.
-  if (!Subtarget->hasVendorXTHeadBb())
+  // Only supported with XTHeadBb/XAndesPerf at the moment.
+  if (!Subtarget->hasVendorXTHeadBb() && !Subtarget->hasVendorXAndesPerf())
     return false;
 
-  SDNode *TH_EXTU = CurDAG->getMachineNode(
-      RISCV::TH_EXTU, DL, VT, X, CurDAG->getTargetConstant(Msb, DL, VT),
-      CurDAG->getTargetConstant(Lsb, DL, VT));
-  ReplaceNode(Node, TH_EXTU);
+  unsigned Opc =
+      Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXTU : RISCV::NDS_BFOZ;
+
+  SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
+                                       CurDAG->getTargetConstant(Msb, DL, VT),
+                                       CurDAG->getTargetConstant(Lsb, DL, VT));
+  ReplaceNode(Node, Ube);
   return true;
 }
 
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index a60251f095cda..72dddddf9f382 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -5,8 +5,7 @@
 define i32 @bfoz_from_and_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_and_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 20
-; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    nds.bfoz a0, a0, 11, 0
 ; CHECK-NEXT:    ret
   %a = and i32 %x, 4095
   ret i32 %a
@@ -16,8 +15,7 @@ define i64 @bfoz_from_and_i64(i64 %x) {
 ; CHECK-LABEL: bfoz_from_and_i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    # kill: def $x11 killed $x10
-; CHECK-NEXT:    slli a0, a0, 20
-; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    nds.bfoz a0, a0, 11, 0
 ; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    ret
   %a = and i64 %x, 4095
@@ -27,8 +25,7 @@ define i64 @bfoz_from_and_i64(i64 %x) {
 define i32 @bfoz_from_and_lshr_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_and_lshr_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 6
-; CHECK-NEXT:    srli a0, a0, 29
+; CHECK-NEXT:    nds.bfoz a0, a0, 25, 23
 ; CHECK-NEXT:    ret
   %shifted = lshr i32 %x, 23
   %masked = and i32 %shifted, 7
@@ -39,8 +36,7 @@ define i64 @bfoz_from_and_lshr_i64(i64 %x) {
 ; CHECK-LABEL: bfoz_from_and_lshr_i64:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    # kill: def $x12 killed $x11
-; CHECK-NEXT:    slli a0, a1, 6
-; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    nds.bfoz a0, a1, 25, 14
 ; CHECK-NEXT:    li a1, 0
 ; CHECK-NEXT:    ret
   %shifted = lshr i64 %x, 46
@@ -51,8 +47,7 @@ define i64 @bfoz_from_and_lshr_i64(i64 %x) {
 define i32 @bfoz_from_lshr_and_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_lshr_and_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 8
-; CHECK-NEXT:    srli a0, a0, 20
+; CHECK-NEXT:    nds.bfoz a0, a0, 23, 12
 ; CHECK-NEXT:    ret
   %masked = and i32 %x, 16773120
   %shifted = lshr i32 %masked, 12
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
index 360a7ba43cd67..13c2234071eb1 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -5,8 +5,7 @@
 define i32 @bfoz_from_and_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_and_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 52
-; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    nds.bfoz a0, a0, 11, 0
 ; CHECK-NEXT:    ret
   %a = and i32 %x, 4095
   ret i32 %a
@@ -15,8 +14,7 @@ define i32 @bfoz_from_and_i32(i32 %x) {
 define i64 @bfoz_from_and_i64(i64 %x) {
 ; CHECK-LABEL: bfoz_from_and_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 52
-; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    nds.bfoz a0, a0, 11, 0
 ; CHECK-NEXT:    ret
   %a = and i64 %x, 4095
   ret i64 %a
@@ -25,8 +23,7 @@ define i64 @bfoz_from_and_i64(i64 %x) {
 define i32 @bfoz_from_and_lshr_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_and_lshr_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 38
-; CHECK-NEXT:    srli a0, a0, 61
+; CHECK-NEXT:    nds.bfoz a0, a0, 25, 23
 ; CHECK-NEXT:    ret
   %shifted = lshr i32 %x, 23
   %masked = and i32 %shifted, 7
@@ -36,8 +33,7 @@ define i32 @bfoz_from_and_lshr_i32(i32 %x) {
 define i64 @bfoz_from_and_lshr_i64(i64 %x) {
 ; CHECK-LABEL: bfoz_from_and_lshr_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 6
-; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    nds.bfoz a0, a0, 57, 46
 ; CHECK-NEXT:    ret
   %shifted = lshr i64 %x, 46
   %masked = and i64 %shifted, 4095
@@ -47,8 +43,7 @@ define i64 @bfoz_from_and_lshr_i64(i64 %x) {
 define i32 @bfoz_from_lshr_and_i32(i32 %x) {
 ; CHECK-LABEL: bfoz_from_lshr_and_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 40
-; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    nds.bfoz a0, a0, 23, 12
 ; CHECK-NEXT:    ret
   %masked = and i32 %x, 16773120
   %shifted = lshr i32 %masked, 12
@@ -58,8 +53,7 @@ define i32 @bfoz_from_lshr_and_i32(i32 %x) {
 define i64 @bfoz_from_lshr_and_i64(i64 %x) {
 ; CHECK-LABEL: bfoz_from_lshr_and_i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    slli a0, a0, 28
-; CHECK-NEXT:    srli a0, a0, 52
+; CHECK-NEXT:    nds.bfoz a0, a0, 35, 24
 ; CHECK-NEXT:    ret
   %masked = and i64 %x, 68702699520
   %shifted = lshr i64 %masked, 24

>From 39e549fd858198e35b52b24faf6ce049eace9b26 Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Tue, 27 May 2025 12:50:26 +0800
Subject: [PATCH 3/3] fix testcase

---
 llvm/test/CodeGen/RISCV/rv64zba.ll | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll
index 6bd808ca9e126..622b302da4c51 100644
--- a/llvm/test/CodeGen/RISCV/rv64zba.ll
+++ b/llvm/test/CodeGen/RISCV/rv64zba.ll
@@ -126,7 +126,7 @@ define i64 @zextw_i64(i64 %a) nounwind {
 ;
 ; RV64XANDESPERF-LABEL: zextw_i64:
 ; RV64XANDESPERF:       # %bb.0:
-; RV64XANDESPERF-NEXT:    nds.lea.b.ze a0, zero, a0
+; RV64XANDESPERF-NEXT:    nds.bfoz a0, a0, 31, 0
 ; RV64XANDESPERF-NEXT:    ret
   %and = and i64 %a, 4294967295
   ret i64 %and
@@ -151,7 +151,7 @@ define i64 @zextw_demandedbits_i64(i64 %0) {
 ; RV64XANDESPERF-LABEL: zextw_demandedbits_i64:
 ; RV64XANDESPERF:       # %bb.0:
 ; RV64XANDESPERF-NEXT:    ori a0, a0, 1
-; RV64XANDESPERF-NEXT:    nds.lea.b.ze a0, zero, a0
+; RV64XANDESPERF-NEXT:    nds.bfoz a0, a0, 31, 0
 ; RV64XANDESPERF-NEXT:    ret
   %2 = and i64 %0, 4294967294
   %3 = or i64 %2, 1
@@ -1577,7 +1577,7 @@ define i64 @adduw_imm(i32 signext %0) nounwind {
 ;
 ; RV64XANDESPERF-LABEL: adduw_imm:
 ; RV64XANDESPERF:       # %bb.0:
-; RV64XANDESPERF-NEXT:    nds.lea.b.ze a0, zero, a0
+; RV64XANDESPERF-NEXT:    nds.bfoz a0, a0, 31, 0
 ; RV64XANDESPERF-NEXT:    addi a0, a0, 5
 ; RV64XANDESPERF-NEXT:    ret
   %a = zext i32 %0 to i64
@@ -2324,8 +2324,7 @@ define zeroext i32 @sext_ashr_zext_i8(i8 %a) nounwind {
 ; RV64XANDESPERF-LABEL: sext_ashr_zext_i8:
 ; RV64XANDESPERF:       # %bb.0:
 ; RV64XANDESPERF-NEXT:    nds.bfos a0, a0, 7, 0
-; RV64XANDESPERF-NEXT:    slli a0, a0, 23
-; RV64XANDESPERF-NEXT:    srli a0, a0, 32
+; RV64XANDESPERF-NEXT:    nds.bfoz a0, a0, 40, 9
 ; RV64XANDESPERF-NEXT:    ret
   %ext = sext i8 %a to i32
   %1 = ashr i32 %ext, 9
@@ -2473,8 +2472,7 @@ define zeroext i32 @sext_ashr_zext_i16(i16 %a) nounwind {
 ; RV64XANDESPERF-LABEL: sext_ashr_zext_i16:
 ; RV64XANDESPERF:       # %bb.0:
 ; RV64XANDESPERF-NEXT:    nds.bfos a0, a0, 15, 0
-; RV64XANDESPERF-NEXT:    slli a0, a0, 23
-; RV64XANDESPERF-NEXT:    srli a0, a0, 32
+; RV64XANDESPERF-NEXT:    nds.bfoz a0, a0, 40, 9
 ; RV64XANDESPERF-NEXT:    ret
   %ext = sext i16 %a to i32
   %1 = ashr i32 %ext, 9



More information about the llvm-commits mailing list