C ++ рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЙрд▓ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдВ

рдмрд╣реБрдд рдкрд╣рд▓реЗ рдирд╣реАрдВ, рдореИрдВрдиреЗ рдПрдХ рд╢рд╛рд╢реНрд╡рдд рд╡рд┐рд╖рдп рдкрд░ рдПрдХ рд╕рд╣рдХрд░реНрдореА рдХреЗ рд╕рд╛рде рдПрдХ рдФрд░ рдмрд╛рддрдЪреАрдд рдХреА: "рд╕рдВрджрд░реНрдн рд╕реЗ, рдпрд╛ рдореВрд▓реНрдп рд╕реЗред" рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдпрд╣ рд▓реЗрдЦ рдЙрддреНрдкрдиреНрди рд╣реБрдЖред рдЗрд╕рдореЗрдВ, рдореИрдВ рдЗрд╕ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рд╡рд┐рд╖рдпреЛрдВ рдкрд░ рдЕрдкрдиреЗ рд╢реЛрдз рдХреЗ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╕реНрддреБрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдЕрдЧрд▓рд╛ рд╡рд┐рдЪрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛:


  • рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдФрд░ рдЙрдирдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдЬрдм рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмреБрд▓рд╛рддреЗ рд╣реИрдВред
  • рд╕рд░рд▓ рдкреНрд░рдХрд╛рд░ рдФрд░ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдФрд░ рд╡рд╛рдкрд╕реАред
  • рд╕рдВрджрд░реНрдн рдФрд░ рдорд╛рди рд╕реЗ рдХреИрд╕реЗ рдЧреБрдЬрд░рддрд╛ рд╣реИ, рдпрд╣ рдХрдВрдкрд╛рдЗрд▓рд░ рджреНрд╡рд╛рд░рд╛ рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА рдХреЗ рдЕрдиреБрдХреВрд▓рди рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИред
  • рдорд▓реНрдЯреАрдкрд▓ рдлрдВрдХреНрд╢рди рдХреЙрд▓реНрд╕ рдореЗрдВ рд╕реНрдкреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  • рд╡рд░реНрдЪреБрдЕрд▓ рдХреЙрд▓ рдХрд╛ рддрдВрддреНрд░ред
  • рдкреВрдВрдЫ рдХреЙрд▓ рдФрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд╛ рдЕрдиреБрдХреВрд▓рдиред
  • рд╕рдВрд░рдЪрдирд╛рдУрдВ, рд╕рд░рдгрд┐рдпреЛрдВ рдФрд░ рд╡реИрдХреНрдЯрд░ рдХрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХрдХрд░рдгред

рдЪреЗрддрд╛рд╡рдиреА! рд▓реЗрдЦ рдореЗрдВ рдмрдбрд╝реА рдорд╛рддреНрд░рд╛ рдореЗрдВ C ++ рдФрд░ рдХреЛрдбрд╛рдВрддрд░рдХ рдХреЛрдб (рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде Intel ASM ), рд╕рд╛рде рд╣реА рдкреНрд░рджрд░реНрд╢рди рд░реЗрдЯрд┐рдВрдЧ рдХреЗ рд╕рд╛рде рдХрдИ рддрд╛рд▓рд┐рдХрд╛рдПрдВ рд╣реИрдВред рд╕рдм рдХреБрдЫ рд▓рд┐рдЦрд╛ x86-64 рд╕рд┐рд╕реНрдЯрдо рд╡реА рдПрдмреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рднреА рдЖрдзреБрдирд┐рдХ рдпреВрдирд┐рдХреНрд╕ рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓рд┐рдирдХреНрд╕ рдФрд░ рдореИрдХрдУрдПрд╕ред


