The logical immediates cannot encode all ones, so the and, or and xor with -1 moved the constant into a temporary and used the register form. LLVM lowers a bitwise not to r ^= -1, as BPF has no not instruction, which the Cilium datapath does hundreds of times. The xor with all ones is an mvn, the 32-bit and with all ones a 32-bit mov of the register to itself and the 64-bit one emits nothing, as the le64 of this JIT already does, and the or with all ones a mov of -1. Before/after for w1 &= -1 and w1 ^= -1: 1280000a mov w10, #0xffffffff 0a0a0000 and w0, w0, w10 2a0003e0 mov w0, w0 1280000a mov w10, #0xffffffff 4a0a0000 eor w0, w0, w10 2a2003e0 mvn w0, w0 Signed-off-by: Daniel Borkmann --- arch/arm64/net/bpf_jit_comp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c index 3c53caf63b04..37fb1df53e30 100644 --- a/arch/arm64/net/bpf_jit_comp.c +++ b/arch/arm64/net/bpf_jit_comp.c @@ -2015,6 +2015,12 @@ static int build_insn(const struct bpf_verifier_env *env, const struct bpf_insn break; case BPF_ALU | BPF_AND | BPF_K: case BPF_ALU64 | BPF_AND | BPF_K: + /* All ones only zero extends the 32-bit variant */ + if (imm == -1) { + if (!is64) + emit(A64_MOV(0, dst, dst), ctx); + break; + } a64_insn = A64_AND_I(is64, dst, dst, imm); if (a64_insn != AARCH64_BREAK_FAULT) { emit(a64_insn, ctx); @@ -2025,6 +2031,11 @@ static int build_insn(const struct bpf_verifier_env *env, const struct bpf_insn break; case BPF_ALU | BPF_OR | BPF_K: case BPF_ALU64 | BPF_OR | BPF_K: + /* The or with all ones is the move of -1 */ + if (imm == -1) { + emit(A64_MOVN(is64, dst, 0, 0), ctx); + break; + } a64_insn = A64_ORR_I(is64, dst, dst, imm); if (a64_insn != AARCH64_BREAK_FAULT) { emit(a64_insn, ctx); @@ -2035,6 +2046,11 @@ static int build_insn(const struct bpf_verifier_env *env, const struct bpf_insn break; case BPF_ALU | BPF_XOR | BPF_K: case BPF_ALU64 | BPF_XOR | BPF_K: + /* The xor with all ones is the not */ + if (imm == -1) { + emit(A64_MVN(is64, dst, dst), ctx); + break; + } a64_insn = A64_EOR_I(is64, dst, dst, imm); if (a64_insn != AARCH64_BREAK_FAULT) { emit(a64_insn, ctx); -- 2.43.0