1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2018 Valve Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
5*61046927SAndroid Build Coastguard Worker */
6*61046927SAndroid Build Coastguard Worker
7*61046927SAndroid Build Coastguard Worker #ifndef ACO_IR_H
8*61046927SAndroid Build Coastguard Worker #define ACO_IR_H
9*61046927SAndroid Build Coastguard Worker
10*61046927SAndroid Build Coastguard Worker #include "aco_opcodes.h"
11*61046927SAndroid Build Coastguard Worker #include "aco_shader_info.h"
12*61046927SAndroid Build Coastguard Worker #include "aco_util.h"
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker #include "util/compiler.h"
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Worker #include "ac_binary.h"
17*61046927SAndroid Build Coastguard Worker #include "ac_hw_stage.h"
18*61046927SAndroid Build Coastguard Worker #include "ac_shader_util.h"
19*61046927SAndroid Build Coastguard Worker #include "amd_family.h"
20*61046927SAndroid Build Coastguard Worker #include <algorithm>
21*61046927SAndroid Build Coastguard Worker #include <bitset>
22*61046927SAndroid Build Coastguard Worker #include <memory>
23*61046927SAndroid Build Coastguard Worker #include <vector>
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker typedef struct nir_shader nir_shader;
26*61046927SAndroid Build Coastguard Worker
27*61046927SAndroid Build Coastguard Worker namespace aco {
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker extern uint64_t debug_flags;
30*61046927SAndroid Build Coastguard Worker
31*61046927SAndroid Build Coastguard Worker enum {
32*61046927SAndroid Build Coastguard Worker DEBUG_VALIDATE_IR = 0x1,
33*61046927SAndroid Build Coastguard Worker DEBUG_VALIDATE_RA = 0x2,
34*61046927SAndroid Build Coastguard Worker DEBUG_VALIDATE_LIVE_VARS = 0x4,
35*61046927SAndroid Build Coastguard Worker DEBUG_FORCE_WAITCNT = 0x8,
36*61046927SAndroid Build Coastguard Worker DEBUG_NO_VN = 0x10,
37*61046927SAndroid Build Coastguard Worker DEBUG_NO_OPT = 0x20,
38*61046927SAndroid Build Coastguard Worker DEBUG_NO_SCHED = 0x40,
39*61046927SAndroid Build Coastguard Worker DEBUG_PERF_INFO = 0x80,
40*61046927SAndroid Build Coastguard Worker DEBUG_LIVE_INFO = 0x100,
41*61046927SAndroid Build Coastguard Worker DEBUG_FORCE_WAITDEPS = 0x200,
42*61046927SAndroid Build Coastguard Worker DEBUG_NO_VALIDATE_IR = 0x400,
43*61046927SAndroid Build Coastguard Worker DEBUG_NO_SCHED_ILP = 0x800,
44*61046927SAndroid Build Coastguard Worker DEBUG_NO_SCHED_VOPD = 0x1000,
45*61046927SAndroid Build Coastguard Worker };
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker enum storage_class : uint8_t {
48*61046927SAndroid Build Coastguard Worker storage_none = 0x0, /* no synchronization and can be reordered around aliasing stores */
49*61046927SAndroid Build Coastguard Worker storage_buffer = 0x1, /* SSBOs and global memory */
50*61046927SAndroid Build Coastguard Worker storage_gds = 0x2,
51*61046927SAndroid Build Coastguard Worker storage_image = 0x4,
52*61046927SAndroid Build Coastguard Worker storage_shared = 0x8, /* or TCS output */
53*61046927SAndroid Build Coastguard Worker storage_vmem_output = 0x10, /* GS or TCS output stores using VMEM */
54*61046927SAndroid Build Coastguard Worker storage_task_payload = 0x20, /* Task-Mesh payload */
55*61046927SAndroid Build Coastguard Worker storage_scratch = 0x40,
56*61046927SAndroid Build Coastguard Worker storage_vgpr_spill = 0x80,
57*61046927SAndroid Build Coastguard Worker storage_count = 8, /* not counting storage_none */
58*61046927SAndroid Build Coastguard Worker };
59*61046927SAndroid Build Coastguard Worker
60*61046927SAndroid Build Coastguard Worker enum memory_semantics : uint8_t {
61*61046927SAndroid Build Coastguard Worker semantic_none = 0x0,
62*61046927SAndroid Build Coastguard Worker /* for loads: don't move any access after this load to before this load (even other loads)
63*61046927SAndroid Build Coastguard Worker * for barriers: don't move any access after the barrier to before any
64*61046927SAndroid Build Coastguard Worker * atomics/control_barriers/sendmsg_gs_done/position-primitive-export before the barrier */
65*61046927SAndroid Build Coastguard Worker semantic_acquire = 0x1,
66*61046927SAndroid Build Coastguard Worker /* for stores: don't move any access before this store to after this store
67*61046927SAndroid Build Coastguard Worker * for barriers: don't move any access before the barrier to after any
68*61046927SAndroid Build Coastguard Worker * atomics/control_barriers/sendmsg_gs_done/position-primitive-export after the barrier */
69*61046927SAndroid Build Coastguard Worker semantic_release = 0x2,
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker /* the rest are for load/stores/atomics only */
72*61046927SAndroid Build Coastguard Worker /* cannot be DCE'd or CSE'd */
73*61046927SAndroid Build Coastguard Worker semantic_volatile = 0x4,
74*61046927SAndroid Build Coastguard Worker /* does not interact with barriers and assumes this lane is the only lane
75*61046927SAndroid Build Coastguard Worker * accessing this memory */
76*61046927SAndroid Build Coastguard Worker semantic_private = 0x8,
77*61046927SAndroid Build Coastguard Worker /* this operation can be reordered around operations of the same storage.
78*61046927SAndroid Build Coastguard Worker * says nothing about barriers */
79*61046927SAndroid Build Coastguard Worker semantic_can_reorder = 0x10,
80*61046927SAndroid Build Coastguard Worker /* this is a atomic instruction (may only read or write memory) */
81*61046927SAndroid Build Coastguard Worker semantic_atomic = 0x20,
82*61046927SAndroid Build Coastguard Worker /* this is instruction both reads and writes memory */
83*61046927SAndroid Build Coastguard Worker semantic_rmw = 0x40,
84*61046927SAndroid Build Coastguard Worker
85*61046927SAndroid Build Coastguard Worker semantic_acqrel = semantic_acquire | semantic_release,
86*61046927SAndroid Build Coastguard Worker semantic_atomicrmw = semantic_volatile | semantic_atomic | semantic_rmw,
87*61046927SAndroid Build Coastguard Worker };
88*61046927SAndroid Build Coastguard Worker
89*61046927SAndroid Build Coastguard Worker enum sync_scope : uint8_t {
90*61046927SAndroid Build Coastguard Worker scope_invocation = 0,
91*61046927SAndroid Build Coastguard Worker scope_subgroup = 1,
92*61046927SAndroid Build Coastguard Worker scope_workgroup = 2,
93*61046927SAndroid Build Coastguard Worker scope_queuefamily = 3,
94*61046927SAndroid Build Coastguard Worker scope_device = 4,
95*61046927SAndroid Build Coastguard Worker };
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker struct memory_sync_info {
memory_sync_infomemory_sync_info98*61046927SAndroid Build Coastguard Worker memory_sync_info() : storage(storage_none), semantics(semantic_none), scope(scope_invocation) {}
99*61046927SAndroid Build Coastguard Worker memory_sync_info(int storage_, int semantics_ = 0, sync_scope scope_ = scope_invocation)
100*61046927SAndroid Build Coastguard Worker : storage((storage_class)storage_), semantics((memory_semantics)semantics_), scope(scope_)
101*61046927SAndroid Build Coastguard Worker {}
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker storage_class storage : 8;
104*61046927SAndroid Build Coastguard Worker memory_semantics semantics : 8;
105*61046927SAndroid Build Coastguard Worker sync_scope scope : 8;
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker bool operator==(const memory_sync_info& rhs) const
108*61046927SAndroid Build Coastguard Worker {
109*61046927SAndroid Build Coastguard Worker return storage == rhs.storage && semantics == rhs.semantics && scope == rhs.scope;
110*61046927SAndroid Build Coastguard Worker }
111*61046927SAndroid Build Coastguard Worker
can_reordermemory_sync_info112*61046927SAndroid Build Coastguard Worker bool can_reorder() const
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker if (semantics & semantic_acqrel)
115*61046927SAndroid Build Coastguard Worker return false;
116*61046927SAndroid Build Coastguard Worker /* Also check storage so that zero-initialized memory_sync_info can be
117*61046927SAndroid Build Coastguard Worker * reordered. */
118*61046927SAndroid Build Coastguard Worker return (!storage || (semantics & semantic_can_reorder)) && !(semantics & semantic_volatile);
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker };
121*61046927SAndroid Build Coastguard Worker static_assert(sizeof(memory_sync_info) == 3, "Unexpected padding");
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker enum fp_round {
124*61046927SAndroid Build Coastguard Worker fp_round_ne = 0,
125*61046927SAndroid Build Coastguard Worker fp_round_pi = 1,
126*61046927SAndroid Build Coastguard Worker fp_round_ni = 2,
127*61046927SAndroid Build Coastguard Worker fp_round_tz = 3,
128*61046927SAndroid Build Coastguard Worker };
129*61046927SAndroid Build Coastguard Worker
130*61046927SAndroid Build Coastguard Worker enum fp_denorm {
131*61046927SAndroid Build Coastguard Worker /* Note that v_rcp_f32, v_exp_f32, v_log_f32, v_sqrt_f32, v_rsq_f32 and
132*61046927SAndroid Build Coastguard Worker * v_mad_f32/v_madak_f32/v_madmk_f32/v_mac_f32 always flush denormals. */
133*61046927SAndroid Build Coastguard Worker fp_denorm_flush = 0x0,
134*61046927SAndroid Build Coastguard Worker fp_denorm_keep_in = 0x1,
135*61046927SAndroid Build Coastguard Worker fp_denorm_keep_out = 0x2,
136*61046927SAndroid Build Coastguard Worker fp_denorm_keep = 0x3,
137*61046927SAndroid Build Coastguard Worker };
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker struct float_mode {
140*61046927SAndroid Build Coastguard Worker /* matches encoding of the MODE register */
141*61046927SAndroid Build Coastguard Worker union {
142*61046927SAndroid Build Coastguard Worker struct {
143*61046927SAndroid Build Coastguard Worker fp_round round32 : 2;
144*61046927SAndroid Build Coastguard Worker fp_round round16_64 : 2;
145*61046927SAndroid Build Coastguard Worker unsigned denorm32 : 2;
146*61046927SAndroid Build Coastguard Worker unsigned denorm16_64 : 2;
147*61046927SAndroid Build Coastguard Worker };
148*61046927SAndroid Build Coastguard Worker struct {
149*61046927SAndroid Build Coastguard Worker uint8_t round : 4;
150*61046927SAndroid Build Coastguard Worker uint8_t denorm : 4;
151*61046927SAndroid Build Coastguard Worker };
152*61046927SAndroid Build Coastguard Worker uint8_t val = 0;
153*61046927SAndroid Build Coastguard Worker };
154*61046927SAndroid Build Coastguard Worker /* if false, optimizations which may remove denormal flushing can be done */
155*61046927SAndroid Build Coastguard Worker bool must_flush_denorms32 : 1;
156*61046927SAndroid Build Coastguard Worker bool must_flush_denorms16_64 : 1;
157*61046927SAndroid Build Coastguard Worker bool care_about_round32 : 1;
158*61046927SAndroid Build Coastguard Worker bool care_about_round16_64 : 1;
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker /* Returns true if instructions using the mode "other" can safely use the
161*61046927SAndroid Build Coastguard Worker * current one instead. */
canReplacefloat_mode162*61046927SAndroid Build Coastguard Worker bool canReplace(float_mode other) const noexcept
163*61046927SAndroid Build Coastguard Worker {
164*61046927SAndroid Build Coastguard Worker return val == other.val && (must_flush_denorms32 || !other.must_flush_denorms32) &&
165*61046927SAndroid Build Coastguard Worker (must_flush_denorms16_64 || !other.must_flush_denorms16_64) &&
166*61046927SAndroid Build Coastguard Worker (care_about_round32 || !other.care_about_round32) &&
167*61046927SAndroid Build Coastguard Worker (care_about_round16_64 || !other.care_about_round16_64);
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker };
170*61046927SAndroid Build Coastguard Worker
171*61046927SAndroid Build Coastguard Worker enum wait_type {
172*61046927SAndroid Build Coastguard Worker wait_type_exp = 0,
173*61046927SAndroid Build Coastguard Worker wait_type_lgkm = 1,
174*61046927SAndroid Build Coastguard Worker wait_type_vm = 2,
175*61046927SAndroid Build Coastguard Worker /* GFX10+ */
176*61046927SAndroid Build Coastguard Worker wait_type_vs = 3,
177*61046927SAndroid Build Coastguard Worker /* GFX12+ */
178*61046927SAndroid Build Coastguard Worker wait_type_sample = 4,
179*61046927SAndroid Build Coastguard Worker wait_type_bvh = 5,
180*61046927SAndroid Build Coastguard Worker wait_type_km = 6,
181*61046927SAndroid Build Coastguard Worker wait_type_num = 7,
182*61046927SAndroid Build Coastguard Worker };
183*61046927SAndroid Build Coastguard Worker
184*61046927SAndroid Build Coastguard Worker struct Instruction;
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Worker struct wait_imm {
187*61046927SAndroid Build Coastguard Worker static const uint8_t unset_counter = 0xff;
188*61046927SAndroid Build Coastguard Worker
189*61046927SAndroid Build Coastguard Worker uint8_t exp;
190*61046927SAndroid Build Coastguard Worker uint8_t lgkm;
191*61046927SAndroid Build Coastguard Worker uint8_t vm;
192*61046927SAndroid Build Coastguard Worker uint8_t vs;
193*61046927SAndroid Build Coastguard Worker uint8_t sample;
194*61046927SAndroid Build Coastguard Worker uint8_t bvh;
195*61046927SAndroid Build Coastguard Worker uint8_t km;
196*61046927SAndroid Build Coastguard Worker
197*61046927SAndroid Build Coastguard Worker wait_imm();
198*61046927SAndroid Build Coastguard Worker wait_imm(uint16_t vm_, uint16_t exp_, uint16_t lgkm_, uint16_t vs_);
199*61046927SAndroid Build Coastguard Worker
200*61046927SAndroid Build Coastguard Worker uint16_t pack(enum amd_gfx_level chip) const;
201*61046927SAndroid Build Coastguard Worker
202*61046927SAndroid Build Coastguard Worker static wait_imm max(enum amd_gfx_level gfx_level);
203*61046927SAndroid Build Coastguard Worker
204*61046927SAndroid Build Coastguard Worker bool unpack(enum amd_gfx_level gfx_level, const Instruction* instr);
205*61046927SAndroid Build Coastguard Worker
206*61046927SAndroid Build Coastguard Worker bool combine(const wait_imm& other);
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker bool empty() const;
209*61046927SAndroid Build Coastguard Worker
210*61046927SAndroid Build Coastguard Worker void print(FILE* output) const;
211*61046927SAndroid Build Coastguard Worker
212*61046927SAndroid Build Coastguard Worker uint8_t& operator[](size_t i)
213*61046927SAndroid Build Coastguard Worker {
214*61046927SAndroid Build Coastguard Worker assert(i < wait_type_num);
215*61046927SAndroid Build Coastguard Worker return *((uint8_t*)this + i);
216*61046927SAndroid Build Coastguard Worker }
217*61046927SAndroid Build Coastguard Worker
218*61046927SAndroid Build Coastguard Worker const uint8_t& operator[](size_t i) const
219*61046927SAndroid Build Coastguard Worker {
220*61046927SAndroid Build Coastguard Worker assert(i < wait_type_num);
221*61046927SAndroid Build Coastguard Worker return *((uint8_t*)this + i);
222*61046927SAndroid Build Coastguard Worker }
223*61046927SAndroid Build Coastguard Worker };
224*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, exp) == wait_type_exp);
225*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, lgkm) == wait_type_lgkm);
226*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, vm) == wait_type_vm);
227*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, vs) == wait_type_vs);
228*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, sample) == wait_type_sample);
229*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, bvh) == wait_type_bvh);
230*61046927SAndroid Build Coastguard Worker static_assert(offsetof(wait_imm, km) == wait_type_km);
231*61046927SAndroid Build Coastguard Worker
232*61046927SAndroid Build Coastguard Worker /* s_wait_event immediate bits. */
233*61046927SAndroid Build Coastguard Worker enum wait_event_imm : uint16_t {
234*61046927SAndroid Build Coastguard Worker /* If this bit is 0, await that the export buffer space has been allocated.
235*61046927SAndroid Build Coastguard Worker * In Primitive Ordered Pixel Shading, export ready means that the overlapped waves have exited
236*61046927SAndroid Build Coastguard Worker * their ordered sections (by performing the `done` export), and that the current wave may enter
237*61046927SAndroid Build Coastguard Worker * its ordered section.
238*61046927SAndroid Build Coastguard Worker */
239*61046927SAndroid Build Coastguard Worker wait_event_imm_dont_wait_export_ready_gfx11 = 0x1,
240*61046927SAndroid Build Coastguard Worker wait_event_imm_wait_export_ready_gfx12 = 0x2,
241*61046927SAndroid Build Coastguard Worker };
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker constexpr Format
asVOP3(Format format)244*61046927SAndroid Build Coastguard Worker asVOP3(Format format)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker return (Format)((uint32_t)Format::VOP3 | (uint32_t)format);
247*61046927SAndroid Build Coastguard Worker };
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker constexpr Format
asSDWA(Format format)250*61046927SAndroid Build Coastguard Worker asSDWA(Format format)
251*61046927SAndroid Build Coastguard Worker {
252*61046927SAndroid Build Coastguard Worker assert(format == Format::VOP1 || format == Format::VOP2 || format == Format::VOPC);
253*61046927SAndroid Build Coastguard Worker return (Format)((uint32_t)Format::SDWA | (uint32_t)format);
254*61046927SAndroid Build Coastguard Worker }
255*61046927SAndroid Build Coastguard Worker
256*61046927SAndroid Build Coastguard Worker constexpr Format
withoutDPP(Format format)257*61046927SAndroid Build Coastguard Worker withoutDPP(Format format)
258*61046927SAndroid Build Coastguard Worker {
259*61046927SAndroid Build Coastguard Worker return (Format)((uint32_t)format & ~((uint32_t)Format::DPP16 | (uint32_t)Format::DPP8));
260*61046927SAndroid Build Coastguard Worker }
261*61046927SAndroid Build Coastguard Worker
262*61046927SAndroid Build Coastguard Worker constexpr Format
withoutVOP3(Format format)263*61046927SAndroid Build Coastguard Worker withoutVOP3(Format format)
264*61046927SAndroid Build Coastguard Worker {
265*61046927SAndroid Build Coastguard Worker return (Format)((uint32_t)format & ~((uint32_t)Format::VOP3));
266*61046927SAndroid Build Coastguard Worker }
267*61046927SAndroid Build Coastguard Worker
268*61046927SAndroid Build Coastguard Worker enum class RegType {
269*61046927SAndroid Build Coastguard Worker sgpr,
270*61046927SAndroid Build Coastguard Worker vgpr,
271*61046927SAndroid Build Coastguard Worker };
272*61046927SAndroid Build Coastguard Worker
273*61046927SAndroid Build Coastguard Worker struct RegClass {
274*61046927SAndroid Build Coastguard Worker
275*61046927SAndroid Build Coastguard Worker enum RC : uint8_t {
276*61046927SAndroid Build Coastguard Worker s1 = 1,
277*61046927SAndroid Build Coastguard Worker s2 = 2,
278*61046927SAndroid Build Coastguard Worker s3 = 3,
279*61046927SAndroid Build Coastguard Worker s4 = 4,
280*61046927SAndroid Build Coastguard Worker s6 = 6,
281*61046927SAndroid Build Coastguard Worker s8 = 8,
282*61046927SAndroid Build Coastguard Worker s16 = 16,
283*61046927SAndroid Build Coastguard Worker v1 = s1 | (1 << 5),
284*61046927SAndroid Build Coastguard Worker v2 = s2 | (1 << 5),
285*61046927SAndroid Build Coastguard Worker v3 = s3 | (1 << 5),
286*61046927SAndroid Build Coastguard Worker v4 = s4 | (1 << 5),
287*61046927SAndroid Build Coastguard Worker v5 = 5 | (1 << 5),
288*61046927SAndroid Build Coastguard Worker v6 = 6 | (1 << 5),
289*61046927SAndroid Build Coastguard Worker v7 = 7 | (1 << 5),
290*61046927SAndroid Build Coastguard Worker v8 = 8 | (1 << 5),
291*61046927SAndroid Build Coastguard Worker /* byte-sized register class */
292*61046927SAndroid Build Coastguard Worker v1b = v1 | (1 << 7),
293*61046927SAndroid Build Coastguard Worker v2b = v2 | (1 << 7),
294*61046927SAndroid Build Coastguard Worker v3b = v3 | (1 << 7),
295*61046927SAndroid Build Coastguard Worker v4b = v4 | (1 << 7),
296*61046927SAndroid Build Coastguard Worker v6b = v6 | (1 << 7),
297*61046927SAndroid Build Coastguard Worker v8b = v8 | (1 << 7),
298*61046927SAndroid Build Coastguard Worker /* these are used for WWM and spills to vgpr */
299*61046927SAndroid Build Coastguard Worker v1_linear = v1 | (1 << 6),
300*61046927SAndroid Build Coastguard Worker v2_linear = v2 | (1 << 6),
301*61046927SAndroid Build Coastguard Worker };
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker RegClass() = default;
RegClassRegClass304*61046927SAndroid Build Coastguard Worker constexpr RegClass(RC rc_) : rc(rc_) {}
RegClassRegClass305*61046927SAndroid Build Coastguard Worker constexpr RegClass(RegType type, unsigned size)
306*61046927SAndroid Build Coastguard Worker : rc((RC)((type == RegType::vgpr ? 1 << 5 : 0) | size))
307*61046927SAndroid Build Coastguard Worker {}
308*61046927SAndroid Build Coastguard Worker
RCRegClass309*61046927SAndroid Build Coastguard Worker constexpr operator RC() const { return rc; }
310*61046927SAndroid Build Coastguard Worker explicit operator bool() = delete;
311*61046927SAndroid Build Coastguard Worker
typeRegClass312*61046927SAndroid Build Coastguard Worker constexpr RegType type() const { return rc <= RC::s16 ? RegType::sgpr : RegType::vgpr; }
is_linear_vgprRegClass313*61046927SAndroid Build Coastguard Worker constexpr bool is_linear_vgpr() const { return rc & (1 << 6); };
is_subdwordRegClass314*61046927SAndroid Build Coastguard Worker constexpr bool is_subdword() const { return rc & (1 << 7); }
bytesRegClass315*61046927SAndroid Build Coastguard Worker constexpr unsigned bytes() const { return ((unsigned)rc & 0x1F) * (is_subdword() ? 1 : 4); }
316*61046927SAndroid Build Coastguard Worker // TODO: use size() less in favor of bytes()
sizeRegClass317*61046927SAndroid Build Coastguard Worker constexpr unsigned size() const { return (bytes() + 3) >> 2; }
is_linearRegClass318*61046927SAndroid Build Coastguard Worker constexpr bool is_linear() const { return rc <= RC::s16 || is_linear_vgpr(); }
as_linearRegClass319*61046927SAndroid Build Coastguard Worker constexpr RegClass as_linear() const { return RegClass((RC)(rc | (1 << 6))); }
as_subdwordRegClass320*61046927SAndroid Build Coastguard Worker constexpr RegClass as_subdword() const { return RegClass((RC)(rc | 1 << 7)); }
321*61046927SAndroid Build Coastguard Worker
getRegClass322*61046927SAndroid Build Coastguard Worker static constexpr RegClass get(RegType type, unsigned bytes)
323*61046927SAndroid Build Coastguard Worker {
324*61046927SAndroid Build Coastguard Worker if (type == RegType::sgpr) {
325*61046927SAndroid Build Coastguard Worker return RegClass(type, DIV_ROUND_UP(bytes, 4u));
326*61046927SAndroid Build Coastguard Worker } else {
327*61046927SAndroid Build Coastguard Worker return bytes % 4u ? RegClass(type, bytes).as_subdword() : RegClass(type, bytes / 4u);
328*61046927SAndroid Build Coastguard Worker }
329*61046927SAndroid Build Coastguard Worker }
330*61046927SAndroid Build Coastguard Worker
resizeRegClass331*61046927SAndroid Build Coastguard Worker constexpr RegClass resize(unsigned bytes) const
332*61046927SAndroid Build Coastguard Worker {
333*61046927SAndroid Build Coastguard Worker if (is_linear_vgpr()) {
334*61046927SAndroid Build Coastguard Worker assert(bytes % 4u == 0);
335*61046927SAndroid Build Coastguard Worker return get(RegType::vgpr, bytes).as_linear();
336*61046927SAndroid Build Coastguard Worker }
337*61046927SAndroid Build Coastguard Worker return get(type(), bytes);
338*61046927SAndroid Build Coastguard Worker }
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker private:
341*61046927SAndroid Build Coastguard Worker RC rc;
342*61046927SAndroid Build Coastguard Worker };
343*61046927SAndroid Build Coastguard Worker
344*61046927SAndroid Build Coastguard Worker /* transitional helper expressions */
345*61046927SAndroid Build Coastguard Worker static constexpr RegClass s1{RegClass::s1};
346*61046927SAndroid Build Coastguard Worker static constexpr RegClass s2{RegClass::s2};
347*61046927SAndroid Build Coastguard Worker static constexpr RegClass s3{RegClass::s3};
348*61046927SAndroid Build Coastguard Worker static constexpr RegClass s4{RegClass::s4};
349*61046927SAndroid Build Coastguard Worker static constexpr RegClass s8{RegClass::s8};
350*61046927SAndroid Build Coastguard Worker static constexpr RegClass s16{RegClass::s16};
351*61046927SAndroid Build Coastguard Worker static constexpr RegClass v1{RegClass::v1};
352*61046927SAndroid Build Coastguard Worker static constexpr RegClass v2{RegClass::v2};
353*61046927SAndroid Build Coastguard Worker static constexpr RegClass v3{RegClass::v3};
354*61046927SAndroid Build Coastguard Worker static constexpr RegClass v4{RegClass::v4};
355*61046927SAndroid Build Coastguard Worker static constexpr RegClass v5{RegClass::v5};
356*61046927SAndroid Build Coastguard Worker static constexpr RegClass v6{RegClass::v6};
357*61046927SAndroid Build Coastguard Worker static constexpr RegClass v7{RegClass::v7};
358*61046927SAndroid Build Coastguard Worker static constexpr RegClass v8{RegClass::v8};
359*61046927SAndroid Build Coastguard Worker static constexpr RegClass v1b{RegClass::v1b};
360*61046927SAndroid Build Coastguard Worker static constexpr RegClass v2b{RegClass::v2b};
361*61046927SAndroid Build Coastguard Worker static constexpr RegClass v3b{RegClass::v3b};
362*61046927SAndroid Build Coastguard Worker static constexpr RegClass v4b{RegClass::v4b};
363*61046927SAndroid Build Coastguard Worker static constexpr RegClass v6b{RegClass::v6b};
364*61046927SAndroid Build Coastguard Worker static constexpr RegClass v8b{RegClass::v8b};
365*61046927SAndroid Build Coastguard Worker
366*61046927SAndroid Build Coastguard Worker /**
367*61046927SAndroid Build Coastguard Worker * Temp Class
368*61046927SAndroid Build Coastguard Worker * Each temporary virtual register has a
369*61046927SAndroid Build Coastguard Worker * register class (i.e. size and type)
370*61046927SAndroid Build Coastguard Worker * and SSA id.
371*61046927SAndroid Build Coastguard Worker */
372*61046927SAndroid Build Coastguard Worker struct Temp {
TempTemp373*61046927SAndroid Build Coastguard Worker Temp() noexcept : id_(0), reg_class(0) {}
TempTemp374*61046927SAndroid Build Coastguard Worker constexpr Temp(uint32_t id, RegClass cls) noexcept : id_(id), reg_class(uint8_t(cls)) {}
375*61046927SAndroid Build Coastguard Worker
idTemp376*61046927SAndroid Build Coastguard Worker constexpr uint32_t id() const noexcept { return id_; }
regClassTemp377*61046927SAndroid Build Coastguard Worker constexpr RegClass regClass() const noexcept { return (RegClass::RC)reg_class; }
378*61046927SAndroid Build Coastguard Worker
bytesTemp379*61046927SAndroid Build Coastguard Worker constexpr unsigned bytes() const noexcept { return regClass().bytes(); }
sizeTemp380*61046927SAndroid Build Coastguard Worker constexpr unsigned size() const noexcept { return regClass().size(); }
typeTemp381*61046927SAndroid Build Coastguard Worker constexpr RegType type() const noexcept { return regClass().type(); }
is_linearTemp382*61046927SAndroid Build Coastguard Worker constexpr bool is_linear() const noexcept { return regClass().is_linear(); }
383*61046927SAndroid Build Coastguard Worker
384*61046927SAndroid Build Coastguard Worker constexpr bool operator<(Temp other) const noexcept { return id() < other.id(); }
385*61046927SAndroid Build Coastguard Worker constexpr bool operator==(Temp other) const noexcept { return id() == other.id(); }
386*61046927SAndroid Build Coastguard Worker constexpr bool operator!=(Temp other) const noexcept { return id() != other.id(); }
387*61046927SAndroid Build Coastguard Worker
388*61046927SAndroid Build Coastguard Worker private:
389*61046927SAndroid Build Coastguard Worker uint32_t id_ : 24;
390*61046927SAndroid Build Coastguard Worker uint32_t reg_class : 8;
391*61046927SAndroid Build Coastguard Worker };
392*61046927SAndroid Build Coastguard Worker
393*61046927SAndroid Build Coastguard Worker /**
394*61046927SAndroid Build Coastguard Worker * PhysReg
395*61046927SAndroid Build Coastguard Worker * Represents the physical register for each
396*61046927SAndroid Build Coastguard Worker * Operand and Definition.
397*61046927SAndroid Build Coastguard Worker */
398*61046927SAndroid Build Coastguard Worker struct PhysReg {
399*61046927SAndroid Build Coastguard Worker constexpr PhysReg() = default;
PhysRegPhysReg400*61046927SAndroid Build Coastguard Worker explicit constexpr PhysReg(unsigned r) : reg_b(r << 2) {}
regPhysReg401*61046927SAndroid Build Coastguard Worker constexpr unsigned reg() const { return reg_b >> 2; }
bytePhysReg402*61046927SAndroid Build Coastguard Worker constexpr unsigned byte() const { return reg_b & 0x3; }
403*61046927SAndroid Build Coastguard Worker constexpr operator unsigned() const { return reg(); }
404*61046927SAndroid Build Coastguard Worker constexpr bool operator==(PhysReg other) const { return reg_b == other.reg_b; }
405*61046927SAndroid Build Coastguard Worker constexpr bool operator!=(PhysReg other) const { return reg_b != other.reg_b; }
406*61046927SAndroid Build Coastguard Worker constexpr bool operator<(PhysReg other) const { return reg_b < other.reg_b; }
advancePhysReg407*61046927SAndroid Build Coastguard Worker constexpr PhysReg advance(int bytes) const
408*61046927SAndroid Build Coastguard Worker {
409*61046927SAndroid Build Coastguard Worker PhysReg res = *this;
410*61046927SAndroid Build Coastguard Worker res.reg_b += bytes;
411*61046927SAndroid Build Coastguard Worker return res;
412*61046927SAndroid Build Coastguard Worker }
413*61046927SAndroid Build Coastguard Worker
414*61046927SAndroid Build Coastguard Worker uint16_t reg_b = 0;
415*61046927SAndroid Build Coastguard Worker };
416*61046927SAndroid Build Coastguard Worker
417*61046927SAndroid Build Coastguard Worker /* helper expressions for special registers */
418*61046927SAndroid Build Coastguard Worker static constexpr PhysReg m0{124};
419*61046927SAndroid Build Coastguard Worker static constexpr PhysReg flat_scr_lo{102}; /* GFX8-GFX9, encoded differently on GFX6-7 */
420*61046927SAndroid Build Coastguard Worker static constexpr PhysReg flat_scr_hi{103}; /* GFX8-GFX9, encoded differently on GFX6-7 */
421*61046927SAndroid Build Coastguard Worker static constexpr PhysReg vcc{106};
422*61046927SAndroid Build Coastguard Worker static constexpr PhysReg vcc_hi{107};
423*61046927SAndroid Build Coastguard Worker static constexpr PhysReg tba{108}; /* GFX6-GFX8 */
424*61046927SAndroid Build Coastguard Worker static constexpr PhysReg tma{110}; /* GFX6-GFX8 */
425*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp0{112};
426*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp1{113};
427*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp2{114};
428*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp3{115};
429*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp4{116};
430*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp5{117};
431*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp6{118};
432*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp7{119};
433*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp8{120};
434*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp9{121};
435*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp10{122};
436*61046927SAndroid Build Coastguard Worker static constexpr PhysReg ttmp11{123};
437*61046927SAndroid Build Coastguard Worker static constexpr PhysReg sgpr_null{125}; /* GFX10+ */
438*61046927SAndroid Build Coastguard Worker static constexpr PhysReg exec{126};
439*61046927SAndroid Build Coastguard Worker static constexpr PhysReg exec_lo{126};
440*61046927SAndroid Build Coastguard Worker static constexpr PhysReg exec_hi{127};
441*61046927SAndroid Build Coastguard Worker static constexpr PhysReg pops_exiting_wave_id{239}; /* GFX9-GFX10.3 */
442*61046927SAndroid Build Coastguard Worker static constexpr PhysReg scc{253};
443*61046927SAndroid Build Coastguard Worker
444*61046927SAndroid Build Coastguard Worker /**
445*61046927SAndroid Build Coastguard Worker * Operand Class
446*61046927SAndroid Build Coastguard Worker * Initially, each Operand refers to either
447*61046927SAndroid Build Coastguard Worker * a temporary virtual register
448*61046927SAndroid Build Coastguard Worker * or to a constant value
449*61046927SAndroid Build Coastguard Worker * Temporary registers get mapped to physical register during RA
450*61046927SAndroid Build Coastguard Worker * Constant values are inlined into the instruction sequence.
451*61046927SAndroid Build Coastguard Worker */
452*61046927SAndroid Build Coastguard Worker class Operand final {
453*61046927SAndroid Build Coastguard Worker public:
Operand()454*61046927SAndroid Build Coastguard Worker constexpr Operand()
455*61046927SAndroid Build Coastguard Worker : reg_(PhysReg{128}), isTemp_(false), isFixed_(true), isConstant_(false), isKill_(false),
456*61046927SAndroid Build Coastguard Worker isUndef_(true), isFirstKill_(false), constSize(0), isLateKill_(false), isClobbered_(false),
457*61046927SAndroid Build Coastguard Worker isCopyKill_(false), is16bit_(false), is24bit_(false), signext(false)
458*61046927SAndroid Build Coastguard Worker {}
459*61046927SAndroid Build Coastguard Worker
Operand(Temp r)460*61046927SAndroid Build Coastguard Worker explicit Operand(Temp r) noexcept
461*61046927SAndroid Build Coastguard Worker {
462*61046927SAndroid Build Coastguard Worker data_.temp = r;
463*61046927SAndroid Build Coastguard Worker if (r.id()) {
464*61046927SAndroid Build Coastguard Worker isTemp_ = true;
465*61046927SAndroid Build Coastguard Worker } else {
466*61046927SAndroid Build Coastguard Worker isUndef_ = true;
467*61046927SAndroid Build Coastguard Worker setFixed(PhysReg{128});
468*61046927SAndroid Build Coastguard Worker }
469*61046927SAndroid Build Coastguard Worker };
Operand(Temp r,PhysReg reg)470*61046927SAndroid Build Coastguard Worker explicit Operand(Temp r, PhysReg reg) noexcept
471*61046927SAndroid Build Coastguard Worker {
472*61046927SAndroid Build Coastguard Worker assert(r.id()); /* Don't allow fixing an undef to a register */
473*61046927SAndroid Build Coastguard Worker data_.temp = r;
474*61046927SAndroid Build Coastguard Worker isTemp_ = true;
475*61046927SAndroid Build Coastguard Worker setFixed(reg);
476*61046927SAndroid Build Coastguard Worker };
477*61046927SAndroid Build Coastguard Worker
478*61046927SAndroid Build Coastguard Worker /* 8-bit constant */
c8(uint8_t v)479*61046927SAndroid Build Coastguard Worker static Operand c8(uint8_t v) noexcept
480*61046927SAndroid Build Coastguard Worker {
481*61046927SAndroid Build Coastguard Worker /* 8-bit constants are only used for copies and copies from any 8-bit
482*61046927SAndroid Build Coastguard Worker * constant can be implemented with a SDWA v_mul_u32_u24. So consider all
483*61046927SAndroid Build Coastguard Worker * to be inline constants. */
484*61046927SAndroid Build Coastguard Worker Operand op;
485*61046927SAndroid Build Coastguard Worker op.control_ = 0;
486*61046927SAndroid Build Coastguard Worker op.data_.i = v;
487*61046927SAndroid Build Coastguard Worker op.isConstant_ = true;
488*61046927SAndroid Build Coastguard Worker op.constSize = 0;
489*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{0u});
490*61046927SAndroid Build Coastguard Worker return op;
491*61046927SAndroid Build Coastguard Worker };
492*61046927SAndroid Build Coastguard Worker
493*61046927SAndroid Build Coastguard Worker /* 16-bit constant */
c16(uint16_t v)494*61046927SAndroid Build Coastguard Worker static Operand c16(uint16_t v) noexcept
495*61046927SAndroid Build Coastguard Worker {
496*61046927SAndroid Build Coastguard Worker Operand op;
497*61046927SAndroid Build Coastguard Worker op.control_ = 0;
498*61046927SAndroid Build Coastguard Worker op.data_.i = v;
499*61046927SAndroid Build Coastguard Worker op.isConstant_ = true;
500*61046927SAndroid Build Coastguard Worker op.constSize = 1;
501*61046927SAndroid Build Coastguard Worker if (v <= 64)
502*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{128u + v});
503*61046927SAndroid Build Coastguard Worker else if (v >= 0xFFF0) /* [-16 .. -1] */
504*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{(unsigned)(192 - (int16_t)v)});
505*61046927SAndroid Build Coastguard Worker else if (v == 0x3800) /* 0.5 */
506*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{240});
507*61046927SAndroid Build Coastguard Worker else if (v == 0xB800) /* -0.5 */
508*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{241});
509*61046927SAndroid Build Coastguard Worker else if (v == 0x3C00) /* 1.0 */
510*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{242});
511*61046927SAndroid Build Coastguard Worker else if (v == 0xBC00) /* -1.0 */
512*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{243});
513*61046927SAndroid Build Coastguard Worker else if (v == 0x4000) /* 2.0 */
514*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{244});
515*61046927SAndroid Build Coastguard Worker else if (v == 0xC000) /* -2.0 */
516*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{245});
517*61046927SAndroid Build Coastguard Worker else if (v == 0x4400) /* 4.0 */
518*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{246});
519*61046927SAndroid Build Coastguard Worker else if (v == 0xC400) /* -4.0 */
520*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{247});
521*61046927SAndroid Build Coastguard Worker else if (v == 0x3118) /* 1/2 PI */
522*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{248});
523*61046927SAndroid Build Coastguard Worker else /* Literal Constant */
524*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{255});
525*61046927SAndroid Build Coastguard Worker return op;
526*61046927SAndroid Build Coastguard Worker }
527*61046927SAndroid Build Coastguard Worker
528*61046927SAndroid Build Coastguard Worker /* 32-bit constant */
c32(uint32_t v)529*61046927SAndroid Build Coastguard Worker static Operand c32(uint32_t v) noexcept { return c32_or_c64(v, false); }
530*61046927SAndroid Build Coastguard Worker
531*61046927SAndroid Build Coastguard Worker /* 64-bit constant */
c64(uint64_t v)532*61046927SAndroid Build Coastguard Worker static Operand c64(uint64_t v) noexcept
533*61046927SAndroid Build Coastguard Worker {
534*61046927SAndroid Build Coastguard Worker Operand op;
535*61046927SAndroid Build Coastguard Worker op.control_ = 0;
536*61046927SAndroid Build Coastguard Worker op.isConstant_ = true;
537*61046927SAndroid Build Coastguard Worker op.constSize = 3;
538*61046927SAndroid Build Coastguard Worker if (v <= 64) {
539*61046927SAndroid Build Coastguard Worker op.data_.i = (uint32_t)v;
540*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{128 + (uint32_t)v});
541*61046927SAndroid Build Coastguard Worker } else if (v >= 0xFFFFFFFFFFFFFFF0) { /* [-16 .. -1] */
542*61046927SAndroid Build Coastguard Worker op.data_.i = (uint32_t)v;
543*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{192 - (uint32_t)v});
544*61046927SAndroid Build Coastguard Worker } else if (v == 0x3FE0000000000000) { /* 0.5 */
545*61046927SAndroid Build Coastguard Worker op.data_.i = 0x3f000000;
546*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{240});
547*61046927SAndroid Build Coastguard Worker } else if (v == 0xBFE0000000000000) { /* -0.5 */
548*61046927SAndroid Build Coastguard Worker op.data_.i = 0xbf000000;
549*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{241});
550*61046927SAndroid Build Coastguard Worker } else if (v == 0x3FF0000000000000) { /* 1.0 */
551*61046927SAndroid Build Coastguard Worker op.data_.i = 0x3f800000;
552*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{242});
553*61046927SAndroid Build Coastguard Worker } else if (v == 0xBFF0000000000000) { /* -1.0 */
554*61046927SAndroid Build Coastguard Worker op.data_.i = 0xbf800000;
555*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{243});
556*61046927SAndroid Build Coastguard Worker } else if (v == 0x4000000000000000) { /* 2.0 */
557*61046927SAndroid Build Coastguard Worker op.data_.i = 0x40000000;
558*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{244});
559*61046927SAndroid Build Coastguard Worker } else if (v == 0xC000000000000000) { /* -2.0 */
560*61046927SAndroid Build Coastguard Worker op.data_.i = 0xc0000000;
561*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{245});
562*61046927SAndroid Build Coastguard Worker } else if (v == 0x4010000000000000) { /* 4.0 */
563*61046927SAndroid Build Coastguard Worker op.data_.i = 0x40800000;
564*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{246});
565*61046927SAndroid Build Coastguard Worker } else if (v == 0xC010000000000000) { /* -4.0 */
566*61046927SAndroid Build Coastguard Worker op.data_.i = 0xc0800000;
567*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{247});
568*61046927SAndroid Build Coastguard Worker } else { /* Literal Constant: we don't know if it is a long or double.*/
569*61046927SAndroid Build Coastguard Worker op.signext = v >> 63;
570*61046927SAndroid Build Coastguard Worker op.data_.i = v & 0xffffffffu;
571*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{255});
572*61046927SAndroid Build Coastguard Worker assert(op.constantValue64() == v &&
573*61046927SAndroid Build Coastguard Worker "attempt to create a unrepresentable 64-bit literal constant");
574*61046927SAndroid Build Coastguard Worker }
575*61046927SAndroid Build Coastguard Worker return op;
576*61046927SAndroid Build Coastguard Worker }
577*61046927SAndroid Build Coastguard Worker
578*61046927SAndroid Build Coastguard Worker /* 32-bit constant stored as a 32-bit or 64-bit operand */
c32_or_c64(uint32_t v,bool is64bit)579*61046927SAndroid Build Coastguard Worker static Operand c32_or_c64(uint32_t v, bool is64bit) noexcept
580*61046927SAndroid Build Coastguard Worker {
581*61046927SAndroid Build Coastguard Worker Operand op;
582*61046927SAndroid Build Coastguard Worker op.control_ = 0;
583*61046927SAndroid Build Coastguard Worker op.data_.i = v;
584*61046927SAndroid Build Coastguard Worker op.isConstant_ = true;
585*61046927SAndroid Build Coastguard Worker op.constSize = is64bit ? 3 : 2;
586*61046927SAndroid Build Coastguard Worker if (v <= 64)
587*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{128 + v});
588*61046927SAndroid Build Coastguard Worker else if (v >= 0xFFFFFFF0) /* [-16 .. -1] */
589*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{192 - v});
590*61046927SAndroid Build Coastguard Worker else if (v == 0x3f000000) /* 0.5 */
591*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{240});
592*61046927SAndroid Build Coastguard Worker else if (v == 0xbf000000) /* -0.5 */
593*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{241});
594*61046927SAndroid Build Coastguard Worker else if (v == 0x3f800000) /* 1.0 */
595*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{242});
596*61046927SAndroid Build Coastguard Worker else if (v == 0xbf800000) /* -1.0 */
597*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{243});
598*61046927SAndroid Build Coastguard Worker else if (v == 0x40000000) /* 2.0 */
599*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{244});
600*61046927SAndroid Build Coastguard Worker else if (v == 0xc0000000) /* -2.0 */
601*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{245});
602*61046927SAndroid Build Coastguard Worker else if (v == 0x40800000) /* 4.0 */
603*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{246});
604*61046927SAndroid Build Coastguard Worker else if (v == 0xc0800000) /* -4.0 */
605*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{247});
606*61046927SAndroid Build Coastguard Worker else { /* Literal Constant */
607*61046927SAndroid Build Coastguard Worker assert(!is64bit && "attempt to create a 64-bit literal constant");
608*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{255});
609*61046927SAndroid Build Coastguard Worker }
610*61046927SAndroid Build Coastguard Worker return op;
611*61046927SAndroid Build Coastguard Worker }
612*61046927SAndroid Build Coastguard Worker
literal32(uint32_t v)613*61046927SAndroid Build Coastguard Worker static Operand literal32(uint32_t v) noexcept
614*61046927SAndroid Build Coastguard Worker {
615*61046927SAndroid Build Coastguard Worker Operand op;
616*61046927SAndroid Build Coastguard Worker op.control_ = 0;
617*61046927SAndroid Build Coastguard Worker op.data_.i = v;
618*61046927SAndroid Build Coastguard Worker op.isConstant_ = true;
619*61046927SAndroid Build Coastguard Worker op.constSize = 2;
620*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{255});
621*61046927SAndroid Build Coastguard Worker return op;
622*61046927SAndroid Build Coastguard Worker }
623*61046927SAndroid Build Coastguard Worker
Operand(RegClass type)624*61046927SAndroid Build Coastguard Worker explicit Operand(RegClass type) noexcept
625*61046927SAndroid Build Coastguard Worker {
626*61046927SAndroid Build Coastguard Worker isUndef_ = true;
627*61046927SAndroid Build Coastguard Worker data_.temp = Temp(0, type);
628*61046927SAndroid Build Coastguard Worker setFixed(PhysReg{128});
629*61046927SAndroid Build Coastguard Worker };
Operand(PhysReg reg,RegClass type)630*61046927SAndroid Build Coastguard Worker explicit Operand(PhysReg reg, RegClass type) noexcept
631*61046927SAndroid Build Coastguard Worker {
632*61046927SAndroid Build Coastguard Worker data_.temp = Temp(0, type);
633*61046927SAndroid Build Coastguard Worker setFixed(reg);
634*61046927SAndroid Build Coastguard Worker }
635*61046927SAndroid Build Coastguard Worker
636*61046927SAndroid Build Coastguard Worker static Operand zero(unsigned bytes = 4) noexcept
637*61046927SAndroid Build Coastguard Worker {
638*61046927SAndroid Build Coastguard Worker if (bytes == 8)
639*61046927SAndroid Build Coastguard Worker return Operand::c64(0);
640*61046927SAndroid Build Coastguard Worker else if (bytes == 4)
641*61046927SAndroid Build Coastguard Worker return Operand::c32(0);
642*61046927SAndroid Build Coastguard Worker else if (bytes == 2)
643*61046927SAndroid Build Coastguard Worker return Operand::c16(0);
644*61046927SAndroid Build Coastguard Worker assert(bytes == 1);
645*61046927SAndroid Build Coastguard Worker return Operand::c8(0);
646*61046927SAndroid Build Coastguard Worker }
647*61046927SAndroid Build Coastguard Worker
648*61046927SAndroid Build Coastguard Worker /* This is useful over the constructors when you want to take a gfx level
649*61046927SAndroid Build Coastguard Worker * for 1/2 PI or an unknown operand size.
650*61046927SAndroid Build Coastguard Worker */
get_const(enum amd_gfx_level chip,uint64_t val,unsigned bytes)651*61046927SAndroid Build Coastguard Worker static Operand get_const(enum amd_gfx_level chip, uint64_t val, unsigned bytes)
652*61046927SAndroid Build Coastguard Worker {
653*61046927SAndroid Build Coastguard Worker if (val == 0x3e22f983 && bytes == 4 && chip >= GFX8) {
654*61046927SAndroid Build Coastguard Worker /* 1/2 PI can be an inline constant on GFX8+ */
655*61046927SAndroid Build Coastguard Worker Operand op = Operand::c32(val);
656*61046927SAndroid Build Coastguard Worker op.setFixed(PhysReg{248});
657*61046927SAndroid Build Coastguard Worker return op;
658*61046927SAndroid Build Coastguard Worker }
659*61046927SAndroid Build Coastguard Worker
660*61046927SAndroid Build Coastguard Worker if (bytes == 8)
661*61046927SAndroid Build Coastguard Worker return Operand::c64(val);
662*61046927SAndroid Build Coastguard Worker else if (bytes == 4)
663*61046927SAndroid Build Coastguard Worker return Operand::c32(val);
664*61046927SAndroid Build Coastguard Worker else if (bytes == 2)
665*61046927SAndroid Build Coastguard Worker return Operand::c16(val);
666*61046927SAndroid Build Coastguard Worker assert(bytes == 1);
667*61046927SAndroid Build Coastguard Worker return Operand::c8(val);
668*61046927SAndroid Build Coastguard Worker }
669*61046927SAndroid Build Coastguard Worker
670*61046927SAndroid Build Coastguard Worker static bool is_constant_representable(uint64_t val, unsigned bytes, bool zext = false,
671*61046927SAndroid Build Coastguard Worker bool sext = false)
672*61046927SAndroid Build Coastguard Worker {
673*61046927SAndroid Build Coastguard Worker if (bytes <= 4)
674*61046927SAndroid Build Coastguard Worker return true;
675*61046927SAndroid Build Coastguard Worker
676*61046927SAndroid Build Coastguard Worker if (zext && (val & 0xFFFFFFFF00000000) == 0x0000000000000000)
677*61046927SAndroid Build Coastguard Worker return true;
678*61046927SAndroid Build Coastguard Worker uint64_t upper33 = val & 0xFFFFFFFF80000000;
679*61046927SAndroid Build Coastguard Worker if (sext && (upper33 == 0xFFFFFFFF80000000 || upper33 == 0))
680*61046927SAndroid Build Coastguard Worker return true;
681*61046927SAndroid Build Coastguard Worker
682*61046927SAndroid Build Coastguard Worker return val >= 0xFFFFFFFFFFFFFFF0 || val <= 64 || /* [-16 .. 64] */
683*61046927SAndroid Build Coastguard Worker val == 0x3FE0000000000000 || /* 0.5 */
684*61046927SAndroid Build Coastguard Worker val == 0xBFE0000000000000 || /* -0.5 */
685*61046927SAndroid Build Coastguard Worker val == 0x3FF0000000000000 || /* 1.0 */
686*61046927SAndroid Build Coastguard Worker val == 0xBFF0000000000000 || /* -1.0 */
687*61046927SAndroid Build Coastguard Worker val == 0x4000000000000000 || /* 2.0 */
688*61046927SAndroid Build Coastguard Worker val == 0xC000000000000000 || /* -2.0 */
689*61046927SAndroid Build Coastguard Worker val == 0x4010000000000000 || /* 4.0 */
690*61046927SAndroid Build Coastguard Worker val == 0xC010000000000000; /* -4.0 */
691*61046927SAndroid Build Coastguard Worker }
692*61046927SAndroid Build Coastguard Worker
isTemp()693*61046927SAndroid Build Coastguard Worker constexpr bool isTemp() const noexcept { return isTemp_; }
694*61046927SAndroid Build Coastguard Worker
setTemp(Temp t)695*61046927SAndroid Build Coastguard Worker constexpr void setTemp(Temp t) noexcept
696*61046927SAndroid Build Coastguard Worker {
697*61046927SAndroid Build Coastguard Worker assert(!isConstant_);
698*61046927SAndroid Build Coastguard Worker if (t.id() != 0)
699*61046927SAndroid Build Coastguard Worker isTemp_ = true;
700*61046927SAndroid Build Coastguard Worker data_.temp = t;
701*61046927SAndroid Build Coastguard Worker }
702*61046927SAndroid Build Coastguard Worker
getTemp()703*61046927SAndroid Build Coastguard Worker constexpr Temp getTemp() const noexcept { return data_.temp; }
704*61046927SAndroid Build Coastguard Worker
tempId()705*61046927SAndroid Build Coastguard Worker constexpr uint32_t tempId() const noexcept { return data_.temp.id(); }
706*61046927SAndroid Build Coastguard Worker
hasRegClass()707*61046927SAndroid Build Coastguard Worker constexpr bool hasRegClass() const noexcept { return !isConstant(); }
708*61046927SAndroid Build Coastguard Worker
regClass()709*61046927SAndroid Build Coastguard Worker constexpr RegClass regClass() const noexcept { return data_.temp.regClass(); }
710*61046927SAndroid Build Coastguard Worker
bytes()711*61046927SAndroid Build Coastguard Worker constexpr unsigned bytes() const noexcept
712*61046927SAndroid Build Coastguard Worker {
713*61046927SAndroid Build Coastguard Worker if (isConstant())
714*61046927SAndroid Build Coastguard Worker return 1 << constSize;
715*61046927SAndroid Build Coastguard Worker else
716*61046927SAndroid Build Coastguard Worker return data_.temp.bytes();
717*61046927SAndroid Build Coastguard Worker }
718*61046927SAndroid Build Coastguard Worker
size()719*61046927SAndroid Build Coastguard Worker constexpr unsigned size() const noexcept
720*61046927SAndroid Build Coastguard Worker {
721*61046927SAndroid Build Coastguard Worker if (isConstant())
722*61046927SAndroid Build Coastguard Worker return constSize > 2 ? 2 : 1;
723*61046927SAndroid Build Coastguard Worker else
724*61046927SAndroid Build Coastguard Worker return data_.temp.size();
725*61046927SAndroid Build Coastguard Worker }
726*61046927SAndroid Build Coastguard Worker
isFixed()727*61046927SAndroid Build Coastguard Worker constexpr bool isFixed() const noexcept { return isFixed_; }
728*61046927SAndroid Build Coastguard Worker
physReg()729*61046927SAndroid Build Coastguard Worker constexpr PhysReg physReg() const noexcept { return reg_; }
730*61046927SAndroid Build Coastguard Worker
setFixed(PhysReg reg)731*61046927SAndroid Build Coastguard Worker constexpr void setFixed(PhysReg reg) noexcept
732*61046927SAndroid Build Coastguard Worker {
733*61046927SAndroid Build Coastguard Worker isFixed_ = reg != unsigned(-1);
734*61046927SAndroid Build Coastguard Worker reg_ = reg;
735*61046927SAndroid Build Coastguard Worker }
736*61046927SAndroid Build Coastguard Worker
isConstant()737*61046927SAndroid Build Coastguard Worker constexpr bool isConstant() const noexcept { return isConstant_; }
738*61046927SAndroid Build Coastguard Worker
isLiteral()739*61046927SAndroid Build Coastguard Worker constexpr bool isLiteral() const noexcept { return isConstant() && reg_ == 255; }
740*61046927SAndroid Build Coastguard Worker
isUndefined()741*61046927SAndroid Build Coastguard Worker constexpr bool isUndefined() const noexcept { return isUndef_; }
742*61046927SAndroid Build Coastguard Worker
constantValue()743*61046927SAndroid Build Coastguard Worker constexpr uint32_t constantValue() const noexcept { return data_.i; }
744*61046927SAndroid Build Coastguard Worker
constantEquals(uint32_t cmp)745*61046927SAndroid Build Coastguard Worker constexpr bool constantEquals(uint32_t cmp) const noexcept
746*61046927SAndroid Build Coastguard Worker {
747*61046927SAndroid Build Coastguard Worker return isConstant() && constantValue() == cmp;
748*61046927SAndroid Build Coastguard Worker }
749*61046927SAndroid Build Coastguard Worker
constantValue64()750*61046927SAndroid Build Coastguard Worker constexpr uint64_t constantValue64() const noexcept
751*61046927SAndroid Build Coastguard Worker {
752*61046927SAndroid Build Coastguard Worker if (constSize == 3) {
753*61046927SAndroid Build Coastguard Worker if (reg_ <= 192)
754*61046927SAndroid Build Coastguard Worker return reg_ - 128;
755*61046927SAndroid Build Coastguard Worker else if (reg_ <= 208)
756*61046927SAndroid Build Coastguard Worker return 0xFFFFFFFFFFFFFFFF - (reg_ - 193);
757*61046927SAndroid Build Coastguard Worker
758*61046927SAndroid Build Coastguard Worker switch (reg_) {
759*61046927SAndroid Build Coastguard Worker case 240: return 0x3FE0000000000000;
760*61046927SAndroid Build Coastguard Worker case 241: return 0xBFE0000000000000;
761*61046927SAndroid Build Coastguard Worker case 242: return 0x3FF0000000000000;
762*61046927SAndroid Build Coastguard Worker case 243: return 0xBFF0000000000000;
763*61046927SAndroid Build Coastguard Worker case 244: return 0x4000000000000000;
764*61046927SAndroid Build Coastguard Worker case 245: return 0xC000000000000000;
765*61046927SAndroid Build Coastguard Worker case 246: return 0x4010000000000000;
766*61046927SAndroid Build Coastguard Worker case 247: return 0xC010000000000000;
767*61046927SAndroid Build Coastguard Worker case 255:
768*61046927SAndroid Build Coastguard Worker return (signext && (data_.i & 0x80000000u) ? 0xffffffff00000000ull : 0ull) | data_.i;
769*61046927SAndroid Build Coastguard Worker }
770*61046927SAndroid Build Coastguard Worker unreachable("invalid register for 64-bit constant");
771*61046927SAndroid Build Coastguard Worker } else {
772*61046927SAndroid Build Coastguard Worker return data_.i;
773*61046927SAndroid Build Coastguard Worker }
774*61046927SAndroid Build Coastguard Worker }
775*61046927SAndroid Build Coastguard Worker
776*61046927SAndroid Build Coastguard Worker /* Value if this were used with vop3/opsel or vop3p. */
constantValue16(bool opsel)777*61046927SAndroid Build Coastguard Worker constexpr uint16_t constantValue16(bool opsel) const noexcept
778*61046927SAndroid Build Coastguard Worker {
779*61046927SAndroid Build Coastguard Worker assert(bytes() == 2 || bytes() == 4);
780*61046927SAndroid Build Coastguard Worker if (opsel) {
781*61046927SAndroid Build Coastguard Worker if (bytes() == 2 && int16_t(data_.i) >= -16 && int16_t(data_.i) <= 64 && !isLiteral())
782*61046927SAndroid Build Coastguard Worker return int16_t(data_.i) >>
783*61046927SAndroid Build Coastguard Worker 16; /* 16-bit inline integers are sign-extended, even with fp16 instrs */
784*61046927SAndroid Build Coastguard Worker else
785*61046927SAndroid Build Coastguard Worker return data_.i >> 16;
786*61046927SAndroid Build Coastguard Worker }
787*61046927SAndroid Build Coastguard Worker return data_.i;
788*61046927SAndroid Build Coastguard Worker }
789*61046927SAndroid Build Coastguard Worker
isOfType(RegType type)790*61046927SAndroid Build Coastguard Worker constexpr bool isOfType(RegType type) const noexcept
791*61046927SAndroid Build Coastguard Worker {
792*61046927SAndroid Build Coastguard Worker return hasRegClass() && regClass().type() == type;
793*61046927SAndroid Build Coastguard Worker }
794*61046927SAndroid Build Coastguard Worker
795*61046927SAndroid Build Coastguard Worker /* Indicates that the killed operand's live range intersects with the
796*61046927SAndroid Build Coastguard Worker * instruction's definitions. Unlike isKill() and isFirstKill(), this is
797*61046927SAndroid Build Coastguard Worker * not set by liveness analysis. */
setLateKill(bool flag)798*61046927SAndroid Build Coastguard Worker constexpr void setLateKill(bool flag) noexcept { isLateKill_ = flag; }
799*61046927SAndroid Build Coastguard Worker
isLateKill()800*61046927SAndroid Build Coastguard Worker constexpr bool isLateKill() const noexcept { return isLateKill_; }
801*61046927SAndroid Build Coastguard Worker
802*61046927SAndroid Build Coastguard Worker /* Indicates that the Operand's register gets clobbered by the instruction. */
setClobbered(bool flag)803*61046927SAndroid Build Coastguard Worker constexpr void setClobbered(bool flag) noexcept { isClobbered_ = flag; }
isClobbered()804*61046927SAndroid Build Coastguard Worker constexpr bool isClobbered() const noexcept { return isClobbered_; }
805*61046927SAndroid Build Coastguard Worker
806*61046927SAndroid Build Coastguard Worker /* Indicates that the Operand must be copied in order to satisfy register
807*61046927SAndroid Build Coastguard Worker * constraints. The copy is immediately killed by the instruction.
808*61046927SAndroid Build Coastguard Worker */
setCopyKill(bool flag)809*61046927SAndroid Build Coastguard Worker constexpr void setCopyKill(bool flag) noexcept
810*61046927SAndroid Build Coastguard Worker {
811*61046927SAndroid Build Coastguard Worker isCopyKill_ = flag;
812*61046927SAndroid Build Coastguard Worker if (flag)
813*61046927SAndroid Build Coastguard Worker setKill(flag);
814*61046927SAndroid Build Coastguard Worker }
isCopyKill()815*61046927SAndroid Build Coastguard Worker constexpr bool isCopyKill() const noexcept { return isCopyKill_; }
816*61046927SAndroid Build Coastguard Worker
setKill(bool flag)817*61046927SAndroid Build Coastguard Worker constexpr void setKill(bool flag) noexcept
818*61046927SAndroid Build Coastguard Worker {
819*61046927SAndroid Build Coastguard Worker isKill_ = flag;
820*61046927SAndroid Build Coastguard Worker if (!flag) {
821*61046927SAndroid Build Coastguard Worker setFirstKill(false);
822*61046927SAndroid Build Coastguard Worker setCopyKill(false);
823*61046927SAndroid Build Coastguard Worker }
824*61046927SAndroid Build Coastguard Worker }
825*61046927SAndroid Build Coastguard Worker
isKill()826*61046927SAndroid Build Coastguard Worker constexpr bool isKill() const noexcept { return isKill_ || isFirstKill(); }
827*61046927SAndroid Build Coastguard Worker
setFirstKill(bool flag)828*61046927SAndroid Build Coastguard Worker constexpr void setFirstKill(bool flag) noexcept
829*61046927SAndroid Build Coastguard Worker {
830*61046927SAndroid Build Coastguard Worker isFirstKill_ = flag;
831*61046927SAndroid Build Coastguard Worker if (flag)
832*61046927SAndroid Build Coastguard Worker setKill(flag);
833*61046927SAndroid Build Coastguard Worker }
834*61046927SAndroid Build Coastguard Worker
835*61046927SAndroid Build Coastguard Worker /* When there are multiple operands killing the same temporary,
836*61046927SAndroid Build Coastguard Worker * isFirstKill() is only returns true for the first one. */
isFirstKill()837*61046927SAndroid Build Coastguard Worker constexpr bool isFirstKill() const noexcept { return isFirstKill_; }
838*61046927SAndroid Build Coastguard Worker
isKillBeforeDef()839*61046927SAndroid Build Coastguard Worker constexpr bool isKillBeforeDef() const noexcept { return isKill() && !isLateKill(); }
840*61046927SAndroid Build Coastguard Worker
isFirstKillBeforeDef()841*61046927SAndroid Build Coastguard Worker constexpr bool isFirstKillBeforeDef() const noexcept { return isFirstKill() && !isLateKill(); }
842*61046927SAndroid Build Coastguard Worker
843*61046927SAndroid Build Coastguard Worker constexpr bool operator==(Operand other) const noexcept
844*61046927SAndroid Build Coastguard Worker {
845*61046927SAndroid Build Coastguard Worker if (other.size() != size())
846*61046927SAndroid Build Coastguard Worker return false;
847*61046927SAndroid Build Coastguard Worker if (isFixed() != other.isFixed() || isKillBeforeDef() != other.isKillBeforeDef())
848*61046927SAndroid Build Coastguard Worker return false;
849*61046927SAndroid Build Coastguard Worker if (isFixed() && other.isFixed() && physReg() != other.physReg())
850*61046927SAndroid Build Coastguard Worker return false;
851*61046927SAndroid Build Coastguard Worker if (isLiteral())
852*61046927SAndroid Build Coastguard Worker return other.isLiteral() && other.constantValue() == constantValue();
853*61046927SAndroid Build Coastguard Worker else if (isConstant())
854*61046927SAndroid Build Coastguard Worker return other.isConstant() && other.physReg() == physReg();
855*61046927SAndroid Build Coastguard Worker else if (isUndefined())
856*61046927SAndroid Build Coastguard Worker return other.isUndefined() && other.regClass() == regClass();
857*61046927SAndroid Build Coastguard Worker else
858*61046927SAndroid Build Coastguard Worker return other.isTemp() && other.getTemp() == getTemp();
859*61046927SAndroid Build Coastguard Worker }
860*61046927SAndroid Build Coastguard Worker
861*61046927SAndroid Build Coastguard Worker constexpr bool operator!=(Operand other) const noexcept { return !operator==(other); }
862*61046927SAndroid Build Coastguard Worker
set16bit(bool flag)863*61046927SAndroid Build Coastguard Worker constexpr void set16bit(bool flag) noexcept { is16bit_ = flag; }
864*61046927SAndroid Build Coastguard Worker
is16bit()865*61046927SAndroid Build Coastguard Worker constexpr bool is16bit() const noexcept { return is16bit_; }
866*61046927SAndroid Build Coastguard Worker
set24bit(bool flag)867*61046927SAndroid Build Coastguard Worker constexpr void set24bit(bool flag) noexcept { is24bit_ = flag; }
868*61046927SAndroid Build Coastguard Worker
is24bit()869*61046927SAndroid Build Coastguard Worker constexpr bool is24bit() const noexcept { return is24bit_; }
870*61046927SAndroid Build Coastguard Worker
871*61046927SAndroid Build Coastguard Worker private:
872*61046927SAndroid Build Coastguard Worker union {
873*61046927SAndroid Build Coastguard Worker Temp temp;
874*61046927SAndroid Build Coastguard Worker uint32_t i;
875*61046927SAndroid Build Coastguard Worker float f;
876*61046927SAndroid Build Coastguard Worker } data_ = {Temp(0, s1)};
877*61046927SAndroid Build Coastguard Worker PhysReg reg_;
878*61046927SAndroid Build Coastguard Worker union {
879*61046927SAndroid Build Coastguard Worker struct {
880*61046927SAndroid Build Coastguard Worker uint8_t isTemp_ : 1;
881*61046927SAndroid Build Coastguard Worker uint8_t isFixed_ : 1;
882*61046927SAndroid Build Coastguard Worker uint8_t isConstant_ : 1;
883*61046927SAndroid Build Coastguard Worker uint8_t isKill_ : 1;
884*61046927SAndroid Build Coastguard Worker uint8_t isUndef_ : 1;
885*61046927SAndroid Build Coastguard Worker uint8_t isFirstKill_ : 1;
886*61046927SAndroid Build Coastguard Worker uint8_t constSize : 2;
887*61046927SAndroid Build Coastguard Worker uint8_t isLateKill_ : 1;
888*61046927SAndroid Build Coastguard Worker uint8_t isClobbered_ : 1;
889*61046927SAndroid Build Coastguard Worker uint8_t isCopyKill_ : 1;
890*61046927SAndroid Build Coastguard Worker uint8_t is16bit_ : 1;
891*61046927SAndroid Build Coastguard Worker uint8_t is24bit_ : 1;
892*61046927SAndroid Build Coastguard Worker uint8_t signext : 1;
893*61046927SAndroid Build Coastguard Worker };
894*61046927SAndroid Build Coastguard Worker /* can't initialize bit-fields in c++11, so work around using a union */
895*61046927SAndroid Build Coastguard Worker uint16_t control_ = 0;
896*61046927SAndroid Build Coastguard Worker };
897*61046927SAndroid Build Coastguard Worker };
898*61046927SAndroid Build Coastguard Worker
899*61046927SAndroid Build Coastguard Worker /**
900*61046927SAndroid Build Coastguard Worker * Definition Class
901*61046927SAndroid Build Coastguard Worker * Definitions are the results of Instructions
902*61046927SAndroid Build Coastguard Worker * and refer to temporary virtual registers
903*61046927SAndroid Build Coastguard Worker * which are later mapped to physical registers
904*61046927SAndroid Build Coastguard Worker */
905*61046927SAndroid Build Coastguard Worker class Definition final {
906*61046927SAndroid Build Coastguard Worker public:
Definition()907*61046927SAndroid Build Coastguard Worker constexpr Definition()
908*61046927SAndroid Build Coastguard Worker : temp(Temp(0, s1)), reg_(0), isFixed_(0), isKill_(0), isPrecise_(0), isInfPreserve_(0),
909*61046927SAndroid Build Coastguard Worker isNaNPreserve_(0), isSZPreserve_(0), isNUW_(0), isNoCSE_(0)
910*61046927SAndroid Build Coastguard Worker {}
Definition(uint32_t index,RegClass type)911*61046927SAndroid Build Coastguard Worker Definition(uint32_t index, RegClass type) noexcept : temp(index, type) {}
Definition(Temp tmp)912*61046927SAndroid Build Coastguard Worker explicit Definition(Temp tmp) noexcept : temp(tmp) {}
Definition(PhysReg reg,RegClass type)913*61046927SAndroid Build Coastguard Worker Definition(PhysReg reg, RegClass type) noexcept : temp(Temp(0, type)) { setFixed(reg); }
Definition(uint32_t tmpId,PhysReg reg,RegClass type)914*61046927SAndroid Build Coastguard Worker Definition(uint32_t tmpId, PhysReg reg, RegClass type) noexcept : temp(Temp(tmpId, type))
915*61046927SAndroid Build Coastguard Worker {
916*61046927SAndroid Build Coastguard Worker setFixed(reg);
917*61046927SAndroid Build Coastguard Worker }
918*61046927SAndroid Build Coastguard Worker
isTemp()919*61046927SAndroid Build Coastguard Worker constexpr bool isTemp() const noexcept { return tempId() > 0; }
920*61046927SAndroid Build Coastguard Worker
getTemp()921*61046927SAndroid Build Coastguard Worker constexpr Temp getTemp() const noexcept { return temp; }
922*61046927SAndroid Build Coastguard Worker
tempId()923*61046927SAndroid Build Coastguard Worker constexpr uint32_t tempId() const noexcept { return temp.id(); }
924*61046927SAndroid Build Coastguard Worker
setTemp(Temp t)925*61046927SAndroid Build Coastguard Worker constexpr void setTemp(Temp t) noexcept { temp = t; }
926*61046927SAndroid Build Coastguard Worker
swapTemp(Definition & other)927*61046927SAndroid Build Coastguard Worker void swapTemp(Definition& other) noexcept { std::swap(temp, other.temp); }
928*61046927SAndroid Build Coastguard Worker
regClass()929*61046927SAndroid Build Coastguard Worker constexpr RegClass regClass() const noexcept { return temp.regClass(); }
930*61046927SAndroid Build Coastguard Worker
bytes()931*61046927SAndroid Build Coastguard Worker constexpr unsigned bytes() const noexcept { return temp.bytes(); }
932*61046927SAndroid Build Coastguard Worker
size()933*61046927SAndroid Build Coastguard Worker constexpr unsigned size() const noexcept { return temp.size(); }
934*61046927SAndroid Build Coastguard Worker
isFixed()935*61046927SAndroid Build Coastguard Worker constexpr bool isFixed() const noexcept { return isFixed_; }
936*61046927SAndroid Build Coastguard Worker
physReg()937*61046927SAndroid Build Coastguard Worker constexpr PhysReg physReg() const noexcept { return reg_; }
938*61046927SAndroid Build Coastguard Worker
setFixed(PhysReg reg)939*61046927SAndroid Build Coastguard Worker constexpr void setFixed(PhysReg reg) noexcept
940*61046927SAndroid Build Coastguard Worker {
941*61046927SAndroid Build Coastguard Worker isFixed_ = 1;
942*61046927SAndroid Build Coastguard Worker reg_ = reg;
943*61046927SAndroid Build Coastguard Worker }
944*61046927SAndroid Build Coastguard Worker
setKill(bool flag)945*61046927SAndroid Build Coastguard Worker constexpr void setKill(bool flag) noexcept { isKill_ = flag; }
946*61046927SAndroid Build Coastguard Worker
isKill()947*61046927SAndroid Build Coastguard Worker constexpr bool isKill() const noexcept { return isKill_; }
948*61046927SAndroid Build Coastguard Worker
setPrecise(bool precise)949*61046927SAndroid Build Coastguard Worker constexpr void setPrecise(bool precise) noexcept { isPrecise_ = precise; }
950*61046927SAndroid Build Coastguard Worker
isPrecise()951*61046927SAndroid Build Coastguard Worker constexpr bool isPrecise() const noexcept { return isPrecise_; }
952*61046927SAndroid Build Coastguard Worker
setInfPreserve(bool inf_preserve)953*61046927SAndroid Build Coastguard Worker constexpr void setInfPreserve(bool inf_preserve) noexcept { isInfPreserve_ = inf_preserve; }
954*61046927SAndroid Build Coastguard Worker
isInfPreserve()955*61046927SAndroid Build Coastguard Worker constexpr bool isInfPreserve() const noexcept { return isInfPreserve_; }
956*61046927SAndroid Build Coastguard Worker
setNaNPreserve(bool nan_preserve)957*61046927SAndroid Build Coastguard Worker constexpr void setNaNPreserve(bool nan_preserve) noexcept { isNaNPreserve_ = nan_preserve; }
958*61046927SAndroid Build Coastguard Worker
isNaNPreserve()959*61046927SAndroid Build Coastguard Worker constexpr bool isNaNPreserve() const noexcept { return isNaNPreserve_; }
960*61046927SAndroid Build Coastguard Worker
setSZPreserve(bool sz_preserve)961*61046927SAndroid Build Coastguard Worker constexpr void setSZPreserve(bool sz_preserve) noexcept { isSZPreserve_ = sz_preserve; }
962*61046927SAndroid Build Coastguard Worker
isSZPreserve()963*61046927SAndroid Build Coastguard Worker constexpr bool isSZPreserve() const noexcept { return isSZPreserve_; }
964*61046927SAndroid Build Coastguard Worker
965*61046927SAndroid Build Coastguard Worker /* No Unsigned Wrap */
setNUW(bool nuw)966*61046927SAndroid Build Coastguard Worker constexpr void setNUW(bool nuw) noexcept { isNUW_ = nuw; }
967*61046927SAndroid Build Coastguard Worker
isNUW()968*61046927SAndroid Build Coastguard Worker constexpr bool isNUW() const noexcept { return isNUW_; }
969*61046927SAndroid Build Coastguard Worker
setNoCSE(bool noCSE)970*61046927SAndroid Build Coastguard Worker constexpr void setNoCSE(bool noCSE) noexcept { isNoCSE_ = noCSE; }
971*61046927SAndroid Build Coastguard Worker
isNoCSE()972*61046927SAndroid Build Coastguard Worker constexpr bool isNoCSE() const noexcept { return isNoCSE_; }
973*61046927SAndroid Build Coastguard Worker
974*61046927SAndroid Build Coastguard Worker private:
975*61046927SAndroid Build Coastguard Worker Temp temp = Temp(0, s1);
976*61046927SAndroid Build Coastguard Worker PhysReg reg_;
977*61046927SAndroid Build Coastguard Worker union {
978*61046927SAndroid Build Coastguard Worker struct {
979*61046927SAndroid Build Coastguard Worker uint8_t isFixed_ : 1;
980*61046927SAndroid Build Coastguard Worker uint8_t isKill_ : 1;
981*61046927SAndroid Build Coastguard Worker uint8_t isPrecise_ : 1;
982*61046927SAndroid Build Coastguard Worker uint8_t isInfPreserve_ : 1;
983*61046927SAndroid Build Coastguard Worker uint8_t isNaNPreserve_ : 1;
984*61046927SAndroid Build Coastguard Worker uint8_t isSZPreserve_ : 1;
985*61046927SAndroid Build Coastguard Worker uint8_t isNUW_ : 1;
986*61046927SAndroid Build Coastguard Worker uint8_t isNoCSE_ : 1;
987*61046927SAndroid Build Coastguard Worker };
988*61046927SAndroid Build Coastguard Worker /* can't initialize bit-fields in c++11, so work around using a union */
989*61046927SAndroid Build Coastguard Worker uint8_t control_ = 0;
990*61046927SAndroid Build Coastguard Worker };
991*61046927SAndroid Build Coastguard Worker };
992*61046927SAndroid Build Coastguard Worker
993*61046927SAndroid Build Coastguard Worker struct RegisterDemand {
994*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand() = default;
RegisterDemandRegisterDemand995*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand(const int16_t v, const int16_t s) noexcept : vgpr{v}, sgpr{s} {}
996*61046927SAndroid Build Coastguard Worker int16_t vgpr = 0;
997*61046927SAndroid Build Coastguard Worker int16_t sgpr = 0;
998*61046927SAndroid Build Coastguard Worker
999*61046927SAndroid Build Coastguard Worker constexpr friend bool operator==(const RegisterDemand a, const RegisterDemand b) noexcept
1000*61046927SAndroid Build Coastguard Worker {
1001*61046927SAndroid Build Coastguard Worker return a.vgpr == b.vgpr && a.sgpr == b.sgpr;
1002*61046927SAndroid Build Coastguard Worker }
1003*61046927SAndroid Build Coastguard Worker
exceedsRegisterDemand1004*61046927SAndroid Build Coastguard Worker constexpr bool exceeds(const RegisterDemand other) const noexcept
1005*61046927SAndroid Build Coastguard Worker {
1006*61046927SAndroid Build Coastguard Worker return vgpr > other.vgpr || sgpr > other.sgpr;
1007*61046927SAndroid Build Coastguard Worker }
1008*61046927SAndroid Build Coastguard Worker
1009*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand operator+(const Temp t) const noexcept
1010*61046927SAndroid Build Coastguard Worker {
1011*61046927SAndroid Build Coastguard Worker if (t.type() == RegType::sgpr)
1012*61046927SAndroid Build Coastguard Worker return RegisterDemand(vgpr, sgpr + t.size());
1013*61046927SAndroid Build Coastguard Worker else
1014*61046927SAndroid Build Coastguard Worker return RegisterDemand(vgpr + t.size(), sgpr);
1015*61046927SAndroid Build Coastguard Worker }
1016*61046927SAndroid Build Coastguard Worker
1017*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand operator+(const RegisterDemand other) const noexcept
1018*61046927SAndroid Build Coastguard Worker {
1019*61046927SAndroid Build Coastguard Worker return RegisterDemand(vgpr + other.vgpr, sgpr + other.sgpr);
1020*61046927SAndroid Build Coastguard Worker }
1021*61046927SAndroid Build Coastguard Worker
1022*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand operator-(const RegisterDemand other) const noexcept
1023*61046927SAndroid Build Coastguard Worker {
1024*61046927SAndroid Build Coastguard Worker return RegisterDemand(vgpr - other.vgpr, sgpr - other.sgpr);
1025*61046927SAndroid Build Coastguard Worker }
1026*61046927SAndroid Build Coastguard Worker
1027*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand& operator+=(const RegisterDemand other) noexcept
1028*61046927SAndroid Build Coastguard Worker {
1029*61046927SAndroid Build Coastguard Worker vgpr += other.vgpr;
1030*61046927SAndroid Build Coastguard Worker sgpr += other.sgpr;
1031*61046927SAndroid Build Coastguard Worker return *this;
1032*61046927SAndroid Build Coastguard Worker }
1033*61046927SAndroid Build Coastguard Worker
1034*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand& operator-=(const RegisterDemand other) noexcept
1035*61046927SAndroid Build Coastguard Worker {
1036*61046927SAndroid Build Coastguard Worker vgpr -= other.vgpr;
1037*61046927SAndroid Build Coastguard Worker sgpr -= other.sgpr;
1038*61046927SAndroid Build Coastguard Worker return *this;
1039*61046927SAndroid Build Coastguard Worker }
1040*61046927SAndroid Build Coastguard Worker
1041*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand& operator+=(const Temp t) noexcept
1042*61046927SAndroid Build Coastguard Worker {
1043*61046927SAndroid Build Coastguard Worker if (t.type() == RegType::sgpr)
1044*61046927SAndroid Build Coastguard Worker sgpr += t.size();
1045*61046927SAndroid Build Coastguard Worker else
1046*61046927SAndroid Build Coastguard Worker vgpr += t.size();
1047*61046927SAndroid Build Coastguard Worker return *this;
1048*61046927SAndroid Build Coastguard Worker }
1049*61046927SAndroid Build Coastguard Worker
1050*61046927SAndroid Build Coastguard Worker constexpr RegisterDemand& operator-=(const Temp t) noexcept
1051*61046927SAndroid Build Coastguard Worker {
1052*61046927SAndroid Build Coastguard Worker if (t.type() == RegType::sgpr)
1053*61046927SAndroid Build Coastguard Worker sgpr -= t.size();
1054*61046927SAndroid Build Coastguard Worker else
1055*61046927SAndroid Build Coastguard Worker vgpr -= t.size();
1056*61046927SAndroid Build Coastguard Worker return *this;
1057*61046927SAndroid Build Coastguard Worker }
1058*61046927SAndroid Build Coastguard Worker
updateRegisterDemand1059*61046927SAndroid Build Coastguard Worker constexpr void update(const RegisterDemand other) noexcept
1060*61046927SAndroid Build Coastguard Worker {
1061*61046927SAndroid Build Coastguard Worker vgpr = std::max(vgpr, other.vgpr);
1062*61046927SAndroid Build Coastguard Worker sgpr = std::max(sgpr, other.sgpr);
1063*61046927SAndroid Build Coastguard Worker }
1064*61046927SAndroid Build Coastguard Worker };
1065*61046927SAndroid Build Coastguard Worker
1066*61046927SAndroid Build Coastguard Worker struct Block;
1067*61046927SAndroid Build Coastguard Worker struct Instruction;
1068*61046927SAndroid Build Coastguard Worker struct Pseudo_instruction;
1069*61046927SAndroid Build Coastguard Worker struct SALU_instruction;
1070*61046927SAndroid Build Coastguard Worker struct SMEM_instruction;
1071*61046927SAndroid Build Coastguard Worker struct DS_instruction;
1072*61046927SAndroid Build Coastguard Worker struct LDSDIR_instruction;
1073*61046927SAndroid Build Coastguard Worker struct MTBUF_instruction;
1074*61046927SAndroid Build Coastguard Worker struct MUBUF_instruction;
1075*61046927SAndroid Build Coastguard Worker struct MIMG_instruction;
1076*61046927SAndroid Build Coastguard Worker struct Export_instruction;
1077*61046927SAndroid Build Coastguard Worker struct FLAT_instruction;
1078*61046927SAndroid Build Coastguard Worker struct Pseudo_branch_instruction;
1079*61046927SAndroid Build Coastguard Worker struct Pseudo_barrier_instruction;
1080*61046927SAndroid Build Coastguard Worker struct Pseudo_reduction_instruction;
1081*61046927SAndroid Build Coastguard Worker struct VALU_instruction;
1082*61046927SAndroid Build Coastguard Worker struct VINTERP_inreg_instruction;
1083*61046927SAndroid Build Coastguard Worker struct VINTRP_instruction;
1084*61046927SAndroid Build Coastguard Worker struct VOPD_instruction;
1085*61046927SAndroid Build Coastguard Worker struct DPP16_instruction;
1086*61046927SAndroid Build Coastguard Worker struct DPP8_instruction;
1087*61046927SAndroid Build Coastguard Worker struct SDWA_instruction;
1088*61046927SAndroid Build Coastguard Worker
1089*61046927SAndroid Build Coastguard Worker struct Instruction {
1090*61046927SAndroid Build Coastguard Worker aco_opcode opcode;
1091*61046927SAndroid Build Coastguard Worker Format format;
1092*61046927SAndroid Build Coastguard Worker union {
1093*61046927SAndroid Build Coastguard Worker uint32_t pass_flags;
1094*61046927SAndroid Build Coastguard Worker RegisterDemand register_demand;
1095*61046927SAndroid Build Coastguard Worker };
1096*61046927SAndroid Build Coastguard Worker
1097*61046927SAndroid Build Coastguard Worker aco::span<Operand> operands;
1098*61046927SAndroid Build Coastguard Worker aco::span<Definition> definitions;
1099*61046927SAndroid Build Coastguard Worker
1100*61046927SAndroid Build Coastguard Worker constexpr bool usesModifiers() const noexcept;
1101*61046927SAndroid Build Coastguard Worker
reads_execInstruction1102*61046927SAndroid Build Coastguard Worker constexpr bool reads_exec() const noexcept
1103*61046927SAndroid Build Coastguard Worker {
1104*61046927SAndroid Build Coastguard Worker for (const Operand& op : operands) {
1105*61046927SAndroid Build Coastguard Worker if (op.isFixed() && (op.physReg() == exec_lo || op.physReg() == exec_hi))
1106*61046927SAndroid Build Coastguard Worker return true;
1107*61046927SAndroid Build Coastguard Worker }
1108*61046927SAndroid Build Coastguard Worker return false;
1109*61046927SAndroid Build Coastguard Worker }
1110*61046927SAndroid Build Coastguard Worker
writes_execInstruction1111*61046927SAndroid Build Coastguard Worker constexpr bool writes_exec() const noexcept
1112*61046927SAndroid Build Coastguard Worker {
1113*61046927SAndroid Build Coastguard Worker for (const Definition& def : definitions) {
1114*61046927SAndroid Build Coastguard Worker if (def.isFixed() && (def.physReg() == exec_lo || def.physReg() == exec_hi))
1115*61046927SAndroid Build Coastguard Worker return true;
1116*61046927SAndroid Build Coastguard Worker }
1117*61046927SAndroid Build Coastguard Worker return false;
1118*61046927SAndroid Build Coastguard Worker }
1119*61046927SAndroid Build Coastguard Worker
pseudoInstruction1120*61046927SAndroid Build Coastguard Worker Pseudo_instruction& pseudo() noexcept
1121*61046927SAndroid Build Coastguard Worker {
1122*61046927SAndroid Build Coastguard Worker assert(isPseudo());
1123*61046927SAndroid Build Coastguard Worker return *(Pseudo_instruction*)this;
1124*61046927SAndroid Build Coastguard Worker }
pseudoInstruction1125*61046927SAndroid Build Coastguard Worker const Pseudo_instruction& pseudo() const noexcept
1126*61046927SAndroid Build Coastguard Worker {
1127*61046927SAndroid Build Coastguard Worker assert(isPseudo());
1128*61046927SAndroid Build Coastguard Worker return *(Pseudo_instruction*)this;
1129*61046927SAndroid Build Coastguard Worker }
isPseudoInstruction1130*61046927SAndroid Build Coastguard Worker constexpr bool isPseudo() const noexcept { return format == Format::PSEUDO; }
1131*61046927SAndroid Build Coastguard Worker
isSOP1Instruction1132*61046927SAndroid Build Coastguard Worker constexpr bool isSOP1() const noexcept { return format == Format::SOP1; }
isSOP2Instruction1133*61046927SAndroid Build Coastguard Worker constexpr bool isSOP2() const noexcept { return format == Format::SOP2; }
isSOPKInstruction1134*61046927SAndroid Build Coastguard Worker constexpr bool isSOPK() const noexcept { return format == Format::SOPK; }
isSOPPInstruction1135*61046927SAndroid Build Coastguard Worker constexpr bool isSOPP() const noexcept { return format == Format::SOPP; }
isSOPCInstruction1136*61046927SAndroid Build Coastguard Worker constexpr bool isSOPC() const noexcept { return format == Format::SOPC; }
1137*61046927SAndroid Build Coastguard Worker
smemInstruction1138*61046927SAndroid Build Coastguard Worker SMEM_instruction& smem() noexcept
1139*61046927SAndroid Build Coastguard Worker {
1140*61046927SAndroid Build Coastguard Worker assert(isSMEM());
1141*61046927SAndroid Build Coastguard Worker return *(SMEM_instruction*)this;
1142*61046927SAndroid Build Coastguard Worker }
smemInstruction1143*61046927SAndroid Build Coastguard Worker const SMEM_instruction& smem() const noexcept
1144*61046927SAndroid Build Coastguard Worker {
1145*61046927SAndroid Build Coastguard Worker assert(isSMEM());
1146*61046927SAndroid Build Coastguard Worker return *(SMEM_instruction*)this;
1147*61046927SAndroid Build Coastguard Worker }
isSMEMInstruction1148*61046927SAndroid Build Coastguard Worker constexpr bool isSMEM() const noexcept { return format == Format::SMEM; }
dsInstruction1149*61046927SAndroid Build Coastguard Worker DS_instruction& ds() noexcept
1150*61046927SAndroid Build Coastguard Worker {
1151*61046927SAndroid Build Coastguard Worker assert(isDS());
1152*61046927SAndroid Build Coastguard Worker return *(DS_instruction*)this;
1153*61046927SAndroid Build Coastguard Worker }
dsInstruction1154*61046927SAndroid Build Coastguard Worker const DS_instruction& ds() const noexcept
1155*61046927SAndroid Build Coastguard Worker {
1156*61046927SAndroid Build Coastguard Worker assert(isDS());
1157*61046927SAndroid Build Coastguard Worker return *(DS_instruction*)this;
1158*61046927SAndroid Build Coastguard Worker }
isDSInstruction1159*61046927SAndroid Build Coastguard Worker constexpr bool isDS() const noexcept { return format == Format::DS; }
ldsdirInstruction1160*61046927SAndroid Build Coastguard Worker LDSDIR_instruction& ldsdir() noexcept
1161*61046927SAndroid Build Coastguard Worker {
1162*61046927SAndroid Build Coastguard Worker assert(isLDSDIR());
1163*61046927SAndroid Build Coastguard Worker return *(LDSDIR_instruction*)this;
1164*61046927SAndroid Build Coastguard Worker }
ldsdirInstruction1165*61046927SAndroid Build Coastguard Worker const LDSDIR_instruction& ldsdir() const noexcept
1166*61046927SAndroid Build Coastguard Worker {
1167*61046927SAndroid Build Coastguard Worker assert(isLDSDIR());
1168*61046927SAndroid Build Coastguard Worker return *(LDSDIR_instruction*)this;
1169*61046927SAndroid Build Coastguard Worker }
isLDSDIRInstruction1170*61046927SAndroid Build Coastguard Worker constexpr bool isLDSDIR() const noexcept { return format == Format::LDSDIR; }
mtbufInstruction1171*61046927SAndroid Build Coastguard Worker MTBUF_instruction& mtbuf() noexcept
1172*61046927SAndroid Build Coastguard Worker {
1173*61046927SAndroid Build Coastguard Worker assert(isMTBUF());
1174*61046927SAndroid Build Coastguard Worker return *(MTBUF_instruction*)this;
1175*61046927SAndroid Build Coastguard Worker }
mtbufInstruction1176*61046927SAndroid Build Coastguard Worker const MTBUF_instruction& mtbuf() const noexcept
1177*61046927SAndroid Build Coastguard Worker {
1178*61046927SAndroid Build Coastguard Worker assert(isMTBUF());
1179*61046927SAndroid Build Coastguard Worker return *(MTBUF_instruction*)this;
1180*61046927SAndroid Build Coastguard Worker }
isMTBUFInstruction1181*61046927SAndroid Build Coastguard Worker constexpr bool isMTBUF() const noexcept { return format == Format::MTBUF; }
mubufInstruction1182*61046927SAndroid Build Coastguard Worker MUBUF_instruction& mubuf() noexcept
1183*61046927SAndroid Build Coastguard Worker {
1184*61046927SAndroid Build Coastguard Worker assert(isMUBUF());
1185*61046927SAndroid Build Coastguard Worker return *(MUBUF_instruction*)this;
1186*61046927SAndroid Build Coastguard Worker }
mubufInstruction1187*61046927SAndroid Build Coastguard Worker const MUBUF_instruction& mubuf() const noexcept
1188*61046927SAndroid Build Coastguard Worker {
1189*61046927SAndroid Build Coastguard Worker assert(isMUBUF());
1190*61046927SAndroid Build Coastguard Worker return *(MUBUF_instruction*)this;
1191*61046927SAndroid Build Coastguard Worker }
isMUBUFInstruction1192*61046927SAndroid Build Coastguard Worker constexpr bool isMUBUF() const noexcept { return format == Format::MUBUF; }
mimgInstruction1193*61046927SAndroid Build Coastguard Worker MIMG_instruction& mimg() noexcept
1194*61046927SAndroid Build Coastguard Worker {
1195*61046927SAndroid Build Coastguard Worker assert(isMIMG());
1196*61046927SAndroid Build Coastguard Worker return *(MIMG_instruction*)this;
1197*61046927SAndroid Build Coastguard Worker }
mimgInstruction1198*61046927SAndroid Build Coastguard Worker const MIMG_instruction& mimg() const noexcept
1199*61046927SAndroid Build Coastguard Worker {
1200*61046927SAndroid Build Coastguard Worker assert(isMIMG());
1201*61046927SAndroid Build Coastguard Worker return *(MIMG_instruction*)this;
1202*61046927SAndroid Build Coastguard Worker }
isMIMGInstruction1203*61046927SAndroid Build Coastguard Worker constexpr bool isMIMG() const noexcept { return format == Format::MIMG; }
expInstruction1204*61046927SAndroid Build Coastguard Worker Export_instruction& exp() noexcept
1205*61046927SAndroid Build Coastguard Worker {
1206*61046927SAndroid Build Coastguard Worker assert(isEXP());
1207*61046927SAndroid Build Coastguard Worker return *(Export_instruction*)this;
1208*61046927SAndroid Build Coastguard Worker }
expInstruction1209*61046927SAndroid Build Coastguard Worker const Export_instruction& exp() const noexcept
1210*61046927SAndroid Build Coastguard Worker {
1211*61046927SAndroid Build Coastguard Worker assert(isEXP());
1212*61046927SAndroid Build Coastguard Worker return *(Export_instruction*)this;
1213*61046927SAndroid Build Coastguard Worker }
isEXPInstruction1214*61046927SAndroid Build Coastguard Worker constexpr bool isEXP() const noexcept { return format == Format::EXP; }
flatInstruction1215*61046927SAndroid Build Coastguard Worker FLAT_instruction& flat() noexcept
1216*61046927SAndroid Build Coastguard Worker {
1217*61046927SAndroid Build Coastguard Worker assert(isFlat());
1218*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1219*61046927SAndroid Build Coastguard Worker }
flatInstruction1220*61046927SAndroid Build Coastguard Worker const FLAT_instruction& flat() const noexcept
1221*61046927SAndroid Build Coastguard Worker {
1222*61046927SAndroid Build Coastguard Worker assert(isFlat());
1223*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1224*61046927SAndroid Build Coastguard Worker }
isFlatInstruction1225*61046927SAndroid Build Coastguard Worker constexpr bool isFlat() const noexcept { return format == Format::FLAT; }
globalInstruction1226*61046927SAndroid Build Coastguard Worker FLAT_instruction& global() noexcept
1227*61046927SAndroid Build Coastguard Worker {
1228*61046927SAndroid Build Coastguard Worker assert(isGlobal());
1229*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1230*61046927SAndroid Build Coastguard Worker }
globalInstruction1231*61046927SAndroid Build Coastguard Worker const FLAT_instruction& global() const noexcept
1232*61046927SAndroid Build Coastguard Worker {
1233*61046927SAndroid Build Coastguard Worker assert(isGlobal());
1234*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1235*61046927SAndroid Build Coastguard Worker }
isGlobalInstruction1236*61046927SAndroid Build Coastguard Worker constexpr bool isGlobal() const noexcept { return format == Format::GLOBAL; }
scratchInstruction1237*61046927SAndroid Build Coastguard Worker FLAT_instruction& scratch() noexcept
1238*61046927SAndroid Build Coastguard Worker {
1239*61046927SAndroid Build Coastguard Worker assert(isScratch());
1240*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1241*61046927SAndroid Build Coastguard Worker }
scratchInstruction1242*61046927SAndroid Build Coastguard Worker const FLAT_instruction& scratch() const noexcept
1243*61046927SAndroid Build Coastguard Worker {
1244*61046927SAndroid Build Coastguard Worker assert(isScratch());
1245*61046927SAndroid Build Coastguard Worker return *(FLAT_instruction*)this;
1246*61046927SAndroid Build Coastguard Worker }
isScratchInstruction1247*61046927SAndroid Build Coastguard Worker constexpr bool isScratch() const noexcept { return format == Format::SCRATCH; }
branchInstruction1248*61046927SAndroid Build Coastguard Worker Pseudo_branch_instruction& branch() noexcept
1249*61046927SAndroid Build Coastguard Worker {
1250*61046927SAndroid Build Coastguard Worker assert(isBranch());
1251*61046927SAndroid Build Coastguard Worker return *(Pseudo_branch_instruction*)this;
1252*61046927SAndroid Build Coastguard Worker }
branchInstruction1253*61046927SAndroid Build Coastguard Worker const Pseudo_branch_instruction& branch() const noexcept
1254*61046927SAndroid Build Coastguard Worker {
1255*61046927SAndroid Build Coastguard Worker assert(isBranch());
1256*61046927SAndroid Build Coastguard Worker return *(Pseudo_branch_instruction*)this;
1257*61046927SAndroid Build Coastguard Worker }
isBranchInstruction1258*61046927SAndroid Build Coastguard Worker constexpr bool isBranch() const noexcept { return format == Format::PSEUDO_BRANCH; }
barrierInstruction1259*61046927SAndroid Build Coastguard Worker Pseudo_barrier_instruction& barrier() noexcept
1260*61046927SAndroid Build Coastguard Worker {
1261*61046927SAndroid Build Coastguard Worker assert(isBarrier());
1262*61046927SAndroid Build Coastguard Worker return *(Pseudo_barrier_instruction*)this;
1263*61046927SAndroid Build Coastguard Worker }
barrierInstruction1264*61046927SAndroid Build Coastguard Worker const Pseudo_barrier_instruction& barrier() const noexcept
1265*61046927SAndroid Build Coastguard Worker {
1266*61046927SAndroid Build Coastguard Worker assert(isBarrier());
1267*61046927SAndroid Build Coastguard Worker return *(Pseudo_barrier_instruction*)this;
1268*61046927SAndroid Build Coastguard Worker }
isBarrierInstruction1269*61046927SAndroid Build Coastguard Worker constexpr bool isBarrier() const noexcept { return format == Format::PSEUDO_BARRIER; }
reductionInstruction1270*61046927SAndroid Build Coastguard Worker Pseudo_reduction_instruction& reduction() noexcept
1271*61046927SAndroid Build Coastguard Worker {
1272*61046927SAndroid Build Coastguard Worker assert(isReduction());
1273*61046927SAndroid Build Coastguard Worker return *(Pseudo_reduction_instruction*)this;
1274*61046927SAndroid Build Coastguard Worker }
reductionInstruction1275*61046927SAndroid Build Coastguard Worker const Pseudo_reduction_instruction& reduction() const noexcept
1276*61046927SAndroid Build Coastguard Worker {
1277*61046927SAndroid Build Coastguard Worker assert(isReduction());
1278*61046927SAndroid Build Coastguard Worker return *(Pseudo_reduction_instruction*)this;
1279*61046927SAndroid Build Coastguard Worker }
isReductionInstruction1280*61046927SAndroid Build Coastguard Worker constexpr bool isReduction() const noexcept { return format == Format::PSEUDO_REDUCTION; }
isVOP3PInstruction1281*61046927SAndroid Build Coastguard Worker constexpr bool isVOP3P() const noexcept { return (uint16_t)format & (uint16_t)Format::VOP3P; }
vinterp_inregInstruction1282*61046927SAndroid Build Coastguard Worker VINTERP_inreg_instruction& vinterp_inreg() noexcept
1283*61046927SAndroid Build Coastguard Worker {
1284*61046927SAndroid Build Coastguard Worker assert(isVINTERP_INREG());
1285*61046927SAndroid Build Coastguard Worker return *(VINTERP_inreg_instruction*)this;
1286*61046927SAndroid Build Coastguard Worker }
vinterp_inregInstruction1287*61046927SAndroid Build Coastguard Worker const VINTERP_inreg_instruction& vinterp_inreg() const noexcept
1288*61046927SAndroid Build Coastguard Worker {
1289*61046927SAndroid Build Coastguard Worker assert(isVINTERP_INREG());
1290*61046927SAndroid Build Coastguard Worker return *(VINTERP_inreg_instruction*)this;
1291*61046927SAndroid Build Coastguard Worker }
isVINTERP_INREGInstruction1292*61046927SAndroid Build Coastguard Worker constexpr bool isVINTERP_INREG() const noexcept { return format == Format::VINTERP_INREG; }
vopdInstruction1293*61046927SAndroid Build Coastguard Worker VOPD_instruction& vopd() noexcept
1294*61046927SAndroid Build Coastguard Worker {
1295*61046927SAndroid Build Coastguard Worker assert(isVOPD());
1296*61046927SAndroid Build Coastguard Worker return *(VOPD_instruction*)this;
1297*61046927SAndroid Build Coastguard Worker }
vopdInstruction1298*61046927SAndroid Build Coastguard Worker const VOPD_instruction& vopd() const noexcept
1299*61046927SAndroid Build Coastguard Worker {
1300*61046927SAndroid Build Coastguard Worker assert(isVOPD());
1301*61046927SAndroid Build Coastguard Worker return *(VOPD_instruction*)this;
1302*61046927SAndroid Build Coastguard Worker }
isVOPDInstruction1303*61046927SAndroid Build Coastguard Worker constexpr bool isVOPD() const noexcept { return format == Format::VOPD; }
isVOP1Instruction1304*61046927SAndroid Build Coastguard Worker constexpr bool isVOP1() const noexcept { return (uint16_t)format & (uint16_t)Format::VOP1; }
isVOP2Instruction1305*61046927SAndroid Build Coastguard Worker constexpr bool isVOP2() const noexcept { return (uint16_t)format & (uint16_t)Format::VOP2; }
isVOPCInstruction1306*61046927SAndroid Build Coastguard Worker constexpr bool isVOPC() const noexcept { return (uint16_t)format & (uint16_t)Format::VOPC; }
isVOP3Instruction1307*61046927SAndroid Build Coastguard Worker constexpr bool isVOP3() const noexcept { return (uint16_t)format & (uint16_t)Format::VOP3; }
vintrpInstruction1308*61046927SAndroid Build Coastguard Worker VINTRP_instruction& vintrp() noexcept
1309*61046927SAndroid Build Coastguard Worker {
1310*61046927SAndroid Build Coastguard Worker assert(isVINTRP());
1311*61046927SAndroid Build Coastguard Worker return *(VINTRP_instruction*)this;
1312*61046927SAndroid Build Coastguard Worker }
vintrpInstruction1313*61046927SAndroid Build Coastguard Worker const VINTRP_instruction& vintrp() const noexcept
1314*61046927SAndroid Build Coastguard Worker {
1315*61046927SAndroid Build Coastguard Worker assert(isVINTRP());
1316*61046927SAndroid Build Coastguard Worker return *(VINTRP_instruction*)this;
1317*61046927SAndroid Build Coastguard Worker }
isVINTRPInstruction1318*61046927SAndroid Build Coastguard Worker constexpr bool isVINTRP() const noexcept { return format == Format::VINTRP; }
dpp16Instruction1319*61046927SAndroid Build Coastguard Worker DPP16_instruction& dpp16() noexcept
1320*61046927SAndroid Build Coastguard Worker {
1321*61046927SAndroid Build Coastguard Worker assert(isDPP16());
1322*61046927SAndroid Build Coastguard Worker return *(DPP16_instruction*)this;
1323*61046927SAndroid Build Coastguard Worker }
dpp16Instruction1324*61046927SAndroid Build Coastguard Worker const DPP16_instruction& dpp16() const noexcept
1325*61046927SAndroid Build Coastguard Worker {
1326*61046927SAndroid Build Coastguard Worker assert(isDPP16());
1327*61046927SAndroid Build Coastguard Worker return *(DPP16_instruction*)this;
1328*61046927SAndroid Build Coastguard Worker }
isDPP16Instruction1329*61046927SAndroid Build Coastguard Worker constexpr bool isDPP16() const noexcept { return (uint16_t)format & (uint16_t)Format::DPP16; }
dpp8Instruction1330*61046927SAndroid Build Coastguard Worker DPP8_instruction& dpp8() noexcept
1331*61046927SAndroid Build Coastguard Worker {
1332*61046927SAndroid Build Coastguard Worker assert(isDPP8());
1333*61046927SAndroid Build Coastguard Worker return *(DPP8_instruction*)this;
1334*61046927SAndroid Build Coastguard Worker }
dpp8Instruction1335*61046927SAndroid Build Coastguard Worker const DPP8_instruction& dpp8() const noexcept
1336*61046927SAndroid Build Coastguard Worker {
1337*61046927SAndroid Build Coastguard Worker assert(isDPP8());
1338*61046927SAndroid Build Coastguard Worker return *(DPP8_instruction*)this;
1339*61046927SAndroid Build Coastguard Worker }
isDPP8Instruction1340*61046927SAndroid Build Coastguard Worker constexpr bool isDPP8() const noexcept { return (uint16_t)format & (uint16_t)Format::DPP8; }
isDPPInstruction1341*61046927SAndroid Build Coastguard Worker constexpr bool isDPP() const noexcept { return isDPP16() || isDPP8(); }
sdwaInstruction1342*61046927SAndroid Build Coastguard Worker SDWA_instruction& sdwa() noexcept
1343*61046927SAndroid Build Coastguard Worker {
1344*61046927SAndroid Build Coastguard Worker assert(isSDWA());
1345*61046927SAndroid Build Coastguard Worker return *(SDWA_instruction*)this;
1346*61046927SAndroid Build Coastguard Worker }
sdwaInstruction1347*61046927SAndroid Build Coastguard Worker const SDWA_instruction& sdwa() const noexcept
1348*61046927SAndroid Build Coastguard Worker {
1349*61046927SAndroid Build Coastguard Worker assert(isSDWA());
1350*61046927SAndroid Build Coastguard Worker return *(SDWA_instruction*)this;
1351*61046927SAndroid Build Coastguard Worker }
isSDWAInstruction1352*61046927SAndroid Build Coastguard Worker constexpr bool isSDWA() const noexcept { return (uint16_t)format & (uint16_t)Format::SDWA; }
1353*61046927SAndroid Build Coastguard Worker
flatlikeInstruction1354*61046927SAndroid Build Coastguard Worker FLAT_instruction& flatlike() { return *(FLAT_instruction*)this; }
1355*61046927SAndroid Build Coastguard Worker
flatlikeInstruction1356*61046927SAndroid Build Coastguard Worker const FLAT_instruction& flatlike() const { return *(FLAT_instruction*)this; }
1357*61046927SAndroid Build Coastguard Worker
isFlatLikeInstruction1358*61046927SAndroid Build Coastguard Worker constexpr bool isFlatLike() const noexcept { return isFlat() || isGlobal() || isScratch(); }
1359*61046927SAndroid Build Coastguard Worker
valuInstruction1360*61046927SAndroid Build Coastguard Worker VALU_instruction& valu() noexcept
1361*61046927SAndroid Build Coastguard Worker {
1362*61046927SAndroid Build Coastguard Worker assert(isVALU());
1363*61046927SAndroid Build Coastguard Worker return *(VALU_instruction*)this;
1364*61046927SAndroid Build Coastguard Worker }
valuInstruction1365*61046927SAndroid Build Coastguard Worker const VALU_instruction& valu() const noexcept
1366*61046927SAndroid Build Coastguard Worker {
1367*61046927SAndroid Build Coastguard Worker assert(isVALU());
1368*61046927SAndroid Build Coastguard Worker return *(VALU_instruction*)this;
1369*61046927SAndroid Build Coastguard Worker }
isVALUInstruction1370*61046927SAndroid Build Coastguard Worker constexpr bool isVALU() const noexcept
1371*61046927SAndroid Build Coastguard Worker {
1372*61046927SAndroid Build Coastguard Worker return isVOP1() || isVOP2() || isVOPC() || isVOP3() || isVOP3P() || isVINTERP_INREG() ||
1373*61046927SAndroid Build Coastguard Worker isVOPD();
1374*61046927SAndroid Build Coastguard Worker }
1375*61046927SAndroid Build Coastguard Worker
saluInstruction1376*61046927SAndroid Build Coastguard Worker SALU_instruction& salu() noexcept
1377*61046927SAndroid Build Coastguard Worker {
1378*61046927SAndroid Build Coastguard Worker assert(isSALU());
1379*61046927SAndroid Build Coastguard Worker return *(SALU_instruction*)this;
1380*61046927SAndroid Build Coastguard Worker }
saluInstruction1381*61046927SAndroid Build Coastguard Worker const SALU_instruction& salu() const noexcept
1382*61046927SAndroid Build Coastguard Worker {
1383*61046927SAndroid Build Coastguard Worker assert(isSALU());
1384*61046927SAndroid Build Coastguard Worker return *(SALU_instruction*)this;
1385*61046927SAndroid Build Coastguard Worker }
isSALUInstruction1386*61046927SAndroid Build Coastguard Worker constexpr bool isSALU() const noexcept
1387*61046927SAndroid Build Coastguard Worker {
1388*61046927SAndroid Build Coastguard Worker return isSOP1() || isSOP2() || isSOPC() || isSOPK() || isSOPP();
1389*61046927SAndroid Build Coastguard Worker }
1390*61046927SAndroid Build Coastguard Worker
isVMEMInstruction1391*61046927SAndroid Build Coastguard Worker constexpr bool isVMEM() const noexcept { return isMTBUF() || isMUBUF() || isMIMG(); }
1392*61046927SAndroid Build Coastguard Worker
1393*61046927SAndroid Build Coastguard Worker bool accessesLDS() const noexcept;
1394*61046927SAndroid Build Coastguard Worker bool isTrans() const noexcept;
1395*61046927SAndroid Build Coastguard Worker };
1396*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Instruction) == 16, "Unexpected padding");
1397*61046927SAndroid Build Coastguard Worker
1398*61046927SAndroid Build Coastguard Worker struct SALU_instruction : public Instruction {
1399*61046927SAndroid Build Coastguard Worker /* In case of SOPP branch instructions, contains the Block index,
1400*61046927SAndroid Build Coastguard Worker * and otherwise, for SOPP and SOPK the 16-bit signed immediate.
1401*61046927SAndroid Build Coastguard Worker */
1402*61046927SAndroid Build Coastguard Worker uint32_t imm;
1403*61046927SAndroid Build Coastguard Worker };
1404*61046927SAndroid Build Coastguard Worker static_assert(sizeof(SALU_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1405*61046927SAndroid Build Coastguard Worker
1406*61046927SAndroid Build Coastguard Worker /**
1407*61046927SAndroid Build Coastguard Worker * Scalar Memory Format:
1408*61046927SAndroid Build Coastguard Worker * For s_(buffer_)load_dword*:
1409*61046927SAndroid Build Coastguard Worker * Operand(0): SBASE - SGPR-pair which provides base address
1410*61046927SAndroid Build Coastguard Worker * Operand(1): Offset - immediate (un)signed offset or SGPR
1411*61046927SAndroid Build Coastguard Worker * Operand(2) / Definition(0): SDATA - SGPR for read / write result
1412*61046927SAndroid Build Coastguard Worker * Operand(n-1): SOffset - SGPR offset (Vega only)
1413*61046927SAndroid Build Coastguard Worker *
1414*61046927SAndroid Build Coastguard Worker * Having no operands is also valid for instructions such as s_dcache_inv.
1415*61046927SAndroid Build Coastguard Worker *
1416*61046927SAndroid Build Coastguard Worker */
1417*61046927SAndroid Build Coastguard Worker struct SMEM_instruction : public Instruction {
1418*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1419*61046927SAndroid Build Coastguard Worker ac_hw_cache_flags cache;
1420*61046927SAndroid Build Coastguard Worker };
1421*61046927SAndroid Build Coastguard Worker static_assert(sizeof(SMEM_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1422*61046927SAndroid Build Coastguard Worker
1423*61046927SAndroid Build Coastguard Worker struct VALU_instruction : public Instruction {
1424*61046927SAndroid Build Coastguard Worker union {
1425*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 0, 3> neg; /* VOP3, SDWA, DPP16, v_fma_mix, VINTERP_inreg */
1426*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 0, 3> neg_lo; /* VOP3P */
1427*61046927SAndroid Build Coastguard Worker
1428*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 3, 3> abs; /* VOP3, SDWA, DPP16, v_fma_mix */
1429*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 3, 3> neg_hi; /* VOP3P */
1430*61046927SAndroid Build Coastguard Worker
1431*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 6, 4> opsel; /* VOP3, VOPC12(GFX11+), VINTERP_inreg */
1432*61046927SAndroid Build Coastguard Worker bitfield_uint8<uint32_t, 10, 2> omod; /* VOP3, SDWA(GFX9+) */
1433*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 12, 3> opsel_lo; /* VOP3P */
1434*61046927SAndroid Build Coastguard Worker bitfield_array8<uint32_t, 15, 3> opsel_hi; /* VOP3P */
1435*61046927SAndroid Build Coastguard Worker bitfield_bool<uint32_t, 18> clamp; /* VOP3, VOP3P, SDWA, VINTERP_inreg */
1436*61046927SAndroid Build Coastguard Worker };
1437*61046927SAndroid Build Coastguard Worker
1438*61046927SAndroid Build Coastguard Worker void swapOperands(unsigned idx0, unsigned idx1);
1439*61046927SAndroid Build Coastguard Worker };
1440*61046927SAndroid Build Coastguard Worker static_assert(sizeof(VALU_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1441*61046927SAndroid Build Coastguard Worker
1442*61046927SAndroid Build Coastguard Worker struct VINTERP_inreg_instruction : public VALU_instruction {
1443*61046927SAndroid Build Coastguard Worker uint8_t wait_exp : 3;
1444*61046927SAndroid Build Coastguard Worker uint8_t padding3 : 5;
1445*61046927SAndroid Build Coastguard Worker uint8_t padding4;
1446*61046927SAndroid Build Coastguard Worker uint8_t padding5;
1447*61046927SAndroid Build Coastguard Worker uint8_t padding6;
1448*61046927SAndroid Build Coastguard Worker };
1449*61046927SAndroid Build Coastguard Worker static_assert(sizeof(VINTERP_inreg_instruction) == sizeof(VALU_instruction) + 4,
1450*61046927SAndroid Build Coastguard Worker "Unexpected padding");
1451*61046927SAndroid Build Coastguard Worker
1452*61046927SAndroid Build Coastguard Worker struct VOPD_instruction : public VALU_instruction {
1453*61046927SAndroid Build Coastguard Worker aco_opcode opy;
1454*61046927SAndroid Build Coastguard Worker uint16_t padding;
1455*61046927SAndroid Build Coastguard Worker };
1456*61046927SAndroid Build Coastguard Worker static_assert(sizeof(VOPD_instruction) == sizeof(VALU_instruction) + 4, "Unexpected padding");
1457*61046927SAndroid Build Coastguard Worker
1458*61046927SAndroid Build Coastguard Worker /**
1459*61046927SAndroid Build Coastguard Worker * Data Parallel Primitives Format:
1460*61046927SAndroid Build Coastguard Worker * This format can be used for VOP1, VOP2 or VOPC instructions.
1461*61046927SAndroid Build Coastguard Worker * The swizzle applies to the src0 operand.
1462*61046927SAndroid Build Coastguard Worker *
1463*61046927SAndroid Build Coastguard Worker */
1464*61046927SAndroid Build Coastguard Worker struct DPP16_instruction : public VALU_instruction {
1465*61046927SAndroid Build Coastguard Worker uint16_t dpp_ctrl;
1466*61046927SAndroid Build Coastguard Worker uint8_t row_mask : 4;
1467*61046927SAndroid Build Coastguard Worker uint8_t bank_mask : 4;
1468*61046927SAndroid Build Coastguard Worker bool bound_ctrl : 1;
1469*61046927SAndroid Build Coastguard Worker uint8_t fetch_inactive : 1;
1470*61046927SAndroid Build Coastguard Worker uint8_t padding3 : 6;
1471*61046927SAndroid Build Coastguard Worker };
1472*61046927SAndroid Build Coastguard Worker static_assert(sizeof(DPP16_instruction) == sizeof(VALU_instruction) + 4, "Unexpected padding");
1473*61046927SAndroid Build Coastguard Worker
1474*61046927SAndroid Build Coastguard Worker struct DPP8_instruction : public VALU_instruction {
1475*61046927SAndroid Build Coastguard Worker uint32_t lane_sel : 24;
1476*61046927SAndroid Build Coastguard Worker uint32_t fetch_inactive : 1;
1477*61046927SAndroid Build Coastguard Worker uint32_t padding : 7;
1478*61046927SAndroid Build Coastguard Worker };
1479*61046927SAndroid Build Coastguard Worker static_assert(sizeof(DPP8_instruction) == sizeof(VALU_instruction) + 4, "Unexpected padding");
1480*61046927SAndroid Build Coastguard Worker
1481*61046927SAndroid Build Coastguard Worker struct SubdwordSel {
1482*61046927SAndroid Build Coastguard Worker enum sdwa_sel : uint8_t {
1483*61046927SAndroid Build Coastguard Worker ubyte = 0x4,
1484*61046927SAndroid Build Coastguard Worker uword = 0x8,
1485*61046927SAndroid Build Coastguard Worker dword = 0x10,
1486*61046927SAndroid Build Coastguard Worker sext = 0x20,
1487*61046927SAndroid Build Coastguard Worker sbyte = ubyte | sext,
1488*61046927SAndroid Build Coastguard Worker sword = uword | sext,
1489*61046927SAndroid Build Coastguard Worker
1490*61046927SAndroid Build Coastguard Worker ubyte0 = ubyte,
1491*61046927SAndroid Build Coastguard Worker ubyte1 = ubyte | 1,
1492*61046927SAndroid Build Coastguard Worker ubyte2 = ubyte | 2,
1493*61046927SAndroid Build Coastguard Worker ubyte3 = ubyte | 3,
1494*61046927SAndroid Build Coastguard Worker sbyte0 = sbyte,
1495*61046927SAndroid Build Coastguard Worker sbyte1 = sbyte | 1,
1496*61046927SAndroid Build Coastguard Worker sbyte2 = sbyte | 2,
1497*61046927SAndroid Build Coastguard Worker sbyte3 = sbyte | 3,
1498*61046927SAndroid Build Coastguard Worker uword0 = uword,
1499*61046927SAndroid Build Coastguard Worker uword1 = uword | 2,
1500*61046927SAndroid Build Coastguard Worker sword0 = sword,
1501*61046927SAndroid Build Coastguard Worker sword1 = sword | 2,
1502*61046927SAndroid Build Coastguard Worker };
1503*61046927SAndroid Build Coastguard Worker
SubdwordSelSubdwordSel1504*61046927SAndroid Build Coastguard Worker SubdwordSel() : sel((sdwa_sel)0) {}
SubdwordSelSubdwordSel1505*61046927SAndroid Build Coastguard Worker constexpr SubdwordSel(sdwa_sel sel_) : sel(sel_) {}
SubdwordSelSubdwordSel1506*61046927SAndroid Build Coastguard Worker constexpr SubdwordSel(unsigned size, unsigned offset, bool sign_extend)
1507*61046927SAndroid Build Coastguard Worker : sel((sdwa_sel)((sign_extend ? sext : 0) | size << 2 | offset))
1508*61046927SAndroid Build Coastguard Worker {}
sdwa_selSubdwordSel1509*61046927SAndroid Build Coastguard Worker constexpr operator sdwa_sel() const { return sel; }
1510*61046927SAndroid Build Coastguard Worker explicit operator bool() const { return sel != 0; }
1511*61046927SAndroid Build Coastguard Worker
sizeSubdwordSel1512*61046927SAndroid Build Coastguard Worker constexpr unsigned size() const { return (sel >> 2) & 0x7; }
offsetSubdwordSel1513*61046927SAndroid Build Coastguard Worker constexpr unsigned offset() const { return sel & 0x3; }
sign_extendSubdwordSel1514*61046927SAndroid Build Coastguard Worker constexpr bool sign_extend() const { return sel & sext; }
to_sdwa_selSubdwordSel1515*61046927SAndroid Build Coastguard Worker constexpr unsigned to_sdwa_sel(unsigned reg_byte_offset) const
1516*61046927SAndroid Build Coastguard Worker {
1517*61046927SAndroid Build Coastguard Worker reg_byte_offset += offset();
1518*61046927SAndroid Build Coastguard Worker if (size() == 1)
1519*61046927SAndroid Build Coastguard Worker return reg_byte_offset;
1520*61046927SAndroid Build Coastguard Worker else if (size() == 2)
1521*61046927SAndroid Build Coastguard Worker return 4 + (reg_byte_offset >> 1);
1522*61046927SAndroid Build Coastguard Worker else
1523*61046927SAndroid Build Coastguard Worker return 6;
1524*61046927SAndroid Build Coastguard Worker }
1525*61046927SAndroid Build Coastguard Worker
1526*61046927SAndroid Build Coastguard Worker private:
1527*61046927SAndroid Build Coastguard Worker sdwa_sel sel;
1528*61046927SAndroid Build Coastguard Worker };
1529*61046927SAndroid Build Coastguard Worker
1530*61046927SAndroid Build Coastguard Worker /**
1531*61046927SAndroid Build Coastguard Worker * Sub-Dword Addressing Format:
1532*61046927SAndroid Build Coastguard Worker * This format can be used for VOP1, VOP2 or VOPC instructions.
1533*61046927SAndroid Build Coastguard Worker *
1534*61046927SAndroid Build Coastguard Worker * omod and SGPR/constant operands are only available on GFX9+. For VOPC,
1535*61046927SAndroid Build Coastguard Worker * the definition doesn't have to be VCC on GFX9+.
1536*61046927SAndroid Build Coastguard Worker *
1537*61046927SAndroid Build Coastguard Worker */
1538*61046927SAndroid Build Coastguard Worker struct SDWA_instruction : public VALU_instruction {
1539*61046927SAndroid Build Coastguard Worker /* these destination modifiers aren't available with VOPC except for
1540*61046927SAndroid Build Coastguard Worker * clamp on GFX8 */
1541*61046927SAndroid Build Coastguard Worker SubdwordSel sel[2];
1542*61046927SAndroid Build Coastguard Worker SubdwordSel dst_sel;
1543*61046927SAndroid Build Coastguard Worker uint8_t padding3;
1544*61046927SAndroid Build Coastguard Worker };
1545*61046927SAndroid Build Coastguard Worker static_assert(sizeof(SDWA_instruction) == sizeof(VALU_instruction) + 4, "Unexpected padding");
1546*61046927SAndroid Build Coastguard Worker
1547*61046927SAndroid Build Coastguard Worker struct VINTRP_instruction : public Instruction {
1548*61046927SAndroid Build Coastguard Worker uint8_t attribute;
1549*61046927SAndroid Build Coastguard Worker uint8_t component;
1550*61046927SAndroid Build Coastguard Worker bool high_16bits;
1551*61046927SAndroid Build Coastguard Worker uint8_t padding;
1552*61046927SAndroid Build Coastguard Worker };
1553*61046927SAndroid Build Coastguard Worker static_assert(sizeof(VINTRP_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1554*61046927SAndroid Build Coastguard Worker
1555*61046927SAndroid Build Coastguard Worker /**
1556*61046927SAndroid Build Coastguard Worker * Local and Global Data Sharing instructions
1557*61046927SAndroid Build Coastguard Worker * Operand(0): ADDR - VGPR which supplies the address.
1558*61046927SAndroid Build Coastguard Worker * Operand(1): DATA0 - First data VGPR.
1559*61046927SAndroid Build Coastguard Worker * Operand(2): DATA1 - Second data VGPR.
1560*61046927SAndroid Build Coastguard Worker * Operand(n-1): M0 - LDS size.
1561*61046927SAndroid Build Coastguard Worker * Definition(0): VDST - Destination VGPR when results returned to VGPRs.
1562*61046927SAndroid Build Coastguard Worker *
1563*61046927SAndroid Build Coastguard Worker */
1564*61046927SAndroid Build Coastguard Worker struct DS_instruction : public Instruction {
1565*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1566*61046927SAndroid Build Coastguard Worker bool gds;
1567*61046927SAndroid Build Coastguard Worker uint16_t offset0;
1568*61046927SAndroid Build Coastguard Worker uint8_t offset1;
1569*61046927SAndroid Build Coastguard Worker uint8_t padding;
1570*61046927SAndroid Build Coastguard Worker };
1571*61046927SAndroid Build Coastguard Worker static_assert(sizeof(DS_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1572*61046927SAndroid Build Coastguard Worker
1573*61046927SAndroid Build Coastguard Worker /**
1574*61046927SAndroid Build Coastguard Worker * LDS Direct instructions
1575*61046927SAndroid Build Coastguard Worker * Operand(0): M0
1576*61046927SAndroid Build Coastguard Worker * Definition(0): VDST - Destination VGPR
1577*61046927SAndroid Build Coastguard Worker */
1578*61046927SAndroid Build Coastguard Worker struct LDSDIR_instruction : public Instruction {
1579*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1580*61046927SAndroid Build Coastguard Worker uint8_t attr : 6;
1581*61046927SAndroid Build Coastguard Worker uint8_t attr_chan : 2;
1582*61046927SAndroid Build Coastguard Worker uint32_t wait_vdst : 4;
1583*61046927SAndroid Build Coastguard Worker uint32_t wait_vsrc : 1;
1584*61046927SAndroid Build Coastguard Worker uint32_t padding : 27;
1585*61046927SAndroid Build Coastguard Worker };
1586*61046927SAndroid Build Coastguard Worker static_assert(sizeof(LDSDIR_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1587*61046927SAndroid Build Coastguard Worker
1588*61046927SAndroid Build Coastguard Worker /**
1589*61046927SAndroid Build Coastguard Worker * Vector Memory Untyped-buffer Instructions
1590*61046927SAndroid Build Coastguard Worker * Operand(0): SRSRC - Specifies which SGPR supplies T# (resource constant)
1591*61046927SAndroid Build Coastguard Worker * Operand(1): VADDR - Address source. Can carry an index and/or offset
1592*61046927SAndroid Build Coastguard Worker * Operand(2): SOFFSET - SGPR to supply unsigned byte offset. (SGPR, M0, or inline constant)
1593*61046927SAndroid Build Coastguard Worker * Operand(3) / Definition(0): VDATA - Vector GPR for write result / read data
1594*61046927SAndroid Build Coastguard Worker *
1595*61046927SAndroid Build Coastguard Worker */
1596*61046927SAndroid Build Coastguard Worker struct MUBUF_instruction : public Instruction {
1597*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1598*61046927SAndroid Build Coastguard Worker ac_hw_cache_flags cache;
1599*61046927SAndroid Build Coastguard Worker bool offen : 1; /* Supply an offset from VGPR (VADDR) */
1600*61046927SAndroid Build Coastguard Worker bool idxen : 1; /* Supply an index from VGPR (VADDR) */
1601*61046927SAndroid Build Coastguard Worker bool addr64 : 1; /* SI, CIK: Address size is 64-bit */
1602*61046927SAndroid Build Coastguard Worker bool tfe : 1; /* texture fail enable */
1603*61046927SAndroid Build Coastguard Worker bool lds : 1; /* Return read-data to LDS instead of VGPRs */
1604*61046927SAndroid Build Coastguard Worker bool disable_wqm : 1; /* Require an exec mask without helper invocations */
1605*61046927SAndroid Build Coastguard Worker uint8_t padding0 : 2;
1606*61046927SAndroid Build Coastguard Worker uint8_t padding1;
1607*61046927SAndroid Build Coastguard Worker uint16_t offset; /* Unsigned byte offset - 12 bit */
1608*61046927SAndroid Build Coastguard Worker };
1609*61046927SAndroid Build Coastguard Worker static_assert(sizeof(MUBUF_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1610*61046927SAndroid Build Coastguard Worker
1611*61046927SAndroid Build Coastguard Worker /**
1612*61046927SAndroid Build Coastguard Worker * Vector Memory Typed-buffer Instructions
1613*61046927SAndroid Build Coastguard Worker * Operand(0): SRSRC - Specifies which SGPR supplies T# (resource constant)
1614*61046927SAndroid Build Coastguard Worker * Operand(1): VADDR - Address source. Can carry an index and/or offset
1615*61046927SAndroid Build Coastguard Worker * Operand(2): SOFFSET - SGPR to supply unsigned byte offset. (SGPR, M0, or inline constant)
1616*61046927SAndroid Build Coastguard Worker * Operand(3) / Definition(0): VDATA - Vector GPR for write result / read data
1617*61046927SAndroid Build Coastguard Worker *
1618*61046927SAndroid Build Coastguard Worker */
1619*61046927SAndroid Build Coastguard Worker struct MTBUF_instruction : public Instruction {
1620*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1621*61046927SAndroid Build Coastguard Worker ac_hw_cache_flags cache;
1622*61046927SAndroid Build Coastguard Worker uint8_t dfmt : 4; /* Data Format of data in memory buffer */
1623*61046927SAndroid Build Coastguard Worker uint8_t nfmt : 3; /* Numeric format of data in memory */
1624*61046927SAndroid Build Coastguard Worker bool offen : 1; /* Supply an offset from VGPR (VADDR) */
1625*61046927SAndroid Build Coastguard Worker bool idxen : 1; /* Supply an index from VGPR (VADDR) */
1626*61046927SAndroid Build Coastguard Worker bool tfe : 1; /* texture fail enable */
1627*61046927SAndroid Build Coastguard Worker bool disable_wqm : 1; /* Require an exec mask without helper invocations */
1628*61046927SAndroid Build Coastguard Worker uint8_t padding : 5;
1629*61046927SAndroid Build Coastguard Worker uint16_t offset; /* Unsigned byte offset - 12 bit */
1630*61046927SAndroid Build Coastguard Worker };
1631*61046927SAndroid Build Coastguard Worker static_assert(sizeof(MTBUF_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1632*61046927SAndroid Build Coastguard Worker
1633*61046927SAndroid Build Coastguard Worker /**
1634*61046927SAndroid Build Coastguard Worker * Vector Memory Image Instructions
1635*61046927SAndroid Build Coastguard Worker * Operand(0) SRSRC - Scalar GPR that specifies the resource constant.
1636*61046927SAndroid Build Coastguard Worker * Operand(1): SSAMP - Scalar GPR that specifies sampler constant.
1637*61046927SAndroid Build Coastguard Worker * Operand(2): VDATA - Vector GPR for write data or zero if TFE/LWE=1.
1638*61046927SAndroid Build Coastguard Worker * Operand(3): VADDR - Address source. Can carry an offset or an index.
1639*61046927SAndroid Build Coastguard Worker * Definition(0): VDATA - Vector GPR for read result.
1640*61046927SAndroid Build Coastguard Worker *
1641*61046927SAndroid Build Coastguard Worker */
1642*61046927SAndroid Build Coastguard Worker struct MIMG_instruction : public Instruction {
1643*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1644*61046927SAndroid Build Coastguard Worker ac_hw_cache_flags cache;
1645*61046927SAndroid Build Coastguard Worker uint8_t dmask; /* Data VGPR enable mask */
1646*61046927SAndroid Build Coastguard Worker uint8_t dim : 3; /* NAVI: dimensionality */
1647*61046927SAndroid Build Coastguard Worker bool unrm : 1; /* Force address to be un-normalized */
1648*61046927SAndroid Build Coastguard Worker bool tfe : 1; /* texture fail enable */
1649*61046927SAndroid Build Coastguard Worker bool da : 1; /* declare an array */
1650*61046927SAndroid Build Coastguard Worker bool lwe : 1; /* LOD warning enable */
1651*61046927SAndroid Build Coastguard Worker bool r128 : 1; /* NAVI: Texture resource size */
1652*61046927SAndroid Build Coastguard Worker bool a16 : 1; /* VEGA, NAVI: Address components are 16-bits */
1653*61046927SAndroid Build Coastguard Worker bool d16 : 1; /* Convert 32-bit data to 16-bit data */
1654*61046927SAndroid Build Coastguard Worker bool disable_wqm : 1; /* Require an exec mask without helper invocations */
1655*61046927SAndroid Build Coastguard Worker bool strict_wqm : 1; /* VADDR is a linear VGPR and additional VGPRs may be copied into it */
1656*61046927SAndroid Build Coastguard Worker uint8_t padding0 : 4;
1657*61046927SAndroid Build Coastguard Worker uint8_t padding1;
1658*61046927SAndroid Build Coastguard Worker };
1659*61046927SAndroid Build Coastguard Worker static_assert(sizeof(MIMG_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1660*61046927SAndroid Build Coastguard Worker
1661*61046927SAndroid Build Coastguard Worker /**
1662*61046927SAndroid Build Coastguard Worker * Flat/Scratch/Global Instructions
1663*61046927SAndroid Build Coastguard Worker * Operand(0): ADDR
1664*61046927SAndroid Build Coastguard Worker * Operand(1): SADDR
1665*61046927SAndroid Build Coastguard Worker * Operand(2) / Definition(0): DATA/VDST
1666*61046927SAndroid Build Coastguard Worker *
1667*61046927SAndroid Build Coastguard Worker */
1668*61046927SAndroid Build Coastguard Worker struct FLAT_instruction : public Instruction {
1669*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1670*61046927SAndroid Build Coastguard Worker ac_hw_cache_flags cache;
1671*61046927SAndroid Build Coastguard Worker bool lds : 1;
1672*61046927SAndroid Build Coastguard Worker bool nv : 1;
1673*61046927SAndroid Build Coastguard Worker bool disable_wqm : 1; /* Require an exec mask without helper invocations */
1674*61046927SAndroid Build Coastguard Worker uint8_t padding0 : 5;
1675*61046927SAndroid Build Coastguard Worker uint8_t padding1;
1676*61046927SAndroid Build Coastguard Worker int16_t offset; /* Vega/Navi only */
1677*61046927SAndroid Build Coastguard Worker };
1678*61046927SAndroid Build Coastguard Worker static_assert(sizeof(FLAT_instruction) == sizeof(Instruction) + 8, "Unexpected padding");
1679*61046927SAndroid Build Coastguard Worker
1680*61046927SAndroid Build Coastguard Worker struct Export_instruction : public Instruction {
1681*61046927SAndroid Build Coastguard Worker uint8_t enabled_mask;
1682*61046927SAndroid Build Coastguard Worker uint8_t dest;
1683*61046927SAndroid Build Coastguard Worker bool compressed : 1;
1684*61046927SAndroid Build Coastguard Worker bool done : 1;
1685*61046927SAndroid Build Coastguard Worker bool valid_mask : 1;
1686*61046927SAndroid Build Coastguard Worker bool row_en : 1;
1687*61046927SAndroid Build Coastguard Worker uint8_t padding0 : 4;
1688*61046927SAndroid Build Coastguard Worker uint8_t padding1;
1689*61046927SAndroid Build Coastguard Worker };
1690*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Export_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1691*61046927SAndroid Build Coastguard Worker
1692*61046927SAndroid Build Coastguard Worker struct Pseudo_instruction : public Instruction {
1693*61046927SAndroid Build Coastguard Worker PhysReg scratch_sgpr; /* might not be valid if it's not needed */
1694*61046927SAndroid Build Coastguard Worker bool tmp_in_scc;
1695*61046927SAndroid Build Coastguard Worker bool needs_scratch_reg; /* if scratch_sgpr/scc can be written, initialized by RA. */
1696*61046927SAndroid Build Coastguard Worker };
1697*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Pseudo_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1698*61046927SAndroid Build Coastguard Worker
1699*61046927SAndroid Build Coastguard Worker struct Pseudo_branch_instruction : public Instruction {
1700*61046927SAndroid Build Coastguard Worker /* target[0] is the block index of the branch target.
1701*61046927SAndroid Build Coastguard Worker * For conditional branches, target[1] contains the fall-through alternative.
1702*61046927SAndroid Build Coastguard Worker * A value of 0 means the target has not been initialized (BB0 cannot be a branch target).
1703*61046927SAndroid Build Coastguard Worker */
1704*61046927SAndroid Build Coastguard Worker uint32_t target[2];
1705*61046927SAndroid Build Coastguard Worker
1706*61046927SAndroid Build Coastguard Worker /* Indicates that this rarely or never jumps to target[0]. */
1707*61046927SAndroid Build Coastguard Worker bool rarely_taken;
1708*61046927SAndroid Build Coastguard Worker bool never_taken;
1709*61046927SAndroid Build Coastguard Worker
1710*61046927SAndroid Build Coastguard Worker uint16_t padding;
1711*61046927SAndroid Build Coastguard Worker };
1712*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Pseudo_branch_instruction) == sizeof(Instruction) + 12, "Unexpected padding");
1713*61046927SAndroid Build Coastguard Worker
1714*61046927SAndroid Build Coastguard Worker struct Pseudo_barrier_instruction : public Instruction {
1715*61046927SAndroid Build Coastguard Worker memory_sync_info sync;
1716*61046927SAndroid Build Coastguard Worker sync_scope exec_scope;
1717*61046927SAndroid Build Coastguard Worker };
1718*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Pseudo_barrier_instruction) == sizeof(Instruction) + 4, "Unexpected padding");
1719*61046927SAndroid Build Coastguard Worker
1720*61046927SAndroid Build Coastguard Worker enum ReduceOp : uint16_t {
1721*61046927SAndroid Build Coastguard Worker // clang-format off
1722*61046927SAndroid Build Coastguard Worker iadd8, iadd16, iadd32, iadd64,
1723*61046927SAndroid Build Coastguard Worker imul8, imul16, imul32, imul64,
1724*61046927SAndroid Build Coastguard Worker fadd16, fadd32, fadd64,
1725*61046927SAndroid Build Coastguard Worker fmul16, fmul32, fmul64,
1726*61046927SAndroid Build Coastguard Worker imin8, imin16, imin32, imin64,
1727*61046927SAndroid Build Coastguard Worker imax8, imax16, imax32, imax64,
1728*61046927SAndroid Build Coastguard Worker umin8, umin16, umin32, umin64,
1729*61046927SAndroid Build Coastguard Worker umax8, umax16, umax32, umax64,
1730*61046927SAndroid Build Coastguard Worker fmin16, fmin32, fmin64,
1731*61046927SAndroid Build Coastguard Worker fmax16, fmax32, fmax64,
1732*61046927SAndroid Build Coastguard Worker iand8, iand16, iand32, iand64,
1733*61046927SAndroid Build Coastguard Worker ior8, ior16, ior32, ior64,
1734*61046927SAndroid Build Coastguard Worker ixor8, ixor16, ixor32, ixor64,
1735*61046927SAndroid Build Coastguard Worker num_reduce_ops,
1736*61046927SAndroid Build Coastguard Worker // clang-format on
1737*61046927SAndroid Build Coastguard Worker };
1738*61046927SAndroid Build Coastguard Worker
1739*61046927SAndroid Build Coastguard Worker /**
1740*61046927SAndroid Build Coastguard Worker * Subgroup Reduction Instructions, everything except for the data to be
1741*61046927SAndroid Build Coastguard Worker * reduced and the result as inserted by setup_reduce_temp().
1742*61046927SAndroid Build Coastguard Worker * Operand(0): data to be reduced
1743*61046927SAndroid Build Coastguard Worker * Operand(1): reduce temporary
1744*61046927SAndroid Build Coastguard Worker * Operand(2): vector temporary
1745*61046927SAndroid Build Coastguard Worker * Definition(0): result
1746*61046927SAndroid Build Coastguard Worker * Definition(1): scalar temporary
1747*61046927SAndroid Build Coastguard Worker * Definition(2): scalar identity temporary (not used to store identity on GFX10)
1748*61046927SAndroid Build Coastguard Worker * Definition(3): scc clobber
1749*61046927SAndroid Build Coastguard Worker * Definition(4): vcc clobber
1750*61046927SAndroid Build Coastguard Worker *
1751*61046927SAndroid Build Coastguard Worker */
1752*61046927SAndroid Build Coastguard Worker struct Pseudo_reduction_instruction : public Instruction {
1753*61046927SAndroid Build Coastguard Worker ReduceOp reduce_op;
1754*61046927SAndroid Build Coastguard Worker uint16_t cluster_size; // must be 0 for scans
1755*61046927SAndroid Build Coastguard Worker };
1756*61046927SAndroid Build Coastguard Worker static_assert(sizeof(Pseudo_reduction_instruction) == sizeof(Instruction) + 4,
1757*61046927SAndroid Build Coastguard Worker "Unexpected padding");
1758*61046927SAndroid Build Coastguard Worker
1759*61046927SAndroid Build Coastguard Worker inline bool
accessesLDS()1760*61046927SAndroid Build Coastguard Worker Instruction::accessesLDS() const noexcept
1761*61046927SAndroid Build Coastguard Worker {
1762*61046927SAndroid Build Coastguard Worker return (isDS() && !ds().gds) || isLDSDIR() || isVINTRP();
1763*61046927SAndroid Build Coastguard Worker }
1764*61046927SAndroid Build Coastguard Worker
1765*61046927SAndroid Build Coastguard Worker inline void
swapOperands(unsigned idx0,unsigned idx1)1766*61046927SAndroid Build Coastguard Worker VALU_instruction::swapOperands(unsigned idx0, unsigned idx1)
1767*61046927SAndroid Build Coastguard Worker {
1768*61046927SAndroid Build Coastguard Worker if (this->isSDWA() && idx0 != idx1) {
1769*61046927SAndroid Build Coastguard Worker assert(idx0 < 2 && idx1 < 2);
1770*61046927SAndroid Build Coastguard Worker std::swap(this->sdwa().sel[0], this->sdwa().sel[1]);
1771*61046927SAndroid Build Coastguard Worker }
1772*61046927SAndroid Build Coastguard Worker assert(idx0 < 3 && idx1 < 3);
1773*61046927SAndroid Build Coastguard Worker std::swap(this->operands[idx0], this->operands[idx1]);
1774*61046927SAndroid Build Coastguard Worker this->neg[idx0].swap(this->neg[idx1]);
1775*61046927SAndroid Build Coastguard Worker this->abs[idx0].swap(this->abs[idx1]);
1776*61046927SAndroid Build Coastguard Worker this->opsel[idx0].swap(this->opsel[idx1]);
1777*61046927SAndroid Build Coastguard Worker this->opsel_lo[idx0].swap(this->opsel_lo[idx1]);
1778*61046927SAndroid Build Coastguard Worker this->opsel_hi[idx0].swap(this->opsel_hi[idx1]);
1779*61046927SAndroid Build Coastguard Worker }
1780*61046927SAndroid Build Coastguard Worker
1781*61046927SAndroid Build Coastguard Worker struct instr_deleter_functor {
1782*61046927SAndroid Build Coastguard Worker /* Don't yet free any instructions. They will be de-allocated
1783*61046927SAndroid Build Coastguard Worker * all at once after compilation finished.
1784*61046927SAndroid Build Coastguard Worker */
operatorinstr_deleter_functor1785*61046927SAndroid Build Coastguard Worker void operator()(void* p) { return; }
1786*61046927SAndroid Build Coastguard Worker };
1787*61046927SAndroid Build Coastguard Worker
1788*61046927SAndroid Build Coastguard Worker template <typename T> using aco_ptr = std::unique_ptr<T, instr_deleter_functor>;
1789*61046927SAndroid Build Coastguard Worker
1790*61046927SAndroid Build Coastguard Worker size_t get_instr_data_size(Format format);
1791*61046927SAndroid Build Coastguard Worker
1792*61046927SAndroid Build Coastguard Worker Instruction* create_instruction(aco_opcode opcode, Format format, uint32_t num_operands,
1793*61046927SAndroid Build Coastguard Worker uint32_t num_definitions);
1794*61046927SAndroid Build Coastguard Worker
1795*61046927SAndroid Build Coastguard Worker constexpr bool
usesModifiers()1796*61046927SAndroid Build Coastguard Worker Instruction::usesModifiers() const noexcept
1797*61046927SAndroid Build Coastguard Worker {
1798*61046927SAndroid Build Coastguard Worker if (isDPP() || isSDWA())
1799*61046927SAndroid Build Coastguard Worker return true;
1800*61046927SAndroid Build Coastguard Worker
1801*61046927SAndroid Build Coastguard Worker if (isVOP3P()) {
1802*61046927SAndroid Build Coastguard Worker const VALU_instruction& vop3p = this->valu();
1803*61046927SAndroid Build Coastguard Worker /* opsel_hi must be 1 to not be considered a modifier - even for constants */
1804*61046927SAndroid Build Coastguard Worker return vop3p.opsel_lo || vop3p.clamp || vop3p.neg_lo || vop3p.neg_hi ||
1805*61046927SAndroid Build Coastguard Worker (vop3p.opsel_hi & BITFIELD_MASK(operands.size())) != BITFIELD_MASK(operands.size());
1806*61046927SAndroid Build Coastguard Worker } else if (isVALU()) {
1807*61046927SAndroid Build Coastguard Worker const VALU_instruction& vop3 = this->valu();
1808*61046927SAndroid Build Coastguard Worker return vop3.opsel || vop3.clamp || vop3.omod || vop3.abs || vop3.neg;
1809*61046927SAndroid Build Coastguard Worker }
1810*61046927SAndroid Build Coastguard Worker return false;
1811*61046927SAndroid Build Coastguard Worker }
1812*61046927SAndroid Build Coastguard Worker
1813*61046927SAndroid Build Coastguard Worker constexpr bool
is_phi(Instruction * instr)1814*61046927SAndroid Build Coastguard Worker is_phi(Instruction* instr)
1815*61046927SAndroid Build Coastguard Worker {
1816*61046927SAndroid Build Coastguard Worker return instr->opcode == aco_opcode::p_phi || instr->opcode == aco_opcode::p_linear_phi;
1817*61046927SAndroid Build Coastguard Worker }
1818*61046927SAndroid Build Coastguard Worker
1819*61046927SAndroid Build Coastguard Worker static inline bool
is_phi(aco_ptr<Instruction> & instr)1820*61046927SAndroid Build Coastguard Worker is_phi(aco_ptr<Instruction>& instr)
1821*61046927SAndroid Build Coastguard Worker {
1822*61046927SAndroid Build Coastguard Worker return is_phi(instr.get());
1823*61046927SAndroid Build Coastguard Worker }
1824*61046927SAndroid Build Coastguard Worker
1825*61046927SAndroid Build Coastguard Worker bool is_wait_export_ready(amd_gfx_level gfx_level, const Instruction* instr);
1826*61046927SAndroid Build Coastguard Worker memory_sync_info get_sync_info(const Instruction* instr);
1827*61046927SAndroid Build Coastguard Worker
1828*61046927SAndroid Build Coastguard Worker inline bool
is_dead(const std::vector<uint16_t> & uses,const Instruction * instr)1829*61046927SAndroid Build Coastguard Worker is_dead(const std::vector<uint16_t>& uses, const Instruction* instr)
1830*61046927SAndroid Build Coastguard Worker {
1831*61046927SAndroid Build Coastguard Worker if (instr->definitions.empty() || instr->isBranch() || instr->opcode == aco_opcode::p_startpgm ||
1832*61046927SAndroid Build Coastguard Worker instr->opcode == aco_opcode::p_init_scratch ||
1833*61046927SAndroid Build Coastguard Worker instr->opcode == aco_opcode::p_dual_src_export_gfx11)
1834*61046927SAndroid Build Coastguard Worker return false;
1835*61046927SAndroid Build Coastguard Worker
1836*61046927SAndroid Build Coastguard Worker if (std::any_of(instr->definitions.begin(), instr->definitions.end(),
1837*61046927SAndroid Build Coastguard Worker [&uses](const Definition& def) { return !def.isTemp() || uses[def.tempId()]; }))
1838*61046927SAndroid Build Coastguard Worker return false;
1839*61046927SAndroid Build Coastguard Worker
1840*61046927SAndroid Build Coastguard Worker return !(get_sync_info(instr).semantics & (semantic_volatile | semantic_acqrel));
1841*61046927SAndroid Build Coastguard Worker }
1842*61046927SAndroid Build Coastguard Worker
1843*61046927SAndroid Build Coastguard Worker bool can_use_input_modifiers(amd_gfx_level gfx_level, aco_opcode op, int idx);
1844*61046927SAndroid Build Coastguard Worker bool can_use_opsel(amd_gfx_level gfx_level, aco_opcode op, int idx);
1845*61046927SAndroid Build Coastguard Worker bool instr_is_16bit(amd_gfx_level gfx_level, aco_opcode op);
1846*61046927SAndroid Build Coastguard Worker uint8_t get_gfx11_true16_mask(aco_opcode op);
1847*61046927SAndroid Build Coastguard Worker bool can_use_SDWA(amd_gfx_level gfx_level, const aco_ptr<Instruction>& instr, bool pre_ra);
1848*61046927SAndroid Build Coastguard Worker bool can_use_DPP(amd_gfx_level gfx_level, const aco_ptr<Instruction>& instr, bool dpp8);
1849*61046927SAndroid Build Coastguard Worker bool can_write_m0(const aco_ptr<Instruction>& instr);
1850*61046927SAndroid Build Coastguard Worker /* updates "instr" and returns the old instruction (or NULL if no update was needed) */
1851*61046927SAndroid Build Coastguard Worker aco_ptr<Instruction> convert_to_SDWA(amd_gfx_level gfx_level, aco_ptr<Instruction>& instr);
1852*61046927SAndroid Build Coastguard Worker aco_ptr<Instruction> convert_to_DPP(amd_gfx_level gfx_level, aco_ptr<Instruction>& instr,
1853*61046927SAndroid Build Coastguard Worker bool dpp8);
1854*61046927SAndroid Build Coastguard Worker bool needs_exec_mask(const Instruction* instr);
1855*61046927SAndroid Build Coastguard Worker
1856*61046927SAndroid Build Coastguard Worker aco_opcode get_vcmp_inverse(aco_opcode op);
1857*61046927SAndroid Build Coastguard Worker aco_opcode get_vcmp_swapped(aco_opcode op);
1858*61046927SAndroid Build Coastguard Worker aco_opcode get_vcmpx(aco_opcode op);
1859*61046927SAndroid Build Coastguard Worker bool is_cmpx(aco_opcode op);
1860*61046927SAndroid Build Coastguard Worker
1861*61046927SAndroid Build Coastguard Worker bool can_swap_operands(aco_ptr<Instruction>& instr, aco_opcode* new_op, unsigned idx0 = 0,
1862*61046927SAndroid Build Coastguard Worker unsigned idx1 = 1);
1863*61046927SAndroid Build Coastguard Worker
1864*61046927SAndroid Build Coastguard Worker uint32_t get_reduction_identity(ReduceOp op, unsigned idx);
1865*61046927SAndroid Build Coastguard Worker
1866*61046927SAndroid Build Coastguard Worker unsigned get_mimg_nsa_dwords(const Instruction* instr);
1867*61046927SAndroid Build Coastguard Worker
1868*61046927SAndroid Build Coastguard Worker unsigned get_vopd_opy_start(const Instruction* instr);
1869*61046927SAndroid Build Coastguard Worker
1870*61046927SAndroid Build Coastguard Worker unsigned get_operand_size(aco_ptr<Instruction>& instr, unsigned index);
1871*61046927SAndroid Build Coastguard Worker
1872*61046927SAndroid Build Coastguard Worker bool should_form_clause(const Instruction* a, const Instruction* b);
1873*61046927SAndroid Build Coastguard Worker
1874*61046927SAndroid Build Coastguard Worker enum vmem_type : uint8_t {
1875*61046927SAndroid Build Coastguard Worker vmem_nosampler = 1 << 0,
1876*61046927SAndroid Build Coastguard Worker vmem_sampler = 1 << 1,
1877*61046927SAndroid Build Coastguard Worker vmem_bvh = 1 << 2,
1878*61046927SAndroid Build Coastguard Worker };
1879*61046927SAndroid Build Coastguard Worker
1880*61046927SAndroid Build Coastguard Worker /* VMEM instructions of the same type return in-order. For GFX12+, this determines which counter
1881*61046927SAndroid Build Coastguard Worker * is used.
1882*61046927SAndroid Build Coastguard Worker */
1883*61046927SAndroid Build Coastguard Worker uint8_t get_vmem_type(enum amd_gfx_level gfx_level, Instruction* instr);
1884*61046927SAndroid Build Coastguard Worker
1885*61046927SAndroid Build Coastguard Worker unsigned parse_vdst_wait(Instruction* instr);
1886*61046927SAndroid Build Coastguard Worker
1887*61046927SAndroid Build Coastguard Worker enum block_kind {
1888*61046927SAndroid Build Coastguard Worker /* uniform indicates that leaving this block,
1889*61046927SAndroid Build Coastguard Worker * all actives lanes stay active */
1890*61046927SAndroid Build Coastguard Worker block_kind_uniform = 1 << 0,
1891*61046927SAndroid Build Coastguard Worker block_kind_top_level = 1 << 1,
1892*61046927SAndroid Build Coastguard Worker block_kind_loop_preheader = 1 << 2,
1893*61046927SAndroid Build Coastguard Worker block_kind_loop_header = 1 << 3,
1894*61046927SAndroid Build Coastguard Worker block_kind_loop_exit = 1 << 4,
1895*61046927SAndroid Build Coastguard Worker block_kind_continue = 1 << 5,
1896*61046927SAndroid Build Coastguard Worker block_kind_break = 1 << 6,
1897*61046927SAndroid Build Coastguard Worker block_kind_continue_or_break = 1 << 7,
1898*61046927SAndroid Build Coastguard Worker block_kind_branch = 1 << 8,
1899*61046927SAndroid Build Coastguard Worker block_kind_merge = 1 << 9,
1900*61046927SAndroid Build Coastguard Worker block_kind_invert = 1 << 10,
1901*61046927SAndroid Build Coastguard Worker block_kind_discard_early_exit = 1 << 11,
1902*61046927SAndroid Build Coastguard Worker block_kind_uses_discard = 1 << 12,
1903*61046927SAndroid Build Coastguard Worker block_kind_resume = 1 << 13,
1904*61046927SAndroid Build Coastguard Worker block_kind_export_end = 1 << 14,
1905*61046927SAndroid Build Coastguard Worker block_kind_end_with_regs = 1 << 15,
1906*61046927SAndroid Build Coastguard Worker };
1907*61046927SAndroid Build Coastguard Worker
1908*61046927SAndroid Build Coastguard Worker /* CFG */
1909*61046927SAndroid Build Coastguard Worker struct Block {
1910*61046927SAndroid Build Coastguard Worker using edge_vec = small_vec<uint32_t, 2>;
1911*61046927SAndroid Build Coastguard Worker
1912*61046927SAndroid Build Coastguard Worker float_mode fp_mode;
1913*61046927SAndroid Build Coastguard Worker unsigned index;
1914*61046927SAndroid Build Coastguard Worker unsigned offset = 0;
1915*61046927SAndroid Build Coastguard Worker std::vector<aco_ptr<Instruction>> instructions;
1916*61046927SAndroid Build Coastguard Worker edge_vec logical_preds;
1917*61046927SAndroid Build Coastguard Worker edge_vec linear_preds;
1918*61046927SAndroid Build Coastguard Worker edge_vec logical_succs;
1919*61046927SAndroid Build Coastguard Worker edge_vec linear_succs;
1920*61046927SAndroid Build Coastguard Worker RegisterDemand register_demand = RegisterDemand();
1921*61046927SAndroid Build Coastguard Worker RegisterDemand live_in_demand = RegisterDemand();
1922*61046927SAndroid Build Coastguard Worker uint32_t kind = 0;
1923*61046927SAndroid Build Coastguard Worker int32_t logical_idom = -1;
1924*61046927SAndroid Build Coastguard Worker int32_t linear_idom = -1;
1925*61046927SAndroid Build Coastguard Worker
1926*61046927SAndroid Build Coastguard Worker /* Preorder and postorder traversal indices of the dominance tree. Because a program can have
1927*61046927SAndroid Build Coastguard Worker * several dominance trees (because of block_kind_resume), these start at the block index of the
1928*61046927SAndroid Build Coastguard Worker * root node. */
1929*61046927SAndroid Build Coastguard Worker uint32_t logical_dom_pre_index = 0;
1930*61046927SAndroid Build Coastguard Worker uint32_t logical_dom_post_index = 0;
1931*61046927SAndroid Build Coastguard Worker uint32_t linear_dom_pre_index = 0;
1932*61046927SAndroid Build Coastguard Worker uint32_t linear_dom_post_index = 0;
1933*61046927SAndroid Build Coastguard Worker
1934*61046927SAndroid Build Coastguard Worker uint16_t loop_nest_depth = 0;
1935*61046927SAndroid Build Coastguard Worker uint16_t divergent_if_logical_depth = 0;
1936*61046927SAndroid Build Coastguard Worker uint16_t uniform_if_depth = 0;
1937*61046927SAndroid Build Coastguard Worker
1938*61046927SAndroid Build Coastguard Worker /* this information is needed for predecessors to blocks with phis when
1939*61046927SAndroid Build Coastguard Worker * moving out of ssa */
1940*61046927SAndroid Build Coastguard Worker bool scc_live_out = false;
1941*61046927SAndroid Build Coastguard Worker
BlockBlock1942*61046927SAndroid Build Coastguard Worker Block() : index(0) {}
1943*61046927SAndroid Build Coastguard Worker };
1944*61046927SAndroid Build Coastguard Worker
1945*61046927SAndroid Build Coastguard Worker /*
1946*61046927SAndroid Build Coastguard Worker * Shader stages as provided in Vulkan by the application. Contrast this to HWStage.
1947*61046927SAndroid Build Coastguard Worker */
1948*61046927SAndroid Build Coastguard Worker enum class SWStage : uint16_t {
1949*61046927SAndroid Build Coastguard Worker None = 0,
1950*61046927SAndroid Build Coastguard Worker VS = 1 << 0, /* Vertex Shader */
1951*61046927SAndroid Build Coastguard Worker GS = 1 << 1, /* Geometry Shader */
1952*61046927SAndroid Build Coastguard Worker TCS = 1 << 2, /* Tessellation Control aka Hull Shader */
1953*61046927SAndroid Build Coastguard Worker TES = 1 << 3, /* Tessellation Evaluation aka Domain Shader */
1954*61046927SAndroid Build Coastguard Worker FS = 1 << 4, /* Fragment aka Pixel Shader */
1955*61046927SAndroid Build Coastguard Worker CS = 1 << 5, /* Compute Shader */
1956*61046927SAndroid Build Coastguard Worker TS = 1 << 6, /* Task Shader */
1957*61046927SAndroid Build Coastguard Worker MS = 1 << 7, /* Mesh Shader */
1958*61046927SAndroid Build Coastguard Worker RT = 1 << 8, /* Raytracing Shader */
1959*61046927SAndroid Build Coastguard Worker
1960*61046927SAndroid Build Coastguard Worker /* Stage combinations merged to run on a single HWStage */
1961*61046927SAndroid Build Coastguard Worker VS_GS = VS | GS,
1962*61046927SAndroid Build Coastguard Worker VS_TCS = VS | TCS,
1963*61046927SAndroid Build Coastguard Worker TES_GS = TES | GS,
1964*61046927SAndroid Build Coastguard Worker };
1965*61046927SAndroid Build Coastguard Worker
1966*61046927SAndroid Build Coastguard Worker constexpr SWStage
1967*61046927SAndroid Build Coastguard Worker operator|(SWStage a, SWStage b)
1968*61046927SAndroid Build Coastguard Worker {
1969*61046927SAndroid Build Coastguard Worker return static_cast<SWStage>(static_cast<uint16_t>(a) | static_cast<uint16_t>(b));
1970*61046927SAndroid Build Coastguard Worker }
1971*61046927SAndroid Build Coastguard Worker
1972*61046927SAndroid Build Coastguard Worker /*
1973*61046927SAndroid Build Coastguard Worker * Set of SWStages to be merged into a single shader paired with the
1974*61046927SAndroid Build Coastguard Worker * HWStage it will run on.
1975*61046927SAndroid Build Coastguard Worker */
1976*61046927SAndroid Build Coastguard Worker struct Stage {
1977*61046927SAndroid Build Coastguard Worker constexpr Stage() = default;
1978*61046927SAndroid Build Coastguard Worker
StageStage1979*61046927SAndroid Build Coastguard Worker explicit constexpr Stage(ac_hw_stage hw_, SWStage sw_) : sw(sw_), hw(hw_) {}
1980*61046927SAndroid Build Coastguard Worker
1981*61046927SAndroid Build Coastguard Worker /* Check if the given SWStage is included */
hasStage1982*61046927SAndroid Build Coastguard Worker constexpr bool has(SWStage stage) const
1983*61046927SAndroid Build Coastguard Worker {
1984*61046927SAndroid Build Coastguard Worker return (static_cast<uint16_t>(sw) & static_cast<uint16_t>(stage));
1985*61046927SAndroid Build Coastguard Worker }
1986*61046927SAndroid Build Coastguard Worker
num_sw_stagesStage1987*61046927SAndroid Build Coastguard Worker unsigned num_sw_stages() const { return util_bitcount(static_cast<uint16_t>(sw)); }
1988*61046927SAndroid Build Coastguard Worker
1989*61046927SAndroid Build Coastguard Worker constexpr bool operator==(const Stage& other) const { return sw == other.sw && hw == other.hw; }
1990*61046927SAndroid Build Coastguard Worker
1991*61046927SAndroid Build Coastguard Worker constexpr bool operator!=(const Stage& other) const { return sw != other.sw || hw != other.hw; }
1992*61046927SAndroid Build Coastguard Worker
1993*61046927SAndroid Build Coastguard Worker /* Mask of merged software stages */
1994*61046927SAndroid Build Coastguard Worker SWStage sw = SWStage::None;
1995*61046927SAndroid Build Coastguard Worker
1996*61046927SAndroid Build Coastguard Worker /* Active hardware stage */
1997*61046927SAndroid Build Coastguard Worker ac_hw_stage hw{};
1998*61046927SAndroid Build Coastguard Worker };
1999*61046927SAndroid Build Coastguard Worker
2000*61046927SAndroid Build Coastguard Worker /* possible settings of Program::stage */
2001*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_vs(AC_HW_VERTEX_SHADER, SWStage::VS);
2002*61046927SAndroid Build Coastguard Worker static constexpr Stage fragment_fs(AC_HW_PIXEL_SHADER, SWStage::FS);
2003*61046927SAndroid Build Coastguard Worker static constexpr Stage compute_cs(AC_HW_COMPUTE_SHADER, SWStage::CS);
2004*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_eval_vs(AC_HW_VERTEX_SHADER, SWStage::TES);
2005*61046927SAndroid Build Coastguard Worker /* Mesh shading pipeline */
2006*61046927SAndroid Build Coastguard Worker static constexpr Stage task_cs(AC_HW_COMPUTE_SHADER, SWStage::TS);
2007*61046927SAndroid Build Coastguard Worker static constexpr Stage mesh_ngg(AC_HW_NEXT_GEN_GEOMETRY_SHADER, SWStage::MS);
2008*61046927SAndroid Build Coastguard Worker /* GFX10/NGG */
2009*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_ngg(AC_HW_NEXT_GEN_GEOMETRY_SHADER, SWStage::VS);
2010*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_geometry_ngg(AC_HW_NEXT_GEN_GEOMETRY_SHADER, SWStage::VS_GS);
2011*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_eval_ngg(AC_HW_NEXT_GEN_GEOMETRY_SHADER, SWStage::TES);
2012*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_eval_geometry_ngg(AC_HW_NEXT_GEN_GEOMETRY_SHADER, SWStage::TES_GS);
2013*61046927SAndroid Build Coastguard Worker /* GFX9 (and GFX10 if NGG isn't used) */
2014*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_geometry_gs(AC_HW_LEGACY_GEOMETRY_SHADER, SWStage::VS_GS);
2015*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_tess_control_hs(AC_HW_HULL_SHADER, SWStage::VS_TCS);
2016*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_eval_geometry_gs(AC_HW_LEGACY_GEOMETRY_SHADER, SWStage::TES_GS);
2017*61046927SAndroid Build Coastguard Worker /* pre-GFX9 */
2018*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_ls(AC_HW_LOCAL_SHADER,
2019*61046927SAndroid Build Coastguard Worker SWStage::VS); /* vertex before tessellation control */
2020*61046927SAndroid Build Coastguard Worker static constexpr Stage vertex_es(AC_HW_EXPORT_SHADER, SWStage::VS); /* vertex before geometry */
2021*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_control_hs(AC_HW_HULL_SHADER, SWStage::TCS);
2022*61046927SAndroid Build Coastguard Worker static constexpr Stage tess_eval_es(AC_HW_EXPORT_SHADER,
2023*61046927SAndroid Build Coastguard Worker SWStage::TES); /* tessellation evaluation before geometry */
2024*61046927SAndroid Build Coastguard Worker static constexpr Stage geometry_gs(AC_HW_LEGACY_GEOMETRY_SHADER, SWStage::GS);
2025*61046927SAndroid Build Coastguard Worker /* Raytracing */
2026*61046927SAndroid Build Coastguard Worker static constexpr Stage raytracing_cs(AC_HW_COMPUTE_SHADER, SWStage::RT);
2027*61046927SAndroid Build Coastguard Worker
2028*61046927SAndroid Build Coastguard Worker struct DeviceInfo {
2029*61046927SAndroid Build Coastguard Worker uint16_t lds_encoding_granule;
2030*61046927SAndroid Build Coastguard Worker uint16_t lds_alloc_granule;
2031*61046927SAndroid Build Coastguard Worker uint32_t lds_limit; /* in bytes */
2032*61046927SAndroid Build Coastguard Worker bool has_16bank_lds;
2033*61046927SAndroid Build Coastguard Worker uint16_t physical_sgprs;
2034*61046927SAndroid Build Coastguard Worker uint16_t physical_vgprs;
2035*61046927SAndroid Build Coastguard Worker uint16_t vgpr_limit;
2036*61046927SAndroid Build Coastguard Worker uint16_t sgpr_limit;
2037*61046927SAndroid Build Coastguard Worker uint16_t sgpr_alloc_granule;
2038*61046927SAndroid Build Coastguard Worker uint16_t vgpr_alloc_granule;
2039*61046927SAndroid Build Coastguard Worker unsigned scratch_alloc_granule;
2040*61046927SAndroid Build Coastguard Worker uint16_t max_waves_per_simd;
2041*61046927SAndroid Build Coastguard Worker unsigned simd_per_cu;
2042*61046927SAndroid Build Coastguard Worker bool has_fast_fma32 = false;
2043*61046927SAndroid Build Coastguard Worker bool has_mac_legacy32 = false;
2044*61046927SAndroid Build Coastguard Worker bool has_fmac_legacy32 = false;
2045*61046927SAndroid Build Coastguard Worker bool fused_mad_mix = false;
2046*61046927SAndroid Build Coastguard Worker bool xnack_enabled = false;
2047*61046927SAndroid Build Coastguard Worker bool sram_ecc_enabled = false;
2048*61046927SAndroid Build Coastguard Worker
2049*61046927SAndroid Build Coastguard Worker int16_t scratch_global_offset_min;
2050*61046927SAndroid Build Coastguard Worker int16_t scratch_global_offset_max;
2051*61046927SAndroid Build Coastguard Worker unsigned max_nsa_vgprs;
2052*61046927SAndroid Build Coastguard Worker };
2053*61046927SAndroid Build Coastguard Worker
2054*61046927SAndroid Build Coastguard Worker enum class CompilationProgress {
2055*61046927SAndroid Build Coastguard Worker after_isel,
2056*61046927SAndroid Build Coastguard Worker after_spilling,
2057*61046927SAndroid Build Coastguard Worker after_ra,
2058*61046927SAndroid Build Coastguard Worker after_lower_to_hw,
2059*61046927SAndroid Build Coastguard Worker };
2060*61046927SAndroid Build Coastguard Worker
2061*61046927SAndroid Build Coastguard Worker class Program final {
2062*61046927SAndroid Build Coastguard Worker public:
2063*61046927SAndroid Build Coastguard Worker aco::monotonic_buffer_resource m{65536};
2064*61046927SAndroid Build Coastguard Worker std::vector<Block> blocks;
2065*61046927SAndroid Build Coastguard Worker std::vector<RegClass> temp_rc = {s1};
2066*61046927SAndroid Build Coastguard Worker RegisterDemand max_reg_demand = RegisterDemand();
2067*61046927SAndroid Build Coastguard Worker ac_shader_config* config;
2068*61046927SAndroid Build Coastguard Worker struct aco_shader_info info;
2069*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level;
2070*61046927SAndroid Build Coastguard Worker enum radeon_family family;
2071*61046927SAndroid Build Coastguard Worker DeviceInfo dev;
2072*61046927SAndroid Build Coastguard Worker unsigned wave_size;
2073*61046927SAndroid Build Coastguard Worker RegClass lane_mask;
2074*61046927SAndroid Build Coastguard Worker Stage stage;
2075*61046927SAndroid Build Coastguard Worker bool needs_exact = false; /* there exists an instruction with disable_wqm = true */
2076*61046927SAndroid Build Coastguard Worker bool needs_wqm = false; /* there exists a p_wqm instruction */
2077*61046927SAndroid Build Coastguard Worker bool has_smem_buffer_or_global_loads = false;
2078*61046927SAndroid Build Coastguard Worker bool has_pops_overlapped_waves_wait = false;
2079*61046927SAndroid Build Coastguard Worker bool has_color_exports = false;
2080*61046927SAndroid Build Coastguard Worker bool is_prolog = false;
2081*61046927SAndroid Build Coastguard Worker bool is_epilog = false;
2082*61046927SAndroid Build Coastguard Worker
2083*61046927SAndroid Build Coastguard Worker std::vector<uint8_t> constant_data;
2084*61046927SAndroid Build Coastguard Worker Temp private_segment_buffer;
2085*61046927SAndroid Build Coastguard Worker Temp scratch_offset;
2086*61046927SAndroid Build Coastguard Worker
2087*61046927SAndroid Build Coastguard Worker uint16_t num_waves = 0;
2088*61046927SAndroid Build Coastguard Worker uint16_t min_waves = 0;
2089*61046927SAndroid Build Coastguard Worker unsigned workgroup_size; /* if known; otherwise UINT_MAX */
2090*61046927SAndroid Build Coastguard Worker bool wgp_mode;
2091*61046927SAndroid Build Coastguard Worker
2092*61046927SAndroid Build Coastguard Worker bool needs_vcc = false;
2093*61046927SAndroid Build Coastguard Worker
2094*61046927SAndroid Build Coastguard Worker CompilationProgress progress;
2095*61046927SAndroid Build Coastguard Worker
2096*61046927SAndroid Build Coastguard Worker bool collect_statistics = false;
2097*61046927SAndroid Build Coastguard Worker uint32_t statistics[aco_num_statistics];
2098*61046927SAndroid Build Coastguard Worker
2099*61046927SAndroid Build Coastguard Worker float_mode next_fp_mode;
2100*61046927SAndroid Build Coastguard Worker unsigned next_loop_depth = 0;
2101*61046927SAndroid Build Coastguard Worker unsigned next_divergent_if_logical_depth = 0;
2102*61046927SAndroid Build Coastguard Worker unsigned next_uniform_if_depth = 0;
2103*61046927SAndroid Build Coastguard Worker
2104*61046927SAndroid Build Coastguard Worker std::vector<Definition> args_pending_vmem;
2105*61046927SAndroid Build Coastguard Worker
2106*61046927SAndroid Build Coastguard Worker /* For shader part with previous shader part that has lds access. */
2107*61046927SAndroid Build Coastguard Worker bool pending_lds_access = false;
2108*61046927SAndroid Build Coastguard Worker
2109*61046927SAndroid Build Coastguard Worker struct {
2110*61046927SAndroid Build Coastguard Worker monotonic_buffer_resource memory;
2111*61046927SAndroid Build Coastguard Worker /* live-in temps per block */
2112*61046927SAndroid Build Coastguard Worker std::vector<IDSet> live_in;
2113*61046927SAndroid Build Coastguard Worker } live;
2114*61046927SAndroid Build Coastguard Worker
2115*61046927SAndroid Build Coastguard Worker struct {
2116*61046927SAndroid Build Coastguard Worker FILE* output = stderr;
2117*61046927SAndroid Build Coastguard Worker bool shorten_messages = false;
2118*61046927SAndroid Build Coastguard Worker void (*func)(void* private_data, enum aco_compiler_debug_level level, const char* message);
2119*61046927SAndroid Build Coastguard Worker void* private_data;
2120*61046927SAndroid Build Coastguard Worker } debug;
2121*61046927SAndroid Build Coastguard Worker
allocateId(RegClass rc)2122*61046927SAndroid Build Coastguard Worker uint32_t allocateId(RegClass rc)
2123*61046927SAndroid Build Coastguard Worker {
2124*61046927SAndroid Build Coastguard Worker assert(allocationID <= 16777215);
2125*61046927SAndroid Build Coastguard Worker temp_rc.push_back(rc);
2126*61046927SAndroid Build Coastguard Worker return allocationID++;
2127*61046927SAndroid Build Coastguard Worker }
2128*61046927SAndroid Build Coastguard Worker
allocateRange(unsigned amount)2129*61046927SAndroid Build Coastguard Worker void allocateRange(unsigned amount)
2130*61046927SAndroid Build Coastguard Worker {
2131*61046927SAndroid Build Coastguard Worker assert(allocationID + amount <= 16777216);
2132*61046927SAndroid Build Coastguard Worker temp_rc.resize(temp_rc.size() + amount);
2133*61046927SAndroid Build Coastguard Worker allocationID += amount;
2134*61046927SAndroid Build Coastguard Worker }
2135*61046927SAndroid Build Coastguard Worker
allocateTmp(RegClass rc)2136*61046927SAndroid Build Coastguard Worker Temp allocateTmp(RegClass rc) { return Temp(allocateId(rc), rc); }
2137*61046927SAndroid Build Coastguard Worker
peekAllocationId()2138*61046927SAndroid Build Coastguard Worker uint32_t peekAllocationId() { return allocationID; }
2139*61046927SAndroid Build Coastguard Worker
2140*61046927SAndroid Build Coastguard Worker friend void reindex_ssa(Program* program, bool update_live_out);
2141*61046927SAndroid Build Coastguard Worker
create_and_insert_block()2142*61046927SAndroid Build Coastguard Worker Block* create_and_insert_block()
2143*61046927SAndroid Build Coastguard Worker {
2144*61046927SAndroid Build Coastguard Worker Block block;
2145*61046927SAndroid Build Coastguard Worker return insert_block(std::move(block));
2146*61046927SAndroid Build Coastguard Worker }
2147*61046927SAndroid Build Coastguard Worker
insert_block(Block && block)2148*61046927SAndroid Build Coastguard Worker Block* insert_block(Block&& block)
2149*61046927SAndroid Build Coastguard Worker {
2150*61046927SAndroid Build Coastguard Worker block.index = blocks.size();
2151*61046927SAndroid Build Coastguard Worker block.fp_mode = next_fp_mode;
2152*61046927SAndroid Build Coastguard Worker block.loop_nest_depth = next_loop_depth;
2153*61046927SAndroid Build Coastguard Worker block.divergent_if_logical_depth = next_divergent_if_logical_depth;
2154*61046927SAndroid Build Coastguard Worker block.uniform_if_depth = next_uniform_if_depth;
2155*61046927SAndroid Build Coastguard Worker blocks.emplace_back(std::move(block));
2156*61046927SAndroid Build Coastguard Worker return &blocks.back();
2157*61046927SAndroid Build Coastguard Worker }
2158*61046927SAndroid Build Coastguard Worker
2159*61046927SAndroid Build Coastguard Worker private:
2160*61046927SAndroid Build Coastguard Worker uint32_t allocationID = 1;
2161*61046927SAndroid Build Coastguard Worker };
2162*61046927SAndroid Build Coastguard Worker
2163*61046927SAndroid Build Coastguard Worker struct ra_test_policy {
2164*61046927SAndroid Build Coastguard Worker /* Force RA to always use its pessimistic fallback algorithm */
2165*61046927SAndroid Build Coastguard Worker bool skip_optimistic_path = false;
2166*61046927SAndroid Build Coastguard Worker };
2167*61046927SAndroid Build Coastguard Worker
2168*61046927SAndroid Build Coastguard Worker void init();
2169*61046927SAndroid Build Coastguard Worker
2170*61046927SAndroid Build Coastguard Worker void init_program(Program* program, Stage stage, const struct aco_shader_info* info,
2171*61046927SAndroid Build Coastguard Worker enum amd_gfx_level gfx_level, enum radeon_family family, bool wgp_mode,
2172*61046927SAndroid Build Coastguard Worker ac_shader_config* config);
2173*61046927SAndroid Build Coastguard Worker
2174*61046927SAndroid Build Coastguard Worker void select_program(Program* program, unsigned shader_count, struct nir_shader* const* shaders,
2175*61046927SAndroid Build Coastguard Worker ac_shader_config* config, const struct aco_compiler_options* options,
2176*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info, const struct ac_shader_args* args);
2177*61046927SAndroid Build Coastguard Worker void select_trap_handler_shader(Program* program, struct nir_shader* shader,
2178*61046927SAndroid Build Coastguard Worker ac_shader_config* config,
2179*61046927SAndroid Build Coastguard Worker const struct aco_compiler_options* options,
2180*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info,
2181*61046927SAndroid Build Coastguard Worker const struct ac_shader_args* args);
2182*61046927SAndroid Build Coastguard Worker void select_rt_prolog(Program* program, ac_shader_config* config,
2183*61046927SAndroid Build Coastguard Worker const struct aco_compiler_options* options,
2184*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info, const struct ac_shader_args* in_args,
2185*61046927SAndroid Build Coastguard Worker const struct ac_shader_args* out_args);
2186*61046927SAndroid Build Coastguard Worker void select_vs_prolog(Program* program, const struct aco_vs_prolog_info* pinfo,
2187*61046927SAndroid Build Coastguard Worker ac_shader_config* config, const struct aco_compiler_options* options,
2188*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info, const struct ac_shader_args* args);
2189*61046927SAndroid Build Coastguard Worker
2190*61046927SAndroid Build Coastguard Worker void select_ps_epilog(Program* program, void* pinfo, ac_shader_config* config,
2191*61046927SAndroid Build Coastguard Worker const struct aco_compiler_options* options,
2192*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info, const struct ac_shader_args* args);
2193*61046927SAndroid Build Coastguard Worker
2194*61046927SAndroid Build Coastguard Worker void select_ps_prolog(Program* program, void* pinfo, ac_shader_config* config,
2195*61046927SAndroid Build Coastguard Worker const struct aco_compiler_options* options,
2196*61046927SAndroid Build Coastguard Worker const struct aco_shader_info* info, const struct ac_shader_args* args);
2197*61046927SAndroid Build Coastguard Worker
2198*61046927SAndroid Build Coastguard Worker void lower_phis(Program* program);
2199*61046927SAndroid Build Coastguard Worker void lower_subdword(Program* program);
2200*61046927SAndroid Build Coastguard Worker void calc_min_waves(Program* program);
2201*61046927SAndroid Build Coastguard Worker void update_vgpr_sgpr_demand(Program* program, const RegisterDemand new_demand);
2202*61046927SAndroid Build Coastguard Worker void live_var_analysis(Program* program);
2203*61046927SAndroid Build Coastguard Worker std::vector<uint16_t> dead_code_analysis(Program* program);
2204*61046927SAndroid Build Coastguard Worker void dominator_tree(Program* program);
2205*61046927SAndroid Build Coastguard Worker void insert_exec_mask(Program* program);
2206*61046927SAndroid Build Coastguard Worker void value_numbering(Program* program);
2207*61046927SAndroid Build Coastguard Worker void optimize(Program* program);
2208*61046927SAndroid Build Coastguard Worker void optimize_postRA(Program* program);
2209*61046927SAndroid Build Coastguard Worker void setup_reduce_temp(Program* program);
2210*61046927SAndroid Build Coastguard Worker void lower_to_cssa(Program* program);
2211*61046927SAndroid Build Coastguard Worker void register_allocation(Program* program, ra_test_policy = {});
2212*61046927SAndroid Build Coastguard Worker void ssa_elimination(Program* program);
2213*61046927SAndroid Build Coastguard Worker void lower_to_hw_instr(Program* program);
2214*61046927SAndroid Build Coastguard Worker void schedule_program(Program* program);
2215*61046927SAndroid Build Coastguard Worker void schedule_ilp(Program* program);
2216*61046927SAndroid Build Coastguard Worker void schedule_vopd(Program* program);
2217*61046927SAndroid Build Coastguard Worker void spill(Program* program);
2218*61046927SAndroid Build Coastguard Worker void insert_waitcnt(Program* program);
2219*61046927SAndroid Build Coastguard Worker void insert_delay_alu(Program* program);
2220*61046927SAndroid Build Coastguard Worker void combine_delay_alu(Program* program);
2221*61046927SAndroid Build Coastguard Worker bool dealloc_vgprs(Program* program);
2222*61046927SAndroid Build Coastguard Worker void insert_NOPs(Program* program);
2223*61046927SAndroid Build Coastguard Worker void form_hard_clauses(Program* program);
2224*61046927SAndroid Build Coastguard Worker unsigned emit_program(Program* program, std::vector<uint32_t>& code,
2225*61046927SAndroid Build Coastguard Worker std::vector<struct aco_symbol>* symbols = NULL, bool append_endpgm = true);
2226*61046927SAndroid Build Coastguard Worker /**
2227*61046927SAndroid Build Coastguard Worker * Returns true if print_asm can disassemble the given program for the current build/runtime
2228*61046927SAndroid Build Coastguard Worker * configuration
2229*61046927SAndroid Build Coastguard Worker */
2230*61046927SAndroid Build Coastguard Worker bool check_print_asm_support(Program* program);
2231*61046927SAndroid Build Coastguard Worker bool print_asm(Program* program, std::vector<uint32_t>& binary, unsigned exec_size, FILE* output);
2232*61046927SAndroid Build Coastguard Worker bool validate_ir(Program* program);
2233*61046927SAndroid Build Coastguard Worker bool validate_cfg(Program* program);
2234*61046927SAndroid Build Coastguard Worker bool validate_ra(Program* program);
2235*61046927SAndroid Build Coastguard Worker bool validate_live_vars(Program* program);
2236*61046927SAndroid Build Coastguard Worker
2237*61046927SAndroid Build Coastguard Worker void collect_presched_stats(Program* program);
2238*61046927SAndroid Build Coastguard Worker void collect_preasm_stats(Program* program);
2239*61046927SAndroid Build Coastguard Worker void collect_postasm_stats(Program* program, const std::vector<uint32_t>& code);
2240*61046927SAndroid Build Coastguard Worker
2241*61046927SAndroid Build Coastguard Worker struct Instruction_cycle_info {
2242*61046927SAndroid Build Coastguard Worker /* Latency until the result is ready (if not needing a waitcnt) */
2243*61046927SAndroid Build Coastguard Worker unsigned latency;
2244*61046927SAndroid Build Coastguard Worker
2245*61046927SAndroid Build Coastguard Worker /* How many cycles issuing this instruction takes (i.e. cycles till the next instruction can be
2246*61046927SAndroid Build Coastguard Worker * issued)*/
2247*61046927SAndroid Build Coastguard Worker unsigned issue_cycles;
2248*61046927SAndroid Build Coastguard Worker };
2249*61046927SAndroid Build Coastguard Worker
2250*61046927SAndroid Build Coastguard Worker Instruction_cycle_info get_cycle_info(const Program& program, const Instruction& instr);
2251*61046927SAndroid Build Coastguard Worker
2252*61046927SAndroid Build Coastguard Worker enum print_flags {
2253*61046927SAndroid Build Coastguard Worker print_no_ssa = 0x1,
2254*61046927SAndroid Build Coastguard Worker print_perf_info = 0x2,
2255*61046927SAndroid Build Coastguard Worker print_kill = 0x4,
2256*61046927SAndroid Build Coastguard Worker print_live_vars = 0x8,
2257*61046927SAndroid Build Coastguard Worker };
2258*61046927SAndroid Build Coastguard Worker
2259*61046927SAndroid Build Coastguard Worker void aco_print_operand(const Operand* operand, FILE* output, unsigned flags = 0);
2260*61046927SAndroid Build Coastguard Worker void aco_print_instr(enum amd_gfx_level gfx_level, const Instruction* instr, FILE* output,
2261*61046927SAndroid Build Coastguard Worker unsigned flags = 0);
2262*61046927SAndroid Build Coastguard Worker void aco_print_program(const Program* program, FILE* output, unsigned flags = 0);
2263*61046927SAndroid Build Coastguard Worker
2264*61046927SAndroid Build Coastguard Worker void _aco_err(Program* program, const char* file, unsigned line, const char* fmt, ...);
2265*61046927SAndroid Build Coastguard Worker
2266*61046927SAndroid Build Coastguard Worker #define aco_err(program, ...) _aco_err(program, __FILE__, __LINE__, __VA_ARGS__)
2267*61046927SAndroid Build Coastguard Worker
2268*61046927SAndroid Build Coastguard Worker int get_op_fixed_to_def(Instruction* instr);
2269*61046927SAndroid Build Coastguard Worker
2270*61046927SAndroid Build Coastguard Worker /* utilities for dealing with register demand */
2271*61046927SAndroid Build Coastguard Worker RegisterDemand get_live_changes(Instruction* instr);
2272*61046927SAndroid Build Coastguard Worker RegisterDemand get_temp_registers(Instruction* instr);
2273*61046927SAndroid Build Coastguard Worker
2274*61046927SAndroid Build Coastguard Worker /* number of sgprs that need to be allocated but might notbe addressable as s0-s105 */
2275*61046927SAndroid Build Coastguard Worker uint16_t get_extra_sgprs(Program* program);
2276*61046927SAndroid Build Coastguard Worker
2277*61046927SAndroid Build Coastguard Worker /* adjust num_waves for workgroup size and LDS limits */
2278*61046927SAndroid Build Coastguard Worker uint16_t max_suitable_waves(Program* program, uint16_t waves);
2279*61046927SAndroid Build Coastguard Worker
2280*61046927SAndroid Build Coastguard Worker /* get number of sgprs/vgprs allocated required to address a number of sgprs/vgprs */
2281*61046927SAndroid Build Coastguard Worker uint16_t get_sgpr_alloc(Program* program, uint16_t addressable_sgprs);
2282*61046927SAndroid Build Coastguard Worker uint16_t get_vgpr_alloc(Program* program, uint16_t addressable_vgprs);
2283*61046927SAndroid Build Coastguard Worker
2284*61046927SAndroid Build Coastguard Worker /* return number of addressable sgprs/vgprs for max_waves */
2285*61046927SAndroid Build Coastguard Worker uint16_t get_addr_sgpr_from_waves(Program* program, uint16_t max_waves);
2286*61046927SAndroid Build Coastguard Worker uint16_t get_addr_vgpr_from_waves(Program* program, uint16_t max_waves);
2287*61046927SAndroid Build Coastguard Worker
2288*61046927SAndroid Build Coastguard Worker bool uses_scratch(Program* program);
2289*61046927SAndroid Build Coastguard Worker
2290*61046927SAndroid Build Coastguard Worker inline bool
dominates_logical(const Block & parent,const Block & child)2291*61046927SAndroid Build Coastguard Worker dominates_logical(const Block& parent, const Block& child)
2292*61046927SAndroid Build Coastguard Worker {
2293*61046927SAndroid Build Coastguard Worker return child.logical_dom_pre_index >= parent.logical_dom_pre_index &&
2294*61046927SAndroid Build Coastguard Worker child.logical_dom_post_index <= parent.logical_dom_post_index;
2295*61046927SAndroid Build Coastguard Worker }
2296*61046927SAndroid Build Coastguard Worker
2297*61046927SAndroid Build Coastguard Worker inline bool
dominates_linear(const Block & parent,const Block & child)2298*61046927SAndroid Build Coastguard Worker dominates_linear(const Block& parent, const Block& child)
2299*61046927SAndroid Build Coastguard Worker {
2300*61046927SAndroid Build Coastguard Worker return child.linear_dom_pre_index >= parent.linear_dom_pre_index &&
2301*61046927SAndroid Build Coastguard Worker child.linear_dom_post_index <= parent.linear_dom_post_index;
2302*61046927SAndroid Build Coastguard Worker }
2303*61046927SAndroid Build Coastguard Worker
2304*61046927SAndroid Build Coastguard Worker typedef struct {
2305*61046927SAndroid Build Coastguard Worker const int16_t opcode_gfx7[static_cast<int>(aco_opcode::num_opcodes)];
2306*61046927SAndroid Build Coastguard Worker const int16_t opcode_gfx9[static_cast<int>(aco_opcode::num_opcodes)];
2307*61046927SAndroid Build Coastguard Worker const int16_t opcode_gfx10[static_cast<int>(aco_opcode::num_opcodes)];
2308*61046927SAndroid Build Coastguard Worker const int16_t opcode_gfx11[static_cast<int>(aco_opcode::num_opcodes)];
2309*61046927SAndroid Build Coastguard Worker const int16_t opcode_gfx12[static_cast<int>(aco_opcode::num_opcodes)];
2310*61046927SAndroid Build Coastguard Worker const std::bitset<static_cast<int>(aco_opcode::num_opcodes)> can_use_input_modifiers;
2311*61046927SAndroid Build Coastguard Worker const std::bitset<static_cast<int>(aco_opcode::num_opcodes)> can_use_output_modifiers;
2312*61046927SAndroid Build Coastguard Worker const std::bitset<static_cast<int>(aco_opcode::num_opcodes)> is_atomic;
2313*61046927SAndroid Build Coastguard Worker const char* name[static_cast<int>(aco_opcode::num_opcodes)];
2314*61046927SAndroid Build Coastguard Worker const aco::Format format[static_cast<int>(aco_opcode::num_opcodes)];
2315*61046927SAndroid Build Coastguard Worker /* sizes used for input/output modifiers and constants */
2316*61046927SAndroid Build Coastguard Worker const unsigned operand_size[static_cast<int>(aco_opcode::num_opcodes)];
2317*61046927SAndroid Build Coastguard Worker const instr_class classes[static_cast<int>(aco_opcode::num_opcodes)];
2318*61046927SAndroid Build Coastguard Worker const uint32_t definitions[static_cast<int>(aco_opcode::num_opcodes)];
2319*61046927SAndroid Build Coastguard Worker const uint32_t operands[static_cast<int>(aco_opcode::num_opcodes)];
2320*61046927SAndroid Build Coastguard Worker } Info;
2321*61046927SAndroid Build Coastguard Worker
2322*61046927SAndroid Build Coastguard Worker extern const Info instr_info;
2323*61046927SAndroid Build Coastguard Worker
2324*61046927SAndroid Build Coastguard Worker } // namespace aco
2325*61046927SAndroid Build Coastguard Worker
2326*61046927SAndroid Build Coastguard Worker #endif /* ACO_IR_H */
2327