X86-64 рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЗ рд▓рд┐рдП рд╕рд┐рд╕реНрдЯрдо V рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдмрд╛рдЗрдирд░реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рдЬрд╛рдирдХрд╛рд░реА рд▓реА рдЧрдИ рдереАред -O3 -std=c++1z -march=sandybridge 5.0.0 x86-64 рдЭрдВрдбреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдкреНрдд рд╣реБрдП рдереЗ -O3 -std=c++1z -march=sandybridge (рд╕рд╛рдЗрдЯ https://godbolt.org рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ)ред Intel┬о Xeon┬о рдкреНрд░реЛрд╕реЗрд╕рд░ E5-2660 2.20GHz рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд░реНрд╢рди рд░реЗрдЯрд┐рдВрдЧ рдмрдирд╛рдИ рдЧрдИ рдереА ред


рд╕рд╛рдордЧреНрд░реА



рд░рдЬрд┐рд╕реНрдЯрд░ x86-64 рдореЗрдВ


рд╕рд╛рд░рд╛ рдбрд╛рдЯрд╛ рд░реИрдо рдореЗрдВ рд╕реНрдЯреЛрд░ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдЧрддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╣реБрд╕реНрддрд░реАрдп рдХреИрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдбреЗрдЯрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рддрд░рд╣ рд╕реЗ рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп, рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ( рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЪрд░реНрдЪрд╛ )ред рдиреАрдЪреЗ x86-64 рд╡рд╛рд╕реНрддреБрдХрд▓рд╛ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдмрд╣реБрдд рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╡рд┐рд╡рд░рдг рд╣реИред


  • 16 рд╕рд╛рдорд╛рдиреНрдп-рдЙрджреНрджреЗрд╢реНрдп рд░рдЬрд┐рд╕реНрдЯрд░: rax, rbx, rcx, rdx, rbp, rsi, rdi, rsp рдФрд░ r8-r15 рднреАред рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛ рдЖрдХрд╛рд░ 64 рдмрд┐рдЯреНрд╕ (8 рдмрд╛рдЗрдЯреНрд╕) рд╣реИред рдирд┐рдЪрд▓реЗ 32 рдмрд┐рдЯреНрд╕ (4 рдмрд╛рдЗрдЯреНрд╕) рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдЙрдкрд╕рд░реНрдЧ e r ( rax тЖТ eax ) рдХреЗ рдмрдЬрд╛рдп e ред рдХреЗрд╡рд▓ рдЧреИрд░-рд╡реЗрдХреНрдЯрд░ рдкреВрд░реНрдгрд╛рдВрдХ рдСрдкрд░реЗрд╢рди рд╕рдорд░реНрдерд┐рдд рд╣реИрдВред
  • rip (рдЕрдиреБрджреЗрд╢ рд╕реВрдЪрдХ) рдЕрдЧрд▓реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрджреЗрд╢ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдореЗрдореЛрд░реА рд╕реЗрдХреНрд╢рди рдореЗрдВ рдкрдбрд╝реЗ рд╡рд┐рднрд┐рдиреНрди рд╕реНрдерд┐рд░ рдбреЗрдЯрд╛ рдХреЛ rip рд╕рд╛рдкреЗрдХреНрд╖ рдПрдХ рдСрдлрд╕реЗрдЯ рдкрд░ рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
  • rsp (рд╕реНрдЯреИрдХ рдкреЙрдЗрдВрдЯрд░) рд╕реНрдЯреИрдХ рдкрд░ рдЕрдВрддрд┐рдо рдЖрдЗрдЯрдо рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред рд╕реНрдЯреИрдХ рдирд┐рдЪрд▓реЗ рдкрддреЛрдВ рдХреА рдУрд░ рдмрдврд╝рддрд╛ рд╣реИред рд╕реНрдЯреИрдХ рдкрд░ рдХреБрдЫ рдкреБрд╢ рдХрд░рдиреЗ рд╕реЗ rsp рдорд╛рди рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
  • 16 SSE рдЖрдХрд╛рд░ рдореЗрдВ 128 рдмрд┐рдЯреНрд╕ рдкрдВрдЬреАрдХреГрдд рдХрд░рддрд╛ рд╣реИ: xmm0 - xmm15 ред рдпрджрд┐ AVX рдореЛрдб рдХрд╛ рд╕рдорд░реНрдерди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╡реЗ ymm0 - ymm15 рдХреЗ рдирд┐рдЪрд▓реЗ 128 рдмрд┐рдЯреНрд╕ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддреЗ рд╣реИрдВ ymm0 - ymm15 рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛ рдЖрдХрд╛рд░ 256 рдмрд┐рдЯреНрд╕ рд╣реЛрддрд╛ рд╣реИред рд╡реЗрдХреНрдЯрд░, рдпрд╛ рдЧреИрд░-рдкреВрд░реНрдгрд╛рдВрдХ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП, рдбреЗрдЯрд╛ рдХреЛ рдкрд╣рд▓реЗ рдЗрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рдкрд╛рд╕рд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░


рдпрд╣ рдЦрдВрдб рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ / рд╕реНрдЯреИрдХ рдХреЗ рддрд░реНрдХреЛрдВ рдХреЛ рд╡рд┐рддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрд▓реНрдЧреЛрд░рд┐рдердо рдХрд╛ рдХреБрдЫ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдФрд░ рд╕рд░рд▓реАрдХреГрдд рд╡рд┐рд╡рд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдкреВрд░реНрдг рд╡рд┐рд╡рд░рдг рдХреЗ рд▓рд┐рдП, рдкреГрд╖реНрда 17 "рд╕рд┐рд╕реНрдЯрдо рд╡реА рдПрдмреАрдЖрдИ" рджреЗрдЦреЗрдВред


рд╣рдо рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдХрдИ рд╡рд░реНрдЧреЛрдВ рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВ:


  • INTEGER - рд╕рд╛рдорд╛рдиреНрдп рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд░рдЦреЗ рдЧрдП рдЗрдВрдЯреАрдЧреНрд░рд▓ рдкреНрд░рдХрд╛рд░ред рдпреЗ bool , char , int рдФрд░ рдЗрддрдиреЗ рд╣реА рд╣реИрдВред
  • SSE рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдирдВрдмрд░ рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд╡реЗрдХреНрдЯрд░ рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдлрд┐рдЯ рд╣реЛрддреЗ рд╣реИрдВред рдпреЗ float рдФрд░ double ред
  • рдореЗрдореЛрд░реА - рд╕реНрдЯреИрдХ рд╕реЗ рдЧреБрдЬрд░реЗ рдСрдмреНрдЬреЗрдХреНрдЯред

рд╡рд┐рд╡рд░рдг рдХреЛ рдПрдХрдЬреБрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, __int128 рдФрд░ complex рдкреНрд░рдХрд╛рд░реЛрдВ __int128 рджреЛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд░реВрдк __int128 рджрд░реНрд╢рд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:


 struct __int128 { int64 low, high; }; struct complexT { T real, imag; }; //  T - float,  double. 

рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рддрд░реНрдХ рдХреЛ рд╡рд░реНрдЧреАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:


  1. рдпрджрд┐ рдкреНрд░рдХрд╛рд░ 128 рдмрд┐рдЯреНрд╕ рд╕реЗ рдмрдбрд╝рд╛ рд╣реИ, рдпрд╛ рдЗрд╕рдореЗрдВ рдЕрд╡рд┐рднрд╛рдЬрд┐рдд рдлрд╝реАрд▓реНрдб рд╣реИрдВ, рддреЛ рдпрд╣ рдореЗрдореЛрд░реА рд╣реИ ред
  2. рдпрджрд┐ рдХреЛрдИ рдЧреИрд░-рддреБрдЪреНрдЫ рд╡рд┐рдзреНрд╡рдВрд╕рдХ, рдХреЙрдкреА рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░, рд╡рд░реНрдЪреБрдЕрд▓ рддрд░реАрдХреЗ, рд╡рд░реНрдЪреБрдЕрд▓ рдмреЗрд╕ рдХрдХреНрд╖рд╛рдПрдВ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ "рдкрд╛рд░рджрд░реНрд╢реА рд▓рд┐рдВрдХ" рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдПрдХ рд╕реВрдЪрдХ рдХреЗ рд╕рд╛рде рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХрд┐ INTEGER рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реЛрддрд╛ рд╣реИред
  3. рдПрдЧреНрд░реАрдЧреЗрдЯреНрд╕, рдФрд░ рдпреЗ рд╕рдВрд░рдЪрдирд╛рдПрдВ рдФрд░ рд╕рд░рдгрд┐рдпрд╛рдВ рд╣реИрдВ, 8 рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдЯреБрдХрдбрд╝реЛрдВ рдореЗрдВ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
    1. рдпрджрд┐ рдЯреБрдХрдбрд╝рд╛ рдореЗрдВ рдЯрд╛рдЗрдк рдореЗрдореЛрд░реА рдХрд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИ, рддреЛ рдкреВрд░рд╛ рдЯреБрдХрдбрд╝рд╛ рдореЗрдореЛрд░реА рд╣реИ ред
    2. рдпрджрд┐ рдХрд┐рд╕реА рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдХреНрд╖реЗрддреНрд░ INTEGER рд╣реИ , рддреЛ рдкреВрд░рд╛ рдЯреБрдХрдбрд╝рд╛ INTEGER рд╣реИ ред
    3. рдЕрдиреНрдпрдерд╛, рдПрд╕рдПрд╕рдИ рдХрд╛ рдкреВрд░рд╛ рдЯреБрдХрдбрд╝рд╛ред
  4. рдпрджрд┐ MEMORY рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╣реИ, рддреЛ рд╕рдВрдкреВрд░реНрдг рддрд░реНрдХ MEMORY рд╣реИ ред
  5. long double рдФрд░ complex long double рдкреНрд░рдХрд╛рд░ x87 FPU рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╕реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдореЗрдореЛрд░реА рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред
  6. __m256 , __m128 рдФрд░ __float128 SSE рдкреНрд░рдХрд╛рд░ рдХреЗ рд╣реИрдВред

рд╡рд░реНрдЧреАрдХрд░рдг рдХреЗ рдмрд╛рдж, рд╕рднреА 8 рдмрд╛рдЗрдЯ рд╡рд┐рдЦрдВрдбреВ (рдПрдХ рдЪрдВрдХ рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдХрдИ рдХреНрд╖реЗрддреНрд░ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рд╕рд░рдгреА рддрддреНрд╡) рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рд╡рд┐рддрд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:


  1. рдореЗрдореЛрд░реА рдХреЛ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  2. INTEGER рдХреЛ рдЙрд╕ рдХреНрд░рдо рдореЗрдВ рдЕрдЧрд▓реЗ рдореБрдлреНрдд рд░рдЬрд┐рд╕реНрдЯрд░ rdi, rsi, rdx, rcx, r8, r9 рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  3. SSE рдХреЛ рдЕрдЧрд▓реЗ рдореБрдлреНрдд рд░рдЬрд┐рд╕реНрдЯрд░ xmm0 - xmm7 рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░реЗрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рддрд░реНрдХ рдХреЛ рдмрд╛рдПрдВ рд╕реЗ рджрд╛рдПрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрд┐рди рддрд░реНрдХреЛрдВ рдореЗрдВ рдкрд░реНрдпрд╛рдкреНрдд рд░рдЬрд┐рд╕реНрдЯрд░ рдирд╣реАрдВ рдереЗ, рдЙрдиреНрд╣реЗрдВ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрджрд┐ рддрд░реНрдХ рдХреЗ рдХрд┐рд╕реА рднреА рдЯреБрдХрдбрд╝реЗ рдореЗрдВ рдПрдХ рд░рдЬрд┐рд╕реНрдЯрд░ рдирд╣реАрдВ рдерд╛, рддреЛ рдкреВрд░реЗ рддрд░реНрдХ рдХреЛ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рд╡рд╛рдкрд╕реА рдорд╛рди рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИрдВ:


  1. рдореЗрдореЛрд░реА рдкреНрд░рдХрд╛рд░ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реМрдЯрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВред рдЗрд╕ рдкрд░ рдЬрдЧрд╣ рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХреА рдЬрд╛рддреА рд╣реИ рдФрд░ рдЗрд╕рдХреА рд╢реБрд░реБрдЖрдд рдХрд╛ рдкрддрд╛ rdi рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреИрд╕реЗ рдХрд┐ рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд╣рд▓рд╛ рддрд░реНрдХ рдерд╛ред рд▓реМрдЯрдиреЗ рдкрд░, рдЗрд╕ рдкрддреЗ рдХреЛ rax рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдкрд╣рд▓реЗ рдореВрд▓ рддрд░реНрдХ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдХреНрд░рдорд╢рдГ рджреВрд╕рд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ, рдФрд░ рдЗрд╕реА рддрд░рд╣ред
  2. INTEGER рдЪрдВрдХ рдХреЛ рдЕрдЧрд▓реЗ рдореБрдлреНрдд рд░рдЬрд┐рд╕реНрдЯрд░ rax, rdx рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  3. SSE chunk рдХреЛ рдЕрдЧрд▓реЗ рдореБрдлреНрдд рд░рдЬрд┐рд╕реНрдЯрд░ xmm0, xmm1 рдорд╛рдзреНрдпрдо рд╕реЗ рд▓реМрдЯрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рд▓реМрдЯрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рд░рдЬрд┐рд╕реНрдЯрд░ рдкрдврд╝рдиреЗ рдХреЗ рджреМрд░рд╛рди рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдФрд░ рдЙрдирдХреЗ рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд╕рд╛рде рдПрдХ рдкрд┐рд╡рдЯ рдЯреЗрдмрд▓ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реИ:


рд░рдЬрд┐рд╕реНрдЯрд░рдирд┐рдпреБрдХреНрддрд┐
raxрдЕрд╕реНрдерд╛рдИ рд░рдЬрд┐рд╕реНрдЯрд░, рдкрд╣рд▓рд╛ (рдкрд┐рдЫрд▓рд╛ 1) INTEGER рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рдПрдВред
rbxрдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрддрд░реНрдЧрдд, рд╡рд╛рдкрд╕реА рдХреЗ рд╕рдордп рдирд╣реАрдВ рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
rcxрдЪреМрдерд╛ (4) рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рддрд░реНрдХред
rdxрддреАрд╕рд░рд╛ (3) INTEGER рддрд░реНрдХ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛, рджреВрд╕рд░рд╛ (2 рдирдВрдмрд░) INTEGER рдкрд░рд┐рдгрд╛рдо рд▓реМрдЯрд╛рддрд╛ рд╣реИред
rspрдвреЗрд░ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░реЗрдВред
rbpрдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрддрд░реНрдЧрдд, рд╡рд╛рдкрд╕реА рдХреЗ рд╕рдордп рдирд╣реАрдВ рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
rsiрджреВрд╕рд░рд╛ (2) рдПрдХреАрдХрд░рдг рддрд░реНрдХ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛ред
rdiрдкрд╣рд▓реЗ (1) рдПрдХреАрдХрд░рдг рддрд░реНрдХ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛ред
r8рдкрд╛рдВрдЪрд╡реА (5) рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рддрд░реНрдХред
r9рдЫрдард╛ (6) рдкрд╛рд╕ рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рддрд░реНрдХред
r10-r11рдЕрд╕реНрдерд╛рдпреА рд░рдЬрд┐рд╕реНрдЯрд░ред
r12-r15рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрддрд░реНрдЧрдд, рд╡рд╛рдкрд╕реА рдХреЗ рд╕рдордп рдирд╣реАрдВ рдмрджрд▓рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
xmm0-xmm1рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ SSE рддрд░реНрдХреЛрдВ рдХреЛ рдкрд╛рд╕ рдФрд░ рд╡рд╛рдкрд╕ рдХрд░реЗрдВред
xmm2-xmm7рдЫрдареЗ SSE рддрд░реНрдХреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рддреАрд╕рд░рд╛ рдкрд╛рд╕ рдХрд░рдирд╛ред
xmm8-xmm15рдЕрд╕реНрдерд╛рдпреА рд░рдЬрд┐рд╕реНрдЯрд░ред

рдХреЙрд▓рд┐рдВрдЧ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЛ рдпрд╛ рддреЛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдпрд╛ рдЙрдирдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдХрд╣реАрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрдЯреИрдХ рдкрд░, рдФрд░ рдлрд┐рд░ рдкреБрдирд░реНрд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ред


рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг


рдЬрдм рддрдХ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЕрдиреНрдпрдерд╛ рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддрдм рддрдХ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдлрд╝рдВрдХреНрд╢рди NOINLINE рдХреЗ рд░реВрдк рдореЗрдВ рдЪрд┐рд╣реНрдирд┐рдд рдХрд┐рдП рдЧрдП рдереЗред рд╣рдо рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдмреЙрдбреА cpp рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИ, рдФрд░ LTO рдЕрдХреНрд╖рдо рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рднреА рдлрд╝рдВрдХреНрд╢рди рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╕рднреА рдХреЛрдб рдХреЛ рд╣рдЯрд╛рдиреЗ рд╕реЗ рдСрдкреНрдЯрд┐рдорд╛рдЗрдЬрд╝рд░ рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЦрд╛рд▓реА NOINLINE рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


 #define NOINLINE __attribute__((noinline)) #define INLINE static __attribute__((always_inline)) 

рдХреБрдЫ рд╕рд░рд▓ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред


 double foo(int8_t a, int16_t b, int32_t c, int64_t d, float x, double y) { return a + b + c + d + x + y; } ... auto result = foo(1, 2, 3, 4, 5, 6); 

рдкреИрд░рд╛рдореАрдЯрд░ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ:


рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
рдПрдХrdiрдШrcxxmm0
рдЦrsiрдПрдХреНрд╕xmm0
рдЧrdxyxmm1

рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдЙрддреНрдкрдиреНрди рдХреЛрдб рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред


 foo(signed char, short, int, long, float, double): add edi, esi #  a  b. add edi, edx #  c. movsxd rax, edi #    rax,    64    . add rax, rcx #  d. vcvtsi2ss xmm2, xmm2, rax #    float     xmm2. vaddss xmm0, xmm2, xmm0 #  x,  's'  vaddss    single precision. vcvtss2sd xmm0, xmm0, xmm0 #    double. vaddsd xmm0, xmm0, xmm1 #  y,  'd'  vaddsd    double precision. ret #       ,    ,    ,   rsp   8. .LCPI1_0: #    . .long 1084227584 # float 5 .LCPI1_1: .quad 4618441417868443648 # double 6 main: # @main sub rsp, 24 #     . vmovss xmm0, dword ptr [rip + .LCPI1_0] # xmm0 = mem[0],zero,zero,zero vmovsd xmm1, qword ptr [rip + .LCPI1_1] # xmm1 = mem[0],zero mov edi, 1 mov esi, 2 mov edx, 3 mov ecx, 4 call foo(signed char, short, int, long, float, double) # call      ,    rsp  8,      . vmovsd qword ptr [rsp + 16], xmm0 #     . 

рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╕рд░рд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдХрдбрд╝реА рдореЗрд╣рдирдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╡реЗ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рди рд╣реЛрдВред


рд╕рдореБрдЪреНрдЪрдп рдХреЗ рд╡рд┐рднрд┐рдиреНрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдПрд░реЗ рдХреЛ рдХрдИ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рд╛рде рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


 struct St { double a, b; }; double foo(St s) { return sa + sb; } ... St s{1, 2}; auto result = foo(s); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
рд╕рд╛xmm0sbxmm1xmm0

рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рднреА рдирд╣реАрдВ рдПрдХ xmm рдмрд╛рд░ рдореЗрдВ рджреЛ double рдХреЛ рдПрдХ xmm рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдзрдХреЗрд▓рдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдлрд╕реЛрд╕, рд╡рд┐рддрд░рдг рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗрд╡рд▓ рдЖрда-рдмрд╛рдЗрдЯ рд╡рд┐рдЦрдВрдбреВ рдкрд░ рдЪрд▓ рд░рд╣рд╛ рд╣реИред


 foo(St): # @foo(St) vaddsd xmm0, xmm0, xmm1 #     ,       . ret .LCPI1_0: .quad 4607182418800017408 # double 1 .LCPI1_1: .quad 4611686018427387904 # double 2 main: # @main sub rsp, 24 #   . vmovsd xmm0, qword ptr [rip + .LCPI1_0] # xmm0 = mem[0],zero vmovsd xmm1, qword ptr [rip + .LCPI1_1] # xmm1 = mem[0],zero call foo(St) vmovsd qword ptr [rsp + 16], xmm0 #  double    . 

рдпрджрд┐ рдЖрдк рдПрдХ рдФрд░ double рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ рдкреВрд░реЗ рдврд╛рдВрдЪреЗ рдХреЛ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдЖрдХрд╛рд░ 128 рдмрд╛рдЗрдЯреНрд╕ рд╕реЗ рдЕрдзрд┐рдХ рд╣реЛрдЧрд╛ред


 struct St { double a, b, c; }; double foo(St s) { return sa + sb + sc; } ... St s{1, 2, 3}; auto result = foo(s); 

 foo(St): # @foo(St) #   ,    8 ,     .        ,         rsp+8. vmovsd xmm0, qword ptr [rsp + 8] # xmm0 = mem[0],zero vaddsd xmm0, xmm0, qword ptr [rsp + 16] vaddsd xmm0, xmm0, qword ptr [rsp + 24] ret .L_ZZ4mainE1s: .quad 4607182418800017408 # double 1 .quad 4611686018427387904 # double 2 .quad 4613937818241073152 # double 3 main: # @main sub rsp, 40 #    40 . #       ,    .      ,   mov       . mov rax, qword ptr [rip + .L_ZZ4mainE1s+16] #    '3'. mov qword ptr [rsp + 16], rax #  '3'  . vmovups xmm0, xmmword ptr [rip + .L_ZZ4mainE1s] #   xmm0  '1'  '2'. vmovups xmmword ptr [rsp], xmm0 #  '1'  '2  .    : 1 = *rsp , 2 = *(rsp+8), 3 = *(rsp+16). call foo(St) vmovsd qword ptr [rsp + 32], xmm0 #     double  . 

рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рд╣рдо uint64_t рд╕рд╛рде double рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред


 struct St { uint64_t a, b; }; uint64_t foo(St s) { return sa + sb; } ... St s{1, 2}; auto result = foo(s); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
рд╕рд╛rdisbrsirax

 foo(St): # @foo(St) lea rax, [rdi + rsi] ret main: # @main sub rsp, 24 mov edi, 1 mov esi, 2 call foo(St) mov qword ptr [rsp + 16], rax 

рдкрд░рд┐рдгрд╛рдо рдХрд╛рдлрд╝реА рдЕрдзрд┐рдХ рдХреЙрдореНрдкреИрдХреНрдЯ рд╣реИред add рдмрдЬрд╛рдп рдЕрдВрддрд┐рдо рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрдпреЛрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдБ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ: https://stackoverflow.com/a/6328441/1418863


рдпрджрд┐ рдЖрдк рдПрдХ рдФрд░ рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рддреЛ, рдЬреИрд╕реЗ рдХрд┐ double рд╕рд╛рде рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдХреЛрдб, рд╡реИрд╕реЗ, рд▓рдЧрднрдЧ рд╕рдорд╛рди рд╣реЛрдЧрд╛, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕реНрдЯреИрдХ рдкрд░ рд▓реЛрдб рдХрд░рдирд╛ xmm рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реЛрдЧрд╛ред


рдХреБрдЫ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред


 struct St { float a, b, c, d; }; St foo(St s1, St s2) { return {s1.a + s2.a, s1.b + s2.b, s1.c + s2.c, s1.d + s2.d}; } ... St s1{1, 2, 3, 4}, s2{5, 6, 7, 8}; auto result = foo(s1, s2); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
s1.axmm0s1.bxmm0xmm0, xmm1
s1.cxmm1s1.dxmm1
s2.axmm2s2.bxmm2
s2.cxmm3s2.dxmm3

рджреЛ float рдлрд╝реАрд▓реНрдб рдкреНрд░рддреНрдпреЗрдХ xmm рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдзрдХреЗрд▓ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред


 foo(St, St): # @foo(St, St) #   vaddps    float . vaddps xmm0, xmm0, xmm2 vaddps xmm1, xmm1, xmm3 ret .LCPI1_0: .long 1065353216 # float 1 .long 1073741824 # float 2 .zero 4 .zero 4 #   LCPI1_1 - LCPI1_3. ... main: # @main sub rsp, 24 #  ,      . vmovapd xmm0, xmmword ptr [rip + .LCPI1_0] # xmm0 = <1,2,u,u> vmovapd xmm1, xmmword ptr [rip + .LCPI1_1] # xmm1 = <3,4,u,u> vmovaps xmm2, xmmword ptr [rip + .LCPI1_2] # xmm2 = <5,6,u,u> vmovaps xmm3, xmmword ptr [rip + .LCPI1_3] # xmm3 = <7,8,u,u> call foo(St, St) #        ,         . xmm   256 ,    128    a  b,   - c  d. vunpcklpd xmm0, xmm0, xmm1 # xmm0 = xmm0[0],xmm1[0] vmovupd xmmword ptr [rsp + 8], xmm0 

рдпрджрд┐ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ 4 рдирд╣реАрдВ рдерд╛, рд▓реЗрдХрд┐рди рддреАрди рдлрд╝реАрд▓реНрдб рд╣реИрдВ, рддреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рд╕рдорд╛рди рд╣реЛрдЧрд╛, рд╕рд┐рд╡рд╛рдп рджреВрд╕рд░реЗ vaddps рдирд┐рд░реНрджреЗрд╢ рдХреЛ vaddss рд╕рд╛рде vaddss , рдЬреЛ рд░рдЬрд┐рд╕реНрдЯрд░ рдХреЗ рдкрд╣рд▓реЗ 64 рдмрд┐рдЯреНрд╕ рдХреЛ рдЬреЛрдбрд╝рддрд╛ рд╣реИред


 struct St { int32_t a, b, c, d; }; St foo(St s1, St s2) { return {s1.a + s2.a, s1.b + s2.b, s1.c + s2.c, s1.d + s2.d}; } ... St s1{1, 2, 3, 4}, s2{5, 6, 7, 8}; auto result = foo(s1, s2); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
s1.ardis1.brdirax, rdx
s1.crsis1.drsi
s2.ardxs2.brdx
s2.crcxs2.drcx

 foo(St, St): # @foo(St, St) lea eax, [rdx + rdi] movabs r8, -4294967296 # 0xFFFFFFFF00000000  . and rdi, r8 add rdi, rdx and rdi, r8 or rax, rdi lea edx, [rcx + rsi] #  ,   add. and rsi, r8 add rsi, rcx and rsi, r8 or rdx, rsi ret main: # @main sub rsp, 24 movabs rdi, 8589934593 #       . movabs rsi, 17179869187 movabs rdx, 25769803781 movabs rcx, 34359738375 call foo(St, St) mov qword ptr [rsp + 8], rax #    . mov qword ptr [rsp + 16], rdx 

рдмрд┐рдЯ рдореИрдЬрд┐рдХ рдлрдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд┐рджреНрдзрд╛рдВрдд рдмрд╣реБрдд рд╕реНрдкрд╖реНрдЯ рд╣реИред 32 рдмрд┐рдЯ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рдкреНрд░рддреНрдпреЗрдХ рдЬреЛрдбрд╝реА рдХреЛ рдПрдХ 64 рдмрд┐рдЯ рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдкреИрдХ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд░рд┐рдлрдВрдб рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЕрдЧрд░ рд╣рдо рдлреАрд▓реНрдб рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдорд┐рд▓рд╛рдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди 8 рдмрд╛рдЗрдЯ рд╡рд┐рдЦрдВрдбреВ рдореЗрдВ рд╡реЗ рдПрдХ рд╣реА рд╡рд░реНрдЧ рдХреЗ рд╣реЛрддреЗ рд╣реИрдВред


 struct St { int32_t a, b; float c, d; }; St foo(St s1, St s2) { return {s1.a + s2.a, s1.b + s2.b, s1.c + s2.c, s1.d + s2.d}; } ... St s1{1, 2, 3, 4}, s2{5, 6, 7, 8}; auto result = foo(s1, s2); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
s1.ardis1.brdirax, xmm0
s1.cxmm0s1.dxmm0
s2.arsis2.brsi
s2.cxmm1s2.dxmm1

 foo(St, St): # @foo(St, St) lea eax, [rsi + rdi] #     . movabs rcx, -4294967296 and rdi, rcx add rdi, rsi and rdi, rcx or rax, rdi vaddps xmm0, xmm0, xmm1 #    . ret .LCPI1_0: .long 1077936128 # float 3 .long 1082130432 # float 4 .zero 4 .zero 4 ... main: # @main sub rsp, 24 vmovaps xmm0, xmmword ptr [rip + .LCPI1_0] # xmm0 = <3,4,u,u> vmovaps xmm1, xmmword ptr [rip + .LCPI1_1] # xmm1 = <7,8,u,u> movabs rdi, 8589934593 movabs rsi, 25769803781 call foo(St, St) mov qword ptr [rsp + 8], rax #    . vmovlps qword ptr [rsp + 16], xmm0 

рд▓реЗрдХрд┐рди рдпрд╣ рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рддреНрдпреЗрдХ 8 рдмрд╛рдЗрдЯ рдЪрдВрдХ рдореЗрдВ рдЦреЗрддреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░ рд╕рдорд╛рди рд╣реИрдВред рдЦреЗрддреЛрдВ рдХреЛ рд╕рдореЗрдЯрдирд╛ред


 struct St { int32_t a; float b; int32_t c; float d; }; St foo(St s1, St s2) { return {s1.a + s2.a, s1.b + s2.b, s1.c + s2.c, s1.d + s2.d}; } ... St s1{1, 2, 3, 4}, s2{5, 6, 7, 8}; auto result = foo(s1, s2); 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
s1.ardis1.brdirax, rdx
s1.crsis1.drsi
s2.ardxs2.brdx
s2.crcxs2.drcx

рдкреИрд░рд╛рдЧреНрд░рд╛рдл 3.2 рджреЗрдЦреЗрдВред рдЪреВрдБрдХрд┐ 8-рдмрд╛рдЗрдЯ рд╡рд╛рд▓реЗ рдЪрдВрдХ рдореЗрдВ float рдФрд░ int рджреЛрдиреЛрдВ рд╣реЛрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдкреВрд░рд╛ рд╣рд┐рд╕реНрд╕рд╛ рдЗрдВрдЯреЗрдЧрд░ рдХрд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рдкрд╛рд╕ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред


 foo(St, St): # @foo(St, St) mov rax, rdx add edx, edi shr rdi, 32 vmovd xmm0, edi mov rdi, rcx add ecx, esi shr rsi, 32 vmovd xmm1, esi shr rax, 32 vmovd xmm2, eax vaddss xmm0, xmm0, xmm2 shr rdi, 32 vmovd xmm2, edi vaddss xmm1, xmm1, xmm2 vmovd eax, xmm0 shl rax, 32 or rdx, rax vmovd eax, xmm1 shl rax, 32 or rcx, rax mov rax, rdx mov rdx, rcx ret main: # @main sub rsp, 24 movabs rdi, 4611686018427387905 # 0x4000000000000001,   32   int,   - float. movabs rsi, 4647714815446351875 movabs rdx, 4665729213955833861 movabs rcx, 4683743612465315847 call foo(St, St) mov qword ptr [rsp + 8], rax #      64  . mov qword ptr [rsp + 16], rdx 

рдпрд╣рд╛рдВ рдЖрдк float рдлрд╝реАрд▓реНрдб рдирд┐рдХрд╛рд▓рдиреЗ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЗ рд╕рд╛рде рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рдзрдХреЗрд▓рдиреЗ рдХреЗ рд▓рд┐рдП 6 рд╢рд┐рдлреНрдЯ рдСрдкрд░реЗрд╢рди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рд╕рд╛рде рд╣реА рдХрд┐рд╕реА рднреА рд╡реЗрдХреНрдЯрд░ рдСрдкрд░реЗрд╢рди рдХреА рдЕрдиреБрдкрд╕реНрдерд┐рддрд┐ред рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╕рдВрд░рдЪрдирд╛ рдХреЗ 8 рдмрд╛рдЗрдЯ рд╡рд┐рдЦрдВрдбреВ рдХреЗ рднреАрддрд░ рдлреАрд▓реНрдб рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рд╣рд╕реНрддрдХреНрд╖реЗрдк рдирд╣реАрдВ рдХрд░рдирд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рд╣реИред


рд▓рд┐рдВрдХ рджреНрд╡рд╛рд░рд╛ рдкрд╛рд╕ рдХрд░реЗрдВ


рдПрдХ рдирд┐рд░рдВрддрд░ рд╕рдВрджрд░реНрдн рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдирд╛ рдПрдХ рд╕рдВрдХреЗрддрдХ рдХреЛ рдХрд┐рд╕реА рд╡рд╕реНрддреБ рдХреЛ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд╕рдорд╛рди рд╣реИред рдпрджрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЗрд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рд╣реЛрддрд╛ рд╣реИред рдпрдерд╛рд░реНрдерд╡рд╛рдж рдХреЗ рд▓рд┐рдП, рддреНрд░рд┐-рдЖрдпрд╛рдореА рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рд╕рдВрд░рдЪрдирд╛ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред


 struct Point3f { float x, y, z; }; struct Point3d { double x, y, z; }; Point3f scale(Point3f p) { return {px * 2, py * 2, pz * 2}; } Point3f scaleR(const Point3f& p) { return {px * 2, py * 2, pz * 2}; } Point3d scale(Point3d p) { return {px * 2, py * 2, pz * 2}; } Point3d scaleR(const Point3d& p) { return {px * 2, py * 2, pz * 2}; } 

рдлрд╝рдВрдХреНрд╢рди рдХреЛрдб рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВред рдЬреНрдпрд╛рджрд╛рддрд░ рдирдП xmm рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕рд▓рд┐рдП рддрд░реНрдХ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред


 scale(Point3f): # @scale(Point3f) #     , x, y   xmm0, z - xmm1,     . vaddps xmm0, xmm0, xmm0 vaddss xmm1, xmm1, xmm1 ret scaleR(Point3f const&): # @scaleR(Point3f const&) #       rdi,     .      xmm0, xmm1. vmovsd xmm0, qword ptr [rdi] # xmm0 = mem[0],zero vaddps xmm0, xmm0, xmm0 vmovss xmm1, dword ptr [rdi + 8] # xmm1 = mem[0],zero,zero,zero vaddss xmm1, xmm1, xmm1 ret scale(Point3d): # @scale(Point3d) #   rdi  ,     .          [rsp+8, rsp+32).  [rsp, rsp+8)     . vmovapd xmm0, xmmword ptr [rsp + 8] vaddpd xmm0, xmm0, xmm0 vmovupd xmmword ptr [rdi], xmm0 vmovsd xmm0, qword ptr [rsp + 24] # xmm0 = mem[0],zero vaddsd xmm0, xmm0, xmm0 vmovsd qword ptr [rdi + 16], xmm0 mov rax, rdi #  ,    . ret scaleR(Point3d const&): # @scaleR(Point3d const&) #   ,      [rsp+8, rsp+32),   [rsi, rsi+24). vmovupd xmm0, xmmword ptr [rsi] vaddpd xmm0, xmm0, xmm0 vmovupd xmmword ptr [rdi], xmm0 vmovsd xmm0, qword ptr [rsi + 16] # xmm0 = mem[0],zero vaddsd xmm0, xmm0, xmm0 vmovsd qword ptr [rdi + 16], xmm0 mov rax, rdi ret 

рдЕрдм рдЖрдЗрдП рдЙрд╕ рдЬрдЧрд╣ рдХреЛ рджреЗрдЦреЗрдВ рдЬрд╣рд╛рдВ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред


 # scale(Point3f) main: # @main sub rsp, 24 #     . vmovaps xmm0, xmmword ptr [rip + .LCPI4_0] # xmm0 = <1,2,u,u> vmovss xmm1, dword ptr [rip + .LCPI4_1] # xmm1 = <3,u,u,u> call scale(Point3f) # scaleR(const Point3f&) main: # @main sub rsp, 24 #         rdi,     . mov edi, .L_ZZ4mainE1p # <1,2,3,u> call scaleR(Point3f const&) # scale(Point3d) main: # @main sub rsp, 64 #        . mov rax, qword ptr [rip + .L_ZZ4mainE1p+16] mov qword ptr [rsp + 16], rax vmovups xmm0, xmmword ptr [rip + .L_ZZ4mainE1p] vmovups xmmword ptr [rsp], xmm0 lea rbx, [rsp + 40] mov rdi, rbx #     [rsp+40, rsp+64). call scale(Point3d) .L_ZZ4mainE1p: .quad 4607182418800017408 # double 1 .quad 4611686018427387904 # double 2 .quad 4613937818241073152 # double 3 # scaleR(const Point3d&) main: # @main sub rsp, 64 #   . mov rax, qword ptr [rip + .L_ZZ4mainE1p+16] mov qword ptr [rsp + 32], rax vmovups xmm0, xmmword ptr [rip + .L_ZZ4mainE1p] vmovaps xmmword ptr [rsp + 16], xmm0 lea rbx, [rsp + 40] lea rsi, [rsp + 16] #     [rsp+16, rsp+40). mov rdi, rbx #     [rsp+40, rsp+64). call scaleR(Point3d const&) 

рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрдИ рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рдВрд░рдЪрдирд╛ рдЕрднреА рднреА рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рдлрд┐рдЯ рдмреИрдарддреА рд╣реИред рдпрд╣рд╛рдВ рдорд╕реНрддреА рд╢реБрд░реВ рд╣реЛрддреА рд╣реИред


 struct St { char d[16]; }; St foo(St s1, St s2) { //   s1  s2. St res; for(int i{}; i < 16; ++i) res.d[i] = s1.d[i] + s2.d[i]; return res; } 

рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдХреЛрдб рдЬреЛ рдореВрд▓реНрдп рджреНрд╡рд╛рд░рд╛ рддрд░реНрдХ рд▓реЗрддрд╛ рд╣реИред


рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
s1.d [1: 8]rdis1.d [8:16]rsirax, rdx
s2.d [1: 8]rdxs2.d [8:16]rcx

 foo(St, St): # @foo(St, St) mov qword ptr [rsp - 16], rdi mov qword ptr [rsp - 8], rsi mov qword ptr [rsp - 32], rdx mov qword ptr [rsp - 24], rcx mov eax, edx add al, dil mov byte ptr [rsp - 48], al mov r8, rdi shr r8, 8 mov rax, rdx shr rax, 8 add al, r8b mov byte ptr [rsp - 47], al mov r8, rdi shr r8, 16 mov rax, rdx shr rax, 16 add al, r8b mov byte ptr [rsp - 46], al mov r8, rdi shr r8, 24 mov rax, rdx shr rax, 24 add al, r8b mov byte ptr [rsp - 45], al mov r8, rdi shr r8, 32 mov rax, rdx shr rax, 32 add al, r8b mov byte ptr [rsp - 44], al mov r8, rdi shr r8, 40 mov rax, rdx shr rax, 40 add al, r8b mov byte ptr [rsp - 43], al mov r8, rdi shr r8, 48 mov rax, rdx shr rax, 48 add al, r8b mov byte ptr [rsp - 42], al shr rdi, 56 shr rdx, 56 add dl, dil mov byte ptr [rsp - 41], dl mov eax, ecx add al, sil mov byte ptr [rsp - 40], al mov rax, rsi shr rax, 8 mov rdx, rcx shr rdx, 8 add dl, al mov byte ptr [rsp - 39], dl shr rsi, 16 shr rcx, 16 add cl, sil mov byte ptr [rsp - 38], cl mov al, byte ptr [rsp - 21] mov cl, byte ptr [rsp - 20] add al, byte ptr [rsp - 5] mov byte ptr [rsp - 37], al add cl, byte ptr [rsp - 4] mov byte ptr [rsp - 36], cl mov al, byte ptr [rsp - 19] mov cl, byte ptr [rsp - 18] add al, byte ptr [rsp - 3] mov byte ptr [rsp - 35], al add cl, byte ptr [rsp - 2] mov byte ptr [rsp - 34], cl mov al, byte ptr [rsp - 17] add al, byte ptr [rsp - 1] mov byte ptr [rsp - 33], al mov rax, qword ptr [rsp - 48] mov rdx, qword ptr [rsp - 40] ret 

рд╣рд╛рдВ, рдпрд╣рд╛рдВ рд╕рднреА рддрд░реНрдХреЛрдВ рдХреЛ рд╕реНрдЯреИрдХ рдкрд░ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдЗрд╕реЗ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдмрд╛рд░ рдореЗрдВ рдПрдХ рдмрд╛рдЗрдЯ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдмрд┐рд▓реНрдХреБрд▓ 16 рдирд┐рд░реНрджреЗрд╢ рд╣реИрдВред рдЬреАрд╕реАрд╕реА, рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдПрдХ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдХреЙрдореНрдкреИрдХреНрдЯ рдХреЛрдб рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирдХрд▓ рдХреЗ рд╕рд╛рдеред рдХреНрдпрд╛ рдХреБрдЫ рд╕реБрдзрд╛рд░рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ? рд╕рдВрджрд░реНрдн рджреНрд╡рд╛рд░рд╛ рд╕рдВрд░рдЪрдирд╛ рдкрд╛рд╕ рдХрд░реЗрдВред


 St fooR(const St& s1, const St& s2) { /*  . */ } 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
рдПрд╕ 1rdis2rsirax, rdx

 fooR(St const&, St const&): # @fooR(St const&, St const&) vmovdqu xmm0, xmmword ptr [rsi] vpaddb xmm0, xmm0, xmmword ptr [rdi] vmovdqa xmmword ptr [rsp - 24], xmm0 mov rax, qword ptr [rsp - 24] mov rdx, qword ptr [rsp - 16] ret 

рдЕрд░реЗ рд╣рд╛рдБ! рдпрд╣ рдмрд╣реБрдд рдмреЗрд╣рддрд░ рд▓рдЧ рд░рд╣рд╛ рд╣реИред рд╣рдо рдПрдХ рдмрд╛рд░ рдореЗрдВ 16 рдПрдХрд▓-рдмрд╛рдЗрдЯ рддрддреНрд╡реЛрдВ рдХреЛ xmm рд░рдЬрд┐рд╕реНрдЯрд░ рдореЗрдВ рд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ vpaddb рдХреЙрд▓ рдХрд░ vpaddb рдЬреЛ рдЙрди рд╕рднреА рдХреЛ рдПрдХ рдСрдкрд░реЗрд╢рди рдореЗрдВ vpaddb рджреЗрдЧрд╛ред рдЙрд╕рдХреЗ рдмрд╛рдж, рдкрд░рд┐рдгрд╛рдо рд╕реНрдЯреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрдЙрдЯрдкреБрдЯ рд░рдЬрд┐рд╕реНрдЯрд░реЛрдВ рдореЗрдВ рдХреЙрдкреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдкрд╣рд▓реЗ рддрд░реНрдХ рдХреЛ рдЧреИрд░-рдирд┐рд░рдВрддрд░ рд╕рдВрджрд░реНрдн рдХреЗ рд╕рд╛рде рдмрджрд▓рдХрд░ рдЖрдк рдЗрд╕ рдЕрдВрддрд┐рдо рдСрдкрд░реЗрд╢рди рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред


 void fooR1(St &s1, const St& s2) { for(int i{}; i < 16; ++i) s1.d[i] += s2.d[i]; } 

рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд╣рд▓рд╛ рдирд╛рдорд░рдЬрд┐рд╕реНрдЯрд░рдкрд░рд┐рдгрд╛рдо
рдПрд╕ 1rdis2rsi

 fooR1(St&, St const&): # @fooR1(St&, St const&) mov al, byte ptr [rsi] add byte ptr [rdi], al mov al, byte ptr [rsi + 1] add byte ptr [rdi + 1], al mov al, byte ptr [rsi + 2] add byte ptr [rdi + 2], al mov al, byte ptr [rsi + 3] add byte ptr [rdi + 3], al mov al, byte ptr [rsi + 4] add byte ptr [rdi + 4], al mov al, byte ptr [rsi + 5] add byte ptr [rdi + 5], al mov al, byte ptr [rsi + 6] add byte ptr [rdi + 6], al mov al, byte ptr [rsi + 7] add byte ptr [rdi + 7], al mov al, byte ptr [rsi + 8] add byte ptr [rdi + 8], al mov al, byte ptr [rsi + 9] add byte ptr [rdi + 9], al mov al, byte ptr [rsi + 10] add byte ptr [rdi + 10], al mov al, byte ptr [rsi + 11] add byte ptr [rdi + 11], al mov al, byte ptr [rsi + 12] add byte ptr [rdi + 12], al mov al, byte ptr [rsi + 13] add byte ptr [rdi + 13], al mov al, byte ptr [rsi + 14] add byte ptr [rdi + 14], al mov al, byte ptr [rsi + 15] add byte ptr [rdi + 15], al ret 

рд▓рдЧрддрд╛ рд╣реИ рдХреБрдЫ рдЧрдбрд╝рдмрдбрд╝ рд╣реЛ рдЧрдИ рд╣реИред рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реБрдЖ, рдХреНрдпреЛрдВрдХрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдХрдВрдкрд╛рдЗрд▓рд░ рдмрд╣реБрдд рд╕рд╛рд╡рдзрд╛рди рд╣реИ, рдФрд░ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реИ рдХрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдЖрдЙрдЯ рдСрдл рд╕реЙрд░реНрдЯ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдФрд░ рдРрд╕рд╛ рдХреБрдЫ рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:


 char buff[17]; fooR1(*reinterpret_cast<St*>(buff+1), reinterpret_cast<const St*>(buff)); 

рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, buff[i+1] += buff[i] рдЧрдгрдирд╛ рдкреНрд░рддреНрдпреЗрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░ рдХреА рдЬрд╛рддреА рд╣реИ, рдпрд╛рдиреА рдкреЙрдЗрдВрдЯрд░ рдЕрд▓рд┐рдпрд╛рд╕рд┐рдВрдЧ рдЙрдкрд▓рдмреНрдз рд╣реИред , , , __restrict .


 void fooR2(St & __restrict s1, const St& s2) { /*  . */ } 

.


 fooR2(St&, St const&): # @fooR2(St&, St const&) vmovdqu xmm0, xmmword ptr [rdi] vpaddb xmm0, xmm0, xmmword ptr [rsi] vmovdqu xmmword ptr [rdi], xmm0 ret 

void fooR3(St &__restrict s1, St s2) , , St foo(St, St) .


, , void foo(char* __restrict s1, const char* s2, int size) , __restrict .



b a , , foo :


 St a, b; st(a, b); // st(St& a, St& b) { a = b = {}; }   . a = foo(a, b); a = foo(a, b); a = foo(a, b); a = foo(a, b); 

CodeCycles per iteration
St a, b; st(a, b);7.6
4 x foo no reuse121.9
4 x foo117.7
4 x fooR no reuse66.3
4 x fooR64.6
4 x fooR184.5
4 x fooR220.6
4 x foo inline51.9
4 x fooR inline30.5
4 x fooR1 inline8.8
4 x fooR2 inline8.8

'no reuse' , . auto a2 = foo(a, b); auto a3 = foo(a2, b); ред 'inline' , INLINE , NOINLINE .


fooR1 inline / fooR2 inline , , , , , foo inline / fooR inline , . , , .



, , .


 struct Point3f { float x, y, z; ~Point3f() {} }; Point3f scale(Point3f p) { return {px * 2, py * 2, pz * 2}; } 

rdi , . , rsi , .


 scale(Point3f): # @scale(Point3f) vmovss xmm0, dword ptr [rsi] # xmm0 = mem[0],zero,zero,zero vaddss xmm0, xmm0, xmm0 vmovss dword ptr [rdi], xmm0 vmovss xmm0, dword ptr [rsi + 4] # xmm0 = mem[0],zero,zero,zero vaddss xmm0, xmm0, xmm0 vmovss dword ptr [rdi + 4], xmm0 vmovss xmm0, dword ptr [rsi + 8] # xmm0 = mem[0],zero,zero,zero vaddss xmm0, xmm0, xmm0 vmovss dword ptr [rdi + 8], xmm0 mov rax, rdi ret 

, , ( ) . POD . Point3f scaleR(const Point3f&) . .


 Point3f p{1, 2, 3}; auto result = scale(p); sink(&result); 

 main: # @main push rbx sub rsp, 48 movabs rax, 4611686019492741120 #    . mov qword ptr [rsp + 16], rax mov dword ptr [rsp + 24], 1077936128 lea rbx, [rsp + 32] lea rsi, [rsp + 16] #    [rsp+16, rsp+28) mov rdi, rbx #    [rsp+32, rsp+44) call scale(Point3f) mov qword ptr [rsp + 8], rbx #  [rsp+8, rsp+16)    . lea rdi, [rsp + 8] call void sink<Point3f*>(Point3f* const&) xor eax, eax add rsp, 48 pop rbx ret #  . mov rdi, rax call _Unwind_Resume 

NOINLINE , .


 main: # @main push r14 push rbx sub rsp, 56 movabs rax, 4611686019492741120 #    [rsp, rsp+12).   p. mov qword ptr [rsp], rax mov dword ptr [rsp + 8], 1077936128 #    [rsp+24, rsp+36),    pTmp. mov eax, dword ptr [rsp + 8] mov dword ptr [rsp + 32], eax mov rax, qword ptr [rsp] mov qword ptr [rsp + 24], rax lea r14, [rsp + 40] lea rbx, [rsp + 24] mov rdi, r14 #    [rsp+40, rsp+52),  result. mov rsi, rbx #   -   pTmp. call scale(Point3f) mov rdi, rbx #    pTmp.    -  this. call Point3f::~Point3f() mov qword ptr [rsp + 16], r14 #  [rsp+16, rsp+24)     result.     sink. lea rdi, [rsp + 16] call void sink<Point3f*>(Point3f* const&) lea rdi, [rsp + 40] #    result. call Point3f::~Point3f() mov rdi, rsp #    p. call Point3f::~Point3f() xor eax, eax add rsp, 56 pop rbx pop r14 ret #  .           . mov rbx, rax lea rdi, [rsp + 40] #    result. call Point3f::~Point3f() mov rdi, rsp #    p. call Point3f::~Point3f() mov rdi, rbx call _Unwind_Resume 

p , .



, . .


 # Point3f result = scale(scale(Point3f{1, 2, 3})); sub rsp, 24 vmovaps xmm0, xmmword ptr [rip + .LCPI4_0] # xmm0 = <1,2,u,u> vmovss xmm1, dword ptr [rip + .LCPI4_1] # xmm1 = mem[0],zero,zero,zero #    xmm0, xmm1    ,    ,       ! call scale(Point3f) call scale(Point3f) vmovlps qword ptr [rsp + 8], xmm0 vmovss dword ptr [rsp + 16], xmm1 # Point3f result = scaleR(scaleR(Point3f{1, 2, 3})); sub rsp, 56 #       [rsp+24, rsp+36). movabs rax, 4611686019492741120 # 0x400000003F800000 = [2.0f, 1.0f] mov qword ptr [rsp + 24], rax mov dword ptr [rsp + 32], 1077936128 # 0x40400000 = 3.0f lea rdi, [rsp + 24] #      . call scaleR(Point3f const&) #    [rsp+8, rsp+20). vmovlps qword ptr [rsp + 8], xmm0 vmovss dword ptr [rsp + 16], xmm1 lea rdi, [rsp + 8] #       . call scaleR(Point3f const&) vmovlps qword ptr [rsp + 40], xmm0 vmovss dword ptr [rsp + 48], xmm1 

, , . , .


 # Point3d result = scale(scale(Point3d{1, 2, 3})); sub rsp, 112 #    [rsp, rsp+24). vmovaps xmm0, xmmword ptr [rip + .LCPI4_0] # xmm0 = [1.000000e+00,2.000000e+00] vmovaps xmmword ptr [rsp + 32], xmm0 movabs rax, 4613937818241073152 # 0x4008000000000000 = 3.0 mov qword ptr [rsp + 48], rax mov rax, qword ptr [rsp + 48] mov qword ptr [rsp + 16], rax vmovaps xmm0, xmmword ptr [rsp + 32] vmovups xmmword ptr [rsp], xmm0 #    [rsp+64, rsp+88). lea rdi, [rsp + 64] #  rdi     . call scale(Point3d) #        [rsp, rsp+24). mov rax, qword ptr [rsp + 80] #  z   z . mov qword ptr [rsp + 16], rax vmovups xmm0, xmmword ptr [rsp + 64] #  [x, y]   [x, y] . vmovups xmmword ptr [rsp], xmm0 #    [rsp+88, rsp+112). lea rbx, [rsp + 88] mov rdi, rbx call scale(Point3d) # Point3d result = scaleR(scaleR(Point3d{1, 2, 3})); sub rsp, 72 #    [rsp, rsp+24),   . vmovaps xmm0, xmmword ptr [rip + .LCPI4_0] vmovaps xmmword ptr [rsp], xmm0 movabs rax, 4613937818241073152 mov qword ptr [rsp + 16], rax lea r14, [rsp + 24] mov rsi, rsp #   -       [rsp, rsp+24). mov rdi, r14 #   -      [rsp+24, rsp+48). call scaleR(Point3d const&) lea rbx, [rsp + 48] mov rdi, rbx #      [rsp+48, rsp+72). mov rsi, r14 #       [rsp+24, rsp+48). call scaleR(Point3d const&) 

, , , , . тАУ . . , , .



, . , . , , Point3f , Point3d тАУ .


 //   data.cpp.  . Point3f pf() { return {1, 2, 3}; } Point3d pd() { return {1, 2, 3}; } 

CodeCycles per iteration
auto r = pf();6.7
auto r = scale(pf());11.1
auto r = scaleR(pf());12.6
auto r = scale(scale(pf()));18.2
auto r = scaleR(scaleR(pf()));18.3
auto r = scale(scale(scale(pf())));16.8
auto r = scaleR(scaleR(scaleR(pf())));20.2
auto r = pd();7.3
auto r = scale(pd());11.7
auto r = scaleR(pd());11.0
auto r = scale(scale(pd()));16.9
auto r = scaleR(scaleR(pd()));14.1
auto r = scale(scale(scale(pd())));21.2
auto r = scaleR(scaleR(scaleR(pd())));17.2
INLINE8.1 тАФ 8.9

Point3f struct Point3i { int32_t x, y, z; }; Point3d struct Point3ll { int64_t x, y, z; }; , . , , , 64 int, . , Point3f struct Point2ll { int64_t x, y; }; Point3d struct Point4ll { int64_t x, y, z, a; }; , -.


:


  • . .
  • , , .
  • inline , . , , , . .

optional


std::optional , boost::optional , , "x86-64 clang (experimental concepts)" , , MSVC ,


 struct Point { float x, y; }; using OptPoint1 = optional<Point>; 


 struct OptPoint2 { float x, y; union { char _; bool d; }; //   std::optional. }; 

, OptPoint1 , OptPoint2 тАУ .


 OptPoint1 foo(OptPoint1 s) { return Point{s->x + 1, s->y + 1}; } OptPoint2 foo(OptPoint2 s) { return {sx + 1, sy + 1, true}; } ... OptPoint1 s1{Point{1, 2}}; OptPoint2 s2{3, 4, true}; auto result1 = foo(s1); auto result2 = foo(s2); 

 .LCPI0_0: .long 1065353216 # float 1 foo(std::optional<Point>): # @foo(std::optional<Point>) vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero #  rsi       . vaddss xmm1, xmm0, dword ptr [rsi] #  x  ,  1. vaddss xmm0, xmm0, dword ptr [rsi + 4] #  y  ,  1. vmovss dword ptr [rdi], xmm1 #  x  , rdi      ,     . vmovss dword ptr [rdi + 4], xmm0 #  y  . mov byte ptr [rdi + 8], 1 #  optional::has_value(). mov rax, rdi #    . ret .LCPI1_0: .long 1065353216 # float 1 .long 1065353216 # float 1 .zero 4 .zero 4 foo(OptPoint2): # @foo(OptPoint2) vaddps xmm0, xmm0, xmmword ptr [rip + .LCPI1_0] #  [x, y] c [1, 1].  xmm0  . mov al, 1 #  d, al -   8   rax. ret .LCPI2_0: .long 1077936128 # float 3 .long 1082130432 # float 4 .zero 4 .zero 4 main: # @main push rbx sub rsp, 64 movabs rax, 4611686019492741120 # 0x400000003F800000  x  y. mov qword ptr [rsp + 32], rax #  x, y  . mov byte ptr [rsp + 40], 1 #  optional::has_value(). lea rbx, [rsp + 48] lea rsi, [rsp + 32] #    . mov rdi, rbx #    . call foo(std::optional<Point>) #     . vmovaps xmm0, xmmword ptr [rip + .LCPI2_0] # xmm0 = <3,4,u,u> mov edi, 1 #  bool d. call foo(OptPoint2) vmovlps qword ptr [rsp + 16], xmm0 #    . mov byte ptr [rsp + 24], al #  al      rax. 

, foo inline , .


  # OptPoint1 foo(OptPoint1)  OptPoint1 foo(const OptPoint1&) vmovss xmm0, dword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero,zero,zero vaddss xmm1, xmm0, dword ptr [rsp + 32] vaddss xmm0, xmm0, dword ptr [rsp + 36] vmovss dword ptr [rsp + 8], xmm1 vmovss dword ptr [rsp + 12], xmm0 mov byte ptr [rsp + 16], 1 # OptPoint2 foo(OptPoint2)  OptPoint2 foo(const OptPoint2&) vmovsd xmm0, qword ptr [rsp + 48] # xmm0 = mem[0],zero vaddps xmm0, xmm0, xmmword ptr [rip + .LCPI0_1] vmovlps qword ptr [rsp + 8], xmm0 mov byte ptr [rsp + 16], 1 

, , , .


: inline , std::optional .



, , . . , . , - , , , . .


 struct Fn { virtual ~Fn() noexcept = default; virtual int call(int x) const = 0; }; struct Add final : Fn { Add(int a) : a(a) {} int call(int x) const override { return a + x; } int a; }; NOINLINE bool isFixedPoint(const Fn& fn, int x) { return fn.call(x) == x; } int main() { Add add{32}; bool result = isFixedPoint(add, 10); } 

- .


 Add::call(int) const: # @Add::call(int) const #  rdi   this  ,   [rdi, rdi+8)      ,       . add esi, dword ptr [rdi + 8] mov eax, esi #    rax, eax     32 . ret #      Add.       16,   RTTI    . vtable for Add: .quad 0 .quad typeinfo for Add #   RTTI.  -8. .quad Fn::~Fn() # ,  0    . .quad Add::~Add() .quad Add::call(int) const # ,  16 . isFixedPoint(Fn const&, int): # @isFixedPoint(Fn const&, int) push rbx #         rbx,    ,    . mov ebx, esi #  32   . mov rax, qword ptr [rdi] #  rdi    -   Fn,         this . call qword ptr [rax + 16] #  Add::call. cmp eax, ebx #   call    rax,    ebx,      . sete al #     8   eax. pop rbx #   rbx. ret main: # @main sub rsp, 40 mov qword ptr [rsp + 24], vtable for Add+16 #          Add,    16  ,    , ,  .    RTTI    . mov dword ptr [rsp + 32], 32 #  add.a   . lea rdi, [rsp + 24] #      . mov esi, 10 #   . call isFixedPoint(Fn const&, int) mov byte ptr [rsp + 15], al #    . ... mov rdi, rax #  . call _Unwind_Resume mov rdi, rax call _Unwind_Resume 

protected , ( 34-37). NOINLINE , ( false ). NOINLINE , . .


 struct Add final { Add(int a) : a(a) {} NOINLINE int call(int x) const { return a + x; } int a; }; template<typename T> NOINLINE bool isFixedPoint(const T& fn, int x) { return fn.call(x) == x; } 

 Add::call(int) const: # @Add::call(int) const add esi, dword ptr [rdi] #    , this   rdi  ,        ,      . mov eax, esi ret bool isFixedPoint<Add>(Add const&, int): # @bool isFixedPoint<Add>(Add const&, int) push rbx mov ebx, esi # Add::call         ,   isFixedPoint. call Add::call(int) const cmp eax, ebx sete al pop rbx ret main: # @main sub rsp, 24 mov dword ptr [rsp + 8], 32 #  add.a. lea rdi, [rsp + 8] #    ,  rdi    add.a. mov esi, 10 call bool isFixedPoint<Add>(Add const&, int) mov byte ptr [rsp + 7], al ... ret 

, NOINLINE .



1000 Add isFixedPoint .


CodeCycles per iteration
call , isFixedPoint call5267
call , NOINLINE isFixedPoint10721
call , INLINE isFixedPoint8291
call , NOINLINE isFixedPoint10571
, NOINLINE call , NOINLINE isFixedPoint10536
, isFixedPoint call4505
, INLINE call , INLINE isFixedPoint4531

:


  • .
  • , .
  • , , , inline. .
  • inline . inline - cpp , NOINLINE .
  • inline .


call , jmp .


. clang . , :


 double exp_by_squaring(double x, int n, double y = 1) { if (n < 0) return exp_by_squaring(1.0 / x, -n, y); if (n == 0) return y; if (n == 1) return x * y; if (n % 2 == 0) return exp_by_squaring(x * x, n / 2, y); return exp_by_squaring(x * x, (n - 1) / 2, x * y); } 

рд╣рдореЗрдВ рдорд┐рд▓рддрд╛ рд╣реИ:


 .LCPI0_0: .quad 4607182418800017408 # double 1 exp_by_squaring(double, int, double): # @exp_by_squaring(double, int, double) vmovsd xmm2, qword ptr [rip + .LCPI0_0] # xmm2 = mem[0],zero vmovapd xmm3, xmm0 test edi, edi jns .LBB0_4 jmp .LBB0_3 .LBB0_9: # in Loop: Header=BB0_4 Depth=1 shr edi vmovapd xmm3, xmm0 test edi, edi jns .LBB0_4 .LBB0_3: # =>This Inner Loop Header: Depth=1 vdivsd xmm3, xmm2, xmm3 neg edi test edi, edi js .LBB0_3 .LBB0_4: # =>This Inner Loop Header: Depth=1 je .LBB0_7 cmp edi, 1 je .LBB0_6 vmulsd xmm0, xmm3, xmm3 test dil, 1 je .LBB0_9 lea eax, [rdi - 1] shr eax, 31 lea edi, [rdi + rax] add edi, -1 sar edi vmulsd xmm1, xmm3, xmm1 vmovapd xmm3, xmm0 test edi, edi jns .LBB0_4 jmp .LBB0_3 .LBB0_6: vmulsd xmm1, xmm3, xmm1 .LBB0_7: vmovapd xmm0, xmm1 ret 

, , . , , . ~10% .


. .


 int64_t sum(int64_t x, int64_t y) { return x + y; } int64_t add1(int64_t x) { return sum(x, 1); } int64_t add2(int64_t x) { return sum(1, x); } int64_t add3(int64_t x) { return sum(-1, x) + 2; } 

 sum(long, long): # @sum(long, long) lea rax, [rdi + rsi] ret add1(long): # @add1(long) mov esi, 1 #   . jmp sum(long, long) # TAILCALL add2(long): # @add2(long) mov rax, rdi #   . mov edi, 1 mov rsi, rax jmp sum(long, long) # TAILCALL add3(long): # @add3(long) push rax #  rax   . mov rax, rdi #  ,    add2,  . mov rdi, -1 mov rsi, rax call sum(long, long) add rax, 2 #  2    . pop rcx ret 

, , call , jmp . , , sum , , add .


, 10%.


:


  • , .
  • .


. 2D :


 struct Point { double x, y; }; struct ZeroPoint { double x{}, y{}; }; struct NanPoint { double x{quietNaN}, y{quietNaN}; }; 

Point . ZeroPoint . IEEE 754-1985:


The number zero is represented specially: sign = 0 for positive zero, 1 for negative zero; biased exponent = 0; fraction = 0;

memset . NanPoint numeric_limits<double>::quiet_NaN(); , .



 Point data; 

  sub rsp, 24 

- .


 ZeroPoint data; Point data{}; 

.


  sub rsp, 40 vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp + 16], xmm0 

. xmm0 . XOR vxorps . .


 NanPoint data; 

  sub rsp, 40 vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] vmovaps xmmword ptr [rsp + 16], xmm0 

, .



:


 static constexpr size_t smallSize = 8; static constexpr size_t bigSize = 321; extern size_t smallUnknownSize; // Also 8 extern size_t bigUnknownSize; // Also 321 

.


 array<Point, smallSize> data; 

тАУ .


  sub rsp, 136 

, .


 array<ZeroPoint, smallSize> data; array<ZeroPoint, smallSize> data{}; array<Point, smallSize> data{}; 

.


  sub rsp, 192 vxorps ymm0, ymm0, ymm0 vmovaps ymmword ptr [rsp + 128], ymm0 vmovaps ymmword ptr [rsp + 96], ymm0 vmovaps ymmword ptr [rsp + 64], ymm0 vmovaps ymmword ptr [rsp + 32], ymm0 

256 , 2 .


 array<NanPoint, smallSize> data; array<NanPoint, smallSize> data{}; 

  sub rsp, 136 vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] vmovups xmmword ptr [rsp + 24], xmm0 vmovups xmmword ptr [rsp + 8], xmm0 vmovups xmmword ptr [rsp + 56], xmm0 vmovups xmmword ptr [rsp + 40], xmm0 vmovups xmmword ptr [rsp + 88], xmm0 vmovups xmmword ptr [rsp + 72], xmm0 vmovups xmmword ptr [rsp + 120], xmm0 vmovups xmmword ptr [rsp + 104], xmm0 

