[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