[llvm] [BPF] treat compiler fence as codegen no-op (PR #196734)
via llvm-commits
llvm-commits at lists.llvm.org
Sat May 9 08:48:48 PDT 2026
https://github.com/bidhan-a created https://github.com/llvm/llvm-project/pull/196734
The BPF backend has no instruction-selection pattern for `ISD::ATOMIC_FENCE`, so LLVM IR containing a fence instruction crashes with `Cannot select: AtomicFence...`.
**Rust code snippet**
```
#[unsafe(no_mangle)]
pub fn entrypoint(_input: *mut u8) -> u64 {
core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
0
}
```
**LLVM IR**
```
; ModuleID = 'linked_module'
source_filename = "linked_module"
target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128"
target triple = "bpfel"
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
define dso_local noundef i64 @entrypoint(ptr noundef readnone captures(none) %0) unnamed_addr #0 {
fence syncscope("singlethread") seq_cst
ret i64 0
}
attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn "target-cpu"="generic" }
!llvm.ident = !{!0}
!0 = !{!"rustc version 1.97.0-nightly (f53b654a8 2026-04-30)"}
```
**Error**
```
LLVM ERROR: Cannot select: 0x7fcf7701a1c0: ch = AtomicFence 0x7fcf75718df8, TargetConstant:i64<7>, TargetConstant:i64<0>
In function: entrypoint
Stack dump:
0. Running pass 'Function Pass Manager' on module 'linked_module'.
1. Running pass 'BPF DAG->DAG Pattern Instruction Selection' on function '@entrypoint'
```
-----
**Fix**
This patch lowers `ATOMIC_FENCE` to `ISD::MEMBARRIER`, which acts as a compiler barrier and codegens to a no-op, following the pattern used by other backends (e.g. [XCore](https://github.com/blueshift-gg/llvm-project/blob/BPF_atomic_fence/llvm/lib/Target/XCore/XCoreISelLowering.cpp#L885)).
>From ff7569d31c87432f8c949e769ed004c4c26f8218 Mon Sep 17 00:00:00 2001
From: bidhan-a <bidhan619 at gmail.com>
Date: Fri, 8 May 2026 13:20:22 +0545
Subject: [PATCH] [BPF] treat compiler fence as codegen no-op
---
llvm/lib/Target/BPF/BPFISelLowering.cpp | 12 ++++++++++++
llvm/lib/Target/BPF/BPFISelLowering.h | 1 +
llvm/test/CodeGen/BPF/atomic-fence.ll | 19 +++++++++++++++++++
3 files changed, 32 insertions(+)
create mode 100644 llvm/test/CodeGen/BPF/atomic-fence.ll
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 6ffa9d1693bc0..2fe934c814b88 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -110,6 +110,8 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::ATOMIC_STORE, VT, Custom);
}
+ setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
+
for (auto VT : { MVT::i32, MVT::i64 }) {
if (VT == MVT::i32 && !STI.getHasAlu32())
continue;
@@ -372,6 +374,8 @@ SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::ATOMIC_LOAD:
case ISD::ATOMIC_STORE:
return LowerATOMIC_LOAD_STORE(Op, DAG);
+ case ISD::ATOMIC_FENCE:
+ return LowerATOMIC_FENCE(Op, DAG);
case ISD::TRAP:
return LowerTRAP(Op, DAG);
}
@@ -770,6 +774,14 @@ SDValue BPFTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op,
return Op;
}
+SDValue BPFTargetLowering::LowerATOMIC_FENCE(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+
+ // MEMBARRIER is a compiler barrier; it codegens to a no-op.
+ return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
+}
+
static Function *createBPFUnreachable(Module *M) {
if (auto *Fn = M->getFunction(BPF_TRAP))
return Fn;
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index b16fce0dd418f..9bcc5157c0646 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -82,6 +82,7 @@ class BPFTargetLowering : public TargetLowering {
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerATOMIC_LOAD_STORE(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerTRAP(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/BPF/atomic-fence.ll b/llvm/test/CodeGen/BPF/atomic-fence.ll
new file mode 100644
index 0000000000000..7c9d10305ef2c
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/atomic-fence.ll
@@ -0,0 +1,19 @@
+; RUN: llc < %s -mtriple=bpfel | FileCheck %s
+; RUN: llc < %s -mtriple=bpfeb | FileCheck %s
+
+; CHECK-LABEL: atomic_fence
+; CHECK: #MEMBARRIER
+; CHECK: #MEMBARRIER
+; CHECK: #MEMBARRIER
+; CHECK: #MEMBARRIER
+; CHECK: #MEMBARRIER
+; CHECK: exit
+define void @atomic_fence() nounwind {
+entry:
+ fence acquire
+ fence release
+ fence acq_rel
+ fence seq_cst
+ fence syncscope("singlethread") seq_cst
+ ret void
+}
More information about the llvm-commits
mailing list