.



 array<Point, bigSize> data; 

  sub rsp, 5144 

.


 array<ZeroPoint, bigSize> data; array<ZeroPoint, bigSize> data{}; array<Point, bigSize> data{}; 

  sub rsp, 5152 lea rbx, [rsp + 16] xor esi, esi mov edx, 5136 mov rdi, rbx call memset #  memset(rsp+16, 0, 5136). 

, memset . , , rdi, esi, edx . e d 32 64- .


 array<NanPoint, bigSize> data; 

  sub rsp, 5144 lea rax, [rsp + 8] lea rcx, [rsp + 5144] vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] #  . .LBB0_1: # =>This Inner Loop Header: Depth=1 vmovups xmmword ptr [rax], xmm0 vmovups xmmword ptr [rax + 16], xmm0 vmovups xmmword ptr [rax + 32], xmm0 add rax, 48 cmp rax, rcx jne .LBB0_1 

. , 321 3 . rax, rcx .


 array<NanPoint, bigSize> data{}; 

  sub rsp, 5152 lea rbx, [rsp + 16] xor esi, esi mov edx, 5136 mov rdi, rbx call memset #  memset(rsp+16, 0, 5136). lea rax, [rsp + 5152] vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] #  . .LBB0_1: # =>This Inner Loop Header: Depth=1 vmovups xmmword ptr [rbx], xmm0 vmovups xmmword ptr [rbx + 16], xmm0 vmovups xmmword ptr [rbx + 32], xmm0 add rbx, 48 cmp rbx, rax jne .LBB0_1 

