X86 Tablegen Description and VEX.W

Hi,

A question from r162999 changes:
http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrFMA.td?r1=162999&r2=162998&pathrev=162999

For the multiclass "fma4s", why is "mr" not inherited from "VEX_W" and
"MemOp4" like those of "rm" or "rr" ?

multiclass fma4s< >
...
  def mr : FMA4<opc, MRMSrcMem, (outs RC:$dst),
           (ins RC:$src1, x86memop:$src2, RC:$src3),
           !strconcat(OpcodeStr,
           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
           [(set RC:$dst, (OpNode RC:$src1, (mem_frag addr:$src2), RC:$src3))]>;
...

It seems that previous revisions for fma4 intrinsics also followed
similar trend. Any idea why?

For the multiclass “fma4s”, why is “mr” not inherited from “VEX_W” and
“MemOp4” like those of “rm” or “rr” ?

Hey Anitha,

The VEX.W bit is used to denote operand order. In other words, this bit allows for a memop to be used as either the second or third source operand of an FMA instruction, offering greater flexibility.

To conceptualize:

VFMADDSD xmm1, xmm2, xmm3/mem64, xmm4 VEX.W == 0
VFMADDSD xmm1, xmm2, xmm3, xmm4/mem64 VEX.W == 1

So, logically, one could create the rr pattern with the VEX.W bit set or not.

The MemOp4 flag is a similar mechanism for setting the ModRM byte, indicating that the second and third source operands have been swapped.

-Cameron

I actually have confusion in mapping the role of vex_w during
instruction selection. For the moment, lets just consider vex_w and
not memop.

[1]. What does " def rr : FMA4<>, VEX_W" mean? As per tablegen
description, "rr" now inherits FMA4 and VEX_W. However VEX_W is not a
class, it is an enumerated value.

[2]. How does vex_w help in instruction selection in-addition to FMA4 class?

[3]. Why does only "rr" and "rm" forms have vex_w but not "mr" ?

(Reference)

multiclass fma4s<bits<8> opc, string OpcodeStr, RegisterClass RC,
                 X86MemOperand x86memop, ValueType OpVT, SDNode OpNode,
                 PatFrag mem_frag> {
  def rr : FMA4<opc, MRMSrcReg, (outs RC:$dst),
           (ins RC:$src1, RC:$src2, RC:$src3),
           !strconcat(OpcodeStr,
           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
           [(set RC:$dst,
             (OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]>, VEX_W, MemOp4;
  def rm : FMA4<opc, MRMSrcMem, (outs RC:$dst),
           (ins RC:$src1, RC:$src2, x86memop:$src3),
           !strconcat(OpcodeStr,
           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
           [(set RC:$dst, (OpNode RC:$src1, RC:$src2,
                           (mem_frag addr:$src3)))]>, VEX_W, MemOp4;
  def mr : FMA4<opc, MRMSrcMem, (outs RC:$dst),
           (ins RC:$src1, x86memop:$src2, RC:$src3),
           !strconcat(OpcodeStr,
           "\t{$src3, $src2, $src1, $dst|$dst, $src1, $src2, $src3}"),
           [(set RC:$dst,
             (OpNode RC:$src1, (mem_frag addr:$src2), RC:$src3))]>;

-- Anitha

I actually have confusion in mapping the role of vex_w during
instruction selection. For the moment, lets just consider vex_w and
not memop.

[1]. What does " def rr : FMA4<>, VEX_W" mean? As per tablegen
description, “rr” now inherits FMA4 and VEX_W. However VEX_W is not a
class, it is an enumerated value.

VEX_W is a class, which sets the VEX.W bit to 1.

class VEX_W { bit hasVEX_WPrefix = 1; }

[2]. How does vex_w help in instruction selection in-addition to FMA4 class?

The VEX prefix is part of the instruction encoding. The VEX.W bit modifies the instruction to allow a memory address as a particular source operand, depending on ModRM. The Intel AVX reference calls this “source operand swizzling”.

[3]. Why does only “rr” and “rm” forms have vex_w but not “mr” ?

In order to accept a memory address as the second source operand, the VEX.W bit must not be set. To accept a memory address as the third source operand, the VEX.W bit must be set. The VEX.W bit is of no consequence when all operands are from registers.

-Cameron

...

I actually have confusion in mapping the role of vex_w during

instruction selection. For the moment, lets just consider vex_w and
not memop.

[1]. What does " def rr : FMA4<>, VEX_W" mean? As per tablegen
description, "rr" now inherits FMA4 and VEX_W. However VEX_W is not a
class, it is an enumerated value.

VEX_W is a class, which sets the VEX.W bit to 1.

class VEX_W { bit hasVEX_WPrefix = 1; }

Guess my grep from doxygen turned out to be outdated.

http://llvm.org/docs/doxygen/html/namespacellvm_1_1X86II.html

[3]. Why does only "rr" and "rm" forms have vex_w but not "mr" ?

In order to accept a memory address as the second source operand, the VEX.W
bit must not be set. To accept a memory address as the third source operand,
the VEX.W bit must be set. The VEX.W bit is of no consequence when all
operands are from registers.

Thanks Cameron! That does sort out everything.

- Anitha