Skip to content

Commit 445450f

Browse files
[BPF] Add CLI option to enable misaligned memory access
1 parent 4f74b76 commit 445450f

File tree

3 files changed

+236
-0
lines changed

3 files changed

+236
-0
lines changed

llvm/lib/Target/BPF/BPFISelLowering.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ static cl::opt<bool> BPFExpandMemcpyInOrder("bpf-expand-memcpy-in-order",
3838
cl::Hidden, cl::init(false),
3939
cl::desc("Expand memcpy into load/store pairs in order"));
4040

41+
static cl::opt<bool> BPFAllowMisalignedMemAccess("bpf-allow-misaligned-mem-access",
42+
cl::Hidden, cl::init(false),
43+
cl::desc("Allow misaligned memory access"));
44+
4145
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg,
4246
SDValue Val = {}) {
4347
std::string Str;
@@ -198,6 +202,26 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
198202
HasMovsx = STI.hasMovsx();
199203
}
200204

205+
bool BPFTargetLowering::allowsMisalignedMemoryAccesses(
206+
EVT VT, unsigned, Align, MachineMemOperand::Flags, unsigned *Fast) const {
207+
if (!BPFAllowMisalignedMemAccess) {
208+
// --bpf-allow-misaligned-mem-access isn't opted in
209+
return false;
210+
}
211+
212+
if (!VT.isSimple()) {
213+
// only allow misalignment for simple value types
214+
return false;
215+
}
216+
217+
if (Fast) {
218+
// always assume fast mode when BPFAllowMisalignedMemAccess is enabled
219+
*Fast = true;
220+
}
221+
222+
return true;
223+
}
224+
201225
bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
202226
return false;
203227
}

