Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Improve Math(F).FusedMultiplyAdd codegen - #27060

Merged
sandreenko merged 23 commits into
dotnet:masterfrom
EgorBo:improve-fma
Nov 6, 2019
Merged

sandreenko merged 23 commits into
dotnet:masterfrom
EgorBo:improve-fma

Conversation

@EgorBo

@EgorBo EgorBo commented Oct 7, 2019

Copy link
Copy Markdown
Member

Fixes https://github.com/dotnet/coreclr/issues/25829 (currently Math(F).FusedMultiplyAdd always emits vfmadd213ss\d and xors if there are negations)

Test cases:

static float Test1(float a, float b, float c) => MathF.FusedMultiplyAdd( a,  b,  c);
static float Test2(float a, float b, float c) => MathF.FusedMultiplyAdd( a, -b,  c);
static float Test3(float a, float b, float c) => MathF.FusedMultiplyAdd(-a,  b,  c);
static float Test4(float a, float b, float c) => MathF.FusedMultiplyAdd(-a, -b,  c);
static float Test5(float a, float b, float c) => MathF.FusedMultiplyAdd( a,  b, -c);
static float Test6(float a, float b, float c) => MathF.FusedMultiplyAdd( a, -b, -c);
static float Test7(float a, float b, float c) => MathF.FusedMultiplyAdd(-a,  b, -c);
static float Test8(float a, float b, float c) => MathF.FusedMultiplyAdd(-a, -b, -c);

Was:

; Method FmaFTests:Test1(float,float,float):float
G_M46841_IG01:
       vzeroupper 
G_M46841_IG02:
       vfmadd213ss xmm0, xmm1, xmm2
G_M46841_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test2(float,float,float):float
G_M46842_IG01:
       vzeroupper 
G_M46842_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm1, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46842_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 21


; Method FmaFTests:Test3(float,float,float):float
G_M46843_IG01:
       vzeroupper 
G_M46843_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm0, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46843_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 21


; Method FmaFTests:Test4(float,float,float):float
G_M46844_IG01:
       vzeroupper 
G_M46844_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm0, xmm3
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm1, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46844_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 33


; Method FmaFTests:Test5(float,float,float):float
G_M46845_IG01:
       vzeroupper 
G_M46845_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm2, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46845_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 21


; Method FmaFTests:Test6(float,float,float):float
G_M46846_IG01:
       vzeroupper 
G_M46846_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm1, xmm3
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm2, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46846_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 33


; Method FmaFTests:Test7(float,float,float):float
G_M46847_IG01:
       vzeroupper 
G_M46847_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm0, xmm3
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm2, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46847_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 33


; Method FmaFTests:Test8(float,float,float):float
G_M46832_IG01:
       vzeroupper 
G_M46832_IG02:
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm0, xmm3
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm1, xmm3
       vmovss   xmm3, dword ptr [reloc @RWD00]
       vxorps   xmm2, xmm3
       vfmadd213ss xmm0, xmm1, xmm2
G_M46832_IG03:
       ret      
RWD00  dd	80000000h
; Total bytes of code: 45

Now:

; Method FmaFTests:Test1(float,float,float):float
G_M12796_IG01:
       vzeroupper 
G_M12796_IG02:
       vfmadd213ss xmm0, xmm1, xmm2
G_M12796_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test2(float,float,float):float
G_M12799_IG01:
       vzeroupper 
G_M12799_IG02:
       vfnmadd213ss xmm0, xmm1, xmm2
G_M12799_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test3(float,float,float):float
G_M12798_IG01:
       vzeroupper 
G_M12798_IG02:
       vfnmadd213ss xmm0, xmm1, xmm2
G_M12798_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test4(float,float,float):float
G_M12793_IG01:
       vzeroupper 
G_M12793_IG02:
       vfmadd213ss xmm0, xmm1, xmm2
G_M12793_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test5(float,float,float):float
G_M12792_IG01:
       vzeroupper 
G_M12792_IG02:
       vfmsub213ss xmm0, xmm1, xmm2
G_M12792_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test6(float,float,float):float
G_M12795_IG01:
       vzeroupper 
G_M12795_IG02:
       vfnmsub213ss xmm0, xmm1, xmm2
G_M12795_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test7(float,float,float):float
G_M12794_IG01:
       vzeroupper 
G_M12794_IG02:
       vfnmsub213ss xmm0, xmm1, xmm2
G_M12794_IG03:
       ret      
; Total bytes of code: 9


; Method FmaFTests:Test8(float,float,float):float
G_M12789_IG01:
       vzeroupper 
G_M12789_IG02:
       vfmsub213ss xmm0, xmm1, xmm2
G_M12789_IG03:
       ret      
; Total bytes of code: 9

Diff.
/cc @tannergooding

@EgorBo

EgorBo commented Oct 7, 2019

Copy link
Copy Markdown
Member Author

This PR doesn't improve:

float t = MathF.FusedMultiplyAdd(x, y, y);

It's expected to be

vfmadd213ss xmm0 xmm1 xmm1

but it emits a redundant mov:

vmovaps  xmm2, xmm1
vfmadd213ss xmm0, xmm2, xmm1

The goal was to make this func:

static float Lerp(float v0, float v1, float t) =>
    MathF.FusedMultiplyAdd(t, v1, MathF.FusedMultiplyAdd(-t, v0, v0));

to have a perfect codegen

Comment thread src/jit/instrsxarch.h
Comment thread src/jit/importer.cpp Outdated
@sandreenko

Copy link
Copy Markdown

PTAL @dotnet/jit-contrib

Comment thread src/jit/lowerxarch.cpp Outdated

@sandreenko sandreenko left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, nice improvement, thank you.

Comment thread src/jit/lowerxarch.cpp Outdated

@echesakov echesakov left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Thank you!

Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp Outdated
@sandreenko

Copy link
Copy Markdown

Could you please add your test cases to https://github.com/dotnet/coreclr/tree/master/tests/src/JIT/HardwareIntrinsics/X86?
@tannergooding could know better to which folder.

Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp
Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp
Comment thread tests/src/JIT/Intrinsics/MathFusedMultiplyAdd.cs
@sandreenko
sandreenko self-requested a review October 25, 2019 17:36
Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp Outdated
Comment thread src/jit/lowerxarch.cpp
Comment thread src/jit/lowerxarch.cpp
@sandreenko

Copy link
Copy Markdown

/azp run coreclr-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@sandreenko sandreenko left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, ADO shows no failures (1 queued job is a github glitch, it has passed already), so I am going to merge that soon.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Math.FusedMultiplyAdd suboptimal codegen

5 participants