Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/gp/gpir.h
4574 views
1
/*
2
* Copyright (c) 2017 Lima Project
3
* Copyright (c) 2013 Connor Abbott
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to deal
7
* in the Software without restriction, including without limitation the rights
8
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
* copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
* THE SOFTWARE.
22
*
23
*/
24
25
#ifndef LIMA_IR_GP_GPIR_H
26
#define LIMA_IR_GP_GPIR_H
27
28
#include "util/list.h"
29
#include "util/u_math.h"
30
31
#include "ir/lima_ir.h"
32
33
/* list of operations that a node can do. */
34
typedef enum {
35
gpir_op_mov,
36
37
/* mul ops */
38
gpir_op_mul,
39
gpir_op_select,
40
gpir_op_complex1,
41
gpir_op_complex2,
42
43
/* add ops */
44
gpir_op_add,
45
gpir_op_floor,
46
gpir_op_sign,
47
gpir_op_ge,
48
gpir_op_lt,
49
gpir_op_min,
50
gpir_op_max,
51
gpir_op_abs,
52
gpir_op_not,
53
54
/* mul/add ops */
55
gpir_op_neg,
56
57
/* passthrough ops */
58
gpir_op_clamp_const,
59
gpir_op_preexp2,
60
gpir_op_postlog2,
61
62
/* complex ops */
63
gpir_op_exp2_impl,
64
gpir_op_log2_impl,
65
gpir_op_rcp_impl,
66
gpir_op_rsqrt_impl,
67
68
/* load/store ops */
69
gpir_op_load_uniform,
70
gpir_op_load_temp,
71
gpir_op_load_attribute,
72
gpir_op_load_reg,
73
gpir_op_store_temp,
74
gpir_op_store_reg,
75
gpir_op_store_varying,
76
gpir_op_store_temp_load_off0,
77
gpir_op_store_temp_load_off1,
78
gpir_op_store_temp_load_off2,
79
80
/* branch */
81
gpir_op_branch_cond,
82
83
/* const (emulated) */
84
gpir_op_const,
85
86
/* emulated ops */
87
gpir_op_exp2,
88
gpir_op_log2,
89
gpir_op_rcp,
90
gpir_op_rsqrt,
91
gpir_op_ceil,
92
gpir_op_exp,
93
gpir_op_log,
94
gpir_op_sin,
95
gpir_op_cos,
96
gpir_op_tan,
97
gpir_op_branch_uncond,
98
gpir_op_eq,
99
gpir_op_ne,
100
101
/* auxiliary ops */
102
gpir_op_dummy_f,
103
gpir_op_dummy_m,
104
105
gpir_op_num,
106
} gpir_op;
107
108
typedef enum {
109
gpir_node_type_alu,
110
gpir_node_type_const,
111
gpir_node_type_load,
112
gpir_node_type_store,
113
gpir_node_type_branch,
114
} gpir_node_type;
115
116
typedef struct {
117
char *name;
118
bool dest_neg;
119
bool src_neg[4];
120
int *slots;
121
gpir_node_type type;
122
bool spillless;
123
bool schedule_first;
124
bool may_consume_two_slots;
125
} gpir_op_info;
126
127
extern const gpir_op_info gpir_op_infos[];
128
129
typedef struct {
130
enum {
131
GPIR_DEP_INPUT, /* def is the input of use */
132
GPIR_DEP_OFFSET, /* def is the offset of use (i.e. temp store) */
133
GPIR_DEP_READ_AFTER_WRITE,
134
GPIR_DEP_WRITE_AFTER_READ,
135
} type;
136
137
/* node execute before succ */
138
struct gpir_node *pred;
139
/* node execute after pred */
140
struct gpir_node *succ;
141
142
/* for node pred_list */
143
struct list_head pred_link;
144
/* for ndoe succ_list */
145
struct list_head succ_link;
146
} gpir_dep;
147
148
struct gpir_instr;
149
struct gpir_store_node;
150
151
typedef struct gpir_node {
152
struct list_head list;
153
gpir_op op;
154
gpir_node_type type;
155
int index;
156
char name[16];
157
bool printed;
158
struct gpir_block *block;
159
160
/* for nodes relationship */
161
/* for node who uses this node (successor) */
162
struct list_head succ_list;
163
/* for node this node uses (predecessor) */
164
struct list_head pred_list;
165
166
/* for scheduler and regalloc */
167
int value_reg;
168
union {
169
struct {
170
struct gpir_instr *instr;
171
struct gpir_store_node *physreg_store;
172
int pos;
173
int dist;
174
int index;
175
bool ready;
176
bool inserted;
177
bool max_node, next_max_node;
178
bool complex_allowed;
179
} sched;
180
struct {
181
int parent_index;
182
float reg_pressure;
183
int est;
184
bool scheduled;
185
} rsched;
186
struct {
187
float index;
188
struct gpir_node *last;
189
} vreg;
190
struct {
191
int index;
192
} preg;
193
};
194
} gpir_node;
195
196
typedef struct {
197
gpir_node node;
198
199
gpir_node *children[3];
200
bool children_negate[3];
201
int num_child;
202
203
bool dest_negate;
204
} gpir_alu_node;
205
206
typedef struct {
207
gpir_node node;
208
union fi value;
209
} gpir_const_node;
210
211
typedef struct {
212
int index;
213
struct list_head list;
214
} gpir_reg;
215
216
typedef struct {
217
gpir_node node;
218
219
unsigned index;
220
unsigned component;
221
222
gpir_reg *reg;
223
struct list_head reg_link;
224
} gpir_load_node;
225
226
typedef struct gpir_store_node {
227
gpir_node node;
228
229
unsigned index;
230
unsigned component;
231
gpir_node *child;
232
233
gpir_reg *reg;
234
} gpir_store_node;
235
236
enum gpir_instr_slot {
237
GPIR_INSTR_SLOT_MUL0,
238
GPIR_INSTR_SLOT_MUL1,
239
GPIR_INSTR_SLOT_ADD0,
240
GPIR_INSTR_SLOT_ADD1,
241
GPIR_INSTR_SLOT_PASS,
242
GPIR_INSTR_SLOT_COMPLEX,
243
GPIR_INSTR_SLOT_REG0_LOAD0,
244
GPIR_INSTR_SLOT_REG0_LOAD1,
245
GPIR_INSTR_SLOT_REG0_LOAD2,
246
GPIR_INSTR_SLOT_REG0_LOAD3,
247
GPIR_INSTR_SLOT_REG1_LOAD0,
248
GPIR_INSTR_SLOT_REG1_LOAD1,
249
GPIR_INSTR_SLOT_REG1_LOAD2,
250
GPIR_INSTR_SLOT_REG1_LOAD3,
251
GPIR_INSTR_SLOT_MEM_LOAD0,
252
GPIR_INSTR_SLOT_MEM_LOAD1,
253
GPIR_INSTR_SLOT_MEM_LOAD2,
254
GPIR_INSTR_SLOT_MEM_LOAD3,
255
GPIR_INSTR_SLOT_STORE0,
256
GPIR_INSTR_SLOT_STORE1,
257
GPIR_INSTR_SLOT_STORE2,
258
GPIR_INSTR_SLOT_STORE3,
259
GPIR_INSTR_SLOT_NUM,
260
GPIR_INSTR_SLOT_END,
261
GPIR_INSTR_SLOT_ALU_BEGIN = GPIR_INSTR_SLOT_MUL0,
262
GPIR_INSTR_SLOT_ALU_END = GPIR_INSTR_SLOT_COMPLEX,
263
GPIR_INSTR_SLOT_DIST_TWO_BEGIN = GPIR_INSTR_SLOT_MUL0,
264
GPIR_INSTR_SLOT_DIST_TWO_END = GPIR_INSTR_SLOT_PASS,
265
};
266
267
typedef struct gpir_instr {
268
int index;
269
struct list_head list;
270
271
gpir_node *slots[GPIR_INSTR_SLOT_NUM];
272
273
/* The number of ALU slots free for moves. */
274
int alu_num_slot_free;
275
276
/* The number of ALU slots free for moves, except for the complex slot. */
277
int alu_non_cplx_slot_free;
278
279
/* We need to make sure that we can insert moves in the following cases:
280
* (1) There was a use of a value two cycles ago.
281
* (2) There were more than 5 uses of a value 1 cycle ago (or else we can't
282
* possibly satisfy (1) for the next cycle).
283
* (3) There is a store instruction scheduled, but not its child.
284
*
285
* The complex slot cannot be used for a move in case (1), since it only
286
* has a FIFO depth of 1, but it can be used for (2) as well as (3) as long
287
* as the uses aren't in certain slots. It turns out that we don't have to
288
* worry about nodes that can't use the complex slot for (2), since there
289
* are at most 4 uses 1 cycle ago that can't use the complex slot, but we
290
* do have to worry about (3). This means tracking stores whose children
291
* cannot be in the complex slot. In order to ensure that we have enough
292
* space for all three, we maintain the following invariants:
293
*
294
* (1) alu_num_slot_free >= alu_num_slot_needed_by_store +
295
* alu_num_slot_needed_by_max +
296
* max(alu_num_unscheduled_next_max - alu_max_allowed_next_max, 0)
297
* (2) alu_non_cplx_slot_free >= alu_num_slot_needed_by_max +
298
* alu_num_slot_needed_by_non_cplx_store
299
*
300
* alu_max_allowed_next_max is normally 5 (since there can be at most 5 max
301
* nodes for the next instruction) but when there is a complex1 node in
302
* this instruction it reduces to 4 to reserve a slot for complex2 in the
303
* next instruction.
304
*/
305
int alu_num_slot_needed_by_store;
306
int alu_num_slot_needed_by_non_cplx_store;
307
int alu_num_slot_needed_by_max;
308
int alu_num_unscheduled_next_max;
309
int alu_max_allowed_next_max;
310
311
/* Used to communicate to the scheduler how many slots need to be cleared
312
* up in order to satisfy the invariants.
313
*/
314
int slot_difference;
315
int non_cplx_slot_difference;
316
317
int reg0_use_count;
318
bool reg0_is_attr;
319
int reg0_index;
320
321
int reg1_use_count;
322
int reg1_index;
323
324
int mem_use_count;
325
bool mem_is_temp;
326
int mem_index;
327
328
enum {
329
GPIR_INSTR_STORE_NONE,
330
GPIR_INSTR_STORE_VARYING,
331
GPIR_INSTR_STORE_REG,
332
GPIR_INSTR_STORE_TEMP,
333
} store_content[2];
334
int store_index[2];
335
} gpir_instr;
336
337
typedef struct gpir_block {
338
struct list_head list;
339
struct list_head node_list;
340
struct list_head instr_list;
341
struct gpir_compiler *comp;
342
343
struct gpir_block *successors[2];
344
struct list_head predecessors;
345
struct list_head predecessors_node;
346
347
/* for regalloc */
348
349
/* The set of live registers, i.e. registers whose value may be used
350
* eventually, at the beginning of the block.
351
*/
352
BITSET_WORD *live_in;
353
354
/* Set of live registers at the end of the block. */
355
BITSET_WORD *live_out;
356
357
/* Set of registers that may have a value defined at the end of the
358
* block.
359
*/
360
BITSET_WORD *def_out;
361
362
/* After register allocation, the set of live physical registers at the end
363
* of the block. Needed for scheduling.
364
*/
365
uint64_t live_out_phys;
366
367
/* For codegen, the offset in the final program. */
368
unsigned instr_offset;
369
370
/* for scheduler */
371
union {
372
struct {
373
int instr_index;
374
} sched;
375
struct {
376
int node_index;
377
} rsched;
378
};
379
} gpir_block;
380
381
typedef struct {
382
gpir_node node;
383
gpir_block *dest;
384
gpir_node *cond;
385
} gpir_branch_node;
386
387
struct lima_vs_compiled_shader;
388
389
#define GPIR_VECTOR_SSA_VIEWPORT_SCALE 0
390
#define GPIR_VECTOR_SSA_VIEWPORT_OFFSET 1
391
#define GPIR_VECTOR_SSA_NUM 2
392
393
typedef struct gpir_compiler {
394
struct list_head block_list;
395
int cur_index;
396
397
/* Find the gpir node for a given NIR SSA def. */
398
gpir_node **node_for_ssa;
399
400
/* Find the gpir node for a given NIR register. */
401
gpir_node **node_for_reg;
402
403
/* Find the gpir register for a given NIR SSA def. */
404
gpir_reg **reg_for_ssa;
405
406
/* Find the gpir register for a given NIR register. */
407
gpir_reg **reg_for_reg;
408
409
/* gpir block for NIR block. */
410
gpir_block **blocks;
411
412
/* for physical reg */
413
struct list_head reg_list;
414
int cur_reg;
415
416
/* lookup for vector ssa */
417
struct {
418
int ssa;
419
gpir_node *nodes[4];
420
} vector_ssa[GPIR_VECTOR_SSA_NUM];
421
422
struct lima_vs_compiled_shader *prog;
423
int constant_base;
424
425
/* shaderdb */
426
int num_instr;
427
int num_loops;
428
int num_spills;
429
int num_fills;
430
} gpir_compiler;
431
432
#define GPIR_VALUE_REG_NUM 11
433
#define GPIR_PHYSICAL_REG_NUM 64
434
435
void *gpir_node_create(gpir_block *block, gpir_op op);
436
gpir_dep *gpir_node_add_dep(gpir_node *succ, gpir_node *pred, int type);
437
void gpir_node_remove_dep(gpir_node *succ, gpir_node *pred);
438
void gpir_node_replace_succ(gpir_node *dst, gpir_node *src);
439
void gpir_node_replace_pred(gpir_dep *dep, gpir_node *new_pred);
440
void gpir_node_replace_child(gpir_node *parent, gpir_node *old_child, gpir_node *new_child);
441
void gpir_node_insert_child(gpir_node *parent, gpir_node *child, gpir_node *insert_child);
442
void gpir_node_delete(gpir_node *node);
443
void gpir_node_print_prog_dep(gpir_compiler *comp);
444
void gpir_node_print_prog_seq(gpir_compiler *comp);
445
446
#define gpir_node_foreach_succ(node, dep) \
447
list_for_each_entry(gpir_dep, dep, &node->succ_list, succ_link)
448
#define gpir_node_foreach_succ_safe(node, dep) \
449
list_for_each_entry_safe(gpir_dep, dep, &node->succ_list, succ_link)
450
#define gpir_node_foreach_pred(node, dep) \
451
list_for_each_entry(gpir_dep, dep, &node->pred_list, pred_link)
452
#define gpir_node_foreach_pred_safe(node, dep) \
453
list_for_each_entry_safe(gpir_dep, dep, &node->pred_list, pred_link)
454
455
static inline bool gpir_node_is_root(gpir_node *node)
456
{
457
return list_is_empty(&node->succ_list);
458
}
459
460
static inline bool gpir_node_is_leaf(gpir_node *node)
461
{
462
return list_is_empty(&node->pred_list);
463
}
464
465
#define gpir_node_to_alu(node) ((gpir_alu_node *)(node))
466
#define gpir_node_to_const(node) ((gpir_const_node *)(node))
467
#define gpir_node_to_load(node) ((gpir_load_node *)(node))
468
#define gpir_node_to_store(node) ((gpir_store_node *)(node))
469
#define gpir_node_to_branch(node) ((gpir_branch_node *)(node))
470
471
gpir_instr *gpir_instr_create(gpir_block *block);
472
bool gpir_instr_try_insert_node(gpir_instr *instr, gpir_node *node);
473
void gpir_instr_remove_node(gpir_instr *instr, gpir_node *node);
474
void gpir_instr_print_prog(gpir_compiler *comp);
475
476
bool gpir_codegen_acc_same_op(gpir_op op1, gpir_op op2);
477
478
bool gpir_optimize(gpir_compiler *comp);
479
bool gpir_pre_rsched_lower_prog(gpir_compiler *comp);
480
bool gpir_reduce_reg_pressure_schedule_prog(gpir_compiler *comp);
481
bool gpir_regalloc_prog(gpir_compiler *comp);
482
bool gpir_schedule_prog(gpir_compiler *comp);
483
bool gpir_codegen_prog(gpir_compiler *comp);
484
485
gpir_reg *gpir_create_reg(gpir_compiler *comp);
486
487
#endif
488
489