mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	Before we learned about :doc:, we used :ref: and put a dummy link at the top of each page. Don't do that anymore. This fixes PR14891 as a special case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172162 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			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:: llvm
 | 
						|
 | 
						|
  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:: llvm
 | 
						|
 | 
						|
  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:: llvm
 | 
						|
 | 
						|
  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:: llvm
 | 
						|
 | 
						|
  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.
 |