. , memset . , , . .



 vector<Point> data(smallSize); 

  sub rsp, 40 vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 mov edi, 128 call operator new(unsigned long) #  new(128). mov qword ptr [rsp], rax mov rcx, rax sub rcx, -128 mov qword ptr [rsp + 16], rcx vxorps xmm0, xmm0, xmm0 #     . vmovups xmmword ptr [rax + 16], xmm0 vmovups xmmword ptr [rax], xmm0 vmovups xmmword ptr [rax + 32], xmm0 vmovups xmmword ptr [rax + 48], xmm0 vmovups xmmword ptr [rax + 64], xmm0 vmovups xmmword ptr [rax + 80], xmm0 vmovups xmmword ptr [rax + 96], xmm0 vmovups xmmword ptr [rax + 112], xmm0 

new . , T{} , , . ZeroPoint NanPoint . :


 vector<Point> data(bigSize); 

 main: # @main push rbx sub rsp, 48 vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 mov edi, 5136 call operator new(unsigned long) #  new(5136). mov qword ptr [rsp], rax mov qword ptr [rsp + 8], rax mov rcx, rax add rcx, 5136 mov qword ptr [rsp + 16], rcx vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp + 32], xmm0 xor edx, edx #    . .LBB0_2: # =>This Inner Loop Header: Depth=1 vmovaps xmm0, xmmword ptr [rsp + 32] vmovups xmmword ptr [rax + rdx], xmm0 vmovaps xmm0, xmmword ptr [rsp + 32] vmovups xmmword ptr [rax + rdx + 16], xmm0 vmovaps xmm0, xmmword ptr [rsp + 32] vmovups xmmword ptr [rax + rdx + 32], xmm0 add rdx, 48 cmp rdx, 5136 jne .LBB0_2 mov qword ptr [rsp + 8], rcx mov rax, rsp 

