Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch > #118579 > unrolled thread

Performance of xchg reg,reg

Started byanton@mips.complang.tuwien.ac.at (Anton Ertl)
First post2026-10-13 08:43 +0000
Last post2026-10-20 16:45 +0000
Articles 20 on this page of 81 — 18 participants

Back to article view | Back to comp.arch


Contents

  Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-13 08:43 +0000
    Re: Performance of xchg reg,reg Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-14 00:23 +0000
      Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-14 07:00 +0000
        Re: Performance of xchg reg,reg MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-14 22:35 +0000
          Re: Performance of xchg reg,reg Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-14 23:07 +0000
          Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-15 06:05 +0000
            Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-15 07:06 +0000
              Re: Performance of xchg reg,reg EricP <ThatWouldBeTelling@thevillage.com> - 2026-10-16 09:47 -0400
                Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-16 16:04 +0000
                Re: Performance of xchg reg,reg Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-17 05:46 +0000
    Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-14 22:29 +0300
    Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-15 14:21 -0700
      Re: Performance of xchg reg,reg Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-15 21:42 +0000
        Re: Performance of xchg reg,reg Terje Mathisen <terje.mathisen@tmsw.no> - 2026-10-16 14:45 +0200
      Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-16 05:50 +0000
        Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-16 11:34 +0300
          Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-16 18:23 +0000
            Re: Performance of xchg reg,reg scott@slp53.sl.home (Scott Lurndal) - 2026-10-16 20:48 +0000
              Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-16 14:28 -0700
              Re: Performance of xchg reg,reg Thomas Koenig <tkoenig@netcologne.de> - 2026-10-17 09:48 +0000
            Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-17 02:50 +0000
              Re: Performance of xchg reg,reg MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-17 17:11 +0000
                Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-17 17:31 +0000
                  Re: Performance of xchg reg,reg MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-17 19:39 +0000
                    Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-17 23:20 +0300
                    Re: Documentation (was Re: Performance of xchg reg,reg) Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-17 20:54 +0000
                      Re: Documentation (was Re: Performance of xchg reg,reg) George Neuner <gneuner2@comcast.net> - 2026-10-18 09:45 -0400
                        Algol 68 (was: Documentation (was Re: Performance of xchg reg,reg)) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-18 14:08 +0000
                          Re: Algol 68 (was: Documentation (was Re: Performance of xchg reg,reg)) quadibloc@invalid.com (John Savard) - 2026-10-19 00:09 +0000
                            Re: Algol 68 (was Re: Documentation) Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-19 01:46 +0000
                              Re: Algol 68 (was Re: Documentation) quadibloc@invalid.com (John Savard) - 2026-10-21 14:15 +0000
                                Re: Algol 68 (was Re: Documentation) Niklas Holsti <niklas.holsti@tidorum.invalid> - 2026-10-21 18:34 +0300
                                  Re: Algol 68 (was Re: Documentation) quadibloc@invalid.com (John Savard) - 2026-10-21 19:38 +0000
                                    Re: Algol 68 (was Re: Documentation) aph@littlepinkcloud.invalid - 2026-10-22 09:51 +0000
                                    Re: Algol 68 (was Re: Documentation) Stephen Fuld <sfuld@alumni.cmu.edu.invalid> - 2026-10-22 14:15 -0700
                                      Re: Algol 68 (was Re: Documentation) scott@slp53.sl.home (Scott Lurndal) - 2026-10-23 14:08 +0000
                          Re: PL/I, was Algol 68 (was: Documentation (was Re: Performance of xchg reg,reg)) John Levine <johnl@taugh.com> - 2026-10-19 03:24 +0000
                            Re: PL/I, was Algol 68 (was: Documentation (was Re: Performance of xchg reg,reg)) anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-19 05:34 +0000
                          Re: Algol 68 Stefan Monnier <monnier@iro.umontreal.ca> - 2026-10-18 23:34 -0400
                        Re: Documentation (was Re: Performance of xchg reg,reg) quadibloc@invalid.com (John Savard) - 2026-10-19 00:18 +0000
                          Re: Documentation (was Re: Performance of xchg reg,reg) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-19 01:52 +0000
                            Re: Documentation (was Re: Performance of xchg reg,reg) George Neuner <gneuner2@comcast.net> - 2026-10-19 14:50 -0400
                              Re: Documentation (was Re: Performance of xchg reg,reg) cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-20 02:05 +0000
                          Re: Algol 68 (was Re: Documentation) Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-19 01:54 +0000
                          Re: Documentation (was Re: Performance of xchg reg,reg) Thomas Koenig <tkoenig@netcologne.de> - 2026-10-19 07:44 +0000
                          Re: Documentation (was Re: Performance of xchg reg,reg) Stefan Monnier <monnier@iro.umontreal.ca> - 2026-10-19 12:24 -0400
                      Re: Documentation (was Re: Performance of xchg reg,reg) MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-18 17:48 +0000
                    Re: Performance of xchg reg,reg George Neuner <gneuner2@comcast.net> - 2026-10-18 08:59 -0400
                    Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-18 15:08 +0000
                      Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-18 18:43 +0300
                        Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-18 16:57 +0000
                          Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-18 20:47 +0300
                            Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 18:07 +0000
                            Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-18 21:04 +0000
                          Re: Performance of xchg reg,reg Stefan Monnier <monnier@iro.umontreal.ca> - 2026-10-18 23:43 -0400
                            Re: Performance of xchg reg,reg Stephen Fuld <sfuld@alumni.cmu.edu.invalid> - 2026-10-19 06:57 -0700
                              Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-19 14:27 -0700
                              Re: Performance of xchg reg,reg Stefan Monnier <monnier@iro.umontreal.ca> - 2026-10-20 10:00 -0400
                            Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-20 02:00 +0000
                              Re: Performance of xchg reg,reg scott@slp53.sl.home (Scott Lurndal) - 2026-10-20 14:09 +0000
                                Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-20 16:44 -0700
                              Re: Performance of xchg reg,reg Stefan Monnier <monnier@iro.umontreal.ca> - 2026-10-20 10:05 -0400
                                Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-20 19:56 +0000
                            Re: Performance of xchg reg,reg anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2026-10-22 10:54 +0000
                              Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-22 22:11 +0300
                        Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 17:40 +0000
                          Re: Performance of xchg reg,reg Michael S <already5chosen@yahoo.com> - 2026-10-18 20:54 +0300
                            Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 18:25 +0000
                        Re: Performance of xchg reg,reg MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-18 18:01 +0000
                      Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 17:59 +0000
                    Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 17:09 +0000
                  Re: Performance of xchg reg,reg EricP <ThatWouldBeTelling@thevillage.com> - 2026-10-18 12:31 -0400
                    Re: Performance of xchg reg,reg cross@spitfire.i.gajendra.net (Dan Cross) - 2026-10-18 17:47 +0000
              Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-18 12:27 -0700
                Re: Performance of xchg reg,reg EricP <ThatWouldBeTelling@thevillage.com> - 2026-10-19 09:38 -0400
                  Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-19 14:08 -0700
                    Re: Performance of xchg reg,reg Lawrence D’Oliveiro <ldo@nz.invalid> - 2026-10-19 21:21 +0000
                      Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-19 14:26 -0700
                    Re: Performance of xchg reg,reg Joseph Seigh <jseigh_es00@xemaps.com> - 2026-10-19 19:17 -0400
                      Re: Performance of xchg reg,reg "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2026-10-19 22:41 -0700
                        Re: Performance of xchg reg,reg MitchAlsup <user5857@newsgrouper.org.invalid> - 2026-10-20 16:45 +0000

