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. */
34typedef 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
108typedef 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
116typedef 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 may_consume_two_slots;
124} gpir_op_info;
125
126extern const gpir_op_info gpir_op_infos[];
127
128typedef struct {
129   enum {
130      GPIR_DEP_INPUT,     /* def is the input of use */
131      GPIR_DEP_OFFSET,    /* def is the offset of use (i.e. temp store) */
132      GPIR_DEP_READ_AFTER_WRITE,
133      GPIR_DEP_WRITE_AFTER_READ,
134      GPIR_DEP_VREG_READ_AFTER_WRITE,
135      GPIR_DEP_VREG_WRITE_AFTER_READ,
136   } type;
137
138   /* node execute before succ */
139   struct gpir_node *pred;
140   /* node execute after pred */
141   struct gpir_node *succ;
142
143   /* for node pred_list */
144   struct list_head pred_link;
145   /* for ndoe succ_list */
146   struct list_head succ_link;
147} gpir_dep;
148
149typedef struct gpir_node {
150   struct list_head list;
151   gpir_op op;
152   gpir_node_type type;
153   int index;
154   char name[16];
155   bool printed;
156   struct gpir_block *block;
157
158   /* for nodes relationship */
159   /* for node who uses this node (successor) */
160   struct list_head succ_list;
161   /* for node this node uses (predecessor) */
162   struct list_head pred_list;
163
164   /* for scheduler and regalloc */
165   int value_reg;
166   union {
167      struct {
168         int instr;
169         int pos;
170         int dist;
171         int index;
172         bool ready;
173         bool inserted;
174      } sched;
175      struct {
176         int parent_index;
177         float reg_pressure;
178         int est;
179         bool scheduled;
180      } rsched;
181      struct {
182         float index;
183         struct gpir_node *last;
184      } vreg;
185      struct {
186         int index;
187      } preg;
188   };
189} gpir_node;
190
191typedef struct {
192   gpir_node node;
193
194   gpir_node *children[3];
195   bool children_negate[3];
196   int num_child;
197
198   bool dest_negate;
199} gpir_alu_node;
200
201typedef struct {
202   gpir_node node;
203   union fi value;
204} gpir_const_node;
205
206typedef struct {
207   int index;
208   struct list_head list;
209
210   struct list_head defs_list;
211   struct list_head uses_list;
212
213   int start, end;
214} gpir_reg;
215
216typedef 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
226typedef struct {
227   gpir_node node;
228
229   unsigned index;
230   unsigned component;
231   gpir_node *child;
232
233   gpir_reg *reg;
234   struct list_head reg_link;
235} gpir_store_node;
236
237enum gpir_instr_slot {
238   GPIR_INSTR_SLOT_MUL0,
239   GPIR_INSTR_SLOT_MUL1,
240   GPIR_INSTR_SLOT_ADD0,
241   GPIR_INSTR_SLOT_ADD1,
242   GPIR_INSTR_SLOT_PASS,
243   GPIR_INSTR_SLOT_COMPLEX,
244   GPIR_INSTR_SLOT_BRANCH,
245   GPIR_INSTR_SLOT_REG0_LOAD0,
246   GPIR_INSTR_SLOT_REG0_LOAD1,
247   GPIR_INSTR_SLOT_REG0_LOAD2,
248   GPIR_INSTR_SLOT_REG0_LOAD3,
249   GPIR_INSTR_SLOT_REG1_LOAD0,
250   GPIR_INSTR_SLOT_REG1_LOAD1,
251   GPIR_INSTR_SLOT_REG1_LOAD2,
252   GPIR_INSTR_SLOT_REG1_LOAD3,
253   GPIR_INSTR_SLOT_MEM_LOAD0,
254   GPIR_INSTR_SLOT_MEM_LOAD1,
255   GPIR_INSTR_SLOT_MEM_LOAD2,
256   GPIR_INSTR_SLOT_MEM_LOAD3,
257   GPIR_INSTR_SLOT_STORE0,
258   GPIR_INSTR_SLOT_STORE1,
259   GPIR_INSTR_SLOT_STORE2,
260   GPIR_INSTR_SLOT_STORE3,
261   GPIR_INSTR_SLOT_NUM,
262   GPIR_INSTR_SLOT_END,
263   GPIR_INSTR_SLOT_ALU_BEGIN      = GPIR_INSTR_SLOT_MUL0,
264   GPIR_INSTR_SLOT_ALU_END        = GPIR_INSTR_SLOT_COMPLEX,
265   GPIR_INSTR_SLOT_DIST_TWO_BEGIN = GPIR_INSTR_SLOT_MUL0,
266   GPIR_INSTR_SLOT_DIST_TWO_END   = GPIR_INSTR_SLOT_PASS,
267};
268
269typedef struct {
270   int index;
271   struct list_head list;
272
273   gpir_node *slots[GPIR_INSTR_SLOT_NUM];
274
275   int alu_num_slot_free;
276   int alu_num_slot_needed_by_store;
277
278   int reg0_use_count;
279   bool reg0_is_attr;
280   int reg0_index;
281
282   int reg1_use_count;
283   int reg1_index;
284
285   int mem_use_count;
286   bool mem_is_temp;
287   int mem_index;
288
289   enum {
290      GPIR_INSTR_STORE_NONE,
291      GPIR_INSTR_STORE_VARYING,
292      GPIR_INSTR_STORE_REG,
293      GPIR_INSTR_STORE_TEMP,
294   } store_content[2];
295   int store_index[2];
296} gpir_instr;
297
298typedef struct gpir_block {
299   struct list_head list;
300   struct list_head node_list;
301   struct list_head instr_list;
302   struct gpir_compiler *comp;
303
304   /* for scheduler */
305   union {
306      struct {
307         int instr_index;
308      } sched;
309      struct {
310         int node_index;
311      } rsched;
312   };
313} gpir_block;
314
315typedef struct {
316   gpir_node node;
317   gpir_block *dest;
318} gpir_branch_node;
319
320struct lima_vs_shader_state;
321
322typedef struct gpir_compiler {
323   struct list_head block_list;
324   int cur_index;
325
326   /* array for searching ssa node */
327   gpir_node **var_nodes;
328
329   /* for physical reg */
330   struct list_head reg_list;
331   int cur_reg;
332
333   struct lima_vs_shader_state *prog;
334   int constant_base;
335} gpir_compiler;
336
337#define GPIR_VALUE_REG_NUM 11
338#define GPIR_PHYSICAL_REG_NUM 64
339
340void *gpir_node_create(gpir_block *block, gpir_op op);
341gpir_dep *gpir_node_add_dep(gpir_node *succ, gpir_node *pred, int type);
342void gpir_node_remove_dep(gpir_node *succ, gpir_node *pred);
343void gpir_node_replace_succ(gpir_node *dst, gpir_node *src);
344void gpir_node_replace_pred(gpir_dep *dep, gpir_node *new_pred);
345void gpir_node_replace_child(gpir_node *parent, gpir_node *old_child, gpir_node *new_child);
346void gpir_node_insert_child(gpir_node *parent, gpir_node *child, gpir_node *insert_child);
347void gpir_node_delete(gpir_node *node);
348void gpir_node_print_prog_dep(gpir_compiler *comp);
349void gpir_node_print_prog_seq(gpir_compiler *comp);
350
351#define gpir_node_foreach_succ(node, dep) \
352   list_for_each_entry(gpir_dep, dep, &node->succ_list, succ_link)
353#define gpir_node_foreach_succ_safe(node, dep) \
354   list_for_each_entry_safe(gpir_dep, dep, &node->succ_list, succ_link)
355#define gpir_node_foreach_pred(node, dep) \
356   list_for_each_entry(gpir_dep, dep, &node->pred_list, pred_link)
357#define gpir_node_foreach_pred_safe(node, dep) \
358   list_for_each_entry_safe(gpir_dep, dep, &node->pred_list, pred_link)
359
360static inline bool gpir_node_is_root(gpir_node *node)
361{
362   return list_empty(&node->succ_list);
363}
364
365static inline bool gpir_node_is_leaf(gpir_node *node)
366{
367   return list_empty(&node->pred_list);
368}
369
370#define gpir_node_to_alu(node) ((gpir_alu_node *)(node))
371#define gpir_node_to_const(node) ((gpir_const_node *)(node))
372#define gpir_node_to_load(node) ((gpir_load_node *)(node))
373#define gpir_node_to_store(node) ((gpir_store_node *)(node))
374
375gpir_instr *gpir_instr_create(gpir_block *block);
376bool gpir_instr_try_insert_node(gpir_instr *instr, gpir_node *node);
377void gpir_instr_remove_node(gpir_instr *instr, gpir_node *node);
378void gpir_instr_print_prog(gpir_compiler *comp);
379
380static inline bool gpir_instr_alu_slot_is_full(gpir_instr *instr)
381{
382   return instr->alu_num_slot_free <= instr->alu_num_slot_needed_by_store;
383}
384
385bool gpir_codegen_acc_same_op(gpir_op op1, gpir_op op2);
386
387bool gpir_pre_rsched_lower_prog(gpir_compiler *comp);
388bool gpir_post_rsched_lower_prog(gpir_compiler *comp);
389bool gpir_reduce_reg_pressure_schedule_prog(gpir_compiler *comp);
390bool gpir_value_regalloc_prog(gpir_compiler *comp);
391bool gpir_physical_regalloc_prog(gpir_compiler *comp);
392bool gpir_schedule_prog(gpir_compiler *comp);
393bool gpir_codegen_prog(gpir_compiler *comp);
394
395gpir_reg *gpir_create_reg(gpir_compiler *comp);
396
397#endif
398