, . NanPoint .


 vector<NanPoint> data(bigSize); 

 main: # @main push rbx sub rsp, 32 vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 mov edi, 5136 call operator new(unsigned long) #  new(5136). mov qword ptr [rsp], rax mov qword ptr [rsp + 8], rax mov rcx, rax add rcx, 5136 mov qword ptr [rsp + 16], rcx xor edx, edx vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] #    NAN. .LBB0_2: # =>This Inner Loop Header: Depth=1 vmovups xmmword ptr [rax + rdx], xmm0 vmovups xmmword ptr [rax + rdx + 16], xmm0 vmovups xmmword ptr [rax + rdx + 32], xmm0 add rdx, 48 cmp rdx, 5136 jne .LBB0_2 mov qword ptr [rsp + 8], rcx mov rax, rsp 

A ZeroPoint .


 vector<ZeroPoint> data(bigSize); 

  sub rsp, 32 vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 mov edi, 5136 call operator new(unsigned long) #  new(5136). mov qword ptr [rsp], rax mov rbx, rax add rbx, 5136 mov qword ptr [rsp + 16], rbx xor esi, esi mov edx, 5136 mov rdi, rax call memset #  memset(&data, 0, 5136). 

memset . , , memset Point . , , bigUnknownSize .


 vector<NanPoint> data(bigUnknownSize); 

  sub rsp, 32 mov rbx, qword ptr [rip + bigUnknownSize] vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 test rbx, rbx #  bigUnknownSize == 0,   new. je .LBB0_1 mov rax, rbx shr rax, 60 jne .LBB0_3 mov rdi, rbx shl rdi, 4 #   16    4. call operator new(unsigned long) #  new(bigUnknownSize*16). jmp .LBB0_6 .LBB0_1: xor eax, eax .LBB0_6: mov rcx, rbx shl rcx, 4 add rcx, rax mov qword ptr [rsp], rax mov qword ptr [rsp + 8], rax mov qword ptr [rsp + 16], rcx test rbx, rbx #  bigUnknownSize == 0,   . je .LBB0_14 lea rdx, [rbx - 1] mov rsi, rbx and rsi, 7 je .LBB0_10 neg rsi vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] #   0-7 . .LBB0_9: # =>This Inner Loop Header: Depth=1 vmovups xmmword ptr [rax], xmm0 dec rbx add rax, 16 inc rsi jne .LBB0_9 .LBB0_10: cmp rdx, 7 jb .LBB0_13 vmovaps xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = [nan,nan] #      8. .LBB0_12: # =>This Inner Loop Header: Depth=1 vmovups xmmword ptr [rax], xmm0 vmovups xmmword ptr [rax + 16], xmm0 vmovups xmmword ptr [rax + 32], xmm0 vmovups xmmword ptr [rax + 48], xmm0 vmovups xmmword ptr [rax + 64], xmm0 vmovups xmmword ptr [rax + 80], xmm0 vmovups xmmword ptr [rax + 96], xmm0 vmovups xmmword ptr [rax + 112], xmm0 sub rax, -128 add rbx, -8 jne .LBB0_12 .LBB0_13: mov rax, rcx .LBB0_14: mov qword ptr [rsp + 8], rax mov rax, rsp 

