[llvm] [BPF] crash fix for memcpy with unsupported alignment (PR #199541)
Claire Fan via llvm-commits
llvm-commits at lists.llvm.org
Mon May 25 09:21:25 PDT 2026
https://github.com/clairechingching updated https://github.com/llvm/llvm-project/pull/199541
>From 4c5139ed13aa9f30a4720f62a9c24a27f2f03d90 Mon Sep 17 00:00:00 2001
From: Claire Fan <fanyungching at gmail.com>
Date: Mon, 25 May 2026 12:21:11 -0400
Subject: [PATCH] [BPF] crash fix for memcpy with unsupported alignment
---
llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp | 13 +++++++++
llvm/lib/Target/BPF/BPFSelectionDAGInfo.h | 2 +-
.../CodeGen/BPF/libcall-memcpy-threshold.ll | 28 +++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/BPF/libcall-memcpy-threshold.ll
diff --git a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp
index 0e6d35dd3781f..ba93c868c2c8b 100644
--- a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp
+++ b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.cpp
@@ -21,9 +21,18 @@ using namespace llvm;
#define DEBUG_TYPE "bpf-selectiondag-info"
+static cl::opt<unsigned> BPFMaxStoresPerMemFunc(
+ "bpf-max-stores-per-memfunc", cl::Hidden, cl::init(128),
+ cl::desc("Set the maximum number of stores for inlined BPF memory "
+ "intrinsics"));
+
BPFSelectionDAGInfo::BPFSelectionDAGInfo()
: SelectionDAGGenTargetInfo(BPFGenSDNodeInfo) {}
+unsigned BPFSelectionDAGInfo::getCommonMaxStoresPerMemFunc() const {
+ return BPFMaxStoresPerMemFunc;
+}
+
SDValue BPFSelectionDAGInfo::EmitTargetCodeForMemcpy(
SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline,
@@ -33,6 +42,10 @@ SDValue BPFSelectionDAGInfo::EmitTargetCodeForMemcpy(
if (!ConstantSize)
return SDValue();
+ // BPF::MEMCPY supports alignment up to 8 bytes.
+ if (Alignment.value() > 8)
+ return SDValue();
+
unsigned CopyLen = ConstantSize->getZExtValue();
unsigned StoresNumEstimate = alignTo(CopyLen, Alignment) >> Log2(Alignment);
// Impose the same copy length limit as MaxStoresPerMemcpy.
diff --git a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h
index 7345d2d7e4738..eebea78435d16 100644
--- a/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h
+++ b/llvm/lib/Target/BPF/BPFSelectionDAGInfo.h
@@ -31,7 +31,7 @@ class BPFSelectionDAGInfo : public SelectionDAGGenTargetInfo {
MachinePointerInfo DstPtrInfo,
MachinePointerInfo SrcPtrInfo) const override;
- unsigned getCommonMaxStoresPerMemFunc() const { return 128; }
+ unsigned getCommonMaxStoresPerMemFunc() const;
};
} // namespace llvm
diff --git a/llvm/test/CodeGen/BPF/libcall-memcpy-threshold.ll b/llvm/test/CodeGen/BPF/libcall-memcpy-threshold.ll
new file mode 100644
index 0000000000000..49f8c12d0d5e1
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/libcall-memcpy-threshold.ll
@@ -0,0 +1,28 @@
+; RUN: llc < %s -mtriple=bpfel -verify-machineinstrs -bpf-max-stores-per-memfunc=1 | FileCheck %s --check-prefix=LIBCALL
+
+; StoresNumEstimate = alignTo(16, 8) >> 3 = 2, which is greater than the
+; getCommonMaxStoresPerMemFunc() value of 1 from -bpf-max-stores-per-memfunc.
+; That prevents inline expansion and lets the generic memcpy libcall path fire.
+define dso_local void @small_copy(ptr nocapture %dst, ptr nocapture readonly %src) local_unnamed_addr {
+entry:
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dst, ptr align 8 %src, i64 16, i1 false)
+ ret void
+}
+
+; StoresNumEstimate = alignTo(16, 16) >> 4 = 1, so the threshold still allows
+; inline expansion here. The memcpy must still avoid BPF::MEMCPY because BPF
+; only supports alignment up to 8 bytes.
+define dso_local void @align16_copy(ptr nocapture %dst, ptr nocapture readonly %src) local_unnamed_addr {
+entry:
+ tail call void @llvm.memcpy.p0.p0.i64(ptr align 16 %dst, ptr align 16 %src, i64 16, i1 false)
+ ret void
+}
+
+declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
+
+; LIBCALL-LABEL: small_copy:
+; LIBCALL: r3 = 16
+; LIBCALL: call memcpy
+; LIBCALL-LABEL: align16_copy:
+; LIBCALL: r3 = 16
+; LIBCALL: call memcpy
More information about the llvm-commits
mailing list