[llvm] [RISCV] Add nds.bfos and nds.bfoz for the short forward branch optimization. (PR #145836)

Jim Lin via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 25 22:34:02 PDT 2025


https://github.com/tclin914 created https://github.com/llvm/llvm-project/pull/145836

This adds nds.bfos and nds.bfoz, which are also supported by Andes
45-series CPUs for short forward branch optimization.

>From eed01b5b31bb9da6614b177e247696bc20932e9a Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Thu, 26 Jun 2025 10:02:14 +0800
Subject: [PATCH 1/2] [RISCV] Pre-commit test

---
 .../CodeGen/RISCV/short-forward-branch-opt.ll | 168 ++++++++++++++++--
 1 file changed, 155 insertions(+), 13 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
index 13c43a3875a08..0b32f19147796 100644
--- a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
+++ b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
@@ -2,7 +2,9 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+c,+zbb -verify-machineinstrs < %s \
 ; RUN:   | FileCheck -check-prefix=NOSFB %s
 ; RUN: llc -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+zbb -verify-machineinstrs < %s \
-; RUN:   | FileCheck -check-prefixes=SFB,NOZICOND,RV64SFB %s
+; RUN:   | FileCheck -check-prefixes=SFB,NOZICOND,RV64SFB,RV64SFBSIFIVEU74 %s
+; RUN: llc -mtriple=riscv64 -mcpu=andes-ax45 -mattr=+zbb -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefixes=SFB,NOZICOND,RV64SFB,RV64SFBANDESAX45 %s
 ; RUN: llc -mtriple=riscv64 -mcpu=sifive-u74 -mattr=+zicond,+zbb \
 ; RUN:   -verify-machineinstrs < %s | FileCheck -check-prefixes=SFB,ZICOND %s
 ; RUN: llc -mtriple=riscv32 -mcpu=sifive-e76 -mattr=+zbb -verify-machineinstrs < %s \
@@ -67,18 +69,31 @@ define signext i32 @test3(i32 signext %v, i32 signext %w, i32 signext %x, i32 si
 ; NOSFB-NEXT:    addw a0, a1, a2
 ; NOSFB-NEXT:    ret
 ;
-; RV64SFB-LABEL: test3:
-; RV64SFB:       # %bb.0:
-; RV64SFB-NEXT:    beqz a4, .LBB2_2
-; RV64SFB-NEXT:  # %bb.1:
-; RV64SFB-NEXT:    mv a2, a3
-; RV64SFB-NEXT:  .LBB2_2:
-; RV64SFB-NEXT:    bnez a4, .LBB2_4
-; RV64SFB-NEXT:  # %bb.3:
-; RV64SFB-NEXT:    mv a0, a1
-; RV64SFB-NEXT:  .LBB2_4:
-; RV64SFB-NEXT:    addw a0, a0, a2
-; RV64SFB-NEXT:    ret
+; RV64SFBSIFIVEU74-LABEL: test3:
+; RV64SFBSIFIVEU74:       # %bb.0:
+; RV64SFBSIFIVEU74-NEXT:    beqz a4, .LBB2_2
+; RV64SFBSIFIVEU74-NEXT:  # %bb.1:
+; RV64SFBSIFIVEU74-NEXT:    mv a2, a3
+; RV64SFBSIFIVEU74-NEXT:  .LBB2_2:
+; RV64SFBSIFIVEU74-NEXT:    bnez a4, .LBB2_4
+; RV64SFBSIFIVEU74-NEXT:  # %bb.3:
+; RV64SFBSIFIVEU74-NEXT:    mv a0, a1
+; RV64SFBSIFIVEU74-NEXT:  .LBB2_4:
+; RV64SFBSIFIVEU74-NEXT:    addw a0, a0, a2
+; RV64SFBSIFIVEU74-NEXT:    ret
+;
+; RV64SFBANDESAX45-LABEL: test3:
+; RV64SFBANDESAX45:       # %bb.0:
+; RV64SFBANDESAX45-NEXT:    bnez a4, .LBB2_2
+; RV64SFBANDESAX45-NEXT:  # %bb.1:
+; RV64SFBANDESAX45-NEXT:    mv a0, a1
+; RV64SFBANDESAX45-NEXT:  .LBB2_2:
+; RV64SFBANDESAX45-NEXT:    beqz a4, .LBB2_4
+; RV64SFBANDESAX45-NEXT:  # %bb.3:
+; RV64SFBANDESAX45-NEXT:    mv a2, a3
+; RV64SFBANDESAX45-NEXT:  .LBB2_4:
+; RV64SFBANDESAX45-NEXT:    addw a0, a0, a2
+; RV64SFBANDESAX45-NEXT:    ret
 ;
 ; ZICOND-LABEL: test3:
 ; ZICOND:       # %bb.0:
@@ -1692,3 +1707,130 @@ entry:
  %2 = select i1 %cond, i64 %C, i64 %1
  ret i64 %2
 }
+
+define i64 @select_bfoz(i64 %A, i64 %B, i1 zeroext %cond) {
+; NOSFB-LABEL: select_bfoz:
+; NOSFB:       # %bb.0: # %entry
+; NOSFB-NEXT:    bnez a2, .LBB39_2
+; NOSFB-NEXT:  # %bb.1: # %entry
+; NOSFB-NEXT:    slli a0, a0, 38
+; NOSFB-NEXT:    srli a1, a0, 61
+; NOSFB-NEXT:  .LBB39_2: # %entry
+; NOSFB-NEXT:    mv a0, a1
+; NOSFB-NEXT:    ret
+;
+; RV64SFBSIFIVEU74-LABEL: select_bfoz:
+; RV64SFBSIFIVEU74:       # %bb.0: # %entry
+; RV64SFBSIFIVEU74-NEXT:    slli a0, a0, 38
+; RV64SFBSIFIVEU74-NEXT:    bnez a2, .LBB39_2
+; RV64SFBSIFIVEU74-NEXT:  # %bb.1: # %entry
+; RV64SFBSIFIVEU74-NEXT:    srli a1, a0, 61
+; RV64SFBSIFIVEU74-NEXT:  .LBB39_2: # %entry
+; RV64SFBSIFIVEU74-NEXT:    mv a0, a1
+; RV64SFBSIFIVEU74-NEXT:    ret
+;
+; RV64SFBANDESAX45-LABEL: select_bfoz:
+; RV64SFBANDESAX45:       # %bb.0: # %entry
+; RV64SFBANDESAX45-NEXT:    nds.bfoz a0, a0, 25, 23
+; RV64SFBANDESAX45-NEXT:    beqz a2, .LBB39_2
+; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
+; RV64SFBANDESAX45-NEXT:    mv a0, a1
+; RV64SFBANDESAX45-NEXT:  .LBB39_2: # %entry
+; RV64SFBANDESAX45-NEXT:    ret
+;
+; ZICOND-LABEL: select_bfoz:
+; ZICOND:       # %bb.0: # %entry
+; ZICOND-NEXT:    slli a0, a0, 38
+; ZICOND-NEXT:    bnez a2, .LBB39_2
+; ZICOND-NEXT:  # %bb.1: # %entry
+; ZICOND-NEXT:    srli a1, a0, 61
+; ZICOND-NEXT:  .LBB39_2: # %entry
+; ZICOND-NEXT:    mv a0, a1
+; ZICOND-NEXT:    ret
+;
+; RV32SFB-LABEL: select_bfoz:
+; RV32SFB:       # %bb.0: # %entry
+; RV32SFB-NEXT:    slli a0, a0, 6
+; RV32SFB-NEXT:    mv a1, a3
+; RV32SFB-NEXT:    bnez a4, .LBB39_2
+; RV32SFB-NEXT:  # %bb.1: # %entry
+; RV32SFB-NEXT:    srli a2, a0, 29
+; RV32SFB-NEXT:  .LBB39_2: # %entry
+; RV32SFB-NEXT:    bnez a4, .LBB39_4
+; RV32SFB-NEXT:  # %bb.3: # %entry
+; RV32SFB-NEXT:    li a1, 0
+; RV32SFB-NEXT:  .LBB39_4: # %entry
+; RV32SFB-NEXT:    mv a0, a2
+; RV32SFB-NEXT:    ret
+entry:
+ %0 = lshr i64 %A, 23
+ %1 = and i64 %0, 7
+ %2 = select i1 %cond, i64 %B, i64 %1
+ ret i64 %2
+}
+
+define i64 @select_bfos(i64 %A, i64 %B, i1 zeroext %cond) {
+; NOSFB-LABEL: select_bfos:
+; NOSFB:       # %bb.0: # %entry
+; NOSFB-NEXT:    bnez a2, .LBB40_2
+; NOSFB-NEXT:  # %bb.1: # %entry
+; NOSFB-NEXT:    slli a0, a0, 31
+; NOSFB-NEXT:    srai a1, a0, 17
+; NOSFB-NEXT:  .LBB40_2: # %entry
+; NOSFB-NEXT:    mv a0, a1
+; NOSFB-NEXT:    ret
+;
+; RV64SFBSIFIVEU74-LABEL: select_bfos:
+; RV64SFBSIFIVEU74:       # %bb.0: # %entry
+; RV64SFBSIFIVEU74-NEXT:    slli a0, a0, 31
+; RV64SFBSIFIVEU74-NEXT:    bnez a2, .LBB40_2
+; RV64SFBSIFIVEU74-NEXT:  # %bb.1: # %entry
+; RV64SFBSIFIVEU74-NEXT:    srai a1, a0, 17
+; RV64SFBSIFIVEU74-NEXT:  .LBB40_2: # %entry
+; RV64SFBSIFIVEU74-NEXT:    mv a0, a1
+; RV64SFBSIFIVEU74-NEXT:    ret
+;
+; RV64SFBANDESAX45-LABEL: select_bfos:
+; RV64SFBANDESAX45:       # %bb.0: # %entry
+; RV64SFBANDESAX45-NEXT:    nds.bfos a0, a0, 14, 46
+; RV64SFBANDESAX45-NEXT:    beqz a2, .LBB40_2
+; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
+; RV64SFBANDESAX45-NEXT:    mv a0, a1
+; RV64SFBANDESAX45-NEXT:  .LBB40_2: # %entry
+; RV64SFBANDESAX45-NEXT:    ret
+;
+; ZICOND-LABEL: select_bfos:
+; ZICOND:       # %bb.0: # %entry
+; ZICOND-NEXT:    slli a0, a0, 31
+; ZICOND-NEXT:    bnez a2, .LBB40_2
+; ZICOND-NEXT:  # %bb.1: # %entry
+; ZICOND-NEXT:    srai a1, a0, 17
+; ZICOND-NEXT:  .LBB40_2: # %entry
+; ZICOND-NEXT:    mv a0, a1
+; ZICOND-NEXT:    ret
+;
+; RV32SFB-LABEL: select_bfos:
+; RV32SFB:       # %bb.0: # %entry
+; RV32SFB-NEXT:    srli a5, a0, 1
+; RV32SFB-NEXT:    slli a6, a1, 31
+; RV32SFB-NEXT:    slli a0, a0, 31
+; RV32SFB-NEXT:    slli a1, a5, 15
+; RV32SFB-NEXT:    srli a0, a0, 17
+; RV32SFB-NEXT:    or a5, a6, a5
+; RV32SFB-NEXT:    bnez a4, .LBB40_2
+; RV32SFB-NEXT:  # %bb.1: # %entry
+; RV32SFB-NEXT:    or a2, a0, a1
+; RV32SFB-NEXT:  .LBB40_2: # %entry
+; RV32SFB-NEXT:    bnez a4, .LBB40_4
+; RV32SFB-NEXT:  # %bb.3: # %entry
+; RV32SFB-NEXT:    srai a3, a5, 17
+; RV32SFB-NEXT:  .LBB40_4: # %entry
+; RV32SFB-NEXT:    mv a0, a2
+; RV32SFB-NEXT:    mv a1, a3
+; RV32SFB-NEXT:    ret
+entry:
+ %0 = shl i64 %A, 31
+ %1 = ashr i64 %0, 17
+ %2 = select i1 %cond, i64 %B, i64 %1
+ ret i64 %2
+}

>From 0ac294d6f0a23bf55d5bccb72440941588c8784b Mon Sep 17 00:00:00 2001
From: Jim Lin <jim at andestech.com>
Date: Thu, 26 Jun 2025 10:02:40 +0800
Subject: [PATCH 2/2] [RISCV] Add nds.bfos and nds.bfoz for the short forward
 branch optimization.

This adds nds.bfos and nds.bfoz, which are also supported by Andes
45-series CPUs for short forward branch optimization.
---
 .../Target/RISCV/RISCVExpandPseudoInsts.cpp    | 18 +++++++++++++++---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp       |  3 +++
 llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td  | 18 ++++++++++++++++++
 .../CodeGen/RISCV/short-forward-branch-opt.ll  | 12 ++++++------
 4 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index d3dce4edb1e75..bd2f0e6b794f5 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -147,6 +147,8 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
   case RISCV::PseudoCCANDN:
   case RISCV::PseudoCCORN:
   case RISCV::PseudoCCXNOR:
+  case RISCV::PseudoCCNDS_BFOS:
+  case RISCV::PseudoCCNDS_BFOZ:
     return expandCCOp(MBB, MBBI, NextMBBI);
   case RISCV::PseudoVMCLR_M_B1:
   case RISCV::PseudoVMCLR_M_B2:
@@ -240,10 +242,20 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
     case RISCV::PseudoCCANDN:  NewOpc = RISCV::ANDN;  break;
     case RISCV::PseudoCCORN:   NewOpc = RISCV::ORN;   break;
     case RISCV::PseudoCCXNOR:  NewOpc = RISCV::XNOR;  break;
+    case RISCV::PseudoCCNDS_BFOS: NewOpc = RISCV::NDS_BFOS; break;
+    case RISCV::PseudoCCNDS_BFOZ: NewOpc = RISCV::NDS_BFOZ; break;
+    }
+
+    if (NewOpc == RISCV::NDS_BFOZ || NewOpc == RISCV::NDS_BFOS) {
+      BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
+          .add(MI.getOperand(5))
+          .add(MI.getOperand(6))
+          .add(MI.getOperand(7));
+    } else {
+      BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
+          .add(MI.getOperand(5))
+          .add(MI.getOperand(6));
     }
