[llvm-commits] [llvm] r166685 - in /llvm/trunk: docs/HowToUseInstrMappings.rst docs/WritingAnLLVMBackend.html include/llvm/Target/Target.td utils/TableGen/CodeGenMapTable.cpp utils/TableGen/InstrInfoEmitter.cpp utils/TableGen/TableGenBackends.h
David Blaikie
dblaikie at gmail.com
Thu Oct 25 10:06:38 PDT 2012
On Thu, Oct 25, 2012 at 8:54 AM, Sebastian Pop <spop at codeaurora.org> wrote:
> Author: spop
> Date: Thu Oct 25 10:54:06 2012
> New Revision: 166685
>
> URL: http://llvm.org/viewvc/llvm-project?rev=166685&view=rev
> Log:
> add TableGen support to create relationship maps between instructions
>
> Relationship maps are represented as InstrMapping records which are parsed by
> TableGen and the information is used to construct mapping tables to represent
> appropriate relations between instructions. These tables are emitted into
> XXXGenInstrInfo.inc file along with the functions to query them.
>
> Patch by Jyotsna Verma <jverma at codeaurora.org>.
>
> Added:
> llvm/trunk/docs/HowToUseInstrMappings.rst (with props)
> llvm/trunk/utils/TableGen/CodeGenMapTable.cpp
> Modified:
> llvm/trunk/docs/WritingAnLLVMBackend.html
> llvm/trunk/include/llvm/Target/Target.td
> llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
> llvm/trunk/utils/TableGen/TableGenBackends.h
>
> Added: llvm/trunk/docs/HowToUseInstrMappings.rst
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HowToUseInstrMappings.rst?rev=166685&view=auto
> ==============================================================================
> --- llvm/trunk/docs/HowToUseInstrMappings.rst (added)
> +++ llvm/trunk/docs/HowToUseInstrMappings.rst Thu Oct 25 10:54:06 2012
> @@ -0,0 +1,179 @@
> +.. _how_to_use_instruction_mappings:
> +
> +===============================
> +How To Use Instruction Mappings
> +===============================
> +
> +.. sectionauthor:: Jyotsna Verma <jverma at codeaurora.org>
> +
> +.. 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.
>
> Propchange: llvm/trunk/docs/HowToUseInstrMappings.rst
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Modified: llvm/trunk/docs/WritingAnLLVMBackend.html
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/WritingAnLLVMBackend.html?rev=166685&r1=166684&r2=166685&view=diff
> ==============================================================================
> --- llvm/trunk/docs/WritingAnLLVMBackend.html (original)
> +++ llvm/trunk/docs/WritingAnLLVMBackend.html Thu Oct 25 10:54:06 2012
> @@ -32,6 +32,7 @@
> <li><a href="#InstructionSet">Instruction Set</a>
> <ul>
> <li><a href="#operandMapping">Instruction Operand Mapping</a></li>
> + <li><a href="#relationMapping">Instruction Relation Mapping</a></li>
> <li><a href="#implementInstr">Implement a subclass of TargetInstrInfo</a></li>
> <li><a href="#branchFolding">Branch Folding and If Conversion</a></li>
> </ul></li>
> @@ -1259,6 +1260,29 @@
>
> <!-- ======================================================================= -->
> <h3>
> + <a name="relationMapping">Instruction Relation Mapping</a>
> +</h3>
> +
> +<div>
> +
> +<p>
> +This TableGen feature is used to relate instructions with each other. It is
> +particularly useful when you have multiple instruction formats and need to
> +switch between them after instruction selection. This entire feature is driven
> +by relation models which can be defined in <tt>XXXInstrInfo.td</tt> files
> +according to the target-specific instruction set. Relation models are defined
> +using <tt>InstrMapping</tt> class as a base. TableGen parses all the models
> +and generates instruction relation maps using the specified information.
> +Relation maps are emitted as tables in the <tt>XXXGenInstrInfo.inc</tt> file
> +along with the functions to query them. For the detailed information on how to
> +use this feature, please refer to
> +<a href="HowToUseInstrMappings.html">How to add Instruction Mappings</a>
> +document.
> +</p>
> +</div>
> +
> +<!-- ======================================================================= -->
> +<h3>
> <a name="implementInstr">Implement a subclass of </a>
> <a href="CodeGenerator.html#targetinstrinfo">TargetInstrInfo</a>
> </h3>
>
> Modified: llvm/trunk/include/llvm/Target/Target.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=166685&r1=166684&r2=166685&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/Target.td (original)
> +++ llvm/trunk/include/llvm/Target/Target.td Thu Oct 25 10:54:06 2012
> @@ -998,6 +998,55 @@
> }
>
> //===----------------------------------------------------------------------===//
> +// InstrMapping - This class is used to create mapping tables to relate
> +// instructions with each other based on the values specified in RowFields,
> +// ColFields, KeyCol and ValueCols.
> +//
> +class InstrMapping {
> + // FilterClass - Used to limit search space only to the instructions that
> + // define the relationship modeled by this InstrMapping record.
> + string FilterClass;
> +
> + // RowFields - 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
> + // model and is used to categorize instructions into subgroups. For instance,
> + // if we want to define a relation that maps 'Add' instruction to its
> + // predicated forms, we can define RowFields like this:
> + //
> + // let RowFields = BaseOp
> + // All add instruction predicated/non-predicated will have to set their BaseOp
> + // to the same value.
> + //
> + // def Add: { let BaseOp = 'ADD'; let predSense = 'nopred' }
> + // def Add_predtrue: { let BaseOp = 'ADD'; let predSense = 'true' }
> + // def Add_predfalse: { let BaseOp = 'ADD'; let predSense = 'false' }
> + list<string> RowFields = [];
> +
> + // List of fields/attributes that are same for all the instructions
> + // in a column of the relation table.
> + // Ex: let ColFields = 'predSense' -- It means that the columns are arranged
> + // based on the 'predSense' values. All the instruction in a specific
> + // column have the same value and it is fixed for the column according
> + // to the values set in 'ValueCols'.
> + list<string> ColFields = [];
> +
> + // Values for the fields/attributes listed in 'ColFields'.
> + // Ex: let KeyCol = 'nopred' -- It means that the key instruction (instruction
> + // that models this relation) should be non-predicated.
> + // In the example above, 'Add' is the key instruction.
> + list<string> KeyCol = [];
> +
> + // List of values for the fields/attributes listed in 'ColFields', one for
> + // each column in the relation table.
> + //
> + // Ex: let ValueCols = [['true'],['false']] -- It adds two columns in the
> + // table. First column requires all the instructions to have predSense
> + // set to 'true' and second column requires it to be 'false'.
> + list<list<string> > ValueCols = [];
> +}
> +
> +//===----------------------------------------------------------------------===//
> // Pull in the common support for calling conventions.
> //
> include "llvm/Target/TargetCallingConv.td"
>
> Added: llvm/trunk/utils/TableGen/CodeGenMapTable.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/CodeGenMapTable.cpp?rev=166685&view=auto
> ==============================================================================
> --- llvm/trunk/utils/TableGen/CodeGenMapTable.cpp (added)
> +++ llvm/trunk/utils/TableGen/CodeGenMapTable.cpp Thu Oct 25 10:54:06 2012
> @@ -0,0 +1,609 @@
> +//===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +// CodeGenMapTable provides functionality for the TabelGen to create
> +// relation mapping between instructions. Relation models are defined using
> +// InstrMapping as a base class. This file implements the functionality which
> +// parses these definitions and generates relation maps using the information
> +// specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc
> +// file along with the functions to query them.
> +//
> +// A relationship model to relate non-predicate instructions with their
> +// predicated true/false forms can be defined as follows:
> +//
> +// def getPredOpcode : InstrMapping {
> +// let FilterClass = "PredRel";
> +// let RowFields = ["BaseOpcode"];
> +// let ColFields = ["PredSense"];
> +// let KeyCol = ["none"];
> +// let ValueCols = [["true"], ["false"]]; }
> +//
> +// CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc
> +// file that contains the instructions modeling this relationship. This table
> +// is defined in the function
> +// "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)"
> +// that can be used to retrieve the predicated form of the instruction by
> +// passing its opcode value and the predicate sense (true/false) of the desired
> +// instruction as arguments.
> +//
> +// Short description of the algorithm:
> +//
> +// 1) Iterate through all the records that derive from "InstrMapping" class.
> +// 2) For each record, filter out instructions based on the FilterClass value.
> +// 3) Iterate through this set of instructions and insert them into
> +// RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the
> +// vector of RowFields values and contains vectors of Records (instructions) as
> +// values. RowFields is a list of fields that are required to have the same
> +// values for all the instructions appearing in the same row of the relation
> +// table. All the instructions in a given row of the relation table have some
> +// sort of relationship with the key instruction defined by the corresponding
> +// relationship model.
> +//
> +// Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ]
> +// Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for
> +// RowFields. These groups of instructions are later matched against ValueCols
> +// to determine the column they belong to, if any.
> +//
> +// While building the RowInstrMap map, collect all the key instructions in
> +// KeyInstrVec. These are the instructions having the same values as KeyCol
> +// for all the fields listed in ColFields.
> +//
> +// For Example:
> +//
> +// Relate non-predicate instructions with their predicated true/false forms.
> +//
> +// def getPredOpcode : InstrMapping {
> +// let FilterClass = "PredRel";
> +// let RowFields = ["BaseOpcode"];
> +// let ColFields = ["PredSense"];
> +// let KeyCol = ["none"];
> +// let ValueCols = [["true"], ["false"]]; }
> +//
> +// Here, only instructions that have "none" as PredSense will be selected as key
> +// instructions.
> +//
> +// 4) For each key instruction, get the group of instructions that share the
> +// same key-value as the key instruction from RowInstrMap. Iterate over the list
> +// of columns in ValueCols (it is defined as a list<list<string> >. Therefore,
> +// it can specify multi-column relationships). For each column, find the
> +// instruction from the group that matches all the values for the column.
> +// Multiple matches are not allowed.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "CodeGenTarget.h"
> +#include "llvm/Support/Format.h"
> +using namespace llvm;
> +typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy;
> +
> +typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy;
> +
> +namespace {
> +
> +//===----------------------------------------------------------------------===//
> +// This class is used to represent InstrMapping class defined in Target.td file.
> +class InstrMap {
> +private:
> + std::string Name;
> + std::string FilterClass;
> + ListInit *RowFields;
> + ListInit *ColFields;
> + ListInit *KeyCol;
> + std::vector<ListInit*> ValueCols;
> +
> +public:
> + InstrMap(Record* MapRec) {
> + Name = MapRec->getName();
> +
> + // FilterClass - It's used to reduce the search space only to the
> + // instructions that define the kind of relationship modeled by
> + // this InstrMapping object/record.
> + const RecordVal *Filter = MapRec->getValue("FilterClass");
> + FilterClass = Filter->getValue()->getAsUnquotedString();
> +
> + // List of fields/attributes that need to be same across all the
> + // instructions in a row of the relation table.
> + RowFields = MapRec->getValueAsListInit("RowFields");
> +
> + // List of fields/attributes that are constant across all the instruction
> + // in a column of the relation table. Ex: ColFields = 'predSense'
> + ColFields = MapRec->getValueAsListInit("ColFields");
> +
> + // Values for the fields/attributes listed in 'ColFields'.
> + // Ex: KeyCol = 'noPred' -- key instruction is non predicated
> + KeyCol = MapRec->getValueAsListInit("KeyCol");
> +
> + // List of values for the fields/attributes listed in 'ColFields', one for
> + // each column in the relation table.
> + //
> + // Ex: ValueCols = [['true'],['false']] -- it results two columns in the
> + // table. First column requires all the instructions to have predSense
> + // set to 'true' and second column requires it to be 'false'.
> + ListInit *ColValList = MapRec->getValueAsListInit("ValueCols");
> +
> + // Each instruction map must specify at least one column for it to be valid.
> + if (ColValList->getSize() == 0)
> + throw "InstrMapping record `" + MapRec->getName() + "' has empty " +
> + "`ValueCols' field!";
> +
> + for (unsigned i = 0, e = ColValList->getSize(); i < e; i++) {
> + ListInit *ColI = dyn_cast<ListInit>(ColValList->getElement(i));
> +
> + // Make sure that all the sub-lists in 'ValueCols' have same number of
> + // elements as the fields in 'ColFields'.
> + if (ColI->getSize() == ColFields->getSize())
> + ValueCols.push_back(ColI);
> + else {
> + throw "Record `" + MapRec->getName() + "', field `" + "ValueCols" +
> + "' entries don't match with the entries in 'ColFields'!";
> + }
> + }
> + }
> +
> + std::string getName() const {
> + return Name;
> + }
> +
> + std::string getFilterClass() {
> + return FilterClass;
> + }
> +
> + ListInit *getRowFields() const {
> + return RowFields;
> + }
> +
> + ListInit *getColFields() const {
> + return ColFields;
> + }
> +
> + ListInit *getKeyCol() const {
> + return KeyCol;
> + }
> +
> + const std::vector<ListInit*> &getValueCols() const {
> + return ValueCols;
> + }
> +};
> +} // End anonymous namespace.
> +
> +
> +//===----------------------------------------------------------------------===//
> +// class MapTableEmitter : It builds the instruction relation maps using
> +// the information provided in InstrMapping records. It outputs these
> +// relationship maps as tables into XXXGenInstrInfo.inc file along with the
> +// functions to query them.
> +
> +namespace {
> +class MapTableEmitter {
> +private:
> +// std::string TargetName;
> + const CodeGenTarget &Target;
> + RecordKeeper &Records;
I removed this unused member (which triggers Clang's
-Wunused-member-variable) in r1666694 (& a nearby unnecessary
semicolon).
If possible, running your local builds with clang & using -Werror
(both the configure+make and cmake builds have options to enable
-Werror) is a great way to avoid these breaks. We all try pretty hard
to keep the clang build clean.
> + // InstrMapDesc - InstrMapping record to be processed.
> + InstrMap InstrMapDesc;
> +
> + // InstrDefs - list of instructions filtered using FilterClass defined
> + // in InstrMapDesc.
> + std::vector<Record*> InstrDefs;
> +
> + // RowInstrMap - maps RowFields values to the instructions. It's keyed by the
> + // values of the row fields and contains vector of records as values.
> + RowInstrMapTy RowInstrMap;
> +
> + // KeyInstrVec - list of key instructions.
> + std::vector<Record*> KeyInstrVec;
> + DenseMap<Record*, std::vector<Record*> > MapTable;
> +
> +public:
> + MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec):
> + Target(Target), Records(Records), InstrMapDesc(IMRec) {
> + const std::string FilterClass = InstrMapDesc.getFilterClass();
> + InstrDefs = Records.getAllDerivedDefinitions(FilterClass);
> + };
> +
> + void buildRowInstrMap();
> +
> + // Returns true if an instruction is a key instruction, i.e., its ColFields
> + // have same values as KeyCol.
> + bool isKeyColInstr(Record* CurInstr);
> +
> + // Find column instruction corresponding to a key instruction based on the
> + // constraints for that column.
> + Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol);
> +
> + // Find column instructions for each key instruction based
> + // on ValueCols and store them into MapTable.
> + void buildMapTable();
> +
> + void emitBinSearch(raw_ostream &OS, unsigned TableSize);
> + void emitTablesWithFunc(raw_ostream &OS);
> + unsigned emitBinSearchTable(raw_ostream &OS);
> +
> + // Lookup functions to query binary search tables.
> + void emitMapFuncBody(raw_ostream &OS, unsigned TableSize);
> +
> +};
> +} // End anonymous namespace.
> +
> +
> +//===----------------------------------------------------------------------===//
> +// Process all the instructions that model this relation (alreday present in
> +// InstrDefs) and insert them into RowInstrMap which is keyed by the values of
> +// the fields listed as RowFields. It stores vectors of records as values.
> +// All the related instructions have the same values for the RowFields thus are
> +// part of the same key-value pair.
> +//===----------------------------------------------------------------------===//
> +
> +void MapTableEmitter::buildRowInstrMap() {
> + for (unsigned i = 0, e = InstrDefs.size(); i < e; i++) {
> + std::vector<Record*> InstrList;
> + Record *CurInstr = InstrDefs[i];
> + std::vector<Init*> KeyValue;
> + ListInit *RowFields = InstrMapDesc.getRowFields();
> + for (unsigned j = 0, endRF = RowFields->getSize(); j < endRF; j++) {
> + Init *RowFieldsJ = RowFields->getElement(j);
> + Init *CurInstrVal = CurInstr->getValue(RowFieldsJ)->getValue();
> + KeyValue.push_back(CurInstrVal);
> + }
> +
> + // Collect key instructions into KeyInstrVec. Later, these instructions are
> + // processed to assign column position to the instructions sharing
> + // their KeyValue in RowInstrMap.
> + if (isKeyColInstr(CurInstr))
> + KeyInstrVec.push_back(CurInstr);
> +
> + RowInstrMap[KeyValue].push_back(CurInstr);
> + }
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Return true if an instruction is a KeyCol instruction.
> +//===----------------------------------------------------------------------===//
> +
> +bool MapTableEmitter::isKeyColInstr(Record* CurInstr) {
> + ListInit *ColFields = InstrMapDesc.getColFields();
> + ListInit *KeyCol = InstrMapDesc.getKeyCol();
> +
> + // Check if the instruction is a KeyCol instruction.
> + bool MatchFound = true;
> + for (unsigned j = 0, endCF = ColFields->getSize();
> + (j < endCF) && MatchFound; j++) {
> + RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j));
> + std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString();
> + std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString();
> + MatchFound = (CurInstrVal == KeyColValue);
> + }
> + return MatchFound;
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Build a map to link key instructions with the column instructions arranged
> +// according to their column positions.
> +//===----------------------------------------------------------------------===//
> +
> +void MapTableEmitter::buildMapTable() {
> + // Find column instructions for a given key based on the ColField
> + // constraints.
> + const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
> + unsigned NumOfCols = ValueCols.size();
> + for (unsigned j = 0, endKI = KeyInstrVec.size(); j < endKI; j++) {
> + Record *CurKeyInstr = KeyInstrVec[j];
> + std::vector<Record*> ColInstrVec(NumOfCols);
> +
> + // Find the column instruction based on the constraints for the column.
> + for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) {
> + ListInit *CurValueCol = ValueCols[ColIdx];
> + Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol);
> + ColInstrVec[ColIdx] = ColInstr;
> + }
> + MapTable[CurKeyInstr] = ColInstrVec;
> + }
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Find column instruction based on the constraints for that column.
> +//===----------------------------------------------------------------------===//
> +
> +Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
> + ListInit *CurValueCol) {
> + ListInit *RowFields = InstrMapDesc.getRowFields();
> + std::vector<Init*> KeyValue;
> +
> + // Construct KeyValue using KeyInstr's values for RowFields.
> + for (unsigned j = 0, endRF = RowFields->getSize(); j < endRF; j++) {
> + Init *RowFieldsJ = RowFields->getElement(j);
> + Init *KeyInstrVal = KeyInstr->getValue(RowFieldsJ)->getValue();
> + KeyValue.push_back(KeyInstrVal);
> + }
> +
> + // Get all the instructions that share the same KeyValue as the KeyInstr
> + // in RowInstrMap. We search through these instructions to find a match
> + // for the current column, i.e., the instruction which has the same values
> + // as CurValueCol for all the fields in ColFields.
> + const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue];
> +
> + ListInit *ColFields = InstrMapDesc.getColFields();
> + Record *MatchInstr = NULL;
> +
> + for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) {
> + bool MatchFound = true;
> + Record *CurInstr = RelatedInstrVec[i];
> + for (unsigned j = 0, endCF = ColFields->getSize();
> + (j < endCF) && MatchFound; j++) {
> + Init *ColFieldJ = ColFields->getElement(j);
> + Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
> + std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
> + Init *ColFieldJVallue = CurValueCol->getElement(j);
> + MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString());
> + }
> +
> + if (MatchFound) {
> + if (MatchInstr) // Already had a match
> + // Error if multiple matches are found for a column.
> + throw "Multiple matches found for `" + KeyInstr->getName() +
> + "', for the relation `" + InstrMapDesc.getName();
> + else
> + MatchInstr = CurInstr;
> + }
> + }
> + return MatchInstr;
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Emit one table per relation. Only instructions with a valid relation of a
> +// given type are included in the table sorted by their enum values (opcodes).
> +// Binary search is used for locating instructions in the table.
> +//===----------------------------------------------------------------------===//
> +
> +unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
> +
> + const std::vector<const CodeGenInstruction*> &NumberedInstructions =
> + Target.getInstructionsByEnumValue();
> + std::string TargetName = Target.getName();
> + const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
> + unsigned NumCol = ValueCols.size();
> + unsigned TotalNumInstr = NumberedInstructions.size();
> + unsigned TableSize = 0;
> +
> + OS << "static const uint16_t "<<InstrMapDesc.getName();
> + // Number of columns in the table are NumCol+1 because key instructions are
> + // emitted as first column.
> + OS << "Table[]["<< NumCol+1 << "] = {\n";
> + for (unsigned i = 0; i < TotalNumInstr; i++) {
> + Record *CurInstr = NumberedInstructions[i]->TheDef;
> + std::vector<Record*> ColInstrs = MapTable[CurInstr];
> + std::string OutStr("");
> + unsigned RelExists = 0;
> + if (ColInstrs.size()) {
> + for (unsigned j = 0; j < NumCol; j++) {
> + if (ColInstrs[j] != NULL) {
> + RelExists = 1;
> + OutStr += ", ";
> + OutStr += TargetName;
> + OutStr += "::";
> + OutStr += ColInstrs[j]->getName();
> + } else { OutStr += ", -1";}
> + }
> +
> + if (RelExists) {
> + OS << " { " << TargetName << "::" << CurInstr->getName();
> + OS << OutStr <<" },\n";
> + TableSize++;
> + }
> + }
> + }
> + if (!TableSize) {
> + OS << " { " << TargetName << "::" << "INSTRUCTION_LIST_END, ";
> + OS << TargetName << "::" << "INSTRUCTION_LIST_END }";
> + }
> + OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n";
> + return TableSize;
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Emit binary search algorithm as part of the functions used to query
> +// relation tables.
> +//===----------------------------------------------------------------------===//
> +
> +void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) {
> + OS << " unsigned mid;\n";
> + OS << " unsigned start = 0;\n";
> + OS << " unsigned end = " << TableSize << ";\n";
> + OS << " while (start < end) {\n";
> + OS << " mid = start + (end - start)/2;\n";
> + OS << " if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n";
> + OS << " break;\n";
> + OS << " }\n";
> + OS << " if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n";
> + OS << " end = mid;\n";
> + OS << " else\n";
> + OS << " start = mid + 1;\n";
> + OS << " }\n";
> + OS << " if (start == end)\n";
> + OS << " return -1; // Instruction doesn't exist in this table.\n\n";
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Emit functions to query relation tables.
> +//===----------------------------------------------------------------------===//
> +
> +void MapTableEmitter::emitMapFuncBody(raw_ostream &OS,
> + unsigned TableSize) {
> +
> + ListInit *ColFields = InstrMapDesc.getColFields();
> + const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
> +
> + // Emit binary search algorithm to locate instructions in the
> + // relation table. If found, return opcode value from the appropriate column
> + // of the table.
> + emitBinSearch(OS, TableSize);
> +
> + if (ValueCols.size() > 1) {
> + for (unsigned i = 0, e = ValueCols.size(); i < e; i++) {
> + ListInit *ColumnI = ValueCols[i];
> + for (unsigned j = 0, ColSize = ColumnI->getSize(); j < ColSize; j++) {
> + std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
> + OS << " if (in" << ColName;
> + OS << " == ";
> + OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString();
> + if (j < ColumnI->getSize() - 1) OS << " && ";
> + else OS << ")\n";
> + }
> + OS << " return " << InstrMapDesc.getName();
> + OS << "Table[mid]["<<i+1<<"];\n";
> + }
> + OS << " return -1;";
> + }
> + else
> + OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n";
> +
> + OS <<"}\n\n";
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Emit relation tables and the functions to query them.
> +//===----------------------------------------------------------------------===//
> +
> +void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {
> +
> + // Emit function name and the input parameters : mostly opcode value of the
> + // current instruction. However, if a table has multiple columns (more than 2
> + // since first column is used for the key instructions), then we also need
> + // to pass another input to indicate the column to be selected.
> +
> + ListInit *ColFields = InstrMapDesc.getColFields();
> + const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
> + OS << "// "<< InstrMapDesc.getName() << "\n";
> + OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode";
> + if (ValueCols.size() > 1) {
> + for (unsigned i = 0, e = ColFields->getSize(); i < e; i++) {
> + std::string ColName = ColFields->getElement(i)->getAsUnquotedString();
> + OS << ", enum " << ColName << " in" << ColName << ") {\n";
> + }
> + } else { OS << ") {\n"; }
> +
> + // Emit map table.
> + unsigned TableSize = emitBinSearchTable(OS);
> +
> + // Emit rest of the function body.
> + emitMapFuncBody(OS, TableSize);
> +}
> +
> +//===----------------------------------------------------------------------===//
> +// Emit enums for the column fields across all the instruction maps.
> +//===----------------------------------------------------------------------===//
> +
> +static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
> +
> + std::vector<Record*> InstrMapVec;
> + InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
> + std::map<std::string, std::vector<Init*> > ColFieldValueMap;
> +
> + // Iterate over all InstrMapping records and create a map between column
> + // fields and their possible values across all records.
> + for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) {
> + Record *CurMap = InstrMapVec[i];
> + ListInit *ColFields;
> + ColFields = CurMap->getValueAsListInit("ColFields");
> + ListInit *List = CurMap->getValueAsListInit("ValueCols");
> + std::vector<ListInit*> ValueCols;
> + unsigned ListSize = List->getSize();
> +
> + for (unsigned j = 0; j < ListSize; j++) {
> + ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j));
> +
> + if (ListJ->getSize() != ColFields->getSize()) {
> + throw "Record `" + CurMap->getName() + "', field `" + "ValueCols" +
> + "' entries don't match with the entries in 'ColFields' !";
> + }
> + ValueCols.push_back(ListJ);
> + }
> +
> + for (unsigned j = 0, endCF = ColFields->getSize(); j < endCF; j++) {
> + for (unsigned k = 0; k < ListSize; k++){
> + std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
> + ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j));
> + }
> + }
> + }
> +
> + for (std::map<std::string, std::vector<Init*> >::iterator
> + II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end();
> + II != IE; II++) {
> + std::vector<Init*> FieldValues = (*II).second;
> + unsigned FieldSize = FieldValues.size();
> +
> + // Delete duplicate entries from ColFieldValueMap
> + for (unsigned i = 0; i < FieldSize - 1; i++) {
> + Init *CurVal = FieldValues[i];
> + for (unsigned j = i+1; j < FieldSize; j++) {
> + if (CurVal == FieldValues[j]) {
> + FieldValues.erase(FieldValues.begin()+j);
> + }
> + }
> + }
> +
> + // Emit enumerated values for the column fields.
> + OS << "enum " << (*II).first << " {\n";
> + for (unsigned i = 0; i < FieldSize; i++) {
> + OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString();
> + if (i != FieldValues.size() - 1)
> + OS << ",\n";
> + else
> + OS << "\n};\n\n";
> + }
> + }
> +}
> +
> +namespace llvm {
> +//===----------------------------------------------------------------------===//
> +// Parse 'InstrMapping' records and use the information to form relationship
> +// between instructions. These relations are emitted as a tables along with the
> +// functions to query them.
> +//===----------------------------------------------------------------------===//
> +void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
> + CodeGenTarget Target(Records);
> + std::string TargetName = Target.getName();
> + std::vector<Record*> InstrMapVec;
> + InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
> +
> + if (!InstrMapVec.size())
> + return;
> +
> + OS << "#ifdef GET_INSTRMAP_INFO\n";
> + OS << "#undef GET_INSTRMAP_INFO\n";
> + OS << "namespace llvm {\n\n";
> + OS << "namespace " << TargetName << " {\n\n";
> +
> + // Emit coulumn field names and their values as enums.
> + emitEnums(OS, Records);
> +
> + // Iterate over all instruction mapping records and construct relationship
> + // maps based on the information specified there.
> + //
> + for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) {
> + MapTableEmitter IMap(Target, Records, InstrMapVec[i]);
> +
> + // Build RowInstrMap to group instructions based on their values for
> + // RowFields. In the process, also collect key instructions into
> + // KeyInstrVec.
> + IMap.buildRowInstrMap();
> +
> + // Build MapTable to map key instructions with the corresponding column
> + // instructions.
> + IMap.buildMapTable();
> +
> + // Emit map tables and the functions to query them.
> + IMap.emitTablesWithFunc(OS);
> + }
> + OS << "} // End " << TargetName << " namespace\n";
> + OS << "} // End llvm namespace\n";
> + OS << "#endif // GET_INSTRMAP_INFO\n\n";
> +}
> +
> +} // End llvm namespace
>
> Modified: llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp?rev=166685&r1=166684&r2=166685&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp (original)
> +++ llvm/trunk/utils/TableGen/InstrInfoEmitter.cpp Thu Oct 25 10:54:06 2012
> @@ -16,6 +16,7 @@
> #include "CodeGenDAGPatterns.h"
> #include "CodeGenSchedule.h"
> #include "CodeGenTarget.h"
> +#include "TableGenBackends.h"
> #include "SequenceToOffsetTable.h"
> #include "llvm/ADT/StringExtras.h"
> #include "llvm/TableGen/Record.h"
> @@ -415,6 +416,7 @@
>
> void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
> InstrInfoEmitter(RK).run(OS);
> + EmitMapTable(RK, OS);
> }
>
> } // End llvm namespace
>
> Modified: llvm/trunk/utils/TableGen/TableGenBackends.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TableGenBackends.h?rev=166685&r1=166684&r2=166685&view=diff
> ==============================================================================
> --- llvm/trunk/utils/TableGen/TableGenBackends.h (original)
> +++ llvm/trunk/utils/TableGen/TableGenBackends.h Thu Oct 25 10:54:06 2012
> @@ -74,5 +74,6 @@
> void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
> void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS);
> void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
> +void EmitMapTable(RecordKeeper &RK, raw_ostream &OS);
>
> } // End llvm namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list