[RFC] TableGen support for RegisterBankInfo v2

Note: This is a continuation of [RFC] TableGen support for RegisterBankInfo - Code Generation / Common CodeGen Infrastructure - LLVM Discussion Forums.

Proposal

This RFC tries to provide a way to define register bank mapping rules by matching TypedOperands, with generating time checks.

Following tablegen classes are introduced:

class RegBankTypeMapping<RegisterBank bank, TypedOperand type> {
  RegisterBank Bank = bank;
  TypedOperand Type = type;
}

class RegBankMappingRule<list<RegBankTypeMapping> typeMappings,
  int cost = 1, int priority = 0, code predicate = [{}]> {
  list<RegBankTypeMapping> TypeMappings = typeMappings;
  int Priority = priority;
  MappingID ID = DefaultMappingID;
  int Cost = cost;
  code Predicate = predicate;
  // TODO: support alternative mapping
  // bit IsAlternative = false;
}

class RegBankInstrMapping<list<GenericInstruction> opcodes,
                          list<RegBankMappingRule> rules> {
  assert !not(!empty(opcodes)), "no opcodes";
  assert !not(!empty(rules)), "no rules";
  list<GenericInstruction> Opcodes = opcodes;
  list<RegBankMappingRule> Rules = rules;
}

A sample mapping rule:

def : RegBankInstrMapping<[G_ADD], [
  RegBankMappingRule<[RegBankTypeMapping<FPRRegBank, type0>],
    predicate=[{Type0.isVector()}]>,
  RegBankMappingRule<[RegBankTypeMapping<GPRRegBank, type0>]>
]>;

Fields explaination

RegBankTypeMapping

  • Type: The operand to match.
  • Bank: This bank will be assigned to operand Type.

RegBankInstrMapping

  • Opcodes: Define mapping rules for these GenericInstructions, these instructions must have the same shape, i.e. after concatenating OutOperandList and InOperandList, all instructions must contain the same kind of TypedOperands, and these operands should be located in the same index.
  • Rules: Mapping rules apply to Opcodes.

RegBankMappingRule

  • TypeMappings: Register bank assignments for TypedOperands, the TypeMappings must cover all TypedOperands in instruction operand list, otherwise, tablegen will issue an error.
  • Priority: Mapping priority, the mapping rule with bigger priority value will appear before rules with smaller priority value in matching function.
  • ID: The instruction mapping ID, which will be passed into RegisterBankInfo::getInstructionMapping.
  • Cost: Mapping cost, which will be passed into RegisterBankInfo::getInstructionMapping.
  • Predicate: When using predicates, the following identifiers are available:
    • LLT [P]Type<N>; which is corresponded to operands in {In,Out}OperandList, i.e. [p]type<N> : TypedOperand.
    • Register <opname>; which is the representative dag operand name in {In,Out}OperandList, i.e. if TypedOperand is type0 then it is the first dag operand name with record type0.

TableGen output

TableGen backend will generate a big value mapping table GeneratedOperandsMappings that covers all instruction shapes and register banks combinations from td file, a helper method

const InstructionMapping& getGeneratedInstructionMapping(const MachineInstr &MI) const;

will make decision by RegBankMappingRule and LLT size for current MI, if it can’t find a proper mapping, it will return a invalid mapping.

Limitations

  • Mappings with break downs are not supported.
  • Only GenericInstructions without varargs are supported.
  • Per operand bank mapping is not supported, although it is possible, this would make the size of value mapping table very big .
  • Alternative mappings are not involved here.
  • HwMode is not considered.

Sample output