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