https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/204724
Backport 9fc458a1d95b Requested by: @yonghong-song >From 2972230af989ecd61fd45e4c5c8b4d56a8e30a84 Mon Sep 17 00:00:00 2001 From: yonghong-song <[email protected]> Date: Thu, 18 Jun 2026 18:38:00 -0700 Subject: [PATCH] [BPF] Fix erroneous removal of non-jump-table globals (#204594) Jump tables are supported only for cpu v4. After lowering them into .jumptables entries, BPFAsmPrinter::doFinalization() removes the private constant arrays that backed the jump tables. But the below 'for' loop is actually a no-op. for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { if (!dyn_cast<BlockAddress>(CA->getOperand(i))) continue; } Targets.push_back(&Global); With current implementation, 'Global' will be added to 'Targets' and later in doFinalization(), 'Global' will be removed. But it is possible in 'Global' there exists non BlockAddress which are used in later code. This will cause the problem like: error: Undefined temporary symbol .L__const.select_fn.fns To fix the problem, For the above 'for' loop, only if all operands are with BlockAddress, 'Global' can be pushed to 'Targets'. The issue is discovered when running bpf selftest with -O1. The related file is tools/testing/selftests/bpf/progs/kprobe_multi_session.c Before optimization, we have @__const.session_check.kfuncs = private unnamed_addr constant [8 x ptr] [ptr @bpf_fentry_test1, ptr @bpf_fentry_test2, ptr @bpf_fentry_test3, ptr @bpf_fentry_test4, ptr @bpf_fentry_test5, ptr @bpf_fentry_test6, ptr @bpf_fentry_test7, ptr @bpf_fentry_test8], align 8 With -O1, `@__const.session_check.kfuncs` is used in codegen like ... $r2 = LD_imm64 @__const.session_check.kfuncs ... which triggered the compilation failure. With -O2, `@__const.session_check.kfuncs` is inlined in llvm GlobalOptPass and each individual funciton `@bpf_fentry_test1` etc. is directly used in IR, e.g., ... %9 = icmp eq i64 %8, ptrtoint (ptr @bpf_fentry_test1 to i64), !dbg !95 ... (cherry picked from commit 9fc458a1d95b9c3edf288e4ec2cd9dcd1fe0d895) --- llvm/lib/Target/BPF/BPFAsmPrinter.cpp | 7 ++-- .../CodeGen/BPF/jump_table_func_ptr_array.ll | 41 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/BPF/jump_table_func_ptr_array.ll diff --git a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp index abe081c0c76fd..2e472bd800888 100644 --- a/llvm/lib/Target/BPF/BPFAsmPrinter.cpp +++ b/llvm/lib/Target/BPF/BPFAsmPrinter.cpp @@ -74,10 +74,9 @@ bool BPFAsmPrinter::doFinalization(Module &M) { if (!CA) continue; - for (unsigned i = 1, e = CA->getNumOperands(); i != e; ++i) { - if (!dyn_cast<BlockAddress>(CA->getOperand(i))) - continue; - } + if (!all_of(CA->operands(), + [](const Use &Op) { return isa<BlockAddress>(Op); })) + continue; Targets.push_back(&Global); } diff --git a/llvm/test/CodeGen/BPF/jump_table_func_ptr_array.ll b/llvm/test/CodeGen/BPF/jump_table_func_ptr_array.ll new file mode 100644 index 0000000000000..0b50d57feb4d0 --- /dev/null +++ b/llvm/test/CodeGen/BPF/jump_table_func_ptr_array.ll @@ -0,0 +1,41 @@ +; RUN: llc -march=bpf -mcpu=v4 < %s | FileCheck %s + +; The real jump table (@__const.foo.jt, all BlockAddress) is converted into a +; .jumptables entry and its global is removed. +; CHECK-LABEL: foo: +; CHECK: r2 = BPF.JT.0.0 ll +; CHECK: gotox r1 +; CHECK: .section .jumptables +; CHECK: BPF.JT.0.0: + +; The function-pointer array is preserved and still emitted. +; CHECK-LABEL: get: +; CHECK: r2 = .Lkfuncs ll +; CHECK: .Lkfuncs: +; CHECK: .size .Lkfuncs, 16 + +@__const.foo.jt = private unnamed_addr constant [2 x ptr] [ptr blockaddress(@foo, %l1), ptr blockaddress(@foo, %l2)], align 8 +@kfuncs = private unnamed_addr constant [2 x ptr] [ptr @ext1, ptr @ext2], align 8 + +declare void @ext1() +declare void @ext2() + +define i32 @foo(i32 %a) { +entry: + %rem = and i32 %a, 1 + %idx = zext nneg i32 %rem to i64 + %g = getelementptr inbounds nuw [2 x ptr], ptr @__const.foo.jt, i64 0, i64 %idx + %t = load ptr, ptr %g, align 8 + indirectbr ptr %t, [label %l1, label %l2] +l1: + br label %l2 +l2: + %ret = phi i32 [ 4, %l1 ], [ 3, %entry ] + ret i32 %ret +} + +define ptr @get(i64 %i) { + %p = getelementptr inbounds [2 x ptr], ptr @kfuncs, i64 0, i64 %i + %v = load ptr, ptr %p, align 8 + ret ptr %v +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
