If you tally up the neighbors using a vertical counter so you have each bit in the neighbor count as a separate variable:
using C operators, | (logical or), & (logical and), and ~ (logical not)

a = state of cell in the next generation
b = state of cell in the current generation
c = bit 2 of neighbor count (count & 4)
d = bit 1 (count & 2)
e = bit 0 (count & 1)

a = (~c)&d&(e|b)
Bit 3 (count & 8) can be ignored (just lose the carry from bit 2) because the rules for 8 neighbors and for 0 are identical. This lets you calculate the next state for multiple cells in parallel.

Truth table:

b c d e | a
-----------
0 0 0 0 | 0
0 0 0 1 | 0
0 0 1 0 | 0
0 0 1 1 | 1 Three neighbors to an 'off' cell.
0 1 0 0 | 0
0 1 0 1 | 0
0 1 1 0 | 0
0 1 1 1 | 0
1 0 0 0 | 0
1 0 0 1 | 0
1 0 1 0 | 1 Two neighbors to an 'on' cell.
1 0 1 1 | 1 Three neighbors to an 'on' cell.
1 1 0 0 | 0
1 1 0 1 | 0
1 1 1 0 | 0
1 1 1 1 | 0