2 * Copyright (c) 2017 Lima Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
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 NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
25 #include "util/u_math.h"
26 #include "util/ralloc.h"
30 const gpir_op_info gpir_op_infos
[] = {
34 GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_MUL1
,
35 GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_MUL0
,
36 GPIR_INSTR_SLOT_PASS
, GPIR_INSTR_SLOT_COMPLEX
,
43 .slots
= (int []) { GPIR_INSTR_SLOT_MUL1
, GPIR_INSTR_SLOT_MUL0
, GPIR_INSTR_SLOT_END
},
48 .slots
= (int []) { GPIR_INSTR_SLOT_MUL0
, GPIR_INSTR_SLOT_END
},
49 .may_consume_two_slots
= true,
51 [gpir_op_complex1
] = {
53 .slots
= (int []) { GPIR_INSTR_SLOT_MUL0
, GPIR_INSTR_SLOT_END
},
55 .may_consume_two_slots
= true,
57 [gpir_op_complex2
] = {
59 .slots
= (int []) { GPIR_INSTR_SLOT_MUL0
, GPIR_INSTR_SLOT_END
},
61 .schedule_first
= true,
65 .src_neg
= {true, true, false, false},
66 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
70 .src_neg
= {true, false, false, false},
71 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
73 .may_consume_two_slots
= true,
77 .src_neg
= {true, false, false, false},
78 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
80 .may_consume_two_slots
= true,
84 .src_neg
= {true, true, false, false},
85 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
87 .may_consume_two_slots
= true,
91 .src_neg
= {true, true, false, false},
92 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
94 .may_consume_two_slots
= true,
98 .src_neg
= {true, true, false, false},
99 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
101 .may_consume_two_slots
= true,
105 .src_neg
= {true, true, false, false},
106 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
108 .may_consume_two_slots
= true,
112 .src_neg
= {true, true, false, false},
117 GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_MUL1
,
118 GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_MUL0
,
124 .src_neg
= {true, true, false, false},
125 .slots
= (int []) { GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
},
130 GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
136 GPIR_INSTR_SLOT_ADD0
, GPIR_INSTR_SLOT_ADD1
, GPIR_INSTR_SLOT_END
139 [gpir_op_clamp_const
] = {
140 .name
= "clamp_const",
142 [gpir_op_preexp2
] = {
145 [gpir_op_postlog2
] = {
148 [gpir_op_exp2_impl
] = {
151 [gpir_op_log2_impl
] = {
154 [gpir_op_rcp_impl
] = {
156 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
158 .schedule_first
= true,
160 [gpir_op_rsqrt_impl
] = {
161 .name
= "rsqrt_impl",
162 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
164 .schedule_first
= true,
166 [gpir_op_load_uniform
] = {
169 GPIR_INSTR_SLOT_MEM_LOAD0
, GPIR_INSTR_SLOT_MEM_LOAD1
,
170 GPIR_INSTR_SLOT_MEM_LOAD2
, GPIR_INSTR_SLOT_MEM_LOAD3
,
173 .type
= gpir_node_type_load
,
175 [gpir_op_load_temp
] = {
177 .type
= gpir_node_type_load
,
179 [gpir_op_load_attribute
] = {
182 GPIR_INSTR_SLOT_REG0_LOAD0
, GPIR_INSTR_SLOT_REG0_LOAD1
,
183 GPIR_INSTR_SLOT_REG0_LOAD2
, GPIR_INSTR_SLOT_REG0_LOAD3
,
186 .type
= gpir_node_type_load
,
188 [gpir_op_load_reg
] = {
191 GPIR_INSTR_SLOT_REG1_LOAD0
, GPIR_INSTR_SLOT_REG1_LOAD1
,
192 GPIR_INSTR_SLOT_REG1_LOAD2
, GPIR_INSTR_SLOT_REG1_LOAD3
,
193 GPIR_INSTR_SLOT_REG0_LOAD0
, GPIR_INSTR_SLOT_REG0_LOAD1
,
194 GPIR_INSTR_SLOT_REG0_LOAD2
, GPIR_INSTR_SLOT_REG0_LOAD3
,
197 .type
= gpir_node_type_load
,
200 [gpir_op_store_temp
] = {
202 .type
= gpir_node_type_store
,
204 [gpir_op_store_reg
] = {
207 GPIR_INSTR_SLOT_STORE0
, GPIR_INSTR_SLOT_STORE1
,
208 GPIR_INSTR_SLOT_STORE2
, GPIR_INSTR_SLOT_STORE3
,
211 .type
= gpir_node_type_store
,
214 [gpir_op_store_varying
] = {
217 GPIR_INSTR_SLOT_STORE0
, GPIR_INSTR_SLOT_STORE1
,
218 GPIR_INSTR_SLOT_STORE2
, GPIR_INSTR_SLOT_STORE3
,
221 .type
= gpir_node_type_store
,
224 [gpir_op_store_temp_load_off0
] = {
226 .type
= gpir_node_type_store
,
228 [gpir_op_store_temp_load_off1
] = {
230 .type
= gpir_node_type_store
,
232 [gpir_op_store_temp_load_off2
] = {
234 .type
= gpir_node_type_store
,
236 [gpir_op_branch_cond
] = {
237 .name
= "branch_cond",
238 .type
= gpir_node_type_branch
,
242 .type
= gpir_node_type_const
,
274 [gpir_op_dummy_f
] = {
276 .type
= gpir_node_type_alu
,
279 [gpir_op_dummy_m
] = {
281 .type
= gpir_node_type_alu
,
283 [gpir_op_branch_uncond
] = {
284 .name
= "branch_uncond",
285 .type
= gpir_node_type_branch
,
289 void *gpir_node_create(gpir_block
*block
, gpir_op op
)
291 static const int node_size
[] = {
292 [gpir_node_type_alu
] = sizeof(gpir_alu_node
),
293 [gpir_node_type_const
] = sizeof(gpir_const_node
),
294 [gpir_node_type_load
] = sizeof(gpir_load_node
),
295 [gpir_node_type_store
] = sizeof(gpir_store_node
),
296 [gpir_node_type_branch
] = sizeof(gpir_branch_node
),
299 gpir_node_type type
= gpir_op_infos
[op
].type
;
300 int size
= node_size
[type
];
301 gpir_node
*node
= rzalloc_size(block
, size
);
305 snprintf(node
->name
, sizeof(node
->name
), "new");
307 list_inithead(&node
->succ_list
);
308 list_inithead(&node
->pred_list
);
312 node
->index
= block
->comp
->cur_index
++;
318 gpir_dep
*gpir_node_add_dep(gpir_node
*succ
, gpir_node
*pred
, int type
)
320 /* don't add dep for two nodes from different block */
321 if (succ
->block
!= pred
->block
)
324 /* don't add self loop dep */
328 /* don't add duplicated dep */
329 gpir_node_foreach_pred(succ
, dep
) {
330 if (dep
->pred
== pred
) {
331 /* use stronger dependency */
332 if (dep
->type
> type
)
338 gpir_dep
*dep
= ralloc(succ
, gpir_dep
);
342 list_addtail(&dep
->pred_link
, &succ
->pred_list
);
343 list_addtail(&dep
->succ_link
, &pred
->succ_list
);
347 void gpir_node_remove_dep(gpir_node
*succ
, gpir_node
*pred
)
349 gpir_node_foreach_pred(succ
, dep
) {
350 if (dep
->pred
== pred
) {
351 list_del(&dep
->succ_link
);
352 list_del(&dep
->pred_link
);
359 void gpir_node_replace_child(gpir_node
*parent
, gpir_node
*old_child
,
360 gpir_node
*new_child
)
362 if (parent
->type
== gpir_node_type_alu
) {
363 gpir_alu_node
*alu
= gpir_node_to_alu(parent
);
364 for (int i
= 0; i
< alu
->num_child
; i
++) {
365 if (alu
->children
[i
] == old_child
)
366 alu
->children
[i
] = new_child
;
369 else if (parent
->type
== gpir_node_type_store
) {
370 gpir_store_node
*store
= gpir_node_to_store(parent
);
371 if (store
->child
== old_child
)
372 store
->child
= new_child
;
376 void gpir_node_replace_pred(gpir_dep
*dep
, gpir_node
*new_pred
)
378 list_del(&dep
->succ_link
);
379 dep
->pred
= new_pred
;
380 list_addtail(&dep
->succ_link
, &new_pred
->succ_list
);
383 void gpir_node_replace_succ(gpir_node
*dst
, gpir_node
*src
)
385 gpir_node_foreach_succ_safe(src
, dep
) {
386 if (dep
->type
!= GPIR_DEP_INPUT
)
389 gpir_node_replace_pred(dep
, dst
);
390 gpir_node_replace_child(dep
->succ
, src
, dst
);
394 void gpir_node_insert_child(gpir_node
*parent
, gpir_node
*child
,
395 gpir_node
*insert_child
)
397 gpir_node_foreach_pred(parent
, dep
) {
398 if (dep
->pred
== child
) {
399 gpir_node_replace_pred(dep
, insert_child
);
403 gpir_node_add_dep(insert_child
, child
, GPIR_DEP_INPUT
);
406 void gpir_node_delete(gpir_node
*node
)
408 gpir_node_foreach_succ_safe(node
, dep
) {
409 list_del(&dep
->succ_link
);
410 list_del(&dep
->pred_link
);
414 gpir_node_foreach_pred_safe(node
, dep
) {
415 list_del(&dep
->succ_link
);
416 list_del(&dep
->pred_link
);
420 if (node
->type
== gpir_node_type_store
) {
421 gpir_store_node
*store
= gpir_node_to_store(node
);
423 list_del(&store
->reg_link
);
425 else if (node
->type
== gpir_node_type_load
) {
426 gpir_load_node
*load
= gpir_node_to_load(node
);
428 list_del(&load
->reg_link
);
431 list_del(&node
->list
);
435 static void gpir_node_print_node(gpir_node
*node
, int type
, int space
)
437 static char *dep_name
[] = {
438 [GPIR_DEP_INPUT
] = "input",
439 [GPIR_DEP_OFFSET
] = "offset",
440 [GPIR_DEP_READ_AFTER_WRITE
] = "RaW",
441 [GPIR_DEP_WRITE_AFTER_READ
] = "WaR",
444 for (int i
= 0; i
< space
; i
++)
446 printf("%s%s %d %s %s\n", node
->printed
&& !gpir_node_is_leaf(node
) ? "+" : "",
447 gpir_op_infos
[node
->op
].name
, node
->index
, node
->name
, dep_name
[type
]);
449 if (!node
->printed
) {
450 gpir_node_foreach_pred(node
, dep
) {
451 gpir_node_print_node(dep
->pred
, dep
->type
, space
+ 2);
454 node
->printed
= true;
458 void gpir_node_print_prog_dep(gpir_compiler
*comp
)
460 if (!(lima_debug
& LIMA_DEBUG_GP
))
463 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
464 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
465 node
->printed
= false;
469 printf("======== node prog dep ========\n");
470 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
471 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
472 if (gpir_node_is_root(node
))
473 gpir_node_print_node(node
, GPIR_DEP_INPUT
, 0);
475 printf("----------------------------\n");
479 void gpir_node_print_prog_seq(gpir_compiler
*comp
)
481 if (!(lima_debug
& LIMA_DEBUG_GP
))
485 printf("======== node prog seq ========\n");
486 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
487 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
488 printf("%03d: %s %d %s pred", index
++, gpir_op_infos
[node
->op
].name
,
489 node
->index
, node
->name
);
490 gpir_node_foreach_pred(node
, dep
) {
491 printf(" %d", dep
->pred
->index
);
494 gpir_node_foreach_succ(node
, dep
) {
495 printf(" %d", dep
->succ
->index
);
499 printf("----------------------------\n");