llvm/lib/Target/BPF/BPFISelLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ class BPFTargetLowering : public TargetLowering {
4646
// with the given GlobalAddress is legal.
4747
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
4848

49+
bool allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
50+
MachineMemOperand::Flags,
51+
unsigned *) const override;
52+
4953
BPFTargetLowering::ConstraintType
5054
getConstraintType(StringRef Constraint) const override;
5155

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
3+
; RUN: llc -mtriple=bpfel -bpf-allow-misaligned-mem-access -verify-machineinstrs %s -o - \
4+
; RUN: | FileCheck --check-prefixes=ALL,MISALIGN %s
5+
; RUN: llc -mtriple=bpfeb -bpf-allow-misaligned-mem-access -verify-machineinstrs %s -o - \
6+
; RUN: | FileCheck --check-prefixes=ALL,MISALIGN %s
7+
8+
; RUN: llc -mtriple=bpfel -verify-machineinstrs %s -o - \
9+
; RUN: | FileCheck --check-prefixes=ALL,ALIGN %s
10+
; RUN: llc -mtriple=bpfeb -verify-machineinstrs %s -o - \
11+
; RUN: | FileCheck --check-prefixes=ALL,ALIGN %s
12+
; NOTE:
13+
; This test verifies that the new +bpf-allow-misaligned-mem-access
14+
; feature allows the BPF backend to emit direct unaligned load/store
15+
; instructions instead of byte-by-byte emulation sequences.
16+
17+
; ---------------------------------------------------------------------
18+
; i8 load
19+
; ---------------------------------------------------------------------
20+
define i8 @test_load_i8(i8* %p) {
21+
; ALL-LABEL: test_load_i8:
22+
; ALL: # %bb.0:
23+
; ALL-NEXT: w{{[0-9]+}} = *(u8 *)(r1 + 0)
24+
; ALL-NEXT: exit
25+
%v = load i8, i8* %p, align 1
26+
ret i8 %v
27+
}
28+
29+
; ---------------------------------------------------------------------
30+
; i8 store
31+
; ---------------------------------------------------------------------
32+
define void @test_store_i8(i8* %p, i8 %v) {
33+
; ALL-LABEL: test_store_i8:
34+
; ALL: # %bb.0:
35+
; ALL-NEXT: *(u8 *)(r1 + 0) = w2
36+
; ALL-NEXT: exit
37+
store i8 %v, i8* %p, align 1
38+
ret void
39+
}
40+
41+
; ---------------------------------------------------------------------
42+
; i16 load
43+
; ---------------------------------------------------------------------
44+
define i16 @test_load_i16(i16* %p) {
45+
; MISALIGN-LABEL: test_load_i16:
46+
; MISALIGN: # %bb.0:
47+
; MISCHECK: w{{[0-9]+}} = *(u16 *)(r1 + 0)
48+
; MISCHECK: exit
49+
;
50+
; ALIGN-LABEL: test_load_i16:
51+
; ALIGN: # %bb.0:
52+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
53+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
54+
; CHECK: w{{[0-9]+}} <<= 8
55+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
56+
; CHECK: exit
57+
%v = load i16, i16* %p, align 1
58+
ret i16 %v
59+
}
60+
61+
; ---------------------------------------------------------------------
62+
; i16 store
63+
; ---------------------------------------------------------------------
64+
define void @test_store_i16(i16* %p, i16 %v) {
65+
; MISALIGN-LABEL: test_store_i16:
66+
; MISALIGN: # %bb.0:
67+
; MISCHECK: *(u16 *)(r1 + 0) = w2
68+
; MISCHECK: exit
69+
;
70+
; ALIGN-LABEL: test_store_i16:
71+
; ALIGN: # %bb.0:
72+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
73+
; CHECK: w{{[0-9]+}} >>= 8
74+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
75+
; CHECK: exit
76+
store i16 %v, i16* %p, align 1
77+
ret void
78+
}
79+
80+
; ---------------------------------------------------------------------
81+
; i32 load
82+
; ---------------------------------------------------------------------
83+
84+
define i32 @test_load_i32(i32* %p) {
85+
; MISALIGN-LABEL: test_load_i32:
86+
; MISALIGN: # %bb.0:
87+
; MISCHECK: w{{[0-9]+}} = *(u32 *)(r1 + 0)
88+
; MISCHECK: exit
89+
;
90+
; ALIGN-LABEL: test_load_i32:
91+
; ALIGN: # %bb.0:
92+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
93+
; CHECK: w{{[0-9]+}} <<= 8
94+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
95+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
96+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
97+
; CHECK: w{{[0-9]+}} <<= 16
98+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
99+
; CHECK: w{{[0-9]+}} <<= 24
100+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
101+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
102+
; CHECK: exit
103+
%v = load i32, i32* %p, align 1
104+
ret i32 %v
105+
}
106+
107+
; ---------------------------------------------------------------------
108+
; i32 store
109+
; ---------------------------------------------------------------------
110+
111+
define void @test_store_i32(i32* %p, i32 %v) {
112+
; MISALIGN-LABEL: test_store_i32:
113+
; MISALIGN: # %bb.0:
114+
; MISCHECK: *(u32 *)(r1 + 0) = w{{[0-9]+}}
115+
; MISCHECK: exit
116+
;
117+
; ALIGN-LABEL: test_store_i32:
118+
; ALIGN: # %bb.0:
119+
; CHECK: w{{[0-9]+}} = w{{[0-9]+}}
120+
; CHECK: w{{[0-9]+}} >>= 24
121+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
122+
; CHECK: w{{[0-9]+}} = w{{[0-9]+}}
123+
; CHECK: w{{[0-9]+}} >>= 16
124+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
125+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
126+
; CHECK: w{{[0-9]+}} >>= 8
127+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
128+
; CHECK: exit
129+
store i32 %v, i32* %p, align 1
130+
ret void
131+
}
132+
133+
; ---------------------------------------------------------------------
134+
; i64 load
135+
; ---------------------------------------------------------------------
136+
137+
define i64 @test_load_i64(i64* %p) {
138+
; MISALIGN-LABEL: test_load_i64:
139+
; MISALIGN: # %bb.0:
140+
; MISCHECK: r0 = *(u64 *)(r1 + 0)
141+
; MISCHECK: exit
142+
;
143+
; ALIGN-LABEL: test_load_i64:
144+
; ALIGN: # %bb.0:
145+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
146+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
147+
; CHECK: r3 <<= 8
148+
; CHECK: r3 |= r2
149+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
150+
; CHECK: r4 <<= 16
151+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
152+
; CHECK: r2 <<= 24
153+
; CHECK: r2 |= r4
154+
; CHECK: r2 |= r3
155+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
156+
; CHECK: w{{[0-9]+}} <<= 8
157+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
158+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
159+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
160+
; CHECK: w{{[0-9]+}} <<= 16
161+
; CHECK: w{{[0-9]+}} = *(u8 *)(r1 + [[OFFSET:[0-9]+]])
162+
; CHECK: w{{[0-9]+}} <<= 24
163+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
164+
; CHECK: w{{[0-9]+}} |= w{{[0-9]+}}
165+
; CHECK: r0 <<= 32
166+
; CHECK: r0 |= r2
167+
; CHECK: exit
168+
%v = load i64, i64* %p, align 1
169+
ret i64 %v
170+
}
171+
172+
; ---------------------------------------------------------------------
173+
; i64 store
174+
; ---------------------------------------------------------------------
175+
176+
define void @test_store_i64(i64* %p, i64 %v) {
177+
; MISALIGN-LABEL: test_store_i64:
178+
; MISALIGN: # %bb.0:
179+
; MISCHECK: *(u64 *)(r1 + 0) = r2
180+
; MISCHECK: exit
181+
;
182+
; ALIGN-LABEL: test_store_i64:
183+
; ALIGN: # %bb.0:
184+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
185+
; CHECK: r3 = r2
186+
; CHECK: r3 >>= 56
187+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
188+
; CHECK: r3 = r2
189+
; CHECK: r3 >>= 48
190+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
191+
; CHECK: r3 = r2
192+
; CHECK: r3 >>= 40
193+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
194+
; CHECK: r3 = r2
195+
; CHECK: r3 >>= 32
196+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
197+
; CHECK: r3 = r2
198+
; CHECK: r3 >>= 24
199+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
200+
; CHECK: r3 = r2
201+
; CHECK: r3 >>= 16
202+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
203+
; CHECK: r2 >>= 8
204+
; CHECK: *(u8 *)(r1 + [[OFFSET:[0-9]+]]) = w{{[0-9]+}}
205+
; CHECK: exit
206+
store i64 %v, i64* %p, align 1
207+
ret void
208+
}

0 commit comments

Comments
 (0)