[llvm-branch-commits] [llvm] [BPF] add allows-misaligned-mem-access target feature (PR #168314)
Claire Fan via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sun Nov 16 20:01:29 PST 2025
https://github.com/clairechingching created https://github.com/llvm/llvm-project/pull/168314
I'd like to backport this change to handle misaligned memory access in the BPF target which was merged in [this original PR](https://github.com/llvm/llvm-project/pull/167013). Backporting it so I can enable this feature in the rust nightly computer
>From 5d2ec95c53bd510a39fd33ab234a961c91b69cd0 Mon Sep 17 00:00:00 2001
From: Claire xyz <fanyungching at gmail.com>
Date: Fri, 7 Nov 2025 11:08:47 -0500
Subject: [PATCH] [BPF] add allows-misaligned-mem-access target feature
This enables misaligned memory access when the feature is enabled
---
llvm/lib/Target/BPF/BPF.td | 4 +
llvm/lib/Target/BPF/BPFISelLowering.cpp | 20 ++
llvm/lib/Target/BPF/BPFISelLowering.h | 7 +
llvm/lib/Target/BPF/BPFSubtarget.cpp | 1 +
llvm/lib/Target/BPF/BPFSubtarget.h | 6 +
llvm/test/CodeGen/BPF/unaligned_load_store.ll | 196 ++++++++++++++++++
6 files changed, 234 insertions(+)
create mode 100644 llvm/test/CodeGen/BPF/unaligned_load_store.ll
diff --git a/llvm/lib/Target/BPF/BPF.td b/llvm/lib/Target/BPF/BPF.td
index dff76ca07af51..a7aa6274f5ac1 100644
--- a/llvm/lib/Target/BPF/BPF.td
+++ b/llvm/lib/Target/BPF/BPF.td
@@ -27,6 +27,10 @@ def ALU32 : SubtargetFeature<"alu32", "HasAlu32", "true",
def DwarfRIS: SubtargetFeature<"dwarfris", "UseDwarfRIS", "true",
"Disable MCAsmInfo DwarfUsesRelocationsAcrossSections">;
+def MisalignedMemAccess : SubtargetFeature<"allows-misaligned-mem-access",
+ "AllowsMisalignedMemAccess", "true",
+ "Allows misaligned memory access">;
+
def : Proc<"generic", []>;
def : Proc<"v1", []>;
def : Proc<"v2", []>;
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index f4f414d192df0..5ec7f5905fd22 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -196,6 +196,26 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
HasJmp32 = STI.getHasJmp32();
HasJmpExt = STI.getHasJmpExt();
HasMovsx = STI.hasMovsx();
+
+ AllowsMisalignedMemAccess = STI.getAllowsMisalignedMemAccess();
+}
+
+bool BPFTargetLowering::allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+ MachineMemOperand::Flags,
+ unsigned *Fast) const {
+ // allows-misaligned-mem-access is disabled
+ if (!AllowsMisalignedMemAccess)
+ return false;
+
+ // only allow misalignment for simple value types
+ if (!VT.isSimple())
+ return false;
+
+ // always assume fast mode when misalignment is allowed
+ if (Fast)
+ *Fast = true;
+
+ return true;
}
bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8f60261c10e9e..fe01bd5b8cf85 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -46,6 +46,10 @@ class BPFTargetLowering : public TargetLowering {
// with the given GlobalAddress is legal.
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
+ bool allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+ MachineMemOperand::Flags,
+ unsigned *) const override;
+
BPFTargetLowering::ConstraintType
getConstraintType(StringRef Constraint) const override;
@@ -73,6 +77,9 @@ class BPFTargetLowering : public TargetLowering {
bool HasJmpExt;
bool HasMovsx;
+ // Allows Misalignment
+ bool AllowsMisalignedMemAccess;
+
SDValue LowerSDIVSREM(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index 4167547680b12..925537710efb0 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -66,6 +66,7 @@ void BPFSubtarget::initializeEnvironment() {
HasGotol = false;
HasStoreImm = false;
HasLoadAcqStoreRel = false;
+ AllowsMisalignedMemAccess = false;
}
void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h b/llvm/lib/Target/BPF/BPFSubtarget.h
index aed2211265e23..a9a20008733c9 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.h
+++ b/llvm/lib/Target/BPF/BPFSubtarget.h
@@ -63,6 +63,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
// whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
bool UseDwarfRIS;
+ // whether we allows misaligned memory access
+ bool AllowsMisalignedMemAccess;
+
// whether cpu v4 insns are enabled.
bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm,
HasLoadAcqStoreRel;
@@ -87,6 +90,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
bool getHasJmp32() const { return HasJmp32; }
bool getHasAlu32() const { return HasAlu32; }
bool getUseDwarfRIS() const { return UseDwarfRIS; }
+ bool getAllowsMisalignedMemAccess() const {
+ return AllowsMisalignedMemAccess;
+ }
bool hasLdsx() const { return HasLdsx; }
bool hasMovsx() const { return HasMovsx; }
bool hasBswap() const { return HasBswap; }
diff --git a/llvm/test/CodeGen/BPF/unaligned_load_store.ll b/llvm/test/CodeGen/BPF/unaligned_load_store.ll
new file mode 100644
index 0000000000000..b302a80d6cd4f
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/unaligned_load_store.ll
@@ -0,0 +1,196 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+
+; RUN: llc -mtriple=bpfel -mattr=+allows-misaligned-mem-access -verify-machineinstrs %s -o - \
+; RUN: | FileCheck --check-prefixes=ALL,MISALIGN %s
+; RUN: llc -mtriple=bpfeb -mattr=+allows-misaligned-mem-access -verify-machineinstrs %s -o - \
+; RUN: | FileCheck --check-prefixes=ALL,MISALIGN %s
+
+; RUN: llc -mtriple=bpfel -verify-machineinstrs %s -o - \
+; RUN: | FileCheck --check-prefixes=ALL,ALIGN %s
+; RUN: llc -mtriple=bpfeb -verify-machineinstrs %s -o - \
+; RUN: | FileCheck --check-prefixes=ALL,ALIGN %s
+; NOTE:
+; This test verifies that the new +bpf-allow-misaligned-mem-access
+; feature allows the BPF backend to emit direct unaligned load/store
+; instructions instead of byte-by-byte emulation sequences.
+
+; ---------------------------------------------------------------------
+; i8 load
+; ---------------------------------------------------------------------
+define i8 @test_load_i8(i8* %p) {
+; ALL-LABEL: test_load_i8:
+; ALL: # %bb.0:
+; ALL-NEXT: w{{[0-9]+}} = *(u8 *)(r1 + 0)
+; ALL-NEXT: exit
+ %v = load i8, i8* %p, align 1
+ ret i8 %v
+}
+
+; ---------------------------------------------------------------------
+; i8 store
+; ---------------------------------------------------------------------
+define void @test_store_i8(i8* %p, i8 %v) {
+; ALL-LABEL: test_store_i8:
+; ALL: # %bb.0:
+; ALL-NEXT: *(u8 *)(r1 + 0) = w{{[0-9]+}}
+; ALL-NEXT: exit
+ store i8 %v, i8* %p, align 1
+ ret void
+}
+
+; ---------------------------------------------------------------------
+; i16 load
+; ---------------------------------------------------------------------
+define i16 @test_load_i16(i16* %p) {
+; MISALIGN-LABEL: test_load_i16:
+; MISALIGN: # %bb.0:
+; MISALIGN: w{{[0-9]+}} = *(u16 *)(r1 + 0)
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_load_i16:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 0)
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 1)
+; ALIGN-DAG: w{{[0-9]+}} <<= 8
+; ALIGN-DAG: w{{[0-9]+}} |= w{{[0-9]+}}
+; ALIGN: exit
+ %v = load i16, i16* %p, align 1
+ ret i16 %v
+}
+
+; ---------------------------------------------------------------------
+; i16 store
+; ---------------------------------------------------------------------
+define void @test_store_i16(i16* %p, i16 %v) {
+; MISALIGN-LABEL: test_store_i16:
+; MISALIGN: # %bb.0:
+; MISALIGN: *(u16 *)(r1 + 0) = w{{[0-9]+}}
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_store_i16:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: *(u8 *)(r1 + 0) = w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} >>= 8
+; ALIGN-DAG: *(u8 *)(r1 + 1) = w{{[0-9]+}}
+; ALIGN: exit
+ store i16 %v, i16* %p, align 1
+ ret void
+}
+
+; ---------------------------------------------------------------------
+; i32 load
+; ---------------------------------------------------------------------
+
+define i32 @test_load_i32(i32* %p) {
+; MISALIGN-LABEL: test_load_i32:
+; MISALIGN: # %bb.0:
+; MISALIGN: w{{[0-9]+}} = *(u32 *)(r1 + 0)
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_load_i32:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 0)
+; ALIGN-DAG: w{{[0-9]+}} <<= 8
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 1)
+; ALIGN-DAG: w{{[0-9]+}} |= w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 2)
+; ALIGN-DAG: w{{[0-9]+}} <<= 16
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 3)
+; ALIGN-DAG: w{{[0-9]+}} <<= 24
+; ALIGN: exit
+ %v = load i32, i32* %p, align 1
+ ret i32 %v
+}
+
+; ---------------------------------------------------------------------
+; i32 store
+; ---------------------------------------------------------------------
+
+define void @test_store_i32(i32* %p, i32 %v) {
+; MISALIGN-LABEL: test_store_i32:
+; MISALIGN: # %bb.0:
+; MISALIGN: *(u32 *)(r1 + 0) = w{{[0-9]+}}
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_store_i32:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: w{{[0-9]+}} = w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} >>= 24
+; ALIGN-DAG: *(u8 *)(r1 + 0) = w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} = w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} >>= 16
+; ALIGN-DAG: *(u8 *)(r1 + 1) = w{{[0-9]+}}
+; ALIGN-DAG: *(u8 *)(r1 + 2) = w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} >>= 8
+; ALIGN-DAG: *(u8 *)(r1 + 3) = w{{[0-9]+}}
+; ALIGN: exit
+ store i32 %v, i32* %p, align 1
+ ret void
+}
+
+; ---------------------------------------------------------------------
+; i64 load
+; ---------------------------------------------------------------------
+
+define i64 @test_load_i64(i64* %p) {
+; MISALIGN-LABEL: test_load_i64:
+; MISALIGN: # %bb.0:
+; MISALIGN: r0 = *(u64 *)(r1 + 0)
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_load_i64:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 0)
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 1)
+; ALIGN-DAG: r{{[0-9]+}} <<= 8
+; ALIGN-DAG: r{{[0-9]+}} |= r{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 2)
+; ALIGN-DAG: r{{[0-9]+}} <<= 16
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 3)
+; ALIGN-DAG: r{{[0-9]+}} <<= 24
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 4)
+; ALIGN-DAG: w{{[0-9]+}} <<= 8
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 5)
+; ALIGN-DAG: w{{[0-9]+}} |= w{{[0-9]+}}
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 6)
+; ALIGN-DAG: w{{[0-9]+}} <<= 16
+; ALIGN-DAG: w{{[0-9]+}} = *(u8 *)(r1 + 7)
+; ALIGN-DAG: w{{[0-9]+}} <<= 24
+; ALIGN-DAG: r{{[0-9]+}} <<= 32
+; ALIGN: exit
+ %v = load i64, i64* %p, align 1
+ ret i64 %v
+}
+
+; ---------------------------------------------------------------------
+; i64 store
+; ---------------------------------------------------------------------
+
+define void @test_store_i64(i64* %p, i64 %v) {
+; MISALIGN-LABEL: test_store_i64:
+; MISALIGN: # %bb.0:
+; MISALIGN: *(u64 *)(r1 + 0) = r2
+; MISALIGN: exit
+;
+; ALIGN-LABEL: test_store_i64:
+; ALIGN: # %bb.0:
+; ALIGN-DAG: *(u8 *)(r1 + 0) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} = r{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 56
+; ALIGN-DAG: *(u8 *)(r1 + 1) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 48
+; ALIGN-DAG: *(u8 *)(r1 + 2) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 40
+; ALIGN-DAG: *(u8 *)(r1 + 3) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 32
+; ALIGN-DAG: *(u8 *)(r1 + 4) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 24
+; ALIGN-DAG: *(u8 *)(r1 + 5) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 16
+; ALIGN-DAG: *(u8 *)(r1 + 6) = w{{[0-9]+}}
+; ALIGN-DAG: r{{[0-9]+}} >>= 8
+; ALIGN-DAG: *(u8 *)(r1 + 7) = w{{[0-9]+}}
+; ALIGN: exit
+ store i64 %v, i64* %p, align 1
+ ret void
+}
More information about the llvm-branch-commits
mailing list