[LLVMdev] Adding xadd instruction to X86

Chris Lattner sabre at nondot.org
Fri Dec 3 22:54:03 PST 2004

On Fri, 3 Dec 2004, John Criswell wrote:
> Chris Lattner wrote:
> > Another problem though, is that (without looking at manual) I think xadd
> > modifies the register value.  If this is the case, you will want to define
> > it as a "two-operand" instruction.  Making the above change should get the
> > assertion to go away though.
> How do we define an instruction as a two-operand instruction?

As Misha said, you add the isTwoAddress attribute to the instruction.
However, this is necessary, but not sufficient. :)

Here's the deal.  X86 is inherently a two address machine, with many
operations like this.  Other architectures have instructions which are
read/modify/write in the same way, e.g. cmoves, rlwimi on PPC, etc, and
are handled the same.  Consider the following X86 instruction:

  REG += REG

This doesn't work well for SSA and many compiler analyses/optimizations.
To deal with this, we model this instruction as:

  DestReg = SrcReg + REG

... splitting the read/modify/write appart.  To make this *CORRECT*, we
force the register allocator to allocate the first two operands to the
same physical register (this is what isTwoAddress actually causes to
happen).  Note that isTwoAddress is currently limited to working with
instructions whose 'twoaddressness' is the 0th and 1st operand, so to use
this, your instruction must have the two-addressy operand there.

>From my understanding of XADD and your goals, you basically want this
instruction (in intel syntax):

 LOCK; XADD [mem], REG32

This operation has the effect of atomically doing these operations:

  tmp = load [mem]
  [mem] += REG32
  REG32 = tmp

This operation read/modify/writes both memory and the register.  The
memory doesn't need special two-address support to implement, so you'd
implement this like this:

R32Result = XADD32mr_LOCKED R32Src, [memloc]

And mark it two address.   This form would lead to something like this in
the .td file:

let isTwoAddress = 1 in
  def XADD32mr_LOCKED  : I<0xC1, MRMDestMem,
                           (ops R32:$dst, R32:$srcreg, i32mem:$mem),
                           "xadd{l} {$dst|$mem}, {$mem|$dst}">, LOCK, TB;

Note that the X86 backend currently doesn't define 'LOCK'.  To implement
it, look at how other prefixes like TB, and REP are implemented.  Also,
I'm not sure where you got the 0x87 opcode from: from what I can see, xadd
(mem32) is 0xC1.

Hopefully this helps, if so, I would appreciate it if you could
massage it and turn it into a patch against llvm/doc/CodeGenerator.html :)



More information about the llvm-dev mailing list