[llvm-branch-commits] [llvm] 761b913 - [BPF] treat compiler fence as codegen no-op (#196734)
Douglas Yung via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jun 10 10:47:01 PDT 2026
Author: Bidhan
Date: 2026-06-10T17:46:45Z
New Revision: 761b9134dd9beda6f133fdc19a42b148834cb06b
URL: https://github.com/llvm/llvm-project/commit/761b9134dd9beda6f133fdc19a42b148834cb06b
DIFF: https://github.com/llvm/llvm-project/commit/761b9134dd9beda6f133fdc19a42b148834cb06b.diff
LOG: [BPF] treat compiler fence as codegen no-op (#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 single-thread (compiler) fences to `ISD::MEMBARRIER`
(no-op) and produces an error for cross-thread (runtime) fences.
Added:
llvm/test/CodeGen/BPF/fence-singlethread.ll
Modified:
llvm/lib/Target/BPF/BPFISelLowering.cpp
llvm/lib/Target/BPF/BPFISelLowering.h
Removed:
################################################################################
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 5c03776dd6653..faf3af0918d54 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;
@@ -368,6 +370,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);
}
@@ -772,6 +776,19 @@ SDValue BPFTargetLowering::LowerATOMIC_LOAD_STORE(SDValue Op,
return Op;
}
+SDValue BPFTargetLowering::LowerATOMIC_FENCE(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SyncScope::ID FenceSSID =
+ static_cast<SyncScope::ID>(Op.getConstantOperandVal(2));
+
+ if (FenceSSID == SyncScope::SingleThread)
+ // MEMBARRIER is a compiler barrier; it codegens to a no-op.
+ return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0));
+
+ report_fatal_error("Runtime fence is not supported at the moment");
+}
+
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 8607e4f8c9e69..df1e2d8114ae1 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -73,6 +73,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/fence-singlethread.ll b/llvm/test/CodeGen/BPF/fence-singlethread.ll
new file mode 100644
index 0000000000000..91ea38db8b8c8
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/fence-singlethread.ll
@@ -0,0 +1,14 @@
+; RUN: llc < %s -mtriple=bpfel | FileCheck %s
+; RUN: llc < %s -mtriple=bpfeb | FileCheck %s
+
+; CHECK-LABEL: fence_singlethread:
+; CHECK-COUNT-4: #MEMBARRIER
+; CHECK-NEXT: exit
+define void @fence_singlethread() nounwind {
+entry:
+ fence syncscope("singlethread") acquire
+ fence syncscope("singlethread") release
+ fence syncscope("singlethread") acq_rel
+ fence syncscope("singlethread") seq_cst
+ ret void
+}
More information about the llvm-branch-commits
mailing list