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にはこのバグがあり*2、Javaプログラム中でintの割り算は正しい結果を返さない可能性がある。kaffe-1.1.4でもこのバグは修正されていない。というか、間違った修正がされている。
(続く)