. , LBB0_9 , 8. 8 .


, Point , ZeroPoint memset :


 vector<ZeroPoint> data(bigUnknownSize); 

  sub rsp, 40 mov rbx, qword ptr [rip + bigUnknownSize] vxorps xmm0, xmm0, xmm0 vmovaps xmmword ptr [rsp], xmm0 mov qword ptr [rsp + 16], 0 test rbx, rbx #  bigUnknownSize == 0,   new. je .LBB0_1 mov rax, rbx shr rax, 60 jne .LBB0_3 mov rdi, rbx shl rdi, 4 call operator new(unsigned long) #  new(bigUnknownSize*16). jmp .LBB0_6 .LBB0_1: xor eax, eax .LBB0_6: mov rdx, rbx shl rdx, 4 lea r14, [rax + rdx] mov qword ptr [rsp], rax mov qword ptr [rsp + 8], rax mov qword ptr [rsp + 16], r14 test rbx, rbx #  bigUnknownSize == 0,   memset. je .LBB0_8 xor esi, esi mov rdi, rax call memset #  memset(&data, 0, bigUnknownSize*16). mov rax, r14 .LBB0_8: mov qword ptr [rsp + 8], rax mov rax, rsp 

,


 vector<NanPoint> data; data.resize(bigUnknownSize); 

