-================================
-Writing an LLVM Compiler Backend
-================================
+=======================
+Writing an LLVM Backend
+=======================
.. toctree::
:hidden:
Formation, SSA-based Optimization, Register Allocation, Prolog/Epilog Code
Insertion, Late Machine Code Optimizations, and Code Emission.
-* :doc:`TableGenFundamentals` --- a document that describes the TableGen
+* :doc:`TableGen/index` --- a document that describes the TableGen
(``tblgen``) application that manages domain-specific information to support
LLVM code generation. TableGen processes input from a target description
file (``.td`` suffix) and generates C++ code that can be used for code
know about your target when parsing the ``--enable-targets`` option. Search
the configure script for ``TARGETS_TO_BUILD``, add your target to the lists
there (some creativity required), and then reconfigure. Alternatively, you can
-change ``autotools/configure.ac`` and regenerate configure by running
+change ``autoconf/configure.ac`` and regenerate configure by running
``./autoconf/AutoRegen.sh``.
Target Machine
* ``getTargetLowering()``
* ``getJITInfo()``
+Some architectures, such as GPUs, do not support jumping to an arbitrary
+program location and implement branching using masked execution and loop using
+special instructions around the loop body. In order to avoid CFG modifications
+that introduce irreducible control flow not handled by such hardware, a target
+must call `setRequiresStructuredCFG(true)` when being initialized.
+
In addition, the ``XXXTargetMachine`` constructor should specify a
``TargetDescription`` string that determines the data layout for the target
machine, including characteristics such as pointer size, alignment, and
def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr),
"ld [$addr], $dst",
- [(set IntRegs:$dst, (load ADDRrr:$addr))]>;
+ [(set i32:$dst, (load ADDRrr:$addr))]>;
The fourth parameter is the input source, which uses the address operand
``MEMrr`` that is defined earlier in ``SparcInstrInfo.td``:
def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr),
"ld [$addr], $dst",
- [(set IntRegs:$dst, (load ADDRri:$addr))]>;
+ [(set i32:$dst, (load ADDRri:$addr))]>;
Writing these definitions for so many similar instructions can involve a lot of
cut and paste. In ``.td`` files, the ``multiclass`` directive enables the
def rr : F3_1 <2, Op3Val,
(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
!strconcat(OpcStr, " $b, $c, $dst"),
- [(set IntRegs:$dst, (OpNode IntRegs:$b, IntRegs:$c))]>;
+ [(set i32:$dst, (OpNode i32:$b, i32:$c))]>;
def ri : F3_2 <2, Op3Val,
(outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
!strconcat(OpcStr, " $b, $c, $dst"),
- [(set IntRegs:$dst, (OpNode IntRegs:$b, simm13:$c))]>;
+ [(set i32:$dst, (OpNode i32:$b, simm13:$c))]>;
}
So when the ``defm`` directive is used for the ``XOR`` and ``ADD``
def XNORrr : F3_1<2, 0b000111,
(outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
"xnor $b, $c, $dst",
- [(set IntRegs:$dst, (not (xor IntRegs:$b, IntRegs:$c)))]>;
+ [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>;
The instruction templates in ``SparcInstrFormats.td`` show the base class for
``F3_1`` is ``InstSP``.
fields. This results in the ``XNORrr`` instruction binding ``$dst``, ``$b``,
and ``$c`` operands to the ``rd``, ``rs1``, and ``rs2`` fields respectively.
+Instruction Operand Name Mapping
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+TableGen will also generate a function called getNamedOperandIdx() which
+can be used to look up an operand's index in a MachineInstr based on its
+TableGen name. Setting the UseNamedOperandTable bit in an instruction's
+TableGen definition will add all of its operands to an enumeration in the
+llvm::XXX:OpName namespace and also add an entry for it into the OperandMap
+table, which can be queried using getNamedOperandIdx()
+
+.. code-block:: llvm
+
+ int DstIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::dst); // => 0
+ int BIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::b); // => 1
+ int CIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::c); // => 2
+ int DIndex = SP::getNamedOperandIdx(SP::XNORrr, SP::OpName::d); // => -1
+
+ ...
+
+The entries in the OpName enum are taken verbatim from the TableGen definitions,
+so operands with lowercase names will have lower case entries in the enum.
+
+To include the getNamedOperandIdx() function in your backend, you will need
+to define a few preprocessor macros in XXXInstrInfo.cpp and XXXInstrInfo.h.
+For example:
+
+XXXInstrInfo.cpp:
+
+.. code-block:: c++
+
+ #define GET_INSTRINFO_NAMED_OPS // For getNamedOperandIdx() function
+ #include "XXXGenInstrInfo.inc"
+
+XXXInstrInfo.h:
+
+.. code-block:: c++
+
+ #define GET_INSTRINFO_OPERAND_ENUM // For OpName enum
+ #include "XXXGenInstrInfo.inc"
+
+ namespace XXX {
+ int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex);
+ } // End namespace XXX
+
+Instruction Operand Types
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+TableGen will also generate an enumeration consisting of all named Operand
+types defined in the backend, in the llvm::XXX::OpTypes namespace.
+Some common immediate Operand types (for instance i8, i32, i64, f32, f64)
+are defined for all targets in ``include/llvm/Target/Target.td``, and are
+available in each Target's OpTypes enum. Also, only named Operand types appear
+in the enumeration: anonymous types are ignored.
+For example, the X86 backend defines ``brtarget`` and ``brtarget8``, both
+instances of the TableGen ``Operand`` class, which represent branch target
+operands:
+
+.. code-block:: llvm
+
+ def brtarget : Operand<OtherVT>;
+ def brtarget8 : Operand<OtherVT>;
+
+This results in:
+
+.. code-block:: c++
+
+ namespace X86 {
+ namespace OpTypes {
+ enum OperandType {
+ ...
+ brtarget,
+ brtarget8,
+ ...
+ i32imm,
+ i64imm,
+ ...
+ OPERAND_TYPE_LIST_END
+ } // End namespace OpTypes
+ } // End namespace X86
+
+In typical TableGen fashion, to use the enum, you will need to define a
+preprocessor macro:
+
+.. code-block:: c++
+
+ #define GET_INSTRINFO_OPERAND_TYPES_ENUM // For OpTypes enum
+ #include "XXXGenInstrInfo.inc"
+
+
+Instruction Scheduling
+----------------------
+
+Instruction itineraries can be queried using MCDesc::getSchedClass(). The
+value can be named by an enumemation in llvm::XXX::Sched namespace generated
+by TableGen in XXXGenInstrInfo.inc. The name of the schedule classes are
+the same as provided in XXXSchedule.td plus a default NoItinerary class.
+
Instruction Relation Mapping
----------------------------
.. code-block:: llvm
def STrr : F3_1< 3, 0b000100, (outs), (ins MEMrr:$addr, IntRegs:$src),
- "st $src, [$addr]", [(store IntRegs:$src, ADDRrr:$addr)]>;
+ "st $src, [$addr]", [(store i32:$src, ADDRrr:$addr)]>;
``ADDRrr`` is a memory mode that is also defined in ``SparcInstrInfo.td``:
SDValue CPTmp0;
SDValue CPTmp1;
- // Pattern: (st:void IntRegs:i32:$src,
+ // Pattern: (st:void i32:i32:$src,
// ADDRrr:i32:$addr)<<P:Predicate_store>>
// Emits: (STrr:void ADDRrr:i32:$addr, IntRegs:i32:$src)
// Pattern complexity = 13 cost = 1 size = 0