diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2018-01-19 19:24:35 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2018-01-19 21:37:00 -0500 |
commit | de0a444ddae61b77683c27cd390e518e33858d20 (patch) | |
tree | b2bb3ce980577d8736bd0174aefa53b5655bf74e | |
parent | 2e4a30983b0f9b19b59e38bbf7427d7fdd480d98 (diff) |
bpf, x86: small optimization in alu ops with imm
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>
-rw-r--r-- | arch/x86/net/bpf_jit_comp.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index b881a979efe1..5acee5139e28 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c | |||
@@ -152,6 +152,11 @@ static bool is_ereg(u32 reg) | |||
152 | BIT(BPF_REG_AX)); | 152 | BIT(BPF_REG_AX)); |
153 | } | 153 | } |
154 | 154 | ||
155 | static bool is_axreg(u32 reg) | ||
156 | { | ||
157 | return reg == BPF_REG_0; | ||
158 | } | ||
159 | |||
155 | /* add modifiers if 'reg' maps to x64 registers r8..r15 */ | 160 | /* add modifiers if 'reg' maps to x64 registers r8..r15 */ |
156 | static u8 add_1mod(u8 byte, u32 reg) | 161 | static u8 add_1mod(u8 byte, u32 reg) |
157 | { | 162 | { |
@@ -445,16 +450,36 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, | |||
445 | else if (is_ereg(dst_reg)) | 450 | else if (is_ereg(dst_reg)) |
446 | EMIT1(add_1mod(0x40, dst_reg)); | 451 | EMIT1(add_1mod(0x40, dst_reg)); |
447 | 452 | ||
453 | /* b3 holds 'normal' opcode, b2 short form only valid | ||
454 | * in case dst is eax/rax. | ||
455 | */ | ||
448 | switch (BPF_OP(insn->code)) { | 456 | switch (BPF_OP(insn->code)) { |
449 | case BPF_ADD: b3 = 0xC0; break; | 457 | case BPF_ADD: |
450 | case BPF_SUB: b3 = 0xE8; break; | 458 | b3 = 0xC0; |
451 | case BPF_AND: b3 = 0xE0; break; | 459 | b2 = 0x05; |
452 | case BPF_OR: b3 = 0xC8; break; | 460 | break; |
453 | case BPF_XOR: b3 = 0xF0; break; | 461 | case BPF_SUB: |
462 | b3 = 0xE8; | ||
463 | b2 = 0x2D; | ||
464 | break; | ||
465 | case BPF_AND: | ||
466 | b3 = 0xE0; | ||
467 | b2 = 0x25; | ||
468 | break; | ||
469 | case BPF_OR: | ||
470 | b3 = 0xC8; | ||
471 | b2 = 0x0D; | ||
472 | break; | ||
473 | case BPF_XOR: | ||
474 | b3 = 0xF0; | ||
475 | b2 = 0x35; | ||
476 | break; | ||
454 | } | 477 | } |
455 | 478 | ||
456 | if (is_imm8(imm32)) | 479 | if (is_imm8(imm32)) |
457 | EMIT3(0x83, add_1reg(b3, dst_reg), imm32); | 480 | EMIT3(0x83, add_1reg(b3, dst_reg), imm32); |
481 | else if (is_axreg(dst_reg)) | ||
482 | EMIT1_off32(b2, imm32); | ||
458 | else | 483 | else |
459 | EMIT2_off32(0x81, add_1reg(b3, dst_reg), imm32); | 484 | EMIT2_off32(0x81, add_1reg(b3, dst_reg), imm32); |
460 | break; | 485 | break; |