Page 1 of 5  [1] 2 3 4 5  Next page →


#118579 — Performance of xchg reg,reg

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-13 08:43 +0000
SubjectPerformance of xchg reg,reg
Message-ID<2026Oct13.104347@mips.complang.tuwien.ac.at>
Microbenchmarks (and this text in HTML form) on
<http://www.complang.tuwien.ac.at/anton/xchg/>.

In compilers, in particular in SSA destruction, or, more generally,
register allocation, you sometimes have situations where you want to
swap the contents of registers, e.g., when r1 contains a and r2
contains b on one path, while r1 contains b and r2 contains a on the
other path, and both paths join. This can be achieved with 3 mov
instructions, but requires an extra register. The AMD64 instruction
set contains the instruction xchg, which swaps the registers without
extra register.

More generally, there may be more than two registers whose values have
to be moved in a cyclic way. This also requires an extra register and
(for an n-register cycle) n+1 mov instructions if performed using mov
instructions, or it can be achieved with n-1 xchg instructions.

Mov instructions are supported very well in recent CPU cores, with the
cores usually being able to perform as many independent (and often
even dependent) moves as the register renamer accepts instructions
(e.g., if the register renamer accepts 8 instructions per cycle, 8
moves per cycle can be performed, usually even dependent moves).

But how do xchg instructions perform? Should a register allocator use
them where they are convenient, or prefer to use mov instructions and
an extra register?

<http://www.complang.tuwien.ac.at/anton/xchg/> contains
microbenchmarks and this posting presents results for them on various
cores from Intel and AMD.  The first set of microbenchmarks perform 1G
xchg instructions in a loop containing 28 xchg instructions (plus two
instructions for the loop).

One (independent) contains a sequence of 7 xchg instructions that are
fully independent of each other, all accessing different registers,
followed by the same sequence another three times. So the xchg
instructions are as independent as possible with 14 registers
involved.

The other (dependent) contains a sequence of 14 xchg instructions
where each subsequent instruction uses one register of the previous
instruction, implementing a 15-register cycle. This sequence is
followed by the reversal of this sequence, resulting in performing the
15-register cycle in the other direction.

Here are the results in Gcycles on recent microarchitectures, i.e., a
result of 0.25 means that the microarchitecture performs 4 xchg
instructions per cycle. Smaller is better.

  indep dep  core        family  CPU 
  0.26  0.26 Zen5        AMD     Ryzen AI Pro 350
  0.35  0.35 Zen4        AMD     Ryzen 8700G
  0.35  0.35 Zen3        AMD     Ryzen 5800X
  0.61  1.50 Lion Cove   Intel P Core Ultra 225
  1.00  1.50 Golden Cove Intel P Core i3-1315U
  0.82  1.50 Rocket Lake Intel P Xeon E-2388G
  2.07  2.05 Skymont     Intel E Core Ultra 225
  3.45  3.45 Gracemont   Intel E Core i3-1315U

Given the results of the dependent benchmark, it looks like the AMD
processors perform xchg in the register renamer, consuming the
resources of two ordinary instructions there (probably because two
result registers are involved).

On Intel microarchitectures, whether P-cores or E-cores, but
especially the latter, xchg seems to have gotten little love.

Let's see how this affects cyclic moves between registers. The
following microbenchmarks perform cyclic moves through 2-5 registers
(cyc2-cyc5) in three different ways:

mem  Store the first register to memory, then perform n-1 moves among
     registers, then load the memory location into the final register.
reg  Move the first register into a spare register, then perform n-1
     moves among the cycled registers, then move the spare register
     into the final register.
xchg Use n-1 xchg instructions. 

