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
] = {
144 .slots
= (int []) { GPIR_INSTR_SLOT_PASS
, GPIR_INSTR_SLOT_END
},
146 .schedule_first
= true,
148 [gpir_op_postlog2
] = {
150 .slots
= (int []) { GPIR_INSTR_SLOT_PASS
, GPIR_INSTR_SLOT_END
},
152 [gpir_op_exp2_impl
] = {
154 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
156 .schedule_first
= true,
158 [gpir_op_log2_impl
] = {
160 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
162 .schedule_first
= true,
164 [gpir_op_rcp_impl
] = {
166 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
168 .schedule_first
= true,
170 [gpir_op_rsqrt_impl
] = {
171 .name
= "rsqrt_impl",
172 .slots
= (int []) { GPIR_INSTR_SLOT_COMPLEX
, GPIR_INSTR_SLOT_END
},
174 .schedule_first
= true,
176 [gpir_op_load_uniform
] = {
179 GPIR_INSTR_SLOT_MEM_LOAD0
, GPIR_INSTR_SLOT_MEM_LOAD1
,
180 GPIR_INSTR_SLOT_MEM_LOAD2
, GPIR_INSTR_SLOT_MEM_LOAD3
,
183 .type
= gpir_node_type_load
,
185 [gpir_op_load_temp
] = {
187 .type
= gpir_node_type_load
,
189 [gpir_op_load_attribute
] = {
192 GPIR_INSTR_SLOT_REG0_LOAD0
, GPIR_INSTR_SLOT_REG0_LOAD1
,
193 GPIR_INSTR_SLOT_REG0_LOAD2
, GPIR_INSTR_SLOT_REG0_LOAD3
,
196 .type
= gpir_node_type_load
,
198 [gpir_op_load_reg
] = {
201 GPIR_INSTR_SLOT_REG1_LOAD0
, GPIR_INSTR_SLOT_REG1_LOAD1
,
202 GPIR_INSTR_SLOT_REG1_LOAD2
, GPIR_INSTR_SLOT_REG1_LOAD3
,
203 GPIR_INSTR_SLOT_REG0_LOAD0
, GPIR_INSTR_SLOT_REG0_LOAD1
,
204 GPIR_INSTR_SLOT_REG0_LOAD2
, GPIR_INSTR_SLOT_REG0_LOAD3
,
207 .type
= gpir_node_type_load
,
210 [gpir_op_store_temp
] = {
212 .type
= gpir_node_type_store
,
214 [gpir_op_store_reg
] = {
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_varying
] = {
227 GPIR_INSTR_SLOT_STORE0
, GPIR_INSTR_SLOT_STORE1
,
228 GPIR_INSTR_SLOT_STORE2
, GPIR_INSTR_SLOT_STORE3
,
231 .type
= gpir_node_type_store
,
234 [gpir_op_store_temp_load_off0
] = {
236 .type
= gpir_node_type_store
,
238 [gpir_op_store_temp_load_off1
] = {
240 .type
= gpir_node_type_store
,
242 [gpir_op_store_temp_load_off2
] = {
244 .type
= gpir_node_type_store
,
246 [gpir_op_branch_cond
] = {
247 .name
= "branch_cond",
248 .type
= gpir_node_type_branch
,
252 .type
= gpir_node_type_const
,
284 [gpir_op_dummy_f
] = {
286 .type
= gpir_node_type_alu
,
289 [gpir_op_dummy_m
] = {
291 .type
= gpir_node_type_alu
,
293 [gpir_op_branch_uncond
] = {
294 .name
= "branch_uncond",
295 .type
= gpir_node_type_branch
,
299 void *gpir_node_create(gpir_block
*block
, gpir_op op
)
301 static const int node_size
[] = {
302 [gpir_node_type_alu
] = sizeof(gpir_alu_node
),
303 [gpir_node_type_const
] = sizeof(gpir_const_node
),
304 [gpir_node_type_load
] = sizeof(gpir_load_node
),
305 [gpir_node_type_store
] = sizeof(gpir_store_node
),
306 [gpir_node_type_branch
] = sizeof(gpir_branch_node
),
309 gpir_node_type type
= gpir_op_infos
[op
].type
;
310 int size
= node_size
[type
];
311 gpir_node
*node
= rzalloc_size(block
, size
);
315 snprintf(node
->name
, sizeof(node
->name
), "new");
317 list_inithead(&node
->succ_list
);
318 list_inithead(&node
->pred_list
);
322 node
->index
= block
->comp
->cur_index
++;
328 gpir_dep
*gpir_node_add_dep(gpir_node
*succ
, gpir_node
*pred
, int type
)
330 /* don't add dep for two nodes from different block */
331 if (succ
->block
!= pred
->block
)
334 /* don't add self loop dep */
338 /* don't add duplicated dep */
339 gpir_node_foreach_pred(succ
, dep
) {
340 if (dep
->pred
== pred
) {
341 /* use stronger dependency */
342 if (dep
->type
> type
)
348 gpir_dep
*dep
= ralloc(succ
, gpir_dep
);
352 list_addtail(&dep
->pred_link
, &succ
->pred_list
);
353 list_addtail(&dep
->succ_link
, &pred
->succ_list
);
357 void gpir_node_remove_dep(gpir_node
*succ
, gpir_node
*pred
)
359 gpir_node_foreach_pred(succ
, dep
) {
360 if (dep
->pred
== pred
) {
361 list_del(&dep
->succ_link
);
362 list_del(&dep
->pred_link
);
369 void gpir_node_replace_child(gpir_node
*parent
, gpir_node
*old_child
,
370 gpir_node
*new_child
)
372 if (parent
->type
== gpir_node_type_alu
) {
373 gpir_alu_node
*alu
= gpir_node_to_alu(parent
);
374 for (int i
= 0; i
< alu
->num_child
; i
++) {
375 if (alu
->children
[i
] == old_child
)
376 alu
->children
[i
] = new_child
;
379 else if (parent
->type
== gpir_node_type_store
) {
380 gpir_store_node
*store
= gpir_node_to_store(parent
);
381 if (store
->child
== old_child
)
382 store
->child
= new_child
;
386 void gpir_node_replace_pred(gpir_dep
*dep
, gpir_node
*new_pred
)
388 list_del(&dep
->succ_link
);
389 dep
->pred
= new_pred
;
390 list_addtail(&dep
->succ_link
, &new_pred
->succ_list
);
393 void gpir_node_replace_succ(gpir_node
*dst
, gpir_node
*src
)
395 gpir_node_foreach_succ_safe(src
, dep
) {
396 if (dep
->type
!= GPIR_DEP_INPUT
)
399 gpir_node_replace_pred(dep
, dst
);
400 gpir_node_replace_child(dep
->succ
, src
, dst
);
404 void gpir_node_insert_child(gpir_node
*parent
, gpir_node
*child
,
405 gpir_node
*insert_child
)
407 gpir_node_foreach_pred(parent
, dep
) {
408 if (dep
->pred
== child
) {
409 gpir_node_replace_pred(dep
, insert_child
);
413 gpir_node_add_dep(insert_child
, child
, GPIR_DEP_INPUT
);
416 void gpir_node_delete(gpir_node
*node
)
418 gpir_node_foreach_succ_safe(node
, dep
) {
419 list_del(&dep
->succ_link
);
420 list_del(&dep
->pred_link
);
424 gpir_node_foreach_pred_safe(node
, dep
) {
425 list_del(&dep
->succ_link
);
426 list_del(&dep
->pred_link
);
430 if (node
->type
== gpir_node_type_store
) {
431 gpir_store_node
*store
= gpir_node_to_store(node
);
433 list_del(&store
->reg_link
);
435 else if (node
->type
== gpir_node_type_load
) {
436 gpir_load_node
*load
= gpir_node_to_load(node
);
438 list_del(&load
->reg_link
);
441 list_del(&node
->list
);
445 static void gpir_node_print_node(gpir_node
*node
, int type
, int space
)
447 static char *dep_name
[] = {
448 [GPIR_DEP_INPUT
] = "input",
449 [GPIR_DEP_OFFSET
] = "offset",
450 [GPIR_DEP_READ_AFTER_WRITE
] = "RaW",
451 [GPIR_DEP_WRITE_AFTER_READ
] = "WaR",
454 for (int i
= 0; i
< space
; i
++)
456 printf("%s%s %d %s %s\n", node
->printed
&& !gpir_node_is_leaf(node
) ? "+" : "",
457 gpir_op_infos
[node
->op
].name
, node
->index
, node
->name
, dep_name
[type
]);
459 if (!node
->printed
) {
460 gpir_node_foreach_pred(node
, dep
) {
461 gpir_node_print_node(dep
->pred
, dep
->type
, space
+ 2);
464 node
->printed
= true;
468 void gpir_node_print_prog_dep(gpir_compiler
*comp
)
470 if (!(lima_debug
& LIMA_DEBUG_GP
))
473 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
474 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
475 node
->printed
= false;
479 printf("======== node prog dep ========\n");
480 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
481 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
482 if (gpir_node_is_root(node
))
483 gpir_node_print_node(node
, GPIR_DEP_INPUT
, 0);
485 printf("----------------------------\n");
489 void gpir_node_print_prog_seq(gpir_compiler
*comp
)
491 if (!(lima_debug
& LIMA_DEBUG_GP
))
495 printf("======== node prog seq ========\n");
496 list_for_each_entry(gpir_block
, block
, &comp
->block_list
, list
) {
497 list_for_each_entry(gpir_node
, node
, &block
->node_list
, list
) {
498 printf("%03d: %s %d %s pred", index
++, gpir_op_infos
[node
->op
].name
,
499 node
->index
, node
->name
);
500 gpir_node_foreach_pred(node
, dep
) {
501 printf(" %d", dep
->pred
->index
);
504 gpir_node_foreach_succ(node
, dep
) {
505 printf(" %d", dep
->succ
->index
);
509 printf("----------------------------\n");