[llvm] [RISCV] Add TuneJumpIsExpensive (PR #191374)

Pengcheng Wang via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 03:17:30 PDT 2026


https://github.com/wangpc-pp updated https://github.com/llvm/llvm-project/pull/191374

>From dbc3d0cc2c52cd3f2b2101d150249040b4267ed1 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Fri, 10 Apr 2026 17:42:03 +0800
Subject: [PATCH 1/3] [RISCV] Add TuneJumpIsExpensive

We have `setJumpIsExpensive(true)` before 18.x but it was removed
in #74647. This feature allows users to tune the ISel behavior.

We have #80124 and #178394 landed, so it should be more flexible
to tune branches and selects now.

This is an alternative of #191158.
---
 llvm/lib/Target/RISCV/RISCVFeatures.td                | 4 ++++
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp           | 2 ++
 llvm/test/CodeGen/RISCV/features-info.ll              | 1 +
 llvm/unittests/TargetParser/RISCVTargetParserTest.cpp | 3 ++-
 4 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 492c44a35b35a..ccc07e5518048 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -2051,6 +2051,10 @@ def TunePreferVsetvliOverReadVLENB
           "prefer-vsetvli-over-read-vlenb", "PreferVsetvliOverReadVLENB",
           "true", "Prefer vsetvli over read vlenb CSR to calculate VLEN">;
 
+def TuneJumpIsExpensive
+    : RISCVSimpleTuneFeature<"jump-is-expensive", "IsJumpExpensive",
+                             "true", "Jump is expensive">;
+
 //===----------------------------------------------------------------------===//
 // CPU Families (alphabetized by vendor).
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index ce8cd0f6f5776..dc427f54c4e07 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -1914,6 +1914,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
 
   setMaxLargeFPConvertBitWidthSupported(Subtarget.is64Bit() ? 128 : 64);
 
+  setJumpIsExpensive(Subtarget.isJumpExpensive());
+
   // Disable strict node mutation.
   IsStrictFPEnabled = true;
   EnableExtLdPromotion = true;
diff --git a/llvm/test/CodeGen/RISCV/features-info.ll b/llvm/test/CodeGen/RISCV/features-info.ll
index 7c4271b409f82..4be8273430a2e 100644
--- a/llvm/test/CodeGen/RISCV/features-info.ll
+++ b/llvm/test/CodeGen/RISCV/features-info.ll
@@ -62,6 +62,7 @@
 ; CHECK-NEXT:   fusion-zextw                     - Enable SLLI+SRLI to be fused to zero extension of word.
 ; CHECK-NEXT:   h                                - 'H' (Hypervisor).
 ; CHECK-NEXT:   i                                - 'I' (Base Integer Instruction Set).
+; CHECK-NEXT:   jump-is-expensive                - Jump is expensive.
 ; CHECK-NEXT:   log-vrgather                     - Has vrgather.vv with LMUL*log2(LMUL) latency
 ; CHECK-NEXT:   m                                - 'M' (Integer Multiplication and Division).
 ; CHECK-NEXT:   mips-p8700                       - MIPS p8700 processor.
diff --git a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
index 0302d56e3e3fa..3949e0f0bab0a 100644
--- a/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/RISCVTargetParserTest.cpp
@@ -44,13 +44,14 @@ TEST(RISCVTuneFeature, AllTuneFeatures) {
   RISCV::getAllTuneFeatures(AllTuneFeatures);
   // Only allowed subtarget features that are explicitly marked by
   // special TableGen class.
-  EXPECT_EQ(AllTuneFeatures.size(), 20U);
+  EXPECT_EQ(AllTuneFeatures.size(), 21U);
   for (auto F : {"conditional-cmv-fusion",
                  "disable-latency-sched-heuristic",
                  "disable-misched-load-clustering",
                  "disable-misched-store-clustering",
                  "disable-postmisched-load-clustering",
                  "disable-postmisched-store-clustering",
+                 "jump-is-expensive",
                  "single-element-vec-fp64",
                  "no-default-unroll",
                  "no-sink-splat-operands",

>From 9ddf9a181436b3ce71ff48ec8f63172c3def8d4c Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Mon, 13 Apr 2026 14:13:44 +0800
Subject: [PATCH 2/3] Use RISCVTuneFeature

---
 llvm/lib/Target/RISCV/RISCVFeatures.td | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index ccc07e5518048..5b6ca7d6cc5d1 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -2052,8 +2052,9 @@ def TunePreferVsetvliOverReadVLENB
           "true", "Prefer vsetvli over read vlenb CSR to calculate VLEN">;
 
 def TuneJumpIsExpensive
-    : RISCVSimpleTuneFeature<"jump-is-expensive", "IsJumpExpensive",
-                             "true", "Jump is expensive">;
+    : RISCVTuneFeature<"jump-is-expensive", "jump-is-expensive",
+                       "jump-is-cheap", "IsJumpExpensive",
+                       "true", "Jump is expensive">;
 
 //===----------------------------------------------------------------------===//
 // CPU Families (alphabetized by vendor).

>From 3ea6b710d97c96ff857ee701e0954f856af09d46 Mon Sep 17 00:00:00 2001
From: Pengcheng Wang <wangpengcheng.pp at bytedance.com>
Date: Thu, 16 Apr 2026 18:17:10 +0800
Subject: [PATCH 3/3] Add test llvm/test/CodeGen/RISCV/jump-is-expensive.ll

---
 llvm/test/CodeGen/RISCV/jump-is-expensive.ll | 92 ++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/jump-is-expensive.ll

diff --git a/llvm/test/CodeGen/RISCV/jump-is-expensive.ll b/llvm/test/CodeGen/RISCV/jump-is-expensive.ll
new file mode 100644
index 0000000000000..a6053fa8efc7a
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/jump-is-expensive.ll
@@ -0,0 +1,92 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=riscv64 | FileCheck %s --check-prefix=CHEAP
+; RUN: llc < %s -mtriple=riscv64 -jump-is-expensive=0 | FileCheck %s --check-prefix=CHEAP
+; RUN: llc < %s -mtriple=riscv64 -mattr=+jump-is-expensive | FileCheck %s --check-prefix=EXPENSIVE
+; RUN: llc < %s -mtriple=riscv64 -jump-is-expensive=1 | FileCheck %s --check-prefix=EXPENSIVE
+
+define void @foo(i32 %X, i32 %Y, i32 %Z) nounwind {
+; CHEAP-LABEL: foo:
+; CHEAP:       # %bb.0: # %entry
+; CHEAP-NEXT:    sext.w a1, a1
+; CHEAP-NEXT:    li a2, 5
+; CHEAP-NEXT:    blt a1, a2, .LBB0_3
+; CHEAP-NEXT:  # %bb.1: # %entry
+; CHEAP-NEXT:    sext.w a0, a0
+; CHEAP-NEXT:    beqz a0, .LBB0_3
+; CHEAP-NEXT:  # %bb.2: # %UnifiedReturnBlock
+; CHEAP-NEXT:    ret
+; CHEAP-NEXT:  .LBB0_3: # %cond_true
+; CHEAP-NEXT:    tail bar
+;
+; EXPENSIVE-LABEL: foo:
+; EXPENSIVE:       # %bb.0: # %entry
+; EXPENSIVE-NEXT:    sext.w a1, a1
+; EXPENSIVE-NEXT:    sext.w a0, a0
+; EXPENSIVE-NEXT:    seqz a0, a0
+; EXPENSIVE-NEXT:    slti a1, a1, 5
+; EXPENSIVE-NEXT:    or a0, a0, a1
+; EXPENSIVE-NEXT:    beqz a0, .LBB0_2
+; EXPENSIVE-NEXT:  # %bb.1: # %cond_true
+; EXPENSIVE-NEXT:    tail bar
+; EXPENSIVE-NEXT:  .LBB0_2: # %UnifiedReturnBlock
+; EXPENSIVE-NEXT:    ret
+entry:
+  %tmp1 = icmp eq i32 %X, 0
+  %tmp3 = icmp slt i32 %Y, 5
+  %tmp4 = or i1 %tmp3, %tmp1
+  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock
+
+cond_true:
+  %tmp5 = tail call i32 (...) @bar( )
+  ret void
+
+UnifiedReturnBlock:
+  ret void
+}
+
+; If the branch is unpredictable, don't add another branch
+; regardless of whether they are expensive or not.
+
+define void @unpredictable(i32 %X, i32 %Y, i32 %Z) nounwind {
+; CHEAP-LABEL: unpredictable:
+; CHEAP:       # %bb.0: # %entry
+; CHEAP-NEXT:    sext.w a1, a1
+; CHEAP-NEXT:    sext.w a0, a0
+; CHEAP-NEXT:    seqz a0, a0
+; CHEAP-NEXT:    slti a1, a1, 5
+; CHEAP-NEXT:    or a0, a0, a1
+; CHEAP-NEXT:    beqz a0, .LBB1_2
+; CHEAP-NEXT:  # %bb.1: # %cond_true
+; CHEAP-NEXT:    tail bar
+; CHEAP-NEXT:  .LBB1_2: # %UnifiedReturnBlock
+; CHEAP-NEXT:    ret
+;
+; EXPENSIVE-LABEL: unpredictable:
+; EXPENSIVE:       # %bb.0: # %entry
+; EXPENSIVE-NEXT:    sext.w a1, a1
+; EXPENSIVE-NEXT:    sext.w a0, a0
+; EXPENSIVE-NEXT:    seqz a0, a0
+; EXPENSIVE-NEXT:    slti a1, a1, 5
+; EXPENSIVE-NEXT:    or a0, a0, a1
+; EXPENSIVE-NEXT:    beqz a0, .LBB1_2
+; EXPENSIVE-NEXT:  # %bb.1: # %cond_true
+; EXPENSIVE-NEXT:    tail bar
+; EXPENSIVE-NEXT:  .LBB1_2: # %UnifiedReturnBlock
+; EXPENSIVE-NEXT:    ret
+entry:
+  %tmp1 = icmp eq i32 %X, 0
+  %tmp3 = icmp slt i32 %Y, 5
+  %tmp4 = or i1 %tmp3, %tmp1
+  br i1 %tmp4, label %cond_true, label %UnifiedReturnBlock, !unpredictable !0
+
+cond_true:
+  %tmp5 = tail call i32 (...) @bar( )
+  ret void
+
+UnifiedReturnBlock:
+  ret void
+}
+
+declare i32 @bar(...)
+
+!0 = !{}



More information about the llvm-commits mailing list