mulとdiv

mulの一方の引数が2のn乗の定数である場合、nビットのshift_leftで代用できる。これはたとえオーバーフローが起きる場合でもmulと同一の結果を返す。

ではdivの除数が2のn乗の定数である場合、nビットのarithmetic_shift_rightで代用できるか、というと必ずしもそうではない。被除数が負数であり、かつdivがround-towards-zeroの場合、arithmetic_shift_rightで代用すると結果が異なってしまう*1

y := x div 2^n

に対しては

t := x arithmetic_shift_right (n - 1)
t := t logical_shift_right (32 - n)
t := x add t
y := t arithmetic_shift_right n

とするのが正しい。

kaffe-1.0.7に付属のjit3にはこのバグがあり*2Javaプログラム中でintの割り算は正しい結果を返さない可能性がある。kaffe-1.1.4でもこのバグは修正されていない。というか、間違った修正がされている。

(続く)

*1:round-towards-negative-infinityならば結果は同一となる。

*2:対して、jitはそもそも引数が2のn乗の場合にシフトで代用するという最適化を行わない。というかコンパイラの設計上、行えないのか?