Author: | ayende |
---|---|
Assignees: | - |
Labels: | `tenet-performance`, `area-CodeGen-coreclr` |
Milestone: | - |
Open ayende opened 1 year ago
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.
Author: | ayende |
---|---|
Assignees: | - |
Labels: | `tenet-performance`, `area-CodeGen-coreclr` |
Milestone: | - |
We do optimize this in JIT but it doesn't work well when constants are small powers of two - those are transformed into shift operation and then confuse the opt.
Note that the 2nd version is folded by Roslyn:
.method private hidebysig static
int32 A (
int32 i
) cil managed
{
// Method begins at RVA 0x2067
// Code size 6 (0x6)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.4
IL_0002: mul
IL_0003: ldc.i4.8
IL_0004: mul
IL_0005: ret
} // end of method Test::A
.method private hidebysig static
int32 B (
int32 i
) cil managed
{
// Method begins at RVA 0x206e
// Code size 5 (0x5)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.s 32
IL_0003: mul
IL_0004: ret
} // end of method Test::B
those are transformed into shift operation and then confuse the opt.
Aren't shift operations mergable too?
The complex case would be that one number is transformed into shift.
Currently the codegen for A is:
; Method Program.Program:A(int):int:this (FullOpts)
G_M29096_IG01: ;; offset=0x0000
;; size=0 bbWeight=1 PerfScore 0.00
G_M29096_IG02: ;; offset=0x0000
lea eax, [4*rdx]
shl eax, 3
;; size=10 bbWeight=1 PerfScore 1.00
G_M29096_IG03: ;; offset=0x000A
ret
;; size=1 bbWeight=1 PerfScore 1.00
; Total bytes of code: 11
Avoiding the LEA would be preferable if we can.
Description
Consider the following code:
These two functions should result in identical results.
But the JIT output slightly different code for each:
This is on:
; Core CLR 7.0.823.31807 on x64
Analysis
Given that multiplication is communicative, and that this is a power of two operation, I would expect the JIT to fold them to the 2nd version, without the parenthesis.
The first version takes two instructions instead of 1.