Current codegen:
8BC1 moveax,ecx C1F81F sareax,31 83E003 andeax,3 03C1 addeax,ecx C1F802 sareax,2 C3 ret; Total bytes of code: 14
Expected codegen:
8D4103 leaeax,[rcx+3] 85C9 testecx,ecx 0F49C1 cmovnseax,ecx C1F802 sareax,2 C3 ret; Total bytes of code: 12
This micro-peephole-optimization was added recently in LLVM (PR, see BuildSDIVPow2), see godbolt: https://godbolt.org/z/M153rj
My working (ugly) prototype for RyuJIT: EgorBo@9b1d149 (I believe it should be done the other way - I'd introduce a GT_SELECT/GT_CMOV operator so we can later use it for other cmov-based optimizations, e.g. remove branches)
Benchmark
[Benchmark]publicvoidTest(){for(inti=0;i<10000;i++)Consume(i/4+i/8+i/16+i/32);}[MethodImpl(MethodImplOptions.NoInlining)]staticvoidConsume(intx){} | Method | Mean | Error | StdDev |
|------- |---------:|---------:|---------:|
master | Test | 19.14 us | 0.017 us | 0.013 us |
prototype | Test | 17.02 us | 0.016 us | 0.013 us | ~11% faster
/cc @AntonLapounov
category:cq
theme:basic-cq
skill-level:beginner
cost:small
impact:small
Current codegen:
Expected codegen:
This micro-peephole-optimization was added recently in LLVM (PR, see
BuildSDIVPow2), see godbolt: https://godbolt.org/z/M153rjMy working (ugly) prototype for RyuJIT: EgorBo@9b1d149 (I believe it should be done the other way - I'd introduce a GT_SELECT/GT_CMOV operator so we can later use it for other cmov-based optimizations, e.g. remove branches)
Benchmark
/cc @AntonLapounov
category:cq
theme:basic-cq
skill-level:beginner
cost:small
impact:small