| =============================== |
| 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. |