[llvm] [BOLT][RISCV] Avoid evaluating indirect branches as direct branches (PR #218088)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 19:16:51 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-bolt
Author: wangjue (WangJee)
<details>
<summary>Changes</summary>
The RISC-V branch evaluator can resolve JALR when the base register state is known. In particular, jalr zero, zero, 0 evaluates to address zero even though it remains an indirect branch.
Do not send indirect branches through the direct branch symbolization path. Leave them to the existing indirect branch handling instead.
Add a regression test modeling a tail call to an undefined weak symbol relaxed by GNU ld.
---
Full diff: https://github.com/llvm/llvm-project/pull/218088.diff
2 Files Affected:
- (modified) bolt/lib/Core/BinaryFunction.cpp (+2-1)
- (added) bolt/test/RISCV/weak-undefined-tail-call.s (+30)
``````````diff
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index a81fa2f45c206..eb904ebef201f 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -1423,7 +1423,8 @@ Error BinaryFunction::disassemble() {
if (MIB->isBranch(Instruction) || MIB->isCall(Instruction)) {
uint64_t TargetAddress = 0;
- if (MIB->evaluateBranch(Instruction, AbsoluteInstrAddr, Size,
+ if (!MIB->isIndirectBranch(Instruction) &&
+ MIB->evaluateBranch(Instruction, AbsoluteInstrAddr, Size,
TargetAddress)) {
// Check if the target is within the same function. Otherwise it's
// a call, possibly a tail call.
diff --git a/bolt/test/RISCV/weak-undefined-tail-call.s b/bolt/test/RISCV/weak-undefined-tail-call.s
new file mode 100644
index 0000000000000..41610630d7a17
--- /dev/null
+++ b/bolt/test/RISCV/weak-undefined-tail-call.s
@@ -0,0 +1,30 @@
+// RUN: llvm-mc -triple riscv64 -filetype=obj -o %t.o %s
+// RUN: ld.lld --emit-relocs -static -o %t.exe %t.o
+// RUN: llvm-bolt --print-cfg --print-only=_start -o %t.bolt %t.exe \
+// RUN: | FileCheck %s
+
+/// GNU ld can relax a tail call to an undefined weak symbol to
+/// `jalr zero, zero, 0`, while preserving the R_RISCV_CALL_PLT relocation on
+/// the preceding AUIPC. The JALR target is evaluatable as zero, but the
+/// instruction is still an indirect branch and must not be rewritten as a
+/// direct branch.
+
+ .text
+ .option norvc
+ .weak weak_func
+
+// CHECK-LABEL: Binary Function "_start
+// CHECK: auipc t1,
+// CHECK-NEXT: jr zero # TAILCALL
+
+ .globl _start
+ .type _start, @function
+_start:
+ li a0, 0
+ beqz a0, .Lreturn
+.Lcall:
+ auipc t1, 0
+ .reloc .Lcall, R_RISCV_CALL_PLT, weak_func
+ jalr zero, zero, 0
+.Lreturn:
+ ret
``````````
</details>
https://github.com/llvm/llvm-project/pull/218088
More information about the llvm-commits
mailing list