[LLVMdev] TableGen and Greenspun

David A. Greene greened at obbligato.org
Thu Oct 6 09:46:50 PDT 2011


greened at obbligato.org (David A. Greene) writes:

> The problem I solved via multidefs was this: how does one write a set of
> Pat<> patterns in a generic way?
>
> For example, I want to be able to do this:
>
> defm MOVH :
>   vs1x_fps_binary_vv_node_rmonly<
>     0x16, "movh", undef, 0,
>            // rr
>            [(undef)],
>            // rm
>            [(set DSTREGCLASS:$dst, 
>                  (DSTTYPE (movlhps SRCREGCLASS:$src1,
>                                  (DSTTYPE (bitconvert
>                                              (v2f64 (scalar_to_vector
>                                                        (loadf64 addr:$src2))))))))],
>            // rr Pat
>            [],
>            // rm Pat
>            [[(DSTTYPE (movlhps SRCREGCLASS:$src1, (load addr:$src2))),
>              (MNEMONIC SRCREGCLASS:$src1, addr:$src2)],
>             [(INTDSTTYPE (movlhps SRCREGCLASS:$src1, (load addr:$src2))),
>              (MNEMONIC SRCREGCLASS:$src1, addr:$src2)]]>;
>
> I need to have the various types substituted and the mnemonic with
> appropriate suffixes substituted.  I need to have this done for each
> Pat<> pattern in the list ("rm Pat" above).  To do this TableGen needs
> to know something about the top-level defm (the "defm name," if you
> will) and something about the types and classes the defm gets
> instantiated with.
>
> Therefore, I need some way to process a list of patterns and do
> substitutions in the context of a specific defm and all of the classes
> it inherits from.

So here's why I think the for loop proposal can't be a preprocessing
phase.  Down in the guts of this I fundamentally need to be able to do
this:

multiclass blah<list<int> Values> {
  for v = Values {
    def DEF#v : base_class<v>;
  }
}

Will that work?  Is the for loop evaluated after parameter binding?

I like the for loop idea.  But it can't be "just" a preprocessing step.

Also, I know I introduced the #..# "pasting" operation but I've found it
to be too limiting.  In this example:

(Equivalent TableGen code with a for-loop)
----------------------------------------
multiclass PTX_FLOAT_4OP<string opcstr, SDNode opnode1, SDNode opnode2> {
  for nbit         = [32, 32, 64, 64],
      op_suffix    = [r, i, r, i],
      op_type      = [RegF32, f32imm, RegF64, f64imm],
      op_node_type = [RegF32, fpimm, RegF64, fpimm] in {
    def rr#op_suffix#nbit
      : InstPTX<(outs RegF#nbit:$d),
                (ins RegF#nbit:$a, RegF#nbit:$b, #op_type:$c),
                !strconcat(opcstr, ".f#nbit\t$d, $a, $b, $c"),
                [(set RegF#nbit:$d,
                   (opnode2 (opnode1 RegF#nbit:$a, RegF#nbit:$b),
                            #op_node_type:$c))]>;
  }
}

what if we instead did this:

(Equivalent TableGen code with a for-loop)
----------------------------------------
multiclass PTX_FLOAT_4OP<string opcstr, SDNode opnode1, SDNode opnode2> {
  for nbit         = [32, 32, 64, 64],
      op_suffix    = [r, i, r, i],
      op_type      = [RegF32, f32imm, RegF64, f64imm],
      op_node_type = [RegF32, fpimm, RegF64, fpimm] in {
    def !strconcat(!strconcat("rr", !cast<string>(op_suffix)), "nbit")
      [...]
  }
}

Yes, it's a bit more verbose but also more flexible in what you can do
with iterator values.

                             -Dave



More information about the llvm-dev mailing list