TableGen pattern for negated operand

I've been unable to come up with the TableGen recipe to match a
negated operand. My target asm syntax allows the following transform:

  FNEG r8, r5
  MUL r6, r8, r9

to

  MUL r6, -r5, r9

Is there a Pattern<> syntax that would allow matching *any* opcode (or
even some subset), not just MUL, with a FNEG'd operand? I expect I can
define a PatFrag:

def fneg_su : PatFrag<(ops node:$val), (fneg node:$val), [{ return
N->hasOneUse(); }]>;

and then use that in each target instruction patten in XXXInstrInfo.td, such as:

def XXX_MUL : XXXInst<
   (outs GPR32:$dst),
   (ins GPR32:$src1, GPR32:$src2),
   "mul $dst, -$src1, $src2",
   [(set $dst, (mul (fneg_su GPR32:$src1), GPR32:$src2))]>;

but I would like to believe there's a way to do this with a Pattern<>
definition instead, with help from PatFrag and the SDNode_XFORM
perhaps.

I looked at the ARM target code with PatFrag for negated immediates
but that approach doesn't seem possible with register operands, as I
don't know what xform would operate on. With immediates you have a DAG
node you can generate.

Also, it does seem like this is a folding operation
PerformDAGCombine() could do but that approach seems like it needs to
modify the registerclass, or something similar, that would eventually
get you to a PrintMethod that could insert the dash/negate in front of
the operand. I didn't want to define a 'mirror' registerclass for my
existing register set that would just have the Name as the negated
version. That would have its own complications. Is there a superior
way to do this with DAG combine?

Thanks,
Joe

Hi Joe,

I've been unable to come up with the TableGen recipe to match a
negated operand. My target asm syntax allows the following transform:

   FNEG r8, r5
   MUL r6, r8, r9

to

   MUL r6, -r5, r9

Is there a Pattern<> syntax that would allow matching *any* opcode (or
even some subset), not just MUL, with a FNEG'd operand?

You may custom lower all binops, no matter which one, and create custom nodes if it meets that condition. But I think a better solution would be to add pattern matching rules for all of them systematically. IMO it's cleaner and easier to maintain. You can use multiclasses :

multiclass Inst< node op, string opc> {
     def _rr : Instruction<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
         "!strcat(opc, " $dst, $src1, $src2")",
             [(set $dst, (op GPR32:$src1, GPR32:$src2))]>;

     def _fneg_rr : Instruction<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2),
         "!strcat(opc, " $dst, -$src1, $src2")",
             [(set $dst, (op (fneg_su GPR32:$src1), GPR32:$src2)))]>;
}

  I expect I can
define a PatFrag:

def fneg_su : PatFrag<(ops node:$val), (fneg node:$val), [{ return
N->hasOneUse(); }]>;

AFAIK, you don't need to verify for hasOneUse() because the instruction selector will do it for you. Also, it's too restrictive if fneg_su is used alone in some other matching rule.

and then use that in each target instruction patten in XXXInstrInfo.td, such as:

def XXX_MUL : XXXInst<
    (outs GPR32:$dst),
    (ins GPR32:$src1, GPR32:$src2),
    "mul $dst, -$src1, $src2",
    [(set $dst, (mul (fneg_su GPR32:$src1), GPR32:$src2))]>;

but I would like to believe there's a way to do this with a Pattern<>
definition instead, with help from PatFrag and the SDNode_XFORM
perhaps.

I looked at the ARM target code with PatFrag for negated immediates
but that approach doesn't seem possible with register operands, as I
don't know what xform would operate on. With immediates you have a DAG
node you can generate.

Also, it does seem like this is a folding operation
PerformDAGCombine() could do but that approach seems like it needs to
modify the registerclass, or something similar, that would eventually
get you to a PrintMethod that could insert the dash/negate in front of
the operand. I didn't want to define a 'mirror' registerclass for my
existing register set that would just have the Name as the negated
version. That would have its own complications. Is there a superior
way to do this with DAG combine?

I don't see how you can implement this in the combiner phase. May be someone else can help you.

Ivan

Thanks for the reply Ivan.

I ended up writing a MachineFunctionPass to handle it, using the code
for FoldImmediate in the peephole optimizer as a guide.

Just thought I'd reply to archive my solution on the mail list.

Joe