annotate llvm/docs/GlobalISel/GMIR.rst @ 201:a96fbbdf2d0f

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 04 Jun 2021 21:07:06 +0900
parents 0572611fdcc8
children 2e18cbf3894f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 .. _gmir:
anatofuz
parents:
diff changeset
2
anatofuz
parents:
diff changeset
3 Generic Machine IR
anatofuz
parents:
diff changeset
4 ==================
anatofuz
parents:
diff changeset
5
anatofuz
parents:
diff changeset
6 .. contents::
anatofuz
parents:
diff changeset
7 :local:
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 Generic MIR (gMIR) is an intermediate representation that shares the same data
anatofuz
parents:
diff changeset
10 structures as :doc:`MachineIR (MIR) <../MIRLangRef>` but has more relaxed
anatofuz
parents:
diff changeset
11 constraints. As the compilation pipeline proceeds, these constraints are
anatofuz
parents:
diff changeset
12 gradually tightened until gMIR has become MIR.
anatofuz
parents:
diff changeset
13
anatofuz
parents:
diff changeset
14 The rest of this document will assume that you are familiar with the concepts
anatofuz
parents:
diff changeset
15 in :doc:`MachineIR (MIR) <../MIRLangRef>` and will highlight the differences
anatofuz
parents:
diff changeset
16 between MIR and gMIR.
anatofuz
parents:
diff changeset
17
anatofuz
parents:
diff changeset
18 .. _gmir-instructions:
anatofuz
parents:
diff changeset
19
anatofuz
parents:
diff changeset
20 Generic Machine Instructions
anatofuz
parents:
diff changeset
21 ----------------------------
anatofuz
parents:
diff changeset
22
anatofuz
parents:
diff changeset
23 .. note::
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 This section expands on :ref:`mir-instructions` from the MIR Language
anatofuz
parents:
diff changeset
26 Reference.
anatofuz
parents:
diff changeset
27
anatofuz
parents:
diff changeset
28 Whereas MIR deals largely in Target Instructions and only has a small set of
anatofuz
parents:
diff changeset
29 target independent opcodes such as ``COPY``, ``PHI``, and ``REG_SEQUENCE``,
anatofuz
parents:
diff changeset
30 gMIR defines a rich collection of ``Generic Opcodes`` which are target
anatofuz
parents:
diff changeset
31 independent and describe operations which are typically supported by targets.
anatofuz
parents:
diff changeset
32 One example is ``G_ADD`` which is the generic opcode for an integer addition.
anatofuz
parents:
diff changeset
33 More information on each of the generic opcodes can be found at
anatofuz
parents:
diff changeset
34 :doc:`GenericOpcode`.
anatofuz
parents:
diff changeset
35
anatofuz
parents:
diff changeset
36 The ``MachineIRBuilder`` class wraps the ``MachineInstrBuilder`` and provides
anatofuz
parents:
diff changeset
37 a convenient way to create these generic instructions.
anatofuz
parents:
diff changeset
38
anatofuz
parents:
diff changeset
39 .. _gmir-gvregs:
anatofuz
parents:
diff changeset
40
anatofuz
parents:
diff changeset
41 Generic Virtual Registers
anatofuz
parents:
diff changeset
42 -------------------------
anatofuz
parents:
diff changeset
43
anatofuz
parents:
diff changeset
44 .. note::
anatofuz
parents:
diff changeset
45
anatofuz
parents:
diff changeset
46 This section expands on :ref:`mir-registers` from the MIR Language
anatofuz
parents:
diff changeset
47 Reference.
anatofuz
parents:
diff changeset
48
anatofuz
parents:
diff changeset
49 Generic virtual registers are like virtual registers but they are not assigned a
anatofuz
parents:
diff changeset
50 Register Class constraint. Instead, generic virtual registers have less strict
anatofuz
parents:
diff changeset
51 constraints starting with a :ref:`gmir-llt` and then further constrained to a
anatofuz
parents:
diff changeset
52 :ref:`gmir-regbank`. Eventually they will be constrained to a register class
anatofuz
parents:
diff changeset
53 at which point they become normal virtual registers.
anatofuz
parents:
diff changeset
54
anatofuz
parents:
diff changeset
55 Generic virtual registers can be used with all the virtual register API's
anatofuz
parents:
diff changeset
56 provided by ``MachineRegisterInfo``. In particular, the def-use chain API's can
anatofuz
parents:
diff changeset
57 be used without needing to distinguish them from non-generic virtual registers.
anatofuz
parents:
diff changeset
58
anatofuz
parents:
diff changeset
59 For simplicity, most generic instructions only accept virtual registers (both
anatofuz
parents:
diff changeset
60 generic and non-generic). There are some exceptions to this but in general:
anatofuz
parents:
diff changeset
61
anatofuz
parents:
diff changeset
62 * instead of immediates, they use a generic virtual register defined by an
anatofuz
parents:
diff changeset
63 instruction that materializes the immediate value (see
anatofuz
parents:
diff changeset
64 :ref:`irtranslator-constants`). Typically this is a G_CONSTANT or a
anatofuz
parents:
diff changeset
65 G_FCONSTANT. One example of an exception to this rule is G_SEXT_INREG where
anatofuz
parents:
diff changeset
66 having an immediate is mandatory.
anatofuz
parents:
diff changeset
67 * instead of physical register, they use a generic virtual register that is
anatofuz
parents:
diff changeset
68 either defined by a ``COPY`` from the physical register or used by a ``COPY``
anatofuz
parents:
diff changeset
69 that defines the physical register.
anatofuz
parents:
diff changeset
70
anatofuz
parents:
diff changeset
71 .. admonition:: Historical Note
anatofuz
parents:
diff changeset
72
anatofuz
parents:
diff changeset
73 We started with an alternative representation, where MRI tracks a size for
anatofuz
parents:
diff changeset
74 each generic virtual register, and instructions have lists of types.
anatofuz
parents:
diff changeset
75 That had two flaws: the type and size are redundant, and there was no generic
anatofuz
parents:
diff changeset
76 way of getting a given operand's type (as there was no 1:1 mapping between
anatofuz
parents:
diff changeset
77 instruction types and operands).
anatofuz
parents:
diff changeset
78 We considered putting the type in some variant of MCInstrDesc instead:
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
79 See `PR26576 <https://llvm.org/PR26576>`_: [GlobalISel] Generic MachineInstrs
150
anatofuz
parents:
diff changeset
80 need a type but this increases the memory footprint of the related objects
anatofuz
parents:
diff changeset
81
anatofuz
parents:
diff changeset
82 .. _gmir-regbank:
anatofuz
parents:
diff changeset
83
anatofuz
parents:
diff changeset
84 Register Bank
anatofuz
parents:
diff changeset
85 -------------
anatofuz
parents:
diff changeset
86
anatofuz
parents:
diff changeset
87 A Register Bank is a set of register classes defined by the target. This
anatofuz
parents:
diff changeset
88 definition is rather loose so let's talk about what they can achieve.
anatofuz
parents:
diff changeset
89
anatofuz
parents:
diff changeset
90 Suppose we have a processor that has two register files, A and B. These are
anatofuz
parents:
diff changeset
91 equal in every way and support the same instructions for the same cost. They're
anatofuz
parents:
diff changeset
92 just physically stored apart and each instruction can only access registers from
anatofuz
parents:
diff changeset
93 A or B but never a mix of the two. If we want to perform an operation on data
anatofuz
parents:
diff changeset
94 that's in split between the two register files, we must first copy all the data
anatofuz
parents:
diff changeset
95 into a single register file.
anatofuz
parents:
diff changeset
96
anatofuz
parents:
diff changeset
97 Given a processor like this, we would benefit from clustering related data
anatofuz
parents:
diff changeset
98 together into one register file so that we minimize the cost of copying data
anatofuz
parents:
diff changeset
99 back and forth to satisfy the (possibly conflicting) requirements of all the
anatofuz
parents:
diff changeset
100 instructions. Register Banks are a means to constrain the register allocator to
anatofuz
parents:
diff changeset
101 use a particular register file for a virtual register.
anatofuz
parents:
diff changeset
102
anatofuz
parents:
diff changeset
103 In practice, register files A and B are rarely equal. They can typically store
anatofuz
parents:
diff changeset
104 the same data but there's usually some restrictions on what operations you can
anatofuz
parents:
diff changeset
105 do on each register file. A fairly common pattern is for one of them to be
anatofuz
parents:
diff changeset
106 accessible to integer operations and the other accessible to floating point
anatofuz
parents:
diff changeset
107 operations. To accomodate this, let's rename A and B to GPR (general purpose
anatofuz
parents:
diff changeset
108 registers) and FPR (floating point registers).
anatofuz
parents:
diff changeset
109
anatofuz
parents:
diff changeset
110 We now have some additional constraints that limit us. An operation like G_FMUL
anatofuz
parents:
diff changeset
111 has to happen in FPR and G_ADD has to happen in GPR. However, even though this
anatofuz
parents:
diff changeset
112 prescribes a lot of the assignments we still have some freedom. A G_LOAD can
anatofuz
parents:
diff changeset
113 happen in both GPR and FPR, and which we want depends on who is going to consume
anatofuz
parents:
diff changeset
114 the loaded data. Similarly, G_FNEG can happen in both GPR and FPR. If we assign
anatofuz
parents:
diff changeset
115 it to FPR, then we'll use floating point negation. However, if we assign it to
anatofuz
parents:
diff changeset
116 GPR then we can equivalently G_XOR the sign bit with 1 to invert it.
anatofuz
parents:
diff changeset
117
anatofuz
parents:
diff changeset
118 In summary, Register Banks are a means of disambiguating between seemingly
anatofuz
parents:
diff changeset
119 equivalent choices based on some analysis of the differences when each choice
anatofuz
parents:
diff changeset
120 is applied in a given context.
anatofuz
parents:
diff changeset
121
anatofuz
parents:
diff changeset
122 To give some concrete examples:
anatofuz
parents:
diff changeset
123
anatofuz
parents:
diff changeset
124 AArch64
anatofuz
parents:
diff changeset
125
anatofuz
parents:
diff changeset
126 AArch64 has three main banks. GPR for integer operations, FPR for floating
anatofuz
parents:
diff changeset
127 point and also for the NEON vector instruction set. The third is CCR and
anatofuz
parents:
diff changeset
128 describes the condition code register used for predication.
anatofuz
parents:
diff changeset
129
anatofuz
parents:
diff changeset
130 MIPS
anatofuz
parents:
diff changeset
131
anatofuz
parents:
diff changeset
132 MIPS has five main banks of which many programs only really use one or two.
anatofuz
parents:
diff changeset
133 GPR is the general purpose bank for integer operations. FGR or CP1 is for
anatofuz
parents:
diff changeset
134 the floating point operations as well as the MSA vector instructions and a
anatofuz
parents:
diff changeset
135 few other application specific extensions. CP0 is for system registers and
anatofuz
parents:
diff changeset
136 few programs will use it. CP2 and CP3 are for any application specific
anatofuz
parents:
diff changeset
137 coprocessors that may be present in the chip. Arguably, there is also a sixth
anatofuz
parents:
diff changeset
138 for the LO and HI registers but these are only used for the result of a few
anatofuz
parents:
diff changeset
139 operations and it's of questionable value to model distinctly from GPR.
anatofuz
parents:
diff changeset
140
anatofuz
parents:
diff changeset
141 X86
anatofuz
parents:
diff changeset
142
anatofuz
parents:
diff changeset
143 X86 can be seen as having 3 main banks: general-purpose, x87, and
anatofuz
parents:
diff changeset
144 vector (which could be further split into a bank per domain for single vs
anatofuz
parents:
diff changeset
145 double precision instructions). It also looks like there's arguably a few
anatofuz
parents:
diff changeset
146 more potential banks such as one for the AVX512 Mask Registers.
anatofuz
parents:
diff changeset
147
anatofuz
parents:
diff changeset
148 Register banks are described by a target-provided API,
anatofuz
parents:
diff changeset
149 :ref:`RegisterBankInfo <api-registerbankinfo>`.
anatofuz
parents:
diff changeset
150
anatofuz
parents:
diff changeset
151 .. _gmir-llt:
anatofuz
parents:
diff changeset
152
anatofuz
parents:
diff changeset
153 Low Level Type
anatofuz
parents:
diff changeset
154 --------------
anatofuz
parents:
diff changeset
155
anatofuz
parents:
diff changeset
156 Additionally, every generic virtual register has a type, represented by an
anatofuz
parents:
diff changeset
157 instance of the ``LLT`` class.
anatofuz
parents:
diff changeset
158
anatofuz
parents:
diff changeset
159 Like ``EVT``/``MVT``/``Type``, it has no distinction between unsigned and signed
anatofuz
parents:
diff changeset
160 integer types. Furthermore, it also has no distinction between integer and
anatofuz
parents:
diff changeset
161 floating-point types: it mainly conveys absolutely necessary information, such
anatofuz
parents:
diff changeset
162 as size and number of vector lanes:
anatofuz
parents:
diff changeset
163
anatofuz
parents:
diff changeset
164 * ``sN`` for scalars
anatofuz
parents:
diff changeset
165 * ``pN`` for pointers
anatofuz
parents:
diff changeset
166 * ``<N x sM>`` for vectors
anatofuz
parents:
diff changeset
167
anatofuz
parents:
diff changeset
168 ``LLT`` is intended to replace the usage of ``EVT`` in SelectionDAG.
anatofuz
parents:
diff changeset
169
anatofuz
parents:
diff changeset
170 Here are some LLT examples and their ``EVT`` and ``Type`` equivalents:
anatofuz
parents:
diff changeset
171
anatofuz
parents:
diff changeset
172 ============= ========= ======================================
anatofuz
parents:
diff changeset
173 LLT EVT IR Type
anatofuz
parents:
diff changeset
174 ============= ========= ======================================
anatofuz
parents:
diff changeset
175 ``s1`` ``i1`` ``i1``
anatofuz
parents:
diff changeset
176 ``s8`` ``i8`` ``i8``
anatofuz
parents:
diff changeset
177 ``s32`` ``i32`` ``i32``
anatofuz
parents:
diff changeset
178 ``s32`` ``f32`` ``float``
anatofuz
parents:
diff changeset
179 ``s17`` ``i17`` ``i17``
anatofuz
parents:
diff changeset
180 ``s16`` N/A ``{i8, i8}`` [#abi-dependent]_
anatofuz
parents:
diff changeset
181 ``s32`` N/A ``[4 x i8]`` [#abi-dependent]_
anatofuz
parents:
diff changeset
182 ``p0`` ``iPTR`` ``i8*``, ``i32*``, ``%opaque*``
anatofuz
parents:
diff changeset
183 ``p2`` ``iPTR`` ``i8 addrspace(2)*``
anatofuz
parents:
diff changeset
184 ``<4 x s32>`` ``v4f32`` ``<4 x float>``
anatofuz
parents:
diff changeset
185 ``s64`` ``v1f64`` ``<1 x double>``
anatofuz
parents:
diff changeset
186 ``<3 x s32>`` ``v3i32`` ``<3 x i32>``
anatofuz
parents:
diff changeset
187 ============= ========= ======================================
anatofuz
parents:
diff changeset
188
anatofuz
parents:
diff changeset
189
anatofuz
parents:
diff changeset
190 Rationale: instructions already encode a specific interpretation of types
anatofuz
parents:
diff changeset
191 (e.g., ``add`` vs. ``fadd``, or ``sdiv`` vs. ``udiv``). Also encoding that
anatofuz
parents:
diff changeset
192 information in the type system requires introducing bitcast with no real
anatofuz
parents:
diff changeset
193 advantage for the selector.
anatofuz
parents:
diff changeset
194
anatofuz
parents:
diff changeset
195 Pointer types are distinguished by address space. This matches IR, as opposed
anatofuz
parents:
diff changeset
196 to SelectionDAG where address space is an attribute on operations.
anatofuz
parents:
diff changeset
197 This representation better supports pointers having different sizes depending
anatofuz
parents:
diff changeset
198 on their addressspace.
anatofuz
parents:
diff changeset
199
anatofuz
parents:
diff changeset
200 .. note::
anatofuz
parents:
diff changeset
201
anatofuz
parents:
diff changeset
202 .. caution::
anatofuz
parents:
diff changeset
203
anatofuz
parents:
diff changeset
204 Is this still true? I thought we'd removed the 1-element vector concept.
anatofuz
parents:
diff changeset
205 Hypothetically, it could be distinct from a scalar but I think we failed to
anatofuz
parents:
diff changeset
206 find a real occurrence.
anatofuz
parents:
diff changeset
207
anatofuz
parents:
diff changeset
208 Currently, LLT requires at least 2 elements in vectors, but some targets have
anatofuz
parents:
diff changeset
209 the concept of a '1-element vector'. Representing them as their underlying
anatofuz
parents:
diff changeset
210 scalar type is a nice simplification.
anatofuz
parents:
diff changeset
211
anatofuz
parents:
diff changeset
212 .. rubric:: Footnotes
anatofuz
parents:
diff changeset
213
anatofuz
parents:
diff changeset
214 .. [#abi-dependent] This mapping is ABI dependent. Here we've assumed no additional padding is required.
anatofuz
parents:
diff changeset
215
anatofuz
parents:
diff changeset
216 Generic Opcode Reference
anatofuz
parents:
diff changeset
217 ------------------------
anatofuz
parents:
diff changeset
218
anatofuz
parents:
diff changeset
219 The Generic Opcodes that are available are described at :doc:`GenericOpcode`.