250 , . operator new , .



.


CodeCycles per iteration
Point p;4.5
ZeroPoint p;5.2
NanPoint p;4.5
array<Point, smallSize> p;4.5
array<ZeroPoint, smallSize> p;6.7
array<NanPoint, smallSize> p;6.7
array<Point, bigSize> p;4.5
array<ZeroPoint, bigSize> p;296.0
array<NanPoint, bigSize> p;391.0
array<Point, bigSize> p{};292.0
array<NanPoint, bigSize> p{};657.0
vector<Point> p(smallSize);32.3
vector<ZeroPoint> p(smallSize);33.8
vector<NanPoint> p(smallSize);33.8
vector<Point> p(bigSize);323.0
vector<ZeroPoint> p(bigSize);308.0
vector<NanPoint> p(bigSize);281.0
vector<ZeroPoint> p(smallUnknownSize);44.1
vector<NanPoint> p(smallUnknownSize);37.6
vector<Point> p(bigUnknownSize);311.0
vector<ZeroPoint> p(bigUnknownSize);315.0
vector<NanPoint> p(bigUnknownSize);290.0
vector<NanPoint> p; p.resize(bigUnknownSize);315.0

:


  • .
  • .
  • memset , .
  • .
  • , . .
  • . .
  • , . .

Source: https://habr.com/ru/post/hi414443/


All Articles