式のつぶし方

主にやってたのこれなのですが、結構いろいろあって、コンパイラ屋さん大変だなぁ、と思ったりしてました(小並感)。
4種類ほど紹介します。

自明な bit 演算

(and 0 A) -> 0, (and 0xFFFFFFFFFFFFFFFF A) -> A, (and A A) -> A, (xor A A) -> 0, (and (not A) A) -> 0, (or (not A) A) -> 0xFFFFFFFFFFFFFFFF,
(not (not A)) -> A, (not (or (not A) B) -> (or A B), (xor (not A) (not B)) -> (xor A B) etc. etc...

0/非0 の判定

定数は畳み込むので

(if0 0 A B) -> A

は即判断化ですが、逆はそうでもない。ので、(if0 C A B) に関して、基本Cの全bitを追いかけて、ひとつでも確実に1になるbitがあるなら B 。わからないときはあきらめてそのまま。

(if0 x A B)

Aが選択されるのは x = 0 の場合のみ。なので、(if0 x A[x/0], B)。さらに A[x/0] == B[x/0] なら B。

不必要な bit 演算の削除

(shr1 (xor 1 (or 1 x)))

みたいな式は、最後の shr1 が末尾の bit 操作をおとしてしまうので、xor も or も実は不必要。