dect
/
libpcap
Archived
13
0
Fork 0

There are a bunch of optimizations we can only do in blocks that end

with jeq #x and that don't have a subsequent block that uses the value
the block leaves in the A register; make sure we only do them if the
last operation is a jeq with a constant operand and if nothing uses this
block's A register value.  (Some were being done with jeq x, and some
were done regardless of the branch that terminated the block and
regardless of whether the block's A register value is being used.)
This commit is contained in:
guy 2004-11-08 09:03:37 +00:00
parent 1e238b3877
commit 379d3179ed
1 changed files with 46 additions and 27 deletions

View File

@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.78 2004-11-07 22:43:01 guy Exp $ (LBL)";
"@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.79 2004-11-08 09:03:37 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@ -755,16 +755,27 @@ opt_peep(b)
}
}
/*
* If we have a subtract to do a comparison, and the X register
* is a known constant, we can merge this value into the
* comparison.
* If the comparison at the end of a block is an equality
* comparison against a constant, and nobody uses the value
* we leave in the A register at the end of a block, and
* the operation preceding the comparison is an arithmetic
* operation, we can sometime optimize it away.
*/
if (BPF_OP(b->s.code) == BPF_JEQ) {
if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) &&
!ATOMELEM(b->out_use, A_ATOM)) {
if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
!ATOMELEM(b->out_use, A_ATOM)) {
/*
* We can optimize away certain subtractions of the
* X register.
*/
if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
val = b->val[X_ATOM];
if (vmap[val].is_const) {
/*
* If we have a subtract to do a comparison,
* and the X register is a known constant,
* we can merge this value into the
* comparison:
*
* sub x -> nop
* jeq #y jeq #(x+y)
*/
@ -773,37 +784,45 @@ opt_peep(b)
done = 0;
} else if (b->s.k == 0) {
/*
* sub #x -> nop
* jeq #0 jeq #x
* If the X register isn't a constant,
* and the comparison in the test is
* against 0, we can compare with the
* X register, instead:
*
* sub x -> nop
* jeq #0 jeq x
*/
last->s.code = NOP;
b->s.code = BPF_CLASS(b->s.code) |
BPF_OP(b->s.code) | BPF_X;
b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
done = 0;
}
}
/*
* Likewise, a constant subtract can be simplified.
* Likewise, a constant subtract can be simplified:
*
* sub #x -> nop
* jeq #y -> jeq #(x+y)
*/
else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) &&
!ATOMELEM(b->out_use, A_ATOM)) {
else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
last->s.code = NOP;
b->s.k += last->s.k;
done = 0;
}
}
/*
* and #k nop
* jeq #0 -> jset #k
*/
if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
!ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) {
b->s.k = last->s.k;
b->s.code = BPF_JMP|BPF_K|BPF_JSET;
last->s.code = NOP;
done = 0;
opt_not(b);
/*
* And, similarly, a constant AND can be simplified
* if we're testing against 0, i.e.:
*
* and #k nop
* jeq #0 -> jset #k
*/
else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
b->s.k == 0) {
b->s.k = last->s.k;
b->s.code = BPF_JMP|BPF_K|BPF_JSET;
last->s.code = NOP;
done = 0;
opt_not(b);
}
}
/*
* jset #0 -> never