176 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
| ===============================
 | |
| 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.
 |