The live interval of write-only registers

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

The live interval of write-only registers

Tzu-Chien Chiu
In my ISA, some registers are write-only. These registers serve as
output ports, writing to these registers will output the values to an
external device. They cannot be read. So their live intervals should
not be joined with any other registers.

The only way I know to do this is defining several instruction
'templates' for an opcode (of course automatically generated by a
script) similar to the x86 code generator in LLVM:

InstrInfo.td:
// ORC: output register class
// TRC: temp register class

def ADDoaa : Inst<0x1234, (ops ORC:$dest, TRC:$src0, $TRC:src1), "add
$dest, $src0, $src1)

The letters (oaa) postfixed to the opcode (ADD) is the template. In
this way the output register won't be joined because they are of
different register classes.

However, the problem with the method is that there are too many
register classes in the ISA.

for destinations:
o: outptu register
x: a relatively addressed output register
i: integer register
f: floating-point temporary register

for sources:
a: floating-point temporary register
r: a relatively addressed temporary register
c: a constant register holding an immediate values

I do not list all class, but imagine how many combinations there are
for a three-address operations like MAD (multiply-and-add). It's very
very inconvenient in the code generator to manipulate the opcodes
because TableGen generates an 'opcode' for each of the templates of an
operation.

For example, this a code snippet for the file generated by the TableGen tool:

namespace llvm {

namespace Nrw {
  enum {
    PHI, // 0
    ...
    CMPfaaaa, // 16
    CMPfaaar, // 17
    CMPfaara, // 18
    CMPfaarr, // 19
    CMPfaraa, // 20
    CMPfarar, // 21
    CMPfarra, // 22
    CMPfarrr, // 23
    CMPfraaa, // 24
    CMPfraar, // 25
    CMPfrara, // 26
    CMPfrarr, // 27
    CMPfrraa, // 28
    CMPfrrar, // 29
    CMPfrrra, // 30
    CMPfrrrr, // 31


Somewhere in my code, I have to write:

  unsigned opcode = MI->getOpcode(); // MachineInstr*
  if (CMPfaaaa == opcode ||
      CMPfaaar == opcode ||
      CMPfaara == opcode ||
      ...

--
Tzu-Chien Chiu - XGI Technology, Inc.
URL: http://www.csie.nctu.edu.tw/~jwchiu/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Chris Lattner
On Tue, 13 Dec 2005, Tzu-Chien Chiu wrote:

> In my ISA, some registers are write-only. These registers serve as
> output ports, writing to these registers will output the values to an
> external device. They cannot be read. So their live intervals should
> not be joined with any other registers.

Ok.  Since they are not really registers in the sense that LLVM is used
to, I wouldn't suggest even exposing them as registers.  You may as well
just tell LLVM they are immediates or something, and have the asm printer
print them however you like.  As an example, the X86 has I/O ports which
can be read and written to.  These are not thought of as registers, but
they have the same property.  They are accessed with in/out instructions,
not with "register writes".

> The only way I know to do this is defining several instruction
> 'templates' for an opcode (of course automatically generated by a
> script) similar to the x86 code generator in LLVM:
>
> InstrInfo.td:
> // ORC: output register class
> // TRC: temp register class
>
> def ADDoaa : Inst<0x1234, (ops ORC:$dest, TRC:$src0, $TRC:src1), "add
> $dest, $src0, $src1)
>
> The letters (oaa) postfixed to the opcode (ADD) is the template. In
> this way the output register won't be joined because they are of
> different register classes.

Yes.  Following the same approach, defining the output registers as
immediates would also work, and would guarantee that the register
allocator wouldn't try to spill their values or do anything else nasty.

> However, the problem with the method is that there are too many
> register classes in the ISA.
>
> for destinations:
> o: outptu register
> x: a relatively addressed output register
> i: integer register
> f: floating-point temporary register
>
> for sources:
> a: floating-point temporary register
> r: a relatively addressed temporary register
> c: a constant register holding an immediate values
>
> I do not list all class, but imagine how many combinations there are
> for a three-address operations like MAD (multiply-and-add). It's very
> very inconvenient in the code generator to manipulate the opcodes
> because TableGen generates an 'opcode' for each of the templates of an
> operation.

Yes, this is a lot.  :(

> For example, this a code snippet for the file generated by the TableGen tool:
...
> Somewhere in my code, I have to write:
>  unsigned opcode = MI->getOpcode(); // MachineInstr*
>  if (CMPfaaaa == opcode ||
>      CMPfaaar == opcode ||
>      CMPfaara == opcode ||
>      ...

Where do you have to write this code?

-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Tzu-Chien Chiu
2005/12/13, Chris Lattner <[hidden email]>:

> > For example, this a code snippet for the file generated by the TableGen tool:
> ...
> > Somewhere in my code, I have to write:
> >  unsigned opcode = MI->getOpcode(); // MachineInstr*
> >  if (CMPfaaaa == opcode ||
> >      CMPfaaar == opcode ||
> >      CMPfaara == opcode ||
> >      ...
>
> Where do you have to write this code?
>
> -Chris

Some machine idioms and instruction combining passes.

--
Tzu-Chien Chiu - XGI Technology, Inc.
URL: http://www.csie.nctu.edu.tw/~jwchiu/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Chris Lattner
On Tue, 13 Dec 2005, Tzu-Chien Chiu wrote:

> 2005/12/13, Chris Lattner <[hidden email]>:
>>> For example, this a code snippet for the file generated by the TableGen tool:
>> ...
>>> Somewhere in my code, I have to write:
>>>  unsigned opcode = MI->getOpcode(); // MachineInstr*
>>>  if (CMPfaaaa == opcode ||
>>>      CMPfaaar == opcode ||
>>>      CMPfaara == opcode ||
>>>      ...
>>
>> Where do you have to write this code?
>
> Some machine idioms and instruction combining passes.

Ok, in that case, I suggest either writing helper functions that
encapsulate these predicates (e.g. is_op0_r) or modifying tablegen to
produce them for you.  Do you have any other suggestions or ideas?

-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Tzu-Chien Chiu
In reply to this post by Chris Lattner
2005/12/13, Chris Lattner <[hidden email]>:

> On Tue, 13 Dec 2005, Tzu-Chien Chiu wrote:
>
> > In my ISA, some registers are write-only. These registers serve as
> > output ports, writing to these registers will output the values to an
> > external device. They cannot be read. So their live intervals should
> > not be joined with any other registers.
>
> Ok.  Since they are not really registers in the sense that LLVM is used
> to, I wouldn't suggest even exposing them as registers.  You may as well
> just tell LLVM they are immediates or something, and have the asm printer
> print them however you like.  As an example, the X86 has I/O ports which
> can be read and written to.  These are not thought of as registers, but
> they have the same property.  They are accessed with in/out instructions,
> not with "register writes".

If the output register is represented by an immediate operand or
belongs to a different register class, the following sequence:

  add %reg1024, %reg1025, %reg1026
  out %o1, %reg1024
  // out is an intrinsic, there is no such machine instruction
  // o1 is a write-only output register, mapping to a physical output port

cannot be changed to:

  add %o1, %reg1025, %reg1026

because LiveIntervals::joinIntervalsInMachineBB() requires one of the
operands of a 'move' instruction (the 'out' intrinsic in this example)
to be a virtual register and both must be in the same register class.

Note this operation cannot be performed in the instruction selector
because %reg1024 must live after the 'out' intrinsic.

--
Tzu-Chien Chiu - XGI Technology, Inc.
URL: http://www.csie.nctu.edu.tw/~jwchiu/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Andrew Lenharth-2
In reply to this post by Tzu-Chien Chiu
On Mon, 2005-12-12 at 23:24, Tzu-Chien Chiu wrote:

> 2005/12/13, Chris Lattner <[hidden email]>:
> > > For example, this a code snippet for the file generated by the TableGen tool:
> > ...
> > > Somewhere in my code, I have to write:
> > >  unsigned opcode = MI->getOpcode(); // MachineInstr*
> > >  if (CMPfaaaa == opcode ||
> > >      CMPfaaar == opcode ||
> > >      CMPfaara == opcode ||
> > >      ...
> >
> > Where do you have to write this code?
> >
> > -Chris
>
> Some machine idioms and instruction combining passes.

You might consider a target specific flag on those instructions:

let isSpecial = 1 in {
instr defs
...
}

Andrew

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: The live interval of write-only registers

Chris Lattner
In reply to this post by Tzu-Chien Chiu
On Tue, 13 Dec 2005, Tzu-Chien Chiu wrote:

> 2005/12/13, Chris Lattner <[hidden email]>:
>>> In my ISA, some registers are write-only. These registers serve as
>>> output ports, writing to these registers will output the values to an
>>> external device. They cannot be read. So their live intervals should
>>> not be joined with any other registers.
>>
>> Ok.  Since they are not really registers in the sense that LLVM is used
>> to, I wouldn't suggest even exposing them as registers.  You may as well
>> just tell LLVM they are immediates or something, and have the asm printer
>> print them however you like.  As an example, the X86 has I/O ports which
>> can be read and written to.  These are not thought of as registers, but
>> they have the same property.  They are accessed with in/out instructions,
>> not with "register writes".
>
> If the output register is represented by an immediate operand or
> belongs to a different register class, the following sequence:
>
>  add %reg1024, %reg1025, %reg1026
>  out %o1, %reg1024
>  // out is an intrinsic, there is no such machine instruction
>  // o1 is a write-only output register, mapping to a physical output port
>
> cannot be changed to:
>
>  add %o1, %reg1025, %reg1026
>
> because LiveIntervals::joinIntervalsInMachineBB() requires one of the
> operands of a 'move' instruction (the 'out' intrinsic in this example)
> to be a virtual register and both must be in the same register class.

I see, you're right.  To do this, you'd need an "out" form of add, and
have the instruction selector match it.  You may not want yet-another form
for each instruction.


-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev