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/ralloc.h"
29 ppir_instr
*ppir_instr_create(ppir_block
*block
)
31 ppir_instr
*instr
= rzalloc(block
, ppir_instr
);
35 list_inithead(&instr
->succ_list
);
36 list_inithead(&instr
->pred_list
);
38 instr
->index
= block
->comp
->cur_instr_index
++;
39 instr
->reg_pressure
= -1;
41 list_addtail(&instr
->list
, &block
->instr_list
);
45 void ppir_instr_add_dep(ppir_instr
*succ
, ppir_instr
*pred
)
47 /* don't add duplicated instr */
48 ppir_instr_foreach_pred(succ
, dep
) {
49 if (pred
== dep
->pred
)
53 ppir_dep
*dep
= ralloc(succ
, ppir_dep
);
56 list_addtail(&dep
->pred_link
, &succ
->pred_list
);
57 list_addtail(&dep
->succ_link
, &pred
->succ_list
);
60 void ppir_instr_insert_mul_node(ppir_node
*add
, ppir_node
*mul
)
62 ppir_instr
*instr
= add
->instr
;
63 int pos
= mul
->instr_pos
;
64 int *slots
= ppir_op_infos
[mul
->op
].slots
;
66 for (int i
= 0; slots
[i
] != PPIR_INSTR_SLOT_END
; i
++) {
67 /* possible to insert at required place */
68 if (slots
[i
] == pos
) {
69 if (!instr
->slots
[pos
]) {
70 ppir_alu_node
*add_alu
= ppir_node_to_alu(add
);
71 ppir_alu_node
*mul_alu
= ppir_node_to_alu(mul
);
72 ppir_dest
*dest
= &mul_alu
->dest
;
73 int pipeline
= pos
== PPIR_INSTR_SLOT_ALU_VEC_MUL
?
74 ppir_pipeline_reg_vmul
: ppir_pipeline_reg_fmul
;
76 /* ^vmul/^fmul can't be used as last arg */
77 if (add_alu
->num_src
> 1) {
78 ppir_src
*last_src
= add_alu
->src
+ add_alu
->num_src
- 1;
79 if (ppir_node_target_equal(last_src
, dest
))
83 /* update add node src to use pipeline reg */
84 ppir_src
*src
= add_alu
->src
;
85 if (add_alu
->num_src
== 3) {
86 if (ppir_node_target_equal(src
, dest
)) {
87 src
->type
= ppir_target_pipeline
;
88 src
->pipeline
= pipeline
;
91 if (ppir_node_target_equal(++src
, dest
)) {
92 src
->type
= ppir_target_pipeline
;
93 src
->pipeline
= pipeline
;
97 assert(ppir_node_target_equal(src
, dest
));
98 src
->type
= ppir_target_pipeline
;
99 src
->pipeline
= pipeline
;
102 /* update mul node dest to output to pipeline reg */
103 dest
->type
= ppir_target_pipeline
;
104 dest
->pipeline
= pipeline
;
106 instr
->slots
[pos
] = mul
;
114 /* check whether a const slot fix into another const slot */
115 static bool ppir_instr_insert_const(ppir_const
*dst
, const ppir_const
*src
,
120 for (i
= 0; i
< src
->num
; i
++) {
121 for (j
= 0; j
< dst
->num
; j
++) {
122 if (src
->value
[i
].ui
== dst
->value
[j
].ui
)
129 dst
->value
[dst
->num
++] = src
->value
[i
];
138 static void ppir_update_src_pipeline(ppir_pipeline pipeline
, ppir_src
*src
,
139 ppir_dest
*dest
, uint8_t *swizzle
)
141 if (ppir_node_target_equal(src
, dest
)) {
142 src
->type
= ppir_target_pipeline
;
143 src
->pipeline
= pipeline
;
146 for (int k
= 0; k
< 4; k
++)
147 src
->swizzle
[k
] = swizzle
[src
->swizzle
[k
]];
152 /* make alu node src reflact the pipeline reg */
153 static void ppir_instr_update_src_pipeline(ppir_instr
*instr
, ppir_pipeline pipeline
,
154 ppir_dest
*dest
, uint8_t *swizzle
)
156 for (int i
= PPIR_INSTR_SLOT_ALU_START
; i
<= PPIR_INSTR_SLOT_ALU_END
; i
++) {
157 if (!instr
->slots
[i
])
160 ppir_alu_node
*alu
= ppir_node_to_alu(instr
->slots
[i
]);
161 for (int j
= 0; j
< alu
->num_src
; j
++) {
162 ppir_src
*src
= alu
->src
+ j
;
163 ppir_update_src_pipeline(pipeline
, src
, dest
, swizzle
);
167 ppir_node
*branch_node
= instr
->slots
[PPIR_INSTR_SLOT_BRANCH
];
168 if (branch_node
&& (branch_node
->type
== ppir_node_type_branch
)) {
169 ppir_branch_node
*branch
= ppir_node_to_branch(branch_node
);
170 for (int j
= 0; j
< 2; j
++) {
171 ppir_src
*src
= branch
->src
+ j
;
172 ppir_update_src_pipeline(pipeline
, src
, dest
, swizzle
);
177 bool ppir_instr_insert_node(ppir_instr
*instr
, ppir_node
*node
)
179 if (node
->op
== ppir_op_const
) {
181 ppir_const_node
*c
= ppir_node_to_const(node
);
182 const ppir_const
*nc
= &c
->constant
;
184 for (i
= 0; i
< 2; i
++) {
185 ppir_const ic
= instr
->constant
[i
];
186 uint8_t swizzle
[4] = {0};
188 if (ppir_instr_insert_const(&ic
, nc
, swizzle
)) {
189 instr
->constant
[i
] = ic
;
190 ppir_instr_update_src_pipeline(
191 instr
, ppir_pipeline_reg_const0
+ i
, &c
->dest
, swizzle
);
196 /* no const slot can insert */
203 int *slots
= ppir_op_infos
[node
->op
].slots
;
204 for (int i
= 0; slots
[i
] != PPIR_INSTR_SLOT_END
; i
++) {
207 if (instr
->slots
[pos
]) {
208 /* node already in this instr, i.e. load_uniform */
209 if (instr
->slots
[pos
] == node
)
215 if (pos
== PPIR_INSTR_SLOT_ALU_SCL_MUL
||
216 pos
== PPIR_INSTR_SLOT_ALU_SCL_ADD
) {
217 ppir_dest
*dest
= ppir_node_get_dest(node
);
218 if (!ppir_target_is_scaler(dest
))
222 instr
->slots
[pos
] = node
;
224 node
->instr_pos
= pos
;
226 if ((node
->op
== ppir_op_load_uniform
) || (node
->op
== ppir_op_load_temp
)) {
227 ppir_load_node
*l
= ppir_node_to_load(node
);
228 ppir_instr_update_src_pipeline(
229 instr
, ppir_pipeline_reg_uniform
, &l
->dest
, NULL
);
242 } ppir_instr_fields
[] = {
243 [PPIR_INSTR_SLOT_VARYING
] = { 4, "vary" },
244 [PPIR_INSTR_SLOT_TEXLD
] = { 4, "texl"},
245 [PPIR_INSTR_SLOT_UNIFORM
] = { 4, "unif" },
246 [PPIR_INSTR_SLOT_ALU_VEC_MUL
] = { 4, "vmul" },
247 [PPIR_INSTR_SLOT_ALU_SCL_MUL
] = { 4, "smul" },
248 [PPIR_INSTR_SLOT_ALU_VEC_ADD
] = { 4, "vadd" },
249 [PPIR_INSTR_SLOT_ALU_SCL_ADD
] = { 4, "sadd" },
250 [PPIR_INSTR_SLOT_ALU_COMBINE
] = { 4, "comb" },
251 [PPIR_INSTR_SLOT_STORE_TEMP
] = { 4, "stor" },
252 [PPIR_INSTR_SLOT_BRANCH
] = { 4, "brch" },
255 void ppir_instr_print_list(ppir_compiler
*comp
)
257 if (!(lima_debug
& LIMA_DEBUG_PP
))
260 printf("======ppir instr list======\n");
262 for (int i
= 0; i
< PPIR_INSTR_SLOT_NUM
; i
++)
263 printf("%-*s ", ppir_instr_fields
[i
].len
, ppir_instr_fields
[i
].name
);
264 printf("const0|1\n");
266 list_for_each_entry(ppir_block
, block
, &comp
->block_list
, list
) {
267 list_for_each_entry(ppir_instr
, instr
, &block
->instr_list
, list
) {
268 printf("%c%03d: ", instr
->is_end
? '*' : ' ', instr
->index
);
269 for (int i
= 0; i
< PPIR_INSTR_SLOT_NUM
; i
++) {
270 ppir_node
*node
= instr
->slots
[i
];
272 printf("%-*d ", ppir_instr_fields
[i
].len
, node
->index
);
274 printf("%-*s ", ppir_instr_fields
[i
].len
, "null");
276 for (int i
= 0; i
< 2; i
++) {
280 for (int j
= 0; j
< instr
->constant
[i
].num
; j
++)
281 printf("%f ", instr
->constant
[i
].value
[j
].f
);
285 printf("------------------------\n");
289 static void ppir_instr_print_sub(ppir_instr
*instr
)
292 instr
->printed
&& !ppir_instr_is_leaf(instr
) ? "+" : "",
295 if (!instr
->printed
) {
296 ppir_instr_foreach_pred(instr
, dep
) {
297 ppir_instr_print_sub(dep
->pred
);
300 instr
->printed
= true;
306 void ppir_instr_print_dep(ppir_compiler
*comp
)
308 if (!(lima_debug
& LIMA_DEBUG_PP
))
311 list_for_each_entry(ppir_block
, block
, &comp
->block_list
, list
) {
312 list_for_each_entry(ppir_instr
, instr
, &block
->instr_list
, list
) {
313 instr
->printed
= false;
317 printf("======ppir instr depend======\n");
318 list_for_each_entry(ppir_block
, block
, &comp
->block_list
, list
) {
319 list_for_each_entry(ppir_instr
, instr
, &block
->instr_list
, list
) {
320 if (ppir_instr_is_root(instr
)) {
321 ppir_instr_print_sub(instr
);
325 printf("------------------------\n");