xref: /aosp_15_r20/external/mesa3d/src/amd/compiler/aco_ir.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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