[llvm] 5713c29 - Update "Writing a Backend" doc to use named operand matching.
James Y Knight via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 26 11:06:27 PDT 2022
Author: James Y Knight
Date: 2022-10-26T14:06:07-04:00
New Revision: 5713c2959cdd56b8d529d71a078981de1333a5f4
URL: https://github.com/llvm/llvm-project/commit/5713c2959cdd56b8d529d71a078981de1333a5f4
DIFF: https://github.com/llvm/llvm-project/commit/5713c2959cdd56b8d529d71a078981de1333a5f4.diff
LOG: Update "Writing a Backend" doc to use named operand matching.
This brings it in line with recommended practice after the
introduction of sub-operand naming in a538d1f13a13, and the
deprecation of positional argument matching in 5351878ba196.
Added:
Modified:
llvm/docs/WritingAnLLVMBackend.rst
Removed:
################################################################################
diff --git a/llvm/docs/WritingAnLLVMBackend.rst b/llvm/docs/WritingAnLLVMBackend.rst
index a6124bc9bcb7..79f1e5b4dea0 100644
--- a/llvm/docs/WritingAnLLVMBackend.rst
+++ b/llvm/docs/WritingAnLLVMBackend.rst
@@ -762,7 +762,7 @@ target description file (``IntRegs``).
.. code-block:: text
- def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$dst), (ins MEMrr:$addr),
+ def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr),
"ld [$addr], $dst",
[(set i32:$dst, (load ADDRrr:$addr))]>;
@@ -790,9 +790,9 @@ class is defined:
.. code-block:: text
- def LDri : F3_2 <3, 0b000000, (outs IntRegs:$dst), (ins MEMri:$addr),
+ def LDri : F3_2 <3, 0b000000, (outs IntRegs:$rd), (ins (MEMri $rs1, $simm13):$addr),
"ld [$addr], $dst",
- [(set i32:$dst, (load ADDRri:$addr))]>;
+ [(set i32:$rd, (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
@@ -805,13 +805,13 @@ pattern ``F3_12`` is defined to create 2 instruction classes each time
multiclass F3_12 <string OpcStr, bits<6> Op3Val, SDNode OpNode> {
def rr : F3_1 <2, Op3Val,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- !strconcat(OpcStr, " $b, $c, $dst"),
- [(set i32:$dst, (OpNode i32:$b, i32:$c))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs1),
+ !strconcat(OpcStr, " $rs1, $rs2, $rd"),
+ [(set i32:$rd, (OpNode i32:$rs1, i32:$rs2))]>;
def ri : F3_2 <2, Op3Val,
- (outs IntRegs:$dst), (ins IntRegs:$b, i32imm:$c),
- !strconcat(OpcStr, " $b, $c, $dst"),
- [(set i32:$dst, (OpNode i32:$b, simm13:$c))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, i32imm:$simm13),
+ !strconcat(OpcStr, " $rs1, $simm13, $rd"),
+ [(set i32:$rd, (OpNode i32:$rs1, simm13:$simm13))]>;
}
So when the ``defm`` directive is used for the ``XOR`` and ``ADD``
@@ -850,17 +850,19 @@ Instruction Operand Mapping
---------------------------
The code generator backend maps instruction operands to fields in the
-instruction. Operands are assigned to unbound fields in the instruction in the
-order they are defined. Fields are bound when they are assigned a value. For
-example, the Sparc target defines the ``XNORrr`` instruction as a ``F3_1``
-format instruction having three operands.
+instruction. Whenever a bit in the instruction encoding ``Inst`` is assigned
+to field without a concrete value, an operand from the ``outs`` or ``ins`` list
+is expected to have a matching name. This operand then populates that undefined
+field. For example, the Sparc target defines the ``XNORrr`` instruction as a
+``F3_1`` format instruction having three operands: the output ``$rd``, and the
+inputs ``$rs1``, and ``$rs2``.
.. code-block:: text
def XNORrr : F3_1<2, 0b000111,
- (outs IntRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
- "xnor $b, $c, $dst",
- [(set i32:$dst, (not (xor i32:$b, i32:$c)))]>;
+ (outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2),
+ "xnor $rs1, $rs2, $rd",
+ [(set i32:$rd, (not (xor i32:$rs1, i32:$rs2)))]>;
The instruction templates in ``SparcInstrFormats.td`` show the base class for
``F3_1`` is ``InstSP``.
@@ -878,7 +880,8 @@ The instruction templates in ``SparcInstrFormats.td`` show the base class for
let Pattern = pattern;
}
-``InstSP`` leaves the ``op`` field unbound.
+``InstSP`` defines the ``op`` field, and uses it to define bits 30 and 31 of the
+instruction, but does not assign a value to it.
.. code-block:: text
@@ -893,9 +896,8 @@ The instruction templates in ``SparcInstrFormats.td`` show the base class for
let Inst{18-14} = rs1;
}
-``F3`` binds the ``op`` field and defines the ``rd``, ``op3``, and ``rs1``
-fields. ``F3`` format instructions will bind the operands ``rd``, ``op3``, and
-``rs1`` fields.
+``F3`` defines the ``rd``, ``op3``, and ``rs1`` fields, and uses them in the
+instruction, and again does not assign values.
.. code-block:: text
@@ -910,10 +912,42 @@ fields. ``F3`` format instructions will bind the operands ``rd``, ``op3``, and
let Inst{4-0} = rs2;
}
-``F3_1`` binds the ``op3`` field and defines the ``rs2`` fields. ``F3_1``
-format instructions will bind the operands to the ``rd``, ``rs1``, and ``rs2``
-fields. This results in the ``XNORrr`` instruction binding ``$dst``, ``$b``,
-and ``$c`` operands to the ``rd``, ``rs1``, and ``rs2`` fields respectively.
+``F3_1`` assigns a value to ``op`` and ``op3`` fields, and defines the ``rs2``
+field. Therefore, a ``F3_1`` format instruction will require a definition for
+``rd``, ``rs1``, and ``rs2`` in order to fully specify the instruction encoding.
+
+The ``XNORrr`` instruction then provides those three operands in its
+OutOperandList and InOperandList, which bind to the corresponding fields, and
+thus complete the instruction encoding.
+
+For some instructions, a single operand may contain sub-operands. As shown
+earlier, the instruction ``LDrr`` uses an input operand of type ``MEMrr``. This
+operand type contains two register sub-operands, defined by the
+``MIOperandInfo`` value to be ``(ops IntRegs, IntRegs)``.
+
+.. code-block:: text
+
+ def LDrr : F3_1 <3, 0b000000, (outs IntRegs:$rd), (ins (MEMrr $rs1, $rs2):$addr),
+ "ld [$addr], $dst",
+ [(set i32:$dst, (load ADDRrr:$addr))]>;
+
+As this instruction is also the ``F3_1`` format, it will expect operands named
+``rd``, ``rs1``, and ``rs2`` as well. In order to allow this, a complex operand
+can optionally give names to each of its sub-operands. In this example
+``MEMrr``'s first sub-operand is named ``$rs1``, the second ``$rs2``, and the
+operand as a whole is also given the name ``$addr``.
+
+When a particular instruction doesn't use all the operands that the instruction
+format defines, a constant value may instead be bound to one or all. For
+example, the ``RDASR`` instruction only takes a single register operand, so we
+assign a constant zero to ``rs2``:
+
+.. code-block:: text
+
+ let rs2 = 0 in
+ def RDASR : F3_1<2, 0b101000,
+ (outs IntRegs:$rd), (ins ASRRegs:$rs1),
+ "rd $rs1, $rd", []>;
Instruction Operand Name Mapping
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
More information about the llvm-commits
mailing list