When sometimes structs or variables need to be initialized/'memset' to 0 in
an eBPF C program, the x86 BPF JIT converts this to use immediates. We can
however save a couple of bytes (f.e. even up to 7 bytes on a single emmission
of BPF_LD | BPF_IMM | BPF_DW) in the image by detecting such case and use xor
on the dst register instead.

Signed-off-by: Daniel Borkmann <dan...@iogearbox.net>
Acked-by: Alexei Starovoitov <a...@kernel.org>
---
 arch/x86/net/bpf_jit_comp.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index c080e81..4286f36 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -459,6 +459,18 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, 
u8 *image,
                        }
 
                case BPF_ALU | BPF_MOV | BPF_K:
+                       /* optimization: if imm32 is zero, use 'xor <dst>,<dst>'
+                        * to save 3 bytes.
+                        */
+                       if (imm32 == 0) {
+                               if (is_ereg(dst_reg))
+                                       EMIT1(add_2mod(0x40, dst_reg, dst_reg));
+                               b2 = 0x31; /* xor */
+                               b3 = 0xC0;
+                               EMIT2(b2, add_2reg(b3, dst_reg, dst_reg));
+                               break;
+                       }
+
                        /* mov %eax, imm32 */
                        if (is_ereg(dst_reg))
                                EMIT1(add_1mod(0x40, dst_reg));
@@ -473,6 +485,20 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, 
u8 *image,
                                return -EINVAL;
                        }
 
+                       /* optimization: if imm64 is zero, use 'xor <dst>,<dst>'
+                        * to save 7 bytes.
+                        */
+                       if (insn[0].imm == 0 && insn[1].imm == 0) {
+                               b1 = add_2mod(0x48, dst_reg, dst_reg);
+                               b2 = 0x31; /* xor */
+                               b3 = 0xC0;
+                               EMIT3(b1, b2, add_2reg(b3, dst_reg, dst_reg));
+
+                               insn++;
+                               i++;
+                               break;
+                       }
+
                        /* movabsq %rax, imm64 */
                        EMIT2(add_1mod(0x48, dst_reg), add_1reg(0xB8, dst_reg));
                        EMIT(insn[0].imm, 4);
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to