| =============================== | |
| How To Use Instruction Mappings | |
| =============================== | |
| .. contents:: | |
| :local: | |
| Introduction | |
| ============ | |
| This document contains information about adding instruction mapping support | |
| for a target. The motivation behind this feature comes from the need to switch | |
| between different instruction formats during various optimizations. One approach | |
| could be to use switch cases which list all the instructions along with formats | |
| they can transition to. However, it has large maintenance overhead | |
| because of the hardcoded instruction names. Also, whenever a new instruction is | |
| added in the .td files, all the relevant switch cases should be modified | |
| accordingly. Instead, the same functionality could be achieved with TableGen and | |
| some support from the .td files for a fraction of maintenance cost. | |
| ``InstrMapping`` Class Overview | |
| =============================== | |
| TableGen uses relationship models to map instructions with each other. These | |
| models are described using ``InstrMapping`` class as a base. Each model sets | |
| various fields of the ``InstrMapping`` class such that they can uniquely | |
| describe all the instructions using that model. TableGen parses all the relation | |
| models and uses the information to construct relation tables which relate | |
| instructions with each other. These tables are emitted in the | |
| ``XXXInstrInfo.inc`` file along with the functions to query them. Following | |
| is the definition of ``InstrMapping`` class definied in Target.td file: | |
| .. code-block:: text | |
| class InstrMapping { | |
| // Used to reduce search space only to the instructions using this | |
| // relation model. | |
| string FilterClass; | |
| // List of fields/attributes that should be same for all the instructions in | |
| // a row of the relation table. Think of this as a set of properties shared | |
| // by all the instructions related by this relationship. | |
| list<string> RowFields = []; | |
| // List of fields/attributes that are same for all the instructions | |
| // in a column of the relation table. | |
| list<string> ColFields = []; | |
| // Values for the fields/attributes listed in 'ColFields' corresponding to | |
| // the key instruction. This is the instruction that will be transformed | |
| // using this relation model. | |
| list<string> KeyCol = []; | |
| // List of values for the fields/attributes listed in 'ColFields', one for | |
| // each column in the relation table. These are the instructions a key | |
| // instruction will be transformed into. | |
| list<list<string> > ValueCols = []; | |
| } | |
| Sample Example | |
| -------------- | |
| Let's say that we want to have a function | |
| ``int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)`` which | |
| takes a non-predicated instruction and returns its predicated true or false form | |
| depending on some input flag, ``inPredSense``. The first step in the process is | |
| to define a relationship model that relates predicated instructions to their | |
| non-predicated form by assigning appropriate values to the ``InstrMapping`` | |
| fields. For this relationship, non-predicated instructions are treated as key | |
| instruction since they are the one used to query the interface function. | |
| .. code-block:: text | |
| def getPredOpcode : InstrMapping { | |
| // Choose a FilterClass that is used as a base class for all the | |
| // instructions modeling this relationship. This is done to reduce the | |
| // search space only to these set of instructions. | |
| let FilterClass = "PredRel"; | |
| // Instructions with same values for all the fields in RowFields form a | |
| // row in the resulting relation table. | |
| // For example, if we want to relate 'ADD' (non-predicated) with 'Add_pt' | |
| // (predicated true) and 'Add_pf' (predicated false), then all 3 | |
| // instructions need to have same value for BaseOpcode field. It can be any | |
| // unique value (Ex: XYZ) and should not be shared with any other | |
| // instruction not related to 'add'. | |
| let RowFields = ["BaseOpcode"]; | |
| // List of attributes that can be used to define key and column instructions | |
| // for a relation. Key instruction is passed as an argument | |
| // to the function used for querying relation tables. Column instructions | |
| // are the instructions they (key) can transform into. | |
| // | |
| // Here, we choose 'PredSense' as ColFields since this is the unique | |
| // attribute of the key (non-predicated) and column (true/false) | |
| // instructions involved in this relationship model. | |
| let ColFields = ["PredSense"]; | |
| // The key column contains non-predicated instructions. | |
| let KeyCol = ["none"]; | |
| // Two value columns - first column contains instructions with | |
| // PredSense=true while second column has instructions with PredSense=false. | |
| let ValueCols = [["true"], ["false"]]; | |
| } | |
| TableGen uses the above relationship model to emit relation table that maps | |
| non-predicated instructions with their predicated forms. It also outputs the | |
| interface function | |
| ``int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)`` to query | |
| the table. Here, Function ``getPredOpcode`` takes two arguments, opcode of the | |
| current instruction and PredSense of the desired instruction, and returns | |
| predicated form of the instruction, if found in the relation table. | |
| In order for an instruction to be added into the relation table, it needs | |
| to include relevant information in its definition. For example, consider | |
| following to be the current definitions of ADD, ADD_pt (true) and ADD_pf (false) | |
| instructions: | |
| .. code-block:: text | |
| def ADD : ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$a, IntRegs:$b), | |
| "$dst = add($a, $b)", | |
| [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$a), | |
| (i32 IntRegs:$b)))]>; | |
| def ADD_Pt : ALU32_rr<(outs IntRegs:$dst), | |
| (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), | |
| "if ($p) $dst = add($a, $b)", | |
| []>; | |
| def ADD_Pf : ALU32_rr<(outs IntRegs:$dst), | |
| (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), | |
| "if (!$p) $dst = add($a, $b)", | |
| []>; | |
| In this step, we modify these instructions to include the information | |
| required by the relationship model, <tt>getPredOpcode</tt>, so that they can | |
| be related. | |
| .. code-block:: text | |
| def ADD : PredRel, ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$a, IntRegs:$b), | |
| "$dst = add($a, $b)", | |
| [(set (i32 IntRegs:$dst), (add (i32 IntRegs:$a), | |
| (i32 IntRegs:$b)))]> { | |
| let BaseOpcode = "ADD"; | |
| let PredSense = "none"; | |
| } | |
| def ADD_Pt : PredRel, ALU32_rr<(outs IntRegs:$dst), | |
| (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), | |
| "if ($p) $dst = add($a, $b)", | |
| []> { | |
| let BaseOpcode = "ADD"; | |
| let PredSense = "true"; | |
| } | |
| def ADD_Pf : PredRel, ALU32_rr<(outs IntRegs:$dst), | |
| (ins PredRegs:$p, IntRegs:$a, IntRegs:$b), | |
| "if (!$p) $dst = add($a, $b)", | |
| []> { | |
| let BaseOpcode = "ADD"; | |
| let PredSense = "false"; | |
| } | |
| Please note that all the above instructions use ``PredRel`` as a base class. | |
| This is extremely important since TableGen uses it as a filter for selecting | |
| instructions for ``getPredOpcode`` model. Any instruction not derived from | |
| ``PredRel`` is excluded from the analysis. ``BaseOpcode`` is another important | |
| field. Since it's selected as a ``RowFields`` of the model, it is required | |
| to have the same value for all 3 instructions in order to be related. Next, | |
| ``PredSense`` is used to determine their column positions by comparing its value | |
| with ``KeyCol`` and ``ValueCols``. If an instruction sets its ``PredSense`` | |
| value to something not used in the relation model, it will not be assigned | |
| a column in the relation table. |