TableGen and computed expressions

Hi LLVMDev,

I am revising an existing LLVM backend for a new variant of our CPU
architecture. I have looked at other targets, and the approach used by
Hexagon seems to suit most of my needs quite well, so I am using Predicates
to enable/disable instructions for the architectures. This works very well
for disabling old instructions, and enabling new instructions.

For the remaining instructions there are many which have to be revised, and
these fall into three principal groups:

1. Those that are very different
    I treat these as if they were an old instruction to be retired
    and a new instruction to be introduced.

2. Those whose latencies have changed

3. Those whose mnemonics have changed

For the latter two, I was wondering if there is some way of providing a
computed value instead of a constant?

For example, with the latency issues, the old instruction might have a
latency of 2 - expressed as the constant '2' - while the value for the
revised instruction is '3'. I would like to be able to provide this value
using a function call ( e.g. 'getLatency()'), or some other externally
computed value.

For the mnemonics I was wondering if it is possible to provide a fragment to
'strconcat' from a function call, or perhaps from an array with an index
(e.g. 'AsmFrag[VALUE]')?

I have tried variants of '[{ code }]' but this does not seem to work for me.

I would like to avoid a wholesale replication of 100s of instruction
patterns that really only differ in minute ways; are there any recommended
ways of doing this type of thing with TableGen?

Thanks,

    Martin O'Riordan - Movidius Ltd.

Martin hi.
I encountered a similar problem, and made a solution for it.
The solution is a tblgen enhancement, and enables tblgen code expressions to be dynamically evaluated.
It works as follows:
1. Code expressions have 'special runtime evaluation' expression (very similar to strings in ruby), e.g.:
code c = {[ My name is #{injected}. }.

2. I have added another command line switch for tablegen, named '--inject-value', that assigns values to records upon activation, so you could use it like so:
tblgen --inject-value=injected->Spartacus <other switches and input files>. As a consequence, the record 'c' of 1. Will have the value:
'My name is Spartacus'.

If you find this feature helpful, I am willing to send you a patch and a small 'how to' over.
Yours, Elior.

Thanks Elior,

Sorry for the delay - emergencies never seem to go away in compiler
development :wink:

That sounds like an interesting approach, a kind-of pre-processor for TD
files. But will this still not result in a constant, although externally
provided, or have I misunderstood?

What I would like to do is compute a different value depending on which
'-target-cpu <cpu>' option was selected for 'clang'. The "[{...}]" syntax
should work for this, but I haven't been able to convince TableGen to do
what I want - it maybe a problem with the context I have:

  let attrList = [Attr<2, id1>, Attr<2, id2>] in { ... }

I want to be able to replace the value '2' with the value returned from a
function-call.

I managed to get the opcode name issue resolved in a neat way using
'multiclass' and 'defm' controlled by a predicate, and this worked pretty
well requiring a minimum amount of re-writing and giving me a good
opportunity to cleanup the code, but the list construction outlined above
doesn't seem to be as straight-forward.

All the best,

  MartinO

PS: My next bit of fun will be moving to v3.3 before v3.4 is shipped :slight_smile:

From what I understand you want to be able to define values in TableGen as "function calls" to a specific evaluator that returns a value depending on the architecture subtarget you are compiling for.

As far as I know this is not possible, because TableGen is like a table of values that have to be known at compile time (compile time of the compiler I mean) so that can they can be stored where they are needed (like instruction binary encoding, operand types and numbers , implicit defs ... etc). The solution Elior proposed gives you more flexibility, but it is still a compile time flexibility.

There are certain specific places where in TableGen is possible to inject dynamic behavior , like with predicates for instruction selection patterns or ParseMethods/DecodeMethods (where basically the value stored is the string containing the method to call when it is needed to decode/parse a certain operand) ... etc, but these values have very specialized purposes in llvm tablegen autogenerated code (instruction selection patterns for ISel, Parse method for tablegen generated MCParser code, DecodeMethods for MCDisassembler), for any other kind of values this is not how it works, but the values are stored statically.

Cheers,
Marcello