custom lowering with multiple results

Here's a concrete example of what I'm having problems with:
trying to use LowerOperation to replace one node with two nodes.

Imagine I have a new instruction "read_world" that sets the status flags
according to some kind of global state. In order to generate this instruction I
have a built-in function with the prototype "int __builtin_read_world(void)".

I also have a new instruction "read_flags" that sets a register according to the
status flags so I can translate a call to __builtin_read_world into a
"read_world" followed by a "read_flags" (at least as a last resort; I'm
expecting the "read_flags" instruction to be optimised away in most cases).

Attached is the patch I have attempted to use to implement this. It's mostly
boring (though I may have made a stupid error in the boring bits). The most
interesting bit is in ARMISelLowering.[ch] where I add the DAG nodes READ_WORLD
and READ_FLAGS and translate Intrinsic::arm_read_world into a READ_WORLD
followed by a READ_FLAGS. This is the bit I'm most worried about as I'm getting
ARMTargetLowering::LowerOperation to do something slightly more complicated than
usual. I may have broken some rule about what LowerOperation is allowed to do.

When I feed the patched Clang/LLVM with the source code

// clang -cc1 -triple thumbv7-eabi -target-cpu cortex-a8 t.c -O3 -S -o t.s

int f1()
{
  return __builtin_read_world();
}

I get:

clang: InstrEmitter.cpp:667: ...
"#operands for dag node doesn't match .td file!"' failed.

What have I done wrong?

Any clues gratefully received.

Edmund

read_world.patch (5.71 KB)

Hi Edmund,

We did some custom lowering for the reminder operation (move the
remainder from R1 to R0), maybe that's more or less what you need?

See in the patch I sent last week (rt-abi), or you can ask Evzen about
it directly.

cheers,
--renato

Hello, Edmund

Here's a concrete example of what I'm having problems with:
trying to use LowerOperation to replace one node with two nodes.

I don't see any problem with such usage. There are a lot of examples
in the current codebase for this.

clang: InstrEmitter.cpp:667: ...
"#operands for dag node doesn't match .td file!"' failed.

Well... You created a node with wrong number of operands. Check how
you created stuff and declared in .td.

In your case:
- for (unsigned i = 0, e = Node->getNumValues(); i != e; ++i) {
+ for (unsigned i = 0, e = Tmp1->getNumValues(); i != e; ++i) {
This hunks looks potentially invalid

And how do you handle chain for your node? You can just gdb at the
place of the assertion and check the expected and provided # of
operands.