In general, BPF programs are JIT-ed to various architectures, and we
cannot say for certain what memory access patterns are preferable.
But it is clear that for the sake of the BPF verifier smaller loads are
to be preferred when possible, so set SLOW_BYTE_ACCESS to zero.

Tested on x86_64-linux-gnu host for bpf-unknown-none, no regressions.
Also tested against Linux kernel bpf-next selftests, no changes.

        PR target/123556
gcc/
        * config/bpf/bpf.h (SLOW_BYTE_ACCESS): Set to 0, update comment.

gcc/testsuite/
        * gcc.target/bpf/pr123556.c: New test.
---
 gcc/config/bpf/bpf.h                    |  8 ++++--
 gcc/testsuite/gcc.target/bpf/pr123556.c | 33 +++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/pr123556.c

diff --git a/gcc/config/bpf/bpf.h b/gcc/config/bpf/bpf.h
index 30bdd6e2639..c8dad55fd4c 100644
--- a/gcc/config/bpf/bpf.h
+++ b/gcc/config/bpf/bpf.h
@@ -365,8 +365,12 @@ enum reg_class
 /* The SPARC port says: Nonzero if access to memory by bytes is slow
    and undesirable.  For RISC chips, it means that access to memory by
    bytes is no better than access by words when possible, so grab a
-   whole word and maybe make use of that.  */
-#define SLOW_BYTE_ACCESS 1
+   whole word and maybe make use of that.
+   BPF programs will be JIT-ed to various architectures, so we cannot
+   say for certain what the access patterns on the final architecture
+   are.  From the BPF verifier perspective, smaller loads are actually
+   preferable so set this to zero.  */
+#define SLOW_BYTE_ACCESS 0
 
 /* Threshold of number of scalar memory-to-memory move instructions,
    _below_ which a sequence of insns should be generated instead of a
diff --git a/gcc/testsuite/gcc.target/bpf/pr123556.c 
b/gcc/testsuite/gcc.target/bpf/pr123556.c
new file mode 100644
index 00000000000..f34e5a27ebc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/pr123556.c
@@ -0,0 +1,33 @@
+/* PR target/123556.
+   Test that we do not load the bit-fields with a larger aligned load
+   that crosses struct boundaries, which the BPF verifier rejects.  */
+/* { dg-do compile } */
+/* { dg-options "-O2 -S -dA -masm=normal" } */
+
+struct problem
+{
+  unsigned char f1;
+  unsigned char f2;
+  struct {
+    unsigned short id;
+    unsigned short val;
+  } stmemb[2];
+
+  unsigned char ba:2;
+  unsigned char bb:3;
+
+  unsigned short f3;
+};
+
+int foo (struct problem *p)
+{
+  if (p->bb != 1)
+    return -1;
+  if (p->ba >= 2)
+    return -1;
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler-not "ldxw" } } */
+/* { dg-final { scan-assembler-not "ldxdw" } } */
-- 
2.51.0

Reply via email to