[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