Instruction with variable number of outputs

Hi,

After Bob fixed the two-address format of the ARM ldm/stm instructions, a problem remains. The load multiple instruction looks like:

// A list of registers separated by comma. Used by load/store multiple.
def reglist : Operand<i32> {
  let PrintMethod = "printRegisterList";
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
                          reglist:$dsts, variable_ops),
                 IndexModeNone, LdStMulFrm, IIC_iLoadm,
                 "ldm${addr:submode}${p}\t$addr, $dsts", "", []>;

Tablegen produces an instruction description with 5 input operands: 2 for $addr, 2 for $p, and 1 for $dsts. But $dsts and the following variable_ops are all outputs!

The description should only have 4 operands + variable_ops.

How can you specify a named, variable list of output operands?

Perhaps this could be made to work:

def reglist : Operand<i32> {
  let PrintMethod = "printRegisterList";
  let MIOperandInfo = (ops variable_ops);
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p, reglist:$dsts),

Hi,

After Bob fixed the two-address format of the ARM ldm/stm instructions, a problem remains. The load multiple instruction looks like:

// A list of registers separated by comma. Used by load/store multiple.
def reglist : Operand<i32> {
let PrintMethod = "printRegisterList";
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
                         reglist:$dsts, variable_ops),
                IndexModeNone, LdStMulFrm, IIC_iLoadm,
                "ldm${addr:submode}${p}\t$addr, $dsts", "", []>;

Tablegen produces an instruction description

Ok, you mean TargetInstrDesc, right?

with 5 input operands: 2 for $addr, 2 for $p, and 1 for $dsts. But $dsts and the following variable_ops are all outputs!

Right, variable_ops means that it takes a variable number of operands, not that an operand has a variable number of registers.

The description should only have 4 operands + variable_ops.

How can you specify a named, variable list of output operands?

Why do you need to do this? You currently can't do it.

-Chris

Hi,

After Bob fixed the two-address format of the ARM ldm/stm instructions, a problem remains. The load multiple instruction looks like:

// A list of registers separated by comma. Used by load/store multiple.
def reglist : Operand<i32> {
let PrintMethod = "printRegisterList";
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
                        reglist:$dsts, variable_ops),
               IndexModeNone, LdStMulFrm, IIC_iLoadm,
               "ldm${addr:submode}${p}\t$addr, $dsts", "", []>;

Tablegen produces an instruction description

Ok, you mean TargetInstrDesc, right?

Yes.

with 5 input operands: 2 for $addr, 2 for $p, and 1 for $dsts. But $dsts and the following variable_ops are all outputs!

Right, variable_ops means that it takes a variable number of operands, not that an operand has a variable number of registers.

The description should only have 4 operands + variable_ops.

How can you specify a named, variable list of output operands?

Why do you need to do this? You currently can't do it.

Because an instruction like LDM loads a variable number of registers. When it specifies "reglist:$dsts, variable_ops", those are really output registers, the registers being loaded.

I am assuming that the operands on a machine instruction are, in order: fixed outs, fixed ins, variable ops, implicit ops. The variable ops can be inputs or outputs.

As far as I can tell, this is only a problem with verification. The operand corresponding to $dsts is a <def>, but the TargetInstrDesc says that it is one of the fixed inputs. The following operands are fine as they fall in the variable_ops part of the instruction.

I need a way of referring to the variable_ops by name without forcing the first operand to be an input.

def reglist : Operand<i32> {
let PrintMethod = "printRegisterList";
let MIOperandInfo = (ops variable_ops);
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p, reglist:$dsts),

This syntax is not ideal, because reglist:$dsts is a variable list of output operands. But at least there is no extra input operand.

I need a way of describing the LDM instruction with:

Fixed outputs: none
Fixed inputs: addr and pred
Variable ops: list of output registers

This produces the right TargetInstrDesc:

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p, variable_ops)

But now there is no way of referring to the reglist in the asm pattern, and there is no way of specifying that the reglist should be printed with "printRegisterList"

The basic problem is that variable_ops require an 'anchor operand' to get a $name and to specify a PrintMethod. The anchor operand is forced to be an input by the current syntax, as far as I can tell.

/jakob

The description should only have 4 operands + variable_ops.

How can you specify a named, variable list of output operands?

Why do you need to do this? You currently can't do it.

Because an instruction like LDM loads a variable number of registers. When it specifies "reglist:$dsts, variable_ops", those are really output registers, the registers being loaded.

Ah, gotcha. LDM is a particularly evil instruction to model. I agree it is best to model them as a variable number of outputs.

I am assuming that the operands on a machine instruction are, in order: fixed outs, fixed ins, variable ops, implicit ops. The variable ops can be inputs or outputs.

As far as I can tell, this is only a problem with verification. The operand corresponding to $dsts is a <def>, but the TargetInstrDesc says that it is one of the fixed inputs. The following operands are fine as they fall in the variable_ops part of the instruction.

I need a way of referring to the variable_ops by name without forcing the first operand to be an input.

Ok.

def reglist : Operand<i32> {
let PrintMethod = "printRegisterList";
let MIOperandInfo = (ops variable_ops);
}

def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p, reglist:$dsts),

This syntax is not ideal, because reglist:$dsts is a variable list of output operands. But at least there is no extra input operand.

I need a way of describing the LDM instruction with:

Fixed outputs: none
Fixed inputs: addr and pred
Variable ops: list of output registers

I would prefer to spell this as:

def LDM : AXI4ld<(outs reglist:$dsts), (ins addrmode4:$addr, pred:$p),

Would this work? You could change 'reglist' to have one fixed operand and the rest variable? There is no reason to support the 'no output' form of reglist.

-Chris

That spelling is better, but you probably want to keep all the reglist operands optional. We don't need to support an empty reglist, but since fixed outputs go first on the machine instruction, the reglist would be broken up:

reglist[0], addr[0], addr[1], pred[0], pred[1], reglist[1], reglist[2], ...

We don't want that. We want this:

addr[0], addr[1], pred[0], pred[1], reglist[0], reglist[1], reglist[2], ...

So we need to change tablegen to support variable_ops in MIOperandInfo on the last element of either outs or ins.

I'll look into it when I get the time.

/jakob