The benchmark loop contains 12 cycles, and cycles involving
non-overlapping sets of registers are benchmarked (6 sets for cyc2, 4
for cyc3, 3 for cyc4, 2 for cyc5). At least three different memory
locations are used for holding the value of the first register in
memory, but the same register is used as the spare register. Here are
the results (execution cycles per cyclic move (i.e., n+1 movs in case
of reg, n-1 xchgs in case of xchg).

    cyc2      |    cyc3      |    cyc4       |    cyc5       |core       
mem  reg  xchg|mem  reg  xchg|mem  reg   xchg|mem  reg   xchg|
0.50 0.50 0.27|0.67 0.58 0.52|0.83 0.83  0.77|1.08 0.83  1.02|Zen5
1.00 0.51 0.36|1.00 0.68 0.69|1.00 0.85  1.03|1.01 1.01  1.36|Zen4
1.00 0.51 0.42|1.00 0.68 0.70|1.00 0.92  1.03|1.02 1.01  1.36|Zen3
0.50 0.40 0.68|0.54 0.56 1.28|0.67 0.66  1.97|0.81 0.81  4.21|Lion Cove
0.61 0.53 1.00|0.70 0.70 2.00|0.89 0.90  3.00|1.06 1.08  4.41|Golden Cove
0.82 0.67 1.00|0.87 0.83 2.00|1.08 1.08  3.00|1.22 1.22  4.66|Rocket Lake
1.00 0.40 1.45|0.65 0.73 4.14|0.65 0.65  7.35|0.78 0.86  9.44|Skymont
0.67 0.67 3.08|0.83 0.83 6.73|1.03 1.03 10.63|1.23 1.23 13.77|Gracemont

On Zen5, even a 5-register cycle can be profitably implemented with
xchg when you have no spare register, a 4-register cycle even when you
have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3 (for
reg) are borderline cases, and for shorter cycles xchg is better.

On Intel processors, xchg is so slow that it never is profitable to
use it. The slowness takes on extreme values in the E-cores, with
slowdowns by a factor >10 for cyc4 and cyc5.

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [next] | [standalone]


#118597

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-10-14 00:23 +0000
Message-ID<11ami2v$11dqu$3@dont-email.me>
In reply to#118579
On Tue, 13 Oct 2026 08:43:47 GMT, Anton Ertl wrote:

> On Zen5, even a 5-register cycle can be profitably implemented with
> xchg when you have no spare register, a 4-register cycle even when
> you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
> (for reg) are borderline cases, and for shorter cycles xchg is
> better.
>
> On Intel processors, xchg is so slow that it never is profitable to
> use it. The slowness takes on extreme values in the E-cores, with
> slowdowns by a factor >10 for cyc4 and cyc5.

You’d think both companies would be running similar kinds of
instruction workloads to find the things worth optimizing in their CPU
architectures. But perhaps not ...

[toc] | [prev] | [next] | [standalone]


#118603

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-14 07:00 +0000
Message-ID<2026Oct14.090023@mips.complang.tuwien.ac.at>
In reply to#118597
Lawrence =?iso-8859-13?q?D=FFOliveiro?= <ldo@nz.invalid> writes:
>On Tue, 13 Oct 2026 08:43:47 GMT, Anton Ertl wrote:
>
>> On Zen5, even a 5-register cycle can be profitably implemented with
>> xchg when you have no spare register, a 4-register cycle even when
>> you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
>> (for reg) are borderline cases, and for shorter cycles xchg is
>> better.
>>
>> On Intel processors, xchg is so slow that it never is profitable to
>> use it. The slowness takes on extreme values in the E-cores, with
>> slowdowns by a factor >10 for cyc4 and cyc5.
>
>You’d think both companies would be running similar kinds of
>instruction workloads to find the things worth optimizing in their CPU
>architectures. But perhaps not ...

Or maybe, given the structure of the renamer, an AMD engineer saw a
relatively easy way to implement xchg efficiently, and did it, without
first looking at how often xchg occurs in benchmark programs.  And at
Intel, either no engineer thought about this, or the structure of the
renamer makes an efficient implementation much harder.

It makes me wonder, however, why cyc2xchg is more expensive than
cyc2reg, though.  An easy implementation should be to decode xchg reg,
reg into three mov reg, reg (i.e., what cyc2reg implements), where the
spare register is a non-architectural register.  But on every measured
Intel microarchitecture cyc2xchg is substantially slower than cyc2reg.

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [prev] | [next] | [standalone]


#118625

FromMitchAlsup <user5857@newsgrouper.org.invalid>
Date2026-10-14 22:35 +0000
Message-ID<1792017353-5857@newsgrouper.org>
In reply to#118603
anton@mips.complang.tuwien.ac.at (Anton Ertl) posted:

> /ERROR "unexpected byte sequence starting at index 607: '\xE2'" while decoding/:
> 
> Lawrence =?iso-8859-13?q?D=FFOliveiro?= <ldo@nz.invalid> writes:
> >On Tue, 13 Oct 2026 08:43:47 GMT, Anton Ertl wrote:
> >
> >> On Zen5, even a 5-register cycle can be profitably implemented with
> >> xchg when you have no spare register, a 4-register cycle even when
> >> you have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3
> >> (for reg) are borderline cases, and for shorter cycles xchg is
> >> better.
> >>
> >> On Intel processors, xchg is so slow that it never is profitable to
> >> use it. The slowness takes on extreme values in the E-cores, with
> >> slowdowns by a factor >10 for cyc4 and cyc5.
> >
> >You’d think both companies would be running similar kinds of
> >instruction workloads to find the things worth optimizing in their CPU
> >architectures. But perhaps not ...
> 
> Or maybe, given the structure of the renamer, an AMD engineer saw a
> relatively easy way to implement xchg efficiently, and did it, without
> first looking at how often xchg occurs in benchmark programs.  And at
> Intel, either no engineer thought about this, or the structure of the
> renamer makes an efficient implementation much harder.

Unlike Mainframes where sort is bread-and-butter operation, on PCs
(and similar) it is not.
 
> It makes me wonder, however, why cyc2xchg is more expensive than
> cyc2reg, though.  An easy implementation should be to decode xchg reg,
> reg into three mov reg, reg (i.e., what cyc2reg implements), where the
> spare register is a non-architectural register.  But on every measured
> Intel microarchitecture cyc2xchg is substantially slower than cyc2reg.
> 
> - anton

[toc] | [prev] | [next] | [standalone]


#118627

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-10-14 23:07 +0000
Message-ID<11ap1un$1tsnt$2@dont-email.me>
In reply to#118625
On Wed, 14 Oct 2026 22:35:53 GMT, MitchAlsup wrote:

> Unlike Mainframes where sort is bread-and-butter operation, on PCs
> (and similar) it is not.

You think Timsort might run faster on a mainframe than a PC?

It was invented by one of the Python developers.

<https://en.wikipedia.org/wiki/Timsort>

[toc] | [prev] | [next] | [standalone]


#118631

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-15 06:05 +0000
Message-ID<2026Oct15.080534@mips.complang.tuwien.ac.at>
In reply to#118625
MitchAlsup <user5857@newsgrouper.org.invalid> writes:
>Unlike Mainframes where sort is bread-and-butter operation, on PCs
>(and similar) it is not.

And the relevance of that for "Performance of xchg reg,reg" is?

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [prev] | [next] | [standalone]


#118634

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-15 07:06 +0000
Message-ID<2026Oct15.090653@mips.complang.tuwien.ac.at>
In reply to#118631
anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>MitchAlsup <user5857@newsgrouper.org.invalid> writes:
>>Unlike Mainframes where sort is bread-and-butter operation, on PCs
>>(and similar) it is not.
>
>And the relevance of that for "Performance of xchg reg,reg" is?

To give you an idea what xchg reg,reg is good for:

long foo(long a, long b);

long bar(long a, long b)
{
  return foo(b,a);
}

Both gcc-16 and clang-19 (even with -mtune=znver5) compile this to:

0000000000000000 <bar>:
   0:   48 89 f8                mov    %rdi,%rax
   3:   48 89 f7                mov    %rsi,%rdi
   6:   48 89 c6                mov    %rax,%rsi
   9:   e9 00 00 00 00          jmp    e <bar+0xe> #actually jmp foo

This could be replaced with

xchg %rdi,%rsi
jmp foo


It's less obvious for

long foo(long a, long b);

long bar(long a, long b, long c, long d)
{
  return foo(b-c,a-d);
}

The gcc-12 (different machines) output even with -mtune=znver3 is:

0000000000000000 <bar>:
   0:   48 89 f8                mov    %rdi,%rax
   3:   48 29 d6                sub    %rdx,%rsi
   6:   48 29 c8                sub    %rcx,%rax
   9:   48 89 f7                mov    %rsi,%rdi
   c:   48 89 c6                mov    %rax,%rsi
   f:   e9 00 00 00 00          jmp    14 <bar+0x14>

and the clang-14 output is similar.  This could be shortened to:

sub %rdx,%rsi
sub %rcx,%rdi
xchg %rdi,%rsi
jmp foo

It also happens with control flow (that's what the SSA destruction on
my web page refers to):

long bar(long a, long b, long c, long d)
{
  if (a<b) {
    long tmp=c;
    c=d-a;
    d=tmp-b;
  }
  return 2*c+d;
}

compiles (gcc-12 -O3 -mtune=znver3) to:

0000000000000000 <bar>:
   0:   48 39 f7                cmp    %rsi,%rdi
   3:   7d 0f                   jge    14 <bar+0x14>
   5:   48 89 c8                mov    %rcx,%rax
   8:   48 29 f2                sub    %rsi,%rdx
   b:   48 29 f8                sub    %rdi,%rax
   e:   48 89 d1                mov    %rdx,%rcx
  11:   48 89 c2                mov    %rax,%rdx
  14:   48 8d 04 51             lea    (%rcx,%rdx,2),%rax
  18:   c3                      ret

and could be:

       cmp    %rsi,%rdi
       jge    L1
       sub    %rsi,%rdx
       sub    %rdi,%rcx
       xchg   %rdx,%rcx
L1:    lea    (%rcx,%rdx,2),%rax
       ret

Given that most operations on AMD64 are performed with two-address
(for binary operations) or one-address (for unary operations), the
compiler can usually not use target preferencing to get data into the
required registers with little or no extra move instructions.  So the
need to rearrange registers at some point is especially relevant on
this architecture; and it has the xchg instruction to make the
rearrangements shorter, and, on AMD processors, faster.

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [prev] | [next] | [standalone]


#118651

FromEricP <ThatWouldBeTelling@thevillage.com>
Date2026-10-16 09:47 -0400
Message-ID<2WpAS.163763$Zbg.15006@fx35.iad>
In reply to#118634
On 2026-Oct-15 03:06, Anton Ertl wrote:
> anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>> MitchAlsup <user5857@newsgrouper.org.invalid> writes:
>>> Unlike Mainframes where sort is bread-and-butter operation, on PCs
>>> (and similar) it is not.
>>
>> And the relevance of that for "Performance of xchg reg,reg" is?
> 
> To give you an idea what xchg reg,reg is good for:
> 
> long foo(long a, long b);
> 
> long bar(long a, long b)
> {
>    return foo(b,a);
> }
> 
> Both gcc-16 and clang-19 (even with -mtune=znver5) compile this to:
> 
> 0000000000000000 <bar>:
>     0:   48 89 f8                mov    %rdi,%rax
>     3:   48 89 f7                mov    %rsi,%rdi
>     6:   48 89 c6                mov    %rax,%rsi
>     9:   e9 00 00 00 00          jmp    e <bar+0xe> #actually jmp foo
> 
> This could be replaced with
> 
> xchg %rdi,%rsi
> jmp foo

There is also the xor swap which doesn't need an extra register

   xor rax,rbx
   xor rbx,rax
   xor rax,rbx


[toc] | [prev] | [next] | [standalone]


#118653

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-16 16:04 +0000
Message-ID<2026Oct16.180410@mips.complang.tuwien.ac.at>
In reply to#118651
EricP <ThatWouldBeTelling@thevillage.com> writes:
>On 2026-Oct-15 03:06, Anton Ertl wrote:
>> Both gcc-16 and clang-19 (even with -mtune=znver5) compile this to:
>> 
>> 0000000000000000 <bar>:
>>     0:   48 89 f8                mov    %rdi,%rax
>>     3:   48 89 f7                mov    %rsi,%rdi
>>     6:   48 89 c6                mov    %rax,%rsi
>>     9:   e9 00 00 00 00          jmp    e <bar+0xe> #actually jmp foo
>> 
>> This could be replaced with
>> 
>> xchg %rdi,%rsi
>> jmp foo
>
>There is also the xor swap which doesn't need an extra register
>
>   xor rax,rbx
>   xor rbx,rax
>   xor rax,rbx

That has a latency of 3 cycles and (probably less of a problem)
consumes 3 ALU slots.  Maybe Gracemont uses this internally, the
number of cycles for the xchg variants of the cycN benchmarks would be
compatible with that explanation.  With 0-cycle store-to-load
forwarding in recent processors, storing to memory and loading from
memory is preferable on Intel processors if no spare register is
available; and on AMD processors, xchg for cyc2 and cyc3, and
sometimes on cyc4, cyc5.  My guess is that using xor would lead to
huge slowdowns, even compared to storing the value in memory.

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [prev] | [next] | [standalone]


#118669

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-10-17 05:46 +0000
Message-ID<11av23o$3ubmb$1@dont-email.me>
In reply to#118651
On Fri, 16 Oct 2026 09:47:39 -0400, EricP wrote:

> There is also the xor swap which doesn't need an extra register
>
>    xor rax,rbx
>    xor rbx,rax
>    xor rax,rbx

It's a clever trick from the old days, but not really
performance-oriented ...

[toc] | [prev] | [next] | [standalone]


#118617

FromMichael S <already5chosen@yahoo.com>
Date2026-10-14 22:29 +0300
Message-ID<20261014222914.0000399e@yahoo.com>
In reply to#118579
On Tue, 13 Oct 2026 08:43:47 GMT
anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:

> Microbenchmarks (and this text in HTML form) on
> <http://www.complang.tuwien.ac.at/anton/xchg/>.
> 
> In compilers, in particular in SSA destruction, or, more generally,
> register allocation, you sometimes have situations where you want to
> swap the contents of registers, e.g., when r1 contains a and r2
> contains b on one path, while r1 contains b and r2 contains a on the
> other path, and both paths join. This can be achieved with 3 mov
> instructions, but requires an extra register. The AMD64 instruction
> set contains the instruction xchg, which swaps the registers without
> extra register.
> 
> More generally, there may be more than two registers whose values have
> to be moved in a cyclic way. This also requires an extra register and
> (for an n-register cycle) n+1 mov instructions if performed using mov
> instructions, or it can be achieved with n-1 xchg instructions.
> 
> Mov instructions are supported very well in recent CPU cores, with the
> cores usually being able to perform as many independent (and often
> even dependent) moves as the register renamer accepts instructions
> (e.g., if the register renamer accepts 8 instructions per cycle, 8
> moves per cycle can be performed, usually even dependent moves).
> 
> But how do xchg instructions perform? Should a register allocator use
> them where they are convenient, or prefer to use mov instructions and
> an extra register?
> 
> <http://www.complang.tuwien.ac.at/anton/xchg/> contains
> microbenchmarks and this posting presents results for them on various
> cores from Intel and AMD.  The first set of microbenchmarks perform 1G
> xchg instructions in a loop containing 28 xchg instructions (plus two
> instructions for the loop).
> 
> One (independent) contains a sequence of 7 xchg instructions that are
> fully independent of each other, all accessing different registers,
> followed by the same sequence another three times. So the xchg
> instructions are as independent as possible with 14 registers
> involved.
> 
> The other (dependent) contains a sequence of 14 xchg instructions
> where each subsequent instruction uses one register of the previous
> instruction, implementing a 15-register cycle. This sequence is
> followed by the reversal of this sequence, resulting in performing the
> 15-register cycle in the other direction.
> 
> Here are the results in Gcycles on recent microarchitectures, i.e., a
> result of 0.25 means that the microarchitecture performs 4 xchg
> instructions per cycle. Smaller is better.
> 
>   indep dep  core        family  CPU 
>   0.26  0.26 Zen5        AMD     Ryzen AI Pro 350
>   0.35  0.35 Zen4        AMD     Ryzen 8700G
>   0.35  0.35 Zen3        AMD     Ryzen 5800X
>   0.61  1.50 Lion Cove   Intel P Core Ultra 225
>   1.00  1.50 Golden Cove Intel P Core i3-1315U
>   0.82  1.50 Rocket Lake Intel P Xeon E-2388G
>   2.07  2.05 Skymont     Intel E Core Ultra 225
>   3.45  3.45 Gracemont   Intel E Core i3-1315U
> 
> Given the results of the dependent benchmark, it looks like the AMD
> processors perform xchg in the register renamer, consuming the
> resources of two ordinary instructions there (probably because two
> result registers are involved).
> 
> On Intel microarchitectures, whether P-cores or E-cores, but
> especially the latter, xchg seems to have gotten little love.
> 
> Let's see how this affects cyclic moves between registers. The
> following microbenchmarks perform cyclic moves through 2-5 registers
> (cyc2-cyc5) in three different ways:
> 
> mem  Store the first register to memory, then perform n-1 moves among
>      registers, then load the memory location into the final register.
> reg  Move the first register into a spare register, then perform n-1
>      moves among the cycled registers, then move the spare register
>      into the final register.
> xchg Use n-1 xchg instructions. 
> 
> The benchmark loop contains 12 cycles, and cycles involving
> non-overlapping sets of registers are benchmarked (6 sets for cyc2, 4
> for cyc3, 3 for cyc4, 2 for cyc5). At least three different memory
> locations are used for holding the value of the first register in
> memory, but the same register is used as the spare register. Here are
> the results (execution cycles per cyclic move (i.e., n+1 movs in case
> of reg, n-1 xchgs in case of xchg).
> 
>     cyc2      |    cyc3      |    cyc4       |    cyc5       |core
> mem  reg  xchg|mem  reg  xchg|mem  reg   xchg|mem  reg   xchg|
> 0.50 0.50 0.27|0.67 0.58 0.52|0.83 0.83  0.77|1.08 0.83  1.02|Zen5
> 1.00 0.51 0.36|1.00 0.68 0.69|1.00 0.85  1.03|1.01 1.01  1.36|Zen4
> 1.00 0.51 0.42|1.00 0.68 0.70|1.00 0.92  1.03|1.02 1.01  1.36|Zen3
> 0.50 0.40 0.68|0.54 0.56 1.28|0.67 0.66  1.97|0.81 0.81  4.21|Lion
> Cove 0.61 0.53 1.00|0.70 0.70 2.00|0.89 0.90  3.00|1.06 1.08
> 4.41|Golden Cove 0.82 0.67 1.00|0.87 0.83 2.00|1.08 1.08  3.00|1.22
> 1.22  4.66|Rocket Lake 1.00 0.40 1.45|0.65 0.73 4.14|0.65 0.65
> 7.35|0.78 0.86  9.44|Skymont 0.67 0.67 3.08|0.83 0.83 6.73|1.03 1.03
> 10.63|1.23 1.23 13.77|Gracemont
> 
> On Zen5, even a 5-register cycle can be profitably implemented with
> xchg when you have no spare register, a 4-register cycle even when you
> have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3 (for
> reg) are borderline cases, and for shorter cycles xchg is better.
> 
> On Intel processors, xchg is so slow that it never is profitable to
> use it. The slowness takes on extreme values in the E-cores, with
> slowdowns by a factor >10 for cyc4 and cyc5.
> 
> - anton


Interesting. Thank you.



[toc] | [prev] | [next] | [standalone]


#118643

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2026-10-15 14:21 -0700
Message-ID<11arg45$2p70p$1@dont-email.me>
In reply to#118579
On 10/13/2026 1:43 AM, Anton Ertl wrote:
> Microbenchmarks (and this text in HTML form) on
> <http://www.complang.tuwien.ac.at/anton/xchg/>.
> 
> In compilers, in particular in SSA destruction, or, more generally,
> register allocation, you sometimes have situations where you want to
> swap the contents of registers, e.g., when r1 contains a and r2
> contains b on one path, while r1 contains b and r2 contains a on the
> other path, and both paths join. This can be achieved with 3 mov
> instructions, but requires an extra register. The AMD64 instruction
> set contains the instruction xchg, which swaps the registers without
> extra register.
> 
> More generally, there may be more than two registers whose values have
> to be moved in a cyclic way. This also requires an extra register and
> (for an n-register cycle) n+1 mov instructions if performed using mov
> instructions, or it can be achieved with n-1 xchg instructions.
> 
> Mov instructions are supported very well in recent CPU cores, with the
> cores usually being able to perform as many independent (and often
> even dependent) moves as the register renamer accepts instructions
> (e.g., if the register renamer accepts 8 instructions per cycle, 8
> moves per cycle can be performed, usually even dependent moves).
> 
> But how do xchg instructions perform? Should a register allocator use
> them where they are convenient, or prefer to use mov instructions and
> an extra register?
> 
> <http://www.complang.tuwien.ac.at/anton/xchg/> contains
> microbenchmarks and this posting presents results for them on various
> cores from Intel and AMD.  The first set of microbenchmarks perform 1G
> xchg instructions in a loop containing 28 xchg instructions (plus two
> instructions for the loop).
> 
> One (independent) contains a sequence of 7 xchg instructions that are
> fully independent of each other, all accessing different registers,
> followed by the same sequence another three times. So the xchg
> instructions are as independent as possible with 14 registers
> involved.
> 
> The other (dependent) contains a sequence of 14 xchg instructions
> where each subsequent instruction uses one register of the previous
> instruction, implementing a 15-register cycle. This sequence is
> followed by the reversal of this sequence, resulting in performing the
> 15-register cycle in the other direction.
> 
> Here are the results in Gcycles on recent microarchitectures, i.e., a
> result of 0.25 means that the microarchitecture performs 4 xchg
> instructions per cycle. Smaller is better.
> 
>    indep dep  core        family  CPU
>    0.26  0.26 Zen5        AMD     Ryzen AI Pro 350
>    0.35  0.35 Zen4        AMD     Ryzen 8700G
>    0.35  0.35 Zen3        AMD     Ryzen 5800X
>    0.61  1.50 Lion Cove   Intel P Core Ultra 225
>    1.00  1.50 Golden Cove Intel P Core i3-1315U
>    0.82  1.50 Rocket Lake Intel P Xeon E-2388G
>    2.07  2.05 Skymont     Intel E Core Ultra 225
>    3.45  3.45 Gracemont   Intel E Core i3-1315U
> 
> Given the results of the dependent benchmark, it looks like the AMD
> processors perform xchg in the register renamer, consuming the
> resources of two ordinary instructions there (probably because two
> result registers are involved).
> 
> On Intel microarchitectures, whether P-cores or E-cores, but
> especially the latter, xchg seems to have gotten little love.
> 
> Let's see how this affects cyclic moves between registers. The
> following microbenchmarks perform cyclic moves through 2-5 registers
> (cyc2-cyc5) in three different ways:
> 
> mem  Store the first register to memory, then perform n-1 moves among
>       registers, then load the memory location into the final register.
> reg  Move the first register into a spare register, then perform n-1
>       moves among the cycled registers, then move the spare register
>       into the final register.
> xchg Use n-1 xchg instructions.
> 
> The benchmark loop contains 12 cycles, and cycles involving
> non-overlapping sets of registers are benchmarked (6 sets for cyc2, 4
> for cyc3, 3 for cyc4, 2 for cyc5). At least three different memory
> locations are used for holding the value of the first register in
> memory, but the same register is used as the spare register. Here are
> the results (execution cycles per cyclic move (i.e., n+1 movs in case
> of reg, n-1 xchgs in case of xchg).
> 
>      cyc2      |    cyc3      |    cyc4       |    cyc5       |core
> mem  reg  xchg|mem  reg  xchg|mem  reg   xchg|mem  reg   xchg|
> 0.50 0.50 0.27|0.67 0.58 0.52|0.83 0.83  0.77|1.08 0.83  1.02|Zen5
> 1.00 0.51 0.36|1.00 0.68 0.69|1.00 0.85  1.03|1.01 1.01  1.36|Zen4
> 1.00 0.51 0.42|1.00 0.68 0.70|1.00 0.92  1.03|1.02 1.01  1.36|Zen3
> 0.50 0.40 0.68|0.54 0.56 1.28|0.67 0.66  1.97|0.81 0.81  4.21|Lion Cove
> 0.61 0.53 1.00|0.70 0.70 2.00|0.89 0.90  3.00|1.06 1.08  4.41|Golden Cove
> 0.82 0.67 1.00|0.87 0.83 2.00|1.08 1.08  3.00|1.22 1.22  4.66|Rocket Lake
> 1.00 0.40 1.45|0.65 0.73 4.14|0.65 0.65  7.35|0.78 0.86  9.44|Skymont
> 0.67 0.67 3.08|0.83 0.83 6.73|1.03 1.03 10.63|1.23 1.23 13.77|Gracemont
> 
> On Zen5, even a 5-register cycle can be profitably implemented with
> xchg when you have no spare register, a 4-register cycle even when you
> have a spare register. For Zen4 and Zen3 cyc4 (for mem) and cyc3 (for
> reg) are borderline cases, and for shorter cycles xchg is better.
> 
> On Intel processors, xchg is so slow that it never is profitable to
> use it. The slowness takes on extreme values in the E-cores, with
> slowdowns by a factor >10 for cyc4 and cyc5.
> 
> - anton

Well, for some reason the LOCK prefix is implied for XCHG.

[toc] | [prev] | [next] | [standalone]


#118644

FromLawrence D’Oliveiro <ldo@nz.invalid>
Date2026-10-15 21:42 +0000
Message-ID<11arhcb$2p8h1$7@dont-email.me>
In reply to#118643
On Thu, 15 Oct 2026 14:21:07 -0700, Chris M. Thomasson wrote:

> Well, for some reason the LOCK prefix is implied for XCHG.

I can imagine that being useful when accessing memory, but not just
for exchanging registers ...

[toc] | [prev] | [next] | [standalone]


#118650

FromTerje Mathisen <terje.mathisen@tmsw.no>
Date2026-10-16 14:45 +0200
Message-ID<11at6a2$39q08$1@dont-email.me>
In reply to#118644
Lawrence D’Oliveiro wrote:
> On Thu, 15 Oct 2026 14:21:07 -0700, Chris M. Thomasson wrote:
> 
>> Well, for some reason the LOCK prefix is implied for XCHG.
> 
> I can imagine that being useful when accessing memory, but not just
> for exchanging registers ...

The implied LOCK only happens with a memory operand specified in the r/m 
byte.

Terje

-- 
- <Terje.Mathisen at tmsw.no>
"almost all programming can be viewed as an exercise in caching"

[toc] | [prev] | [next] | [standalone]


#118646

Fromanton@mips.complang.tuwien.ac.at (Anton Ertl)
Date2026-10-16 05:50 +0000
Message-ID<2026Oct16.075055@mips.complang.tuwien.ac.at>
In reply to#118643
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>Well, for some reason the LOCK prefix is implied for XCHG.

According to <https://www.felixcloutier.com/x86/xchg> (which is based
on (I think) Intel's documentation):

|If a memory operand is referenced, the processor’s locking protocol is
|automatically implemented for the duration of the exchange operation,
|regardless of the presence or absence of the LOCK prefix or of the
|value of the IOPL.

This does not cover the "xchg reg, reg" case.

<https://www.felixcloutier.com/x86/lock> says:
|The XCHG instruction always asserts the LOCK# signal regardless of the
|presence or absence of the LOCK prefix.

This seems to include the "xchg reg, reg" case, but asserting the
LOCK# signal would make no difference, because: "the LOCK# signal
ensures that the processor has exclusive use of any shared memory
while the signal is asserted" and "the processor’s cache coherency
mechanism ensures that the operation is carried out atomically with
regards to memory", but "xchg reg, reg" does not use memory at all,
and other processors have no access to a processor's registers.

- anton
-- 
'Anyone trying for "industrial quality" ISA should avoid undefined behavior.'
  Mitch Alsup, <c17fcd89-f024-40e7-a594-88a85ac10d20o@googlegroups.com>

[toc] | [prev] | [next] | [standalone]


#118649

FromMichael S <already5chosen@yahoo.com>
Date2026-10-16 11:34 +0300
Message-ID<20261016113441.00002a5f@yahoo.com>
In reply to#118646
On Fri, 16 Oct 2026 05:50:55 GMT
anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:

> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
> >Well, for some reason the LOCK prefix is implied for XCHG.  
> 
> According to <https://www.felixcloutier.com/x86/xchg> (which is based
> on (I think) Intel's documentation):
> 
> |If a memory operand is referenced, the processor’s locking
> protocol is |automatically implemented for the duration of the
> exchange operation, |regardless of the presence or absence of the
> LOCK prefix or of the |value of the IOPL.
> 
> This does not cover the "xchg reg, reg" case.
> 
> <https://www.felixcloutier.com/x86/lock> says:
> |The XCHG instruction always asserts the LOCK# signal regardless of
> the |presence or absence of the LOCK prefix.
> 
> This seems to include the "xchg reg, reg" case, 

No, it does not.

> but asserting the
> LOCK# signal would make no difference, because: "the LOCK# signal
> ensures that the processor has exclusive use of any shared memory
> while the signal is asserted" and "the processor’s cache coherency
> mechanism ensures that the operation is carried out atomically with
> regards to memory", but "xchg reg, reg" does not use memory at all,
> and other processors have no access to a processor's registers.
> 
> - anton


Intel text (325383-060US September 2016):
Exchanges the contents of the destination (first) and source (second)
operands. The operands can be two general- purpose registers or a
register and a memory location. If a memory operand is referenced, the
processor’s locking protocol is automatically implemented for the
duration of the exchange operation, regardless of the presence or
absence of the LOCK prefix or of the value of the IOPL. (See the LOCK
prefix description in this chapter for more information on the locking
protocol.) This instruction is useful for implementing semaphores or
similar data structures for process synchronization. (See “Bus Locking”
in Chapter 8 of the Intel® 64 and IA-32 Architectures Software
Developer’s Manual, Volume 3A, for more information on bus locking.)
The XCHG instruction can also be used instead of the BSWAP instruction
for 16-bit operands. In 64-bit mode, the instruction’s default
operation size is 32 bits. Using a REX prefix in the form of REX.R
permits access to additional registers (R8-R15). Using a REX prefix in
the form of REX.W promotes operation to 64 bits. See the summary chart
at the beginning of this section for encoding data and limits.

NOTE
XCHG (E)AX, (E)AX (encoded instruction byte is 90H) is an alias for NOP
regardless of data size prefixes, including REX.W.


AMD Text (24594 Rev. 3.04 April 2003):
Exchanges the contents of the two operands. The operands can be two
general- purpose registers or a register and a memory location. If
either operand references memory, the processor locks automatically,
whether or not the LOCK prefix is used and independently of the value
of IOPL. For details about the LOCK prefix, see “Lock Prefix” on page
10. The x86 architecture commonly uses the XCHG EAX, EAX instruction
(opcode 90h) as a one-byte NOP. In 64-bit mode, the processor treats
opcode 90h as a true NOP only if it would exchange rAX with itself.
Without this special handling, the instruction would zero-extend the
upper 32 bits of RAX, and thus it would not be a true no- operation.
Opcode 90h can still be used to exchange rAX and r8 if the appropriate
REX prefix is used. This special handling does not apply to the
two-byte ModRM form of the XCHG instruction.



[toc] | [prev] | [next] | [standalone]


#118656

Fromcross@spitfire.i.gajendra.net (Dan Cross)
Date2026-10-16 18:23 +0000
Message-ID<11atq3a$nqi$1@reader2.panix.com>
In reply to#118649
In article <20261016113441.00002a5f@yahoo.com>,
Michael S  <already5chosen@yahoo.com> wrote:
>On Fri, 16 Oct 2026 05:50:55 GMT
>anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
>
>> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>> >Well, for some reason the LOCK prefix is implied for XCHG.  
>> 
>> According to <https://www.felixcloutier.com/x86/xchg> (which is based
>> on (I think) Intel's documentation):
>> 
>> |If a memory operand is referenced, the processor’s locking protocol is
>> |automatically implemented for the duration of the exchange operation,
>> |regardless of the presence or absence of the LOCK prefix or of the
>> |value of the IOPL.
>> 
>> This does not cover the "xchg reg, reg" case.
>> 
>> <https://www.felixcloutier.com/x86/lock> says:
>> |The XCHG instruction always asserts the LOCK# signal regardless of the
>> |presence or absence of the LOCK prefix.
>> 
>> This seems to include the "xchg reg, reg" case, 
>
>No, it does not.

Unfortunately, the information is spread across two sections,
and they contradict.  The description in the `LOCK` prefix
section in the latest version of the Intel SDM includes the text
Anton quoted, while the description of `XCHG` itself makes clear
that the destination operand must be a memory operand for the
locking protocol to automatically apply.  Which is correct?

Personally, I suspect it's the one in the `XCHG` description.
Context is important, and the full paragraph that talks about
`XCHG` includes more:

|The LOCK prefix can be prepended only to the following
|instructions and only to those forms of the instructions where
|the destination operand is a memory operand: `ADD`, `ADC`,
|`AND`, `BTC`, `BTR`, `BTS`, `CMPXCHG`, `CMPXCH8B`,
|`CMPXCHG16B`, `DEC`, `INC`, `NEG`, `NOT`, `OR`, `SBB`, `SUB`,
|`XOR`, `XADD`, and `XCHG`.  If the `LOCK` prefix is used with
|one of these instructions and the source operand is a memory
|operand, an undefined opcode exception (`#UD`) may be
|generated.  An undefined opcode exception will also be
|generated if the `LOCK` prefix is used with any instruction not
|in the above list.  The `XCHG` instruction always asserts the
|`LOCK#` signal regardless of the presence or absence of the
|`LOCK` prefix.

So while the last sentence seems independent of operands, its
presence in this paragraph leads me to believe that it only
applies in the context of a destination operand that is a
memory operand.

If not, however, an interesting question is, does an `XCHG` that
only specifies register operands affect memory ordering?
Looking at secs 11.1 and 11.2, I believe the answer is no: the
description of locked instructions explicitly only applies to
those with memory operands.

	- Dan C.

[toc] | [prev] | [next] | [standalone]


#118661

Fromscott@slp53.sl.home (Scott Lurndal)
Date2026-10-16 20:48 +0000
Message-ID<g4wAS.119956$2%g.24960@fx41.iad>
In reply to#118656
Thomas Koenig <tkoenig@netcologne.de> writes:
>Dan Cross <cross@spitfire.i.gajendra.net> schrieb:
>> In article <20261016113441.00002a5f@yahoo.com>,
>> Michael S  <already5chosen@yahoo.com> wrote:
>>>On Fri, 16 Oct 2026 05:50:55 GMT
>>>anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
>>>
>>>> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>>>> >Well, for some reason the LOCK prefix is implied for XCHG.  
>>>> 
>>>> According to <https://www.felixcloutier.com/x86/xchg> (which is based
>>>> on (I think) Intel's documentation):
>>>> 
>>>> |If a memory operand is referenced, the processor’s locking protocol is
>>>> |automatically implemented for the duration of the exchange operation,
>>>> |regardless of the presence or absence of the LOCK prefix or of the
>>>> |value of the IOPL.
>>>> 
>>>> This does not cover the "xchg reg, reg" case.
>>>> 
>>>> <https://www.felixcloutier.com/x86/lock> says:
>>>> |The XCHG instruction always asserts the LOCK# signal regardless of the
>>>> |presence or absence of the LOCK prefix.
>>>> 
>>>> This seems to include the "xchg reg, reg" case, 
>>>
>>>No, it does not.
>>
>> Unfortunately, the information is spread across two sections,
>> and they contradict.  The description in the `LOCK` prefix
>> section in the latest version of the Intel SDM includes the text
>> Anton quoted, while the description of `XCHG` itself makes clear
>> that the destination operand must be a memory operand for the
>> locking protocol to automatically apply.  Which is correct?
>
>What would be the meaning of LOCK with memory operands?  I can't
>think of any.

Did you mean 'without memory operands'?   It's clear that there
is no need to acquire the cache and/or system lock if there
are no memory operands, and a substantial performance penalty;
besides, which cache line would it use for the case where both
operands are registers?

[toc] | [prev] | [next] | [standalone]


#118662

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2026-10-16 14:28 -0700
Message-ID<11au4u4$3llb5$1@dont-email.me>
In reply to#118661
On 10/16/2026 1:48 PM, Scott Lurndal wrote:
> Thomas Koenig <tkoenig@netcologne.de> writes:
>> Dan Cross <cross@spitfire.i.gajendra.net> schrieb:
>>> In article <20261016113441.00002a5f@yahoo.com>,
>>> Michael S  <already5chosen@yahoo.com> wrote:
>>>> On Fri, 16 Oct 2026 05:50:55 GMT
>>>> anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
>>>>
>>>>> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>>>>>> Well, for some reason the LOCK prefix is implied for XCHG.
>>>>>
>>>>> According to <https://www.felixcloutier.com/x86/xchg> (which is based
>>>>> on (I think) Intel's documentation):
>>>>>
>>>>> |If a memory operand is referenced, the processor’s locking protocol is
>>>>> |automatically implemented for the duration of the exchange operation,
>>>>> |regardless of the presence or absence of the LOCK prefix or of the
>>>>> |value of the IOPL.
>>>>>
>>>>> This does not cover the "xchg reg, reg" case.
>>>>>
>>>>> <https://www.felixcloutier.com/x86/lock> says:
>>>>> |The XCHG instruction always asserts the LOCK# signal regardless of the
>>>>> |presence or absence of the LOCK prefix.
>>>>>
>>>>> This seems to include the "xchg reg, reg" case,
>>>>
>>>> No, it does not.
>>>
>>> Unfortunately, the information is spread across two sections,
>>> and they contradict.  The description in the `LOCK` prefix
>>> section in the latest version of the Intel SDM includes the text
>>> Anton quoted, while the description of `XCHG` itself makes clear
>>> that the destination operand must be a memory operand for the
>>> locking protocol to automatically apply.  Which is correct?
>>
>> What would be the meaning of LOCK with memory operands?  I can't
>> think of any.
> 
> Did you mean 'without memory operands'?   It's clear that there
> is no need to acquire the cache and/or system lock if there
> are no memory operands, and a substantial performance penalty;
> besides, which cache line would it use for the case where both
> operands are registers?

One on the threads stack? Kidding, but I have seen people use LOCK XCHG 
for memory operands, and XCHG for "local" registers and such. But, the 
Intel docs are rather interesting. Using XCHG works, without LOCK 
prefix. But, its a point of confusion.

[toc] | [prev] | [next] | [standalone]


#118671

FromThomas Koenig <tkoenig@netcologne.de>
Date2026-10-17 09:48 +0000
Message-ID<11avg8t$2skj$1@dont-email.me>
In reply to#118661
Scott Lurndal <scott@slp53.sl.home> schrieb:
> Thomas Koenig <tkoenig@netcologne.de> writes:
>>Dan Cross <cross@spitfire.i.gajendra.net> schrieb:
>>> In article <20261016113441.00002a5f@yahoo.com>,
>>> Michael S  <already5chosen@yahoo.com> wrote:
>>>>On Fri, 16 Oct 2026 05:50:55 GMT
>>>>anton@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
>>>>
>>>>> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>>>>> >Well, for some reason the LOCK prefix is implied for XCHG.  
>>>>> 
>>>>> According to <https://www.felixcloutier.com/x86/xchg> (which is based
>>>>> on (I think) Intel's documentation):
>>>>> 
>>>>> |If a memory operand is referenced, the processor’s locking protocol is
>>>>> |automatically implemented for the duration of the exchange operation,
>>>>> |regardless of the presence or absence of the LOCK prefix or of the
>>>>> |value of the IOPL.
>>>>> 
>>>>> This does not cover the "xchg reg, reg" case.
>>>>> 
>>>>> <https://www.felixcloutier.com/x86/lock> says:
>>>>> |The XCHG instruction always asserts the LOCK# signal regardless of the
>>>>> |presence or absence of the LOCK prefix.
>>>>> 
>>>>> This seems to include the "xchg reg, reg" case, 
>>>>
>>>>No, it does not.
>>>
>>> Unfortunately, the information is spread across two sections,
>>> and they contradict.  The description in the `LOCK` prefix
>>> section in the latest version of the Intel SDM includes the text
>>> Anton quoted, while the description of `XCHG` itself makes clear
>>> that the destination operand must be a memory operand for the
>>> locking protocol to automatically apply.  Which is correct?
>>
>>What would be the meaning of LOCK with memory operands?  I can't
>>think of any.
>
> Did you mean 'without memory operands'?

Yes.  I canceled the article, but either was too late or some
server does not honor the cancel.

> It's clear that there
> is no need to acquire the cache and/or system lock if there
> are no memory operands, and a substantial performance penalty;
> besides, which cache line would it use for the case where both
> operands are registers?

Exactly.

-- 
This USENET posting was made without artificial intelligence,
artificial impertinence, artificial arrogance, artificial stupidity,
artificial flavorings or artificial colorants.

[toc] | [prev] | [next] | [standalone]


Page 1 of 5  [1] 2 3 4 5  Next page →

Back to top | Article view | comp.arch


csiph-web