Llvm-tblgen: how to reference mathcing node (self, this) in Pat?

Hi Everyone,

A question about using Pat in tablegen instruction definitions.
Suppose I have an instruction STORE defined to take 3 parameters: value, address and address space (I want to encode address space in the instruction itself, but that is probably not important). I want to write a pattern that matches SDNode store and extracts address space from it to pass to my instruction. E.g. as follows:

def AddrSpace : SDNodeXForm<timm, [{
  uint64_t Val = cast<MemSDNode>(N)->getAddressSpace();
  return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i64);
}]>;

class STORE : Instruction {
  ...
  dag InOperandList = (ins GPR:$src, MEMri:$addr, i64imm:$aspace)
  ...
}

def : Pat<(store (i64 imm:$src), ADDRri:$dst),
          (STORE $src, ADDRri:$dst, (AddrSpace $this))>;

Details about ADDRri/MEMri are probably not important, but for completeness: ADDRri is a ComplexPattern that returns two i64.

In the current form pattern obviously does not work, as tblgen reports an error for undefined name “this”:

Node 'this' in output pattern but not input pattern

Giving name to store as (store:$this ...) does not work either, fails with internal assertion:

llvm-tblgen: /home/eddy/work/llvm-project/llvm/utils/TableGen/CodeGenDAGPatterns.cpp:3125: bool llvm::TreePattern::InferAllTypes(const StringMap<SmallVector<TreePatternNode *, 1>> *): Assertion `Node->getNumTypes() == 1 && InNodes[0]->getNumTypes() == 1 && "FIXME: cannot name multiple result nodes yet"' failed.

And I can’t figure out from the doc or from existing td files how to actually reference “self”, the node that actually matched, in Pat.

Would be glad to hear an advice.

Thanks,
Eduard

1 Like

Found a usage of (op:$name ...) pattern in existing td file for AVX512 (link):

multiclass vinsert_for_size_lowering<string InstrStr, X86VectorVTInfo From,
                      X86VectorVTInfo To, PatFrag vinsert_insert,
                      SDNodeXForm INSERT_get_vinsert_imm , list<Predicate> p> {
 let Predicates = p in {
   def : Pat<(vinsert_insert:$ins
                    (To.VT To.RC:$src1), (From.VT From.RC:$src2), (iPTR imm)),
             (To.VT (!cast<Instruction>(InstrStr#"rr")
                    To.RC:$src1, From.RC:$src2,
                    (INSERT_get_vinsert_imm To.RC:$ins)))>;

Which suggests that there is something special about store node that does not allow me to write (store:$this ...).

Can you make the ComplexPattern for ADDRri return 3 results, with the address space being the third? If you add the SDNPWantParent on the ComplexPattern, the MemSDNode will get passed as an additional parameter to the ComplexPattern function.

Yes, sounds like a way to go, thank you!