-    BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
-        .add(MI.getOperand(5))
-        .add(MI.getOperand(6));
   }
 
   TrueBB->addSuccessor(MergeBB);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 5711f0077b12d..f703a69cc9a2e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1575,6 +1575,9 @@ unsigned getPredicatedOpcode(unsigned Opcode) {
   case RISCV::ANDN:  return RISCV::PseudoCCANDN;  break;
   case RISCV::ORN:   return RISCV::PseudoCCORN;   break;
   case RISCV::XNOR:  return RISCV::PseudoCCXNOR;  break;
+
+  case RISCV::NDS_BFOS:  return RISCV::PseudoCCNDS_BFOS;  break;
+  case RISCV::NDS_BFOZ:  return RISCV::PseudoCCNDS_BFOZ;  break;
   }
 
   return RISCV::INSTRUCTION_LIST_END;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
index 0e2fcd2336151..3d2b9c209dc59 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td
@@ -625,3 +625,21 @@ defset list<VTypeInfoToWide> AllQuadWidenableVD4DOTVectors = {
 defm : VPatTernaryVD4DOT_VV<"int_riscv_nds_vd4dots", "PseudoNDS_VD4DOTS", AllQuadWidenableVD4DOTVectors>;
 defm : VPatTernaryVD4DOT_VV<"int_riscv_nds_vd4dotu", "PseudoNDS_VD4DOTU", AllQuadWidenableVD4DOTVectors>;
 defm : VPatTernaryVD4DOT_VV<"int_riscv_nds_vd4dotsu", "PseudoNDS_VD4DOTSU", AllQuadWidenableVD4DOTVectors>;
+
+//===----------------------------------------------------------------------===//
+// Pseudo-instructions for SFB (Short Forward Branch)
+//===----------------------------------------------------------------------===//
+
+let Predicates = [HasShortForwardBranchOpt], hasSideEffects = 0,
+    mayLoad = 0, mayStore = 0, Size = 8, Constraints = "$dst = $falsev" in {
+def PseudoCCNDS_BFOS : Pseudo<(outs GPR:$dst),
+                              (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
+                               GPR:$falsev, GPR:$rs1, uimmlog2xlen:$msb, uimmlog2xlen:$lsb), []>,
+                       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
+                              ReadSFBALU]>;
+def PseudoCCNDS_BFOZ : Pseudo<(outs GPR:$dst),
+                              (ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
+                               GPR:$falsev, GPR:$rs1, uimmlog2xlen:$msb, uimmlog2xlen:$lsb), []>,
+                       Sched<[WriteSFB, ReadSFBJmp, ReadSFBJmp, ReadSFBALU,
+                              ReadSFBALU]>;
+}
diff --git a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
index 0b32f19147796..990039d765df8 100644
--- a/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
+++ b/llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll
@@ -1731,11 +1731,11 @@ define i64 @select_bfoz(i64 %A, i64 %B, i1 zeroext %cond) {
 ;
 ; RV64SFBANDESAX45-LABEL: select_bfoz:
 ; RV64SFBANDESAX45:       # %bb.0: # %entry
-; RV64SFBANDESAX45-NEXT:    nds.bfoz a0, a0, 25, 23
-; RV64SFBANDESAX45-NEXT:    beqz a2, .LBB39_2
+; RV64SFBANDESAX45-NEXT:    bnez a2, .LBB39_2
 ; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
-; RV64SFBANDESAX45-NEXT:    mv a0, a1
+; RV64SFBANDESAX45-NEXT:    nds.bfoz a1, a0, 25, 23
 ; RV64SFBANDESAX45-NEXT:  .LBB39_2: # %entry
+; RV64SFBANDESAX45-NEXT:    mv a0, a1
 ; RV64SFBANDESAX45-NEXT:    ret
 ;
 ; ZICOND-LABEL: select_bfoz:
@@ -1792,11 +1792,11 @@ define i64 @select_bfos(i64 %A, i64 %B, i1 zeroext %cond) {
 ;
 ; RV64SFBANDESAX45-LABEL: select_bfos:
 ; RV64SFBANDESAX45:       # %bb.0: # %entry
-; RV64SFBANDESAX45-NEXT:    nds.bfos a0, a0, 14, 46
-; RV64SFBANDESAX45-NEXT:    beqz a2, .LBB40_2
+; RV64SFBANDESAX45-NEXT:    bnez a2, .LBB40_2
 ; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
-; RV64SFBANDESAX45-NEXT:    mv a0, a1
+; RV64SFBANDESAX45-NEXT:    nds.bfos a1, a0, 14, 46
 ; RV64SFBANDESAX45-NEXT:  .LBB40_2: # %entry
+; RV64SFBANDESAX45-NEXT:    mv a0, a1
 ; RV64SFBANDESAX45-NEXT:    ret
 ;
 ; ZICOND-LABEL: select_bfos:



More information about the llvm-commits mailing list