Operand order in dag pattern matching in td files

Hi,

I have a simple question w.r.t the order of operands used in dag
pattern matching in target files. Some of them seem intuitive. But I
want to get it clarified anyway. I am using a pattern from
X86InstrFMA.td in the below example. Consider FMA3 pattern
(simplified).

let Constraints = "$src1 = $dst" in {
multiclass fma3s_rm<bits<8> opc, string OpcodeStr, X86MemOperand x86memop,
                    RegisterClass RC, ValueType OpVT, PatFrag mem_frag,
                    SDPatternOperator OpNode = null_frag> {

  def r : FMA3<opc, MRMSrcReg, (outs RC:$dst),
                   (ins RC:$src1, RC:$src2, RC:$src3),
                   !strconcat(OpcodeStr,
                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
                   [(set RC:$dst,
                     (OpVT (OpNode RC:$src2, RC:$src1, RC:$src3)))]>;

Given that it is an FMA pattern, the OpNode can be one of X86Fmadd,
X86Fmsub (among other opnodes). The respective operations are :
(a*b+c) and (a*b-c). My questions are:

1. Why does $src2 and not $src1 come first in (OpNode RC:$src2,
RC:$src1, RC:$src3) ? In other words what is the difference between
(a) and (b):
   (a) [(set RC:$dst, (OpVT (OpNode RC:$src2, RC:$src1, RC:$src3)))]
   (b) [(set RC:$dst,(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]

2. Why happens when OpNode is null_frag?

Hi,

I have a simple question w.r.t the order of operands used in dag
pattern matching in target files. Some of them seem intuitive. But I
want to get it clarified anyway. I am using a pattern from
X86InstrFMA.td in the below example. Consider FMA3 pattern
(simplified).

let Constraints = "$src1 = $dst" in {
multiclass fma3s_rm<bits<8> opc, string OpcodeStr, X86MemOperand x86memop,
                    RegisterClass RC, ValueType OpVT, PatFrag mem_frag,
                    SDPatternOperator OpNode = null_frag> {

  def r : FMA3<opc, MRMSrcReg, (outs RC:$dst),
                   (ins RC:$src1, RC:$src2, RC:$src3),
                   !strconcat(OpcodeStr,
                              "\t{$src3, $src2, $dst|$dst, $src2, $src3}"),
                   [(set RC:$dst,
                     (OpVT (OpNode RC:$src2, RC:$src1, RC:$src3)))]>;

Given that it is an FMA pattern, the OpNode can be one of X86Fmadd,
X86Fmsub (among other opnodes). The respective operations are :
(a*b+c) and (a*b-c). My questions are:

1. Why does $src2 and not $src1 come first in (OpNode RC:$src2,
RC:$src1, RC:$src3) ? In other words what is the difference between
(a) and (b):
   (a) [(set RC:$dst, (OpVT (OpNode RC:$src2, RC:$src1, RC:$src3)))]
   (b) [(set RC:$dst,(OpVT (OpNode RC:$src1, RC:$src2, RC:$src3)))]

Typo.

2. Why happens when OpNode is null_frag?

2. What happens when OpNode is null_frag?

You’ve unfortunately chosen a complex example.

Your second question is needs be answered first. null_frag causes the pattern to be dropped.

Now having covered that the reason the operands are in the order they are is because the only instruction that doesn’t use null_frag is this one

defm r213 : fma3s_rm<opc213, !strconcat(OpStr, !strconcat(“213”, PackTy)),
x86memop, RC, OpVT, mem_frag, OpNode>

Which specifies the operand order as 213 thus why they are 2, 1, 3 in the pattern.

~Craig

Thanks. I get it. Looking into DAGCombiner and X86ISelLowering made it
more clear.

I am just wondering if there is any reason why only "213" form of FMA
is supported. Is it more of an initial support? Clearly it impacts
performance negatively when "231" or "132" forms are required (due to
the store/move of operands).

-Anitha