From eab2538b0d6713038e21ca45a36c6ce2e1746b0b Mon Sep 17 00:00:00 2001 From: Felix Maurer Date: Fri, 8 Sep 2023 19:22:06 +0200 Subject: [PATCH] filterc: Optimize jumps When one of the branches goes to the next insn, it is not necessary to emit two eBPF insns. We can either leave out the second jump if the false case is the next insn, or we can invert the condition and leave out the second jump if the true case is the next insn. --- filterc/bpfc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/filterc/bpfc.c b/filterc/bpfc.c index df3d6453..1701f5c7 100644 --- a/filterc/bpfc.c +++ b/filterc/bpfc.c @@ -278,6 +278,36 @@ static int convert_cbpf(struct cbpf_program *cbpf_prog, src_reg = bpf_src == BPF_X ? BPF_REG_X : 0; } + // Only emit one jump if jump_false is next insn + if (fp->jf == 0) { + code = BPF_JMP | BPF_OP(fp->code) | bpf_src; + target = i + fp->jt + 1; + *insn++ = BPF_JMP_INSN(code, dst_reg, src_reg, imm, target); + break; + } + + // Invert conditons where possible if jump_true is next insn + if (fp->jt == 0) { + switch (BPF_OP(fp->code)) { + case BPF_JEQ: + code = BPF_JMP | BPF_JNE | bpf_src; + break; + case BPF_JGT: + code = BPF_JMP | BPF_JLE | bpf_src; + break; + case BPF_JGE: + code = BPF_JMP | BPF_JLT | bpf_src; + break; + default: + goto jmp_rest; + } + + target = i + fp->jf + 1; + *insn++ = BPF_JMP_INSN(code, dst_reg, src_reg, imm, target); + break; + } + +jmp_rest: /* Other jumps are mapped into two insns: Jxx and JA. */ code = BPF_JMP | BPF_OP(fp->code) | bpf_src; target = i + fp->jt + 1;