bpf, x86: small optimization in alu ops with imm
authorDaniel Borkmann <daniel@iogearbox.net>
Sat, 20 Jan 2018 00:24:35 +0000 (01:24 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Sat, 20 Jan 2018 02:37:00 +0000 (18:37 -0800)
For the BPF_REG_0 (BPF_REG_A in cBPF, respectively), we can use
the short form of the opcode as dst mapping is on eax/rax and
thus save a byte per such operation. Added to add/sub/and/or/xor
for 32/64 bit when K immediate is used. There may be more such
low-hanging fruit to add in future as well.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
arch/x86/net/bpf_jit_comp.c

index b881a979efe1a470de2c051612db59c819962634..5acee5139e2875508d87ca2eac1c1e8fdf884f30 100644 (file)
@@ -152,6 +152,11 @@ static bool is_ereg(u32 reg)
                             BIT(BPF_REG_AX));
 }
 
+static bool is_axreg(u32 reg)
+{
+       return reg == BPF_REG_0;
+}
+
 /* add modifiers if 'reg' maps to x64 registers r8..r15 */
 static u8 add_1mod(u8 byte, u32 reg)
 {
@@ -445,16 +450,36 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
                        else if (is_ereg(dst_reg))
                                EMIT1(add_1mod(0x40, dst_reg));
 
+                       /* b3 holds 'normal' opcode, b2 short form only valid
+                        * in case dst is eax/rax.
+                        */
                        switch (BPF_OP(insn->code)) {
-                       case BPF_ADD: b3 = 0xC0; break;
-                       case BPF_SUB: b3 = 0xE8; break;
-                       case BPF_AND: b3 = 0xE0; break;
-                       case BPF_OR: b3 = 0xC8; break;
-                       case BPF_XOR: b3 = 0xF0; break;
+                       case BPF_ADD:
+                               b3 = 0xC0;
+                               b2 = 0x05;
+                               break;
+                       case BPF_SUB:
+                               b3 = 0xE8;
+                               b2 = 0x2D;
+                               break;
+                       case BPF_AND:
+                               b3 = 0xE0;
+                               b2 = 0x25;
+                               break;
+                       case BPF_OR:
+                               b3 = 0xC8;
+                               b2 = 0x0D;
+                               break;
+                       case BPF_XOR:
+                               b3 = 0xF0;
+                               b2 = 0x35;
+                               break;
                        }
 
                        if (is_imm8(imm32))
                                EMIT3(0x83, add_1reg(b3, dst_reg), imm32);
+                       else if (is_axreg(dst_reg))
+                               EMIT1_off32(b2, imm32);
                        else
                                EMIT2_off32(0x81, add_1reg(b3, dst_reg), imm32);
                        break;