Generate store immediate instruction when CPUv4 is enabled.
For example:
$ cat test.c
struct foo {
unsigned char b;
unsigned short h;
unsigned int w;
unsigned long d;
};
void bar(volatile struct foo *p) {
p->b = 1;
p->h = 2;
p->w = 3;
p->d = 4;
}
$ clang -O2 --target=bpf -mcpu=v4 test.c -c -o - | llvm-objdump -d -
...
0000000000000000 <bar>:
0: 72 01 00 00 01 00 00 00 *(u8 *)(r1 + 0x0) = 0x1
1: 6a 01 02 00 02 00 00 00 *(u16 *)(r1 + 0x2) = 0x2
2: 62 01 04 00 03 00 00 00 *(u32 *)(r1 + 0x4) = 0x3
3: 7a 01 08 00 04 00 00 00 *(u64 *)(r1 + 0x8) = 0x4
4: 95 00 00 00 00 00 00 00 exit
Take special care to:
- apply `BPFMISimplifyPatchable::checkADDrr` rewrite for BPF_ST
- validate immediate value when BPF_ST write is 64-bit:
BPF interprets `(BPF_ST | BPF_MEM | BPF_DW)` writes as writes with
sign extension. Thus it is fine to generate such write when
immediate is -1, but it is incorrect to generate such write when
immediate is +0xffff_ffff.
This commit was previously reverted in e66affa17e.
The reason for revert was an unrelated bug in BPF backend,
triggered by test case added in this commit if LLVM is built
with LLVM_ENABLE_EXPENSIVE_CHECKS.
The bug was fixed in D157806.
Differential Revision: https://reviews.llvm.org/D140804
105 lines
4.1 KiB
LLVM
105 lines
4.1 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc < %s -march=bpfel -mcpu=v4 -show-mc-encoding | FileCheck %s
|
|
|
|
target triple = "bpf"
|
|
|
|
define void @byte(ptr %p0) {
|
|
; CHECK-LABEL: byte:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u8 *)(r1 + 0) = 1 # encoding: [0x72,0x01,0x00,0x00,0x01,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u8 *)(r1 + 1) = 255 # encoding: [0x72,0x01,0x01,0x00,0xff,0x00,0x00,0x00]
|
|
%p1 = getelementptr i8, ptr %p0, i32 1
|
|
|
|
store volatile i8 1, ptr %p0, align 1
|
|
store volatile i8 -1, ptr %p1, align 1
|
|
|
|
unreachable
|
|
}
|
|
|
|
define void @half(ptr, ptr %p0) {
|
|
; CHECK-LABEL: half:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u16 *)(r2 + 0) = 1 # encoding: [0x6a,0x02,0x00,0x00,0x01,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u16 *)(r2 + 2) = 65535 # encoding: [0x6a,0x02,0x02,0x00,0xff,0xff,0x00,0x00]
|
|
%p1 = getelementptr i8, ptr %p0, i32 2
|
|
|
|
store volatile i16 1, ptr %p0, align 2
|
|
store volatile i16 -1, ptr %p1, align 2
|
|
|
|
unreachable
|
|
}
|
|
|
|
define void @word(ptr, ptr, ptr %p0) {
|
|
; CHECK-LABEL: word:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u32 *)(r3 + 0) = 1 # encoding: [0x62,0x03,0x00,0x00,0x01,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u32 *)(r3 + 4) = -1 # encoding: [0x62,0x03,0x04,0x00,0xff,0xff,0xff,0xff]
|
|
; CHECK-NEXT: *(u32 *)(r3 + 8) = -2000000000 # encoding: [0x62,0x03,0x08,0x00,0x00,0x6c,0xca,0x88]
|
|
; CHECK-NEXT: *(u32 *)(r3 + 12) = -1 # encoding: [0x62,0x03,0x0c,0x00,0xff,0xff,0xff,0xff]
|
|
; CHECK-NEXT: *(u32 *)(r3 + 12) = 0 # encoding: [0x62,0x03,0x0c,0x00,0x00,0x00,0x00,0x00]
|
|
%p1 = getelementptr i8, ptr %p0, i32 4
|
|
%p2 = getelementptr i8, ptr %p0, i32 8
|
|
%p3 = getelementptr i8, ptr %p0, i32 12
|
|
|
|
store volatile i32 1, ptr %p0, align 4
|
|
store volatile i32 -1, ptr %p1, align 4
|
|
store volatile i32 -2000000000, ptr %p2, align 4
|
|
store volatile i32 4294967295, ptr %p3, align 4
|
|
store volatile i32 4294967296, ptr %p3, align 4
|
|
|
|
unreachable
|
|
}
|
|
|
|
define void @dword(ptr, ptr, ptr, ptr %p0) {
|
|
; CHECK-LABEL: dword:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u64 *)(r4 + 0) = 1 # encoding: [0x7a,0x04,0x00,0x00,0x01,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u64 *)(r4 + 8) = -1 # encoding: [0x7a,0x04,0x08,0x00,0xff,0xff,0xff,0xff]
|
|
; CHECK-NEXT: *(u64 *)(r4 + 16) = 2000000000 # encoding: [0x7a,0x04,0x10,0x00,0x00,0x94,0x35,0x77]
|
|
; CHECK-NEXT: *(u64 *)(r4 + 16) = -2000000000 # encoding: [0x7a,0x04,0x10,0x00,0x00,0x6c,0xca,0x88]
|
|
; CHECK-NEXT: r1 = 4294967295 ll # encoding: [0x18,0x01,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u64 *)(r4 + 24) = r1 # encoding: [0x7b,0x14,0x18,0x00,0x00,0x00,0x00,0x00]
|
|
%p1 = getelementptr i8, ptr %p0, i32 8
|
|
%p2 = getelementptr i8, ptr %p0, i32 16
|
|
%p3 = getelementptr i8, ptr %p0, i32 24
|
|
|
|
store volatile i64 1, ptr %p0, align 8
|
|
store volatile i64 -1, ptr %p1, align 8
|
|
store volatile i64 2000000000, ptr %p2, align 8
|
|
store volatile i64 -2000000000, ptr %p2, align 8
|
|
store volatile i64 4294967295, ptr %p3, align 8
|
|
|
|
unreachable
|
|
}
|
|
|
|
define void @unaligned(ptr %p0) {
|
|
; CHECK-LABEL: unaligned:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: *(u8 *)(r1 + 1) = 255 # encoding: [0x72,0x01,0x01,0x00,0xff,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u8 *)(r1 + 0) = 254 # encoding: [0x72,0x01,0x00,0x00,0xfe,0x00,0x00,0x00]
|
|
; CHECK-NEXT: *(u16 *)(r1 + 10) = 65535 # encoding: [0x6a,0x01,0x0a,0x00,0xff,0xff,0x00,0x00]
|
|
; CHECK-NEXT: *(u16 *)(r1 + 8) = 65534 # encoding: [0x6a,0x01,0x08,0x00,0xfe,0xff,0x00,0x00]
|
|
; CHECK-NEXT: *(u32 *)(r1 + 20) = -1 # encoding: [0x62,0x01,0x14,0x00,0xff,0xff,0xff,0xff]
|
|
; CHECK-NEXT: *(u32 *)(r1 + 16) = -2 # encoding: [0x62,0x01,0x10,0x00,0xfe,0xff,0xff,0xff]
|
|
%p1 = getelementptr i8, ptr %p0, i32 8
|
|
%p2 = getelementptr i8, ptr %p0, i32 16
|
|
|
|
store volatile i16 -2, ptr %p0, align 1
|
|
store volatile i32 -2, ptr %p1, align 2
|
|
store volatile i64 -2, ptr %p2, align 4
|
|
|
|
unreachable
|
|
}
|
|
|
|
define void @inline_asm(ptr %p0) {
|
|
; CHECK-LABEL: inline_asm:
|
|
; CHECK: # %bb.0:
|
|
; CHECK-NEXT: #APP
|
|
; CHECK-NEXT: *(u32 *)(r0 + 42) = 7 # encoding: [0x62,0x00,0x2a,0x00,0x07,0x00,0x00,0x00]
|
|
; CHECK-EMPTY:
|
|
; CHECK-NEXT: #NO_APP
|
|
call void asm "*(u32 *)(r0 + 42) = 7;", "~{r0},~{mem}"()
|
|
|
|
unreachable
|
|
}
|