The result of the
mul
operation is in two combined registers [edx:eax].The value of edx is
result/0xFFFFFFFF
.This optimization takes advantage of that fact:
(value*multiply/0xFFFFFFFF)>>shift =>; value*original
A multiplication followed by a division is sometimes optimized the same way.
Multiply | Shift | Original |
0x069C16BD | 0 | 665/25756 |
0x10624DD3 | 4 | 1/250 |
0x10624DD3 | 5 | 1/500 |
0x10624DD3 | 6 | 1/1000 |
0x2AAAAAAB | 0 | 1/6 |
0x30C30C31 | 3 | 1/42 |
0x38E38E39 | 1 | 1/9 |
0x4EC4EC4F | 3 | 1/26 |
0x51EB851F | 5 | 1/100 |
0x55555556 | 0 | 1/3 |
0x66666667 | 1 | 1/5 |
0x66666667 | 2 | 1/10 |
0x66666667 | 3 | 1/20 |
0x66666667 | 4 | 1/40 |
0x66666667 | 5 | 1/80 |
0x66666667 | 6 | 1/160 |
0x66666667 | 7 | 1/320 |
0x66666667 | 8 | 1/640 |
0x6BCA1AF3 | 5 | 1/76 |
0x88888889 | 8 | 1/480 |
0x92492493 | 3 | 1/14 |
0xA0A0A0A1 | 7 | 1/204 |
0xAAAAAAAB | 1 | 1/3 |
0xAAAAAAAB | 2 | 1/6 |
0xAAAAAAAB | 3 | 1/12 |
0xAAAAAAAB | 4 | 1/24 |
0xAE147AE1 | 5 | 17/800 |
0xB21642C9 | 5 | 1/46 |
0xB60B60B7 | 5 | 1/45 |
0xBA2E8BA3 | 3 | 1/11 |
0xEA0EA0EB | 0 | 32/35 |
Note: these optimization are only used if the resulting value doesn't lose precision in comparison to the original operation.