Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 27, 2025

Conversation

tclin914
Copy link
Contributor

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

tclin914 added 2 commits June 26, 2025 13:18
…zation.

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

llvmbot commented Jun 26, 2025

@llvm/pr-subscribers-backend-risc-v

Author: Jim Lin (tclin914)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/145836.diff

4 Files Affected:

  • (modified) llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (+15-3)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+3)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td (+18)
  • (modified) llvm/test/CodeGen/RISCV/short-forward-branch-opt.ll (+155-13)
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 13c43a3875a08..990039d765df8 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:    bnez a2, .LBB39_2
+; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
+; 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:
+; 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:    bnez a2, .LBB40_2
+; RV64SFBANDESAX45-NEXT:  # %bb.1: # %entry
+; 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:
+; 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
+}

Copy link

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions cpp -- llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
View the diff from clang-format here.
diff --git a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
index bd2f0e6b7..e3b1aac9d 100644
--- a/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
@@ -242,8 +242,12 @@ 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;
+    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) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index b3cc6b2cf..fba5311f2 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1586,8 +1586,12 @@ unsigned getPredicatedOpcode(unsigned Opcode) {
   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;
+  case RISCV::NDS_BFOS:
+    return RISCV::PseudoCCNDS_BFOS;
+    break;
+  case RISCV::NDS_BFOZ:
+    return RISCV::PseudoCCNDS_BFOZ;
+    break;
   }
 
   return RISCV::INSTRUCTION_LIST_END;

Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tclin914 tclin914 merged commit 96ec1c2 into llvm:main Jun 27, 2025
8 of 9 checks passed
@tclin914 tclin914 deleted the andes-bfoz-bfos-sfb branch June 27, 2025 02:54
rlavaee pushed a commit to rlavaee/llvm-project that referenced this pull request Jul 1, 2025
…zation. (llvm#145836)

This adds nds.bfos and nds.bfoz, which are also supported by Andes
45-series CPUs for short forward branch optimization.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants