What's RegState usage?

I have read RegState usage in MachineInstrBuilder.h. No further information was obtained in src code or doc. But my backend always use BuildMI to set Register flag.
I hope someone can describe these states in detail.
thanks.

namespace RegState {

enum {
Define = 0x2,
Implicit = 0x4,
Kill = 0x8,
Dead = 0x10,
Undef = 0x20,
EarlyClobber = 0x40,
Debug = 0x80,
InternalRead = 0x100,
Renamable = 0x200,
DefineNoRead = Define | Undef,
ImplicitDefine = Implicit | Define,
ImplicitKill = Implicit | Kill
};

} // end namespace RegState

1 Like

Most of these flags keep information about register liveness. Register is “live” at a given point in the program if its value could be used in a subsequent instruction. More specifically, if there exists an execution path from the given location to an instruction that uses this register (without an intervening modification, obviously). The assumed operation of each instruction is that all input (use) operands are read first, then the output operand(s) are written to.

  • Define means that this operand puts a new value in the register. This applies to output operands.
  • Implicit means that the instruction accesses this register, but this register is not a part of the instruction syntax. For example, branches modify the program counter (instruction pointer, etc.), but this register is not explicitly provided to the instruction as an operand.
  • Kill means that this operand is the last use (it only applies to use operands), i.e. that after this point the register is no longer live.
  • Dead is an extra flag that is added to “define” operands, if the value in the register is never used. This is kind of like “kill”, which indicates that the register is dead after this point, except “kill” means “last use”, and here there aren’t any uses to begin with.
  • Undef can have several meanings. When it’s on a use operand, it means that the register is used, but that its value is unimportant. For example, if you want to put 0 in a register, you could do “reg = xor reg, reg”, and it doesn’t matter what value “reg” has. If the register was not dead, it would be an error to have it in a use operand without the “undef” flag. When it’s used on a def, it only really applies to a definition of a sub-register, and it means that the remaining part of the super-register may not be preserved.
  • EarlyClobber means that this output operand may be modified before the instruction has read all of its input operands. This tells the register allocator that a register allocated for this operand should not be an input register at the same time.
  • Debug means that this is a register operand in a debug instruction. These operands aren’t generally subjected to the same scrutiny when it comes to liveness analysis.
  • InternalRead applies to input operands within instruction bundles. Normally, an instruction bundle is treated a single large instruction, i.e. all input operands from all instructions in the bundle are read first, then all outputs are written to. This implies that any use operand will read a value that was set prior to executing this bundle. “Internal read” means that this particular input operand will a value that was set within the bundle.
  • Renamable applies to physical registers, and it means that the register may be changed to another register. An example where a register cannot be renamed is in instructions that load arguments into registers before a function call. Most registers in most cases are renamable.
4 Likes

Thank you very much.
I got it.

This is a really good explanation! Any chance you can add it to the enum definitions in the source code? :smile:

1 Like