• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2017 Lima Project
3  *
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:
10  *
11  * The above copyright notice and this permission notice (including the
12  * next paragraph) shall be included in all copies or substantial portions
13  * 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 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.
22  *
23  */
24 
25 #include "util/ralloc.h"
26 
27 #include "ppir.h"
28 
ppir_instr_create(ppir_block * block)29 ppir_instr *ppir_instr_create(ppir_block *block)
30 {
31    ppir_instr *instr = rzalloc(block, ppir_instr);
32    if (!instr)
33       return NULL;
34 
35    list_inithead(&instr->succ_list);
36    list_inithead(&instr->pred_list);
37 
38    instr->index = block->comp->cur_instr_index++;
39    instr->reg_pressure = -1;
40 
41    list_addtail(&instr->list, &block->instr_list);
42    return instr;
43 }
44 
ppir_instr_add_dep(ppir_instr * succ,ppir_instr * pred)45 void ppir_instr_add_dep(ppir_instr *succ, ppir_instr *pred)
46 {
47    /* don't add duplicated instr */
48    ppir_instr_foreach_pred(succ, dep) {
49       if (pred == dep->pred)
50          return;
51    }
52 
53    ppir_dep *dep = ralloc(succ, ppir_dep);
54    dep->pred = pred;
55    dep->succ = succ;
56    list_addtail(&dep->pred_link, &succ->pred_list);
57    list_addtail(&dep->succ_link, &pred->succ_list);
58 }
59 
ppir_instr_insert_mul_node(ppir_node * add,ppir_node * mul)60 void ppir_instr_insert_mul_node(ppir_node *add, ppir_node *mul)
61 {
62    ppir_instr *instr = add->instr;
63    int pos = mul->instr_pos;
64    int *slots = ppir_op_infos[mul->op].slots;
65 
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;
75 
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))
80                   return;
81             }
82 
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;
89                }
90 
91                if (ppir_node_target_equal(++src, dest)) {
92                   src->type = ppir_target_pipeline;
93                   src->pipeline = pipeline;
94                }
95             }
96             else {
97                assert(ppir_node_target_equal(src, dest));
98                src->type = ppir_target_pipeline;
99                src->pipeline = pipeline;
100             }
101 
102             /* update mul node dest to output to pipeline reg */
103             dest->type = ppir_target_pipeline;
104             dest->pipeline = pipeline;
105 
106             instr->slots[pos] = mul;
107             mul->instr = instr;
108          }
109          return;
110       }
111    }
112 }
113 
114 /* check whether a const slot fix into another const slot */
ppir_instr_insert_const(ppir_const * dst,const ppir_const * src,uint8_t * swizzle)115 static bool ppir_instr_insert_const(ppir_const *dst, const ppir_const *src,
116                                     uint8_t *swizzle)
117 {
118    int i, j;
119 
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)
123             break;
124       }
125 
126       if (j == dst->num) {
127          if (dst->num == 4)
128             return false;
129          dst->value[dst->num++] = src->value[i];
130       }
131 
132       swizzle[i] = j;
133    }
134 
135    return true;
136 }
137 
ppir_update_src_pipeline(ppir_pipeline pipeline,ppir_src * src,ppir_dest * dest,uint8_t * swizzle)138 static void ppir_update_src_pipeline(ppir_pipeline pipeline, ppir_src *src,
139                                      ppir_dest *dest, uint8_t *swizzle)
140 {
141    if (ppir_node_target_equal(src, dest)) {
142       src->type = ppir_target_pipeline;
143       src->pipeline = pipeline;
144 
145       if (swizzle) {
146          for (int k = 0; k < 4; k++)
147             src->swizzle[k] = swizzle[src->swizzle[k]];
148       }
149    }
150 }
151 
152 /* make alu node src reflact the pipeline reg */
ppir_instr_update_src_pipeline(ppir_instr * instr,ppir_pipeline pipeline,ppir_dest * dest,uint8_t * swizzle)153 static void ppir_instr_update_src_pipeline(ppir_instr *instr, ppir_pipeline pipeline,
154                                            ppir_dest *dest, uint8_t *swizzle)
155 {
156    for (int i = PPIR_INSTR_SLOT_ALU_START; i <= PPIR_INSTR_SLOT_ALU_END; i++) {
157       if (!instr->slots[i])
158          continue;
159 
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);
164       }
165    }
166 
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);
173       }
174    }
175 }
176 
ppir_instr_insert_node(ppir_instr * instr,ppir_node * node)177 bool ppir_instr_insert_node(ppir_instr *instr, ppir_node *node)
178 {
179    if (node->op == ppir_op_const) {
180       int i;
181       ppir_const_node *c = ppir_node_to_const(node);
182       const ppir_const *nc = &c->constant;
183 
184       for (i = 0; i < 2; i++) {
185          ppir_const ic = instr->constant[i];
186          uint8_t swizzle[4] = {0};
187 
188          if (ppir_instr_insert_const(&ic, nc, swizzle)) {
189             instr->constant[i] = ic;
190             ppir_node *succ = ppir_node_first_succ(node);
191             for (int s = 0; s < ppir_node_get_src_num(succ); s++) {
192                ppir_src *src = ppir_node_get_src(succ, s);
193                assert(src);
194                if (src->node != node)
195                   continue;
196 
197                ppir_update_src_pipeline(ppir_pipeline_reg_const0 + i, src,
198                                         &c->dest, swizzle);
199             }
200             break;
201          }
202       }
203 
204       /* no const slot can insert */
205       if (i == 2)
206          return false;
207 
208       return true;
209    }
210    else {
211       int *slots = ppir_op_infos[node->op].slots;
212       for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) {
213          int pos = slots[i];
214 
215          if (instr->slots[pos]) {
216             /* node already in this instr, i.e. load_uniform */
217             if (instr->slots[pos] == node)
218                return true;
219             else
220                continue;
221          }
222 
223          /* ^fmul dests (e.g. condition for select) can only be
224           * scheduled to ALU_SCL_MUL */
225          if (pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {
226             ppir_dest *dest = ppir_node_get_dest(node);
227             if (dest && dest->type == ppir_target_pipeline &&
228                 dest->pipeline == ppir_pipeline_reg_fmul)
229             continue;
230          }
231 
232          if (pos == PPIR_INSTR_SLOT_ALU_SCL_MUL ||
233              pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {
234             ppir_dest *dest = ppir_node_get_dest(node);
235             if (!ppir_target_is_scalar(dest))
236                continue;
237          }
238 
239          instr->slots[pos] = node;
240          node->instr = instr;
241          node->instr_pos = pos;
242 
243          if ((node->op == ppir_op_load_uniform) || (node->op == ppir_op_load_temp)) {
244             ppir_load_node *l = ppir_node_to_load(node);
245             ppir_instr_update_src_pipeline(
246                instr, ppir_pipeline_reg_uniform, &l->dest, NULL);
247          }
248 
249          return true;
250       }
251 
252       return false;
253    }
254 }
255 
256 static struct {
257    int len;
258    char *name;
259 } ppir_instr_fields[] = {
260    [PPIR_INSTR_SLOT_VARYING] = { 4, "vary" },
261    [PPIR_INSTR_SLOT_TEXLD] = { 4, "texl"},
262    [PPIR_INSTR_SLOT_UNIFORM] = { 4, "unif" },
263    [PPIR_INSTR_SLOT_ALU_VEC_MUL] = { 4, "vmul" },
264    [PPIR_INSTR_SLOT_ALU_SCL_MUL] = { 4, "smul" },
265    [PPIR_INSTR_SLOT_ALU_VEC_ADD] = { 4, "vadd" },
266    [PPIR_INSTR_SLOT_ALU_SCL_ADD] = { 4, "sadd" },
267    [PPIR_INSTR_SLOT_ALU_COMBINE] = { 4, "comb" },
268    [PPIR_INSTR_SLOT_STORE_TEMP] = { 4, "stor" },
269    [PPIR_INSTR_SLOT_BRANCH] = { 4, "brch" },
270 };
271 
ppir_instr_print_list(ppir_compiler * comp)272 void ppir_instr_print_list(ppir_compiler *comp)
273 {
274    if (!(lima_debug & LIMA_DEBUG_PP))
275       return;
276 
277    printf("======ppir instr list======\n");
278    printf("      ");
279    for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++)
280       printf("%-*s ", ppir_instr_fields[i].len, ppir_instr_fields[i].name);
281    printf("const0|1\n");
282 
283    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
284       printf("-------block %3d-------\n", block->index);
285       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
286          printf("%c%03d: ", instr->stop ? '*' : ' ', instr->index);
287          for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
288             ppir_node *node = instr->slots[i];
289             if (node)
290                printf("%-*d ", ppir_instr_fields[i].len, node->index);
291             else
292                printf("%-*s ", ppir_instr_fields[i].len, "null");
293          }
294          for (int i = 0; i < 2; i++) {
295             if (i)
296                printf("| ");
297 
298             for (int j = 0; j < instr->constant[i].num; j++)
299                printf("%f ", instr->constant[i].value[j].f);
300          }
301          printf("\n");
302       }
303    }
304    printf("===========================\n");
305 }
306 
ppir_instr_print_sub(ppir_instr * instr)307 static void ppir_instr_print_sub(ppir_instr *instr)
308 {
309    printf("[%s%d",
310           instr->printed && !ppir_instr_is_leaf(instr) ? "+" : "",
311           instr->index);
312 
313    if (!instr->printed) {
314       ppir_instr_foreach_pred(instr, dep) {
315          ppir_instr_print_sub(dep->pred);
316       }
317 
318       instr->printed = true;
319    }
320 
321    printf("]");
322 }
323 
ppir_instr_print_dep(ppir_compiler * comp)324 void ppir_instr_print_dep(ppir_compiler *comp)
325 {
326    if (!(lima_debug & LIMA_DEBUG_PP))
327       return;
328 
329    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
330       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
331          instr->printed = false;
332       }
333    }
334 
335    printf("======ppir instr depend======\n");
336    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
337       printf("-------block %3d-------\n", block->index);
338       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
339          if (ppir_instr_is_root(instr)) {
340             ppir_instr_print_sub(instr);
341             printf("\n");
342          }
343       }
344    }
345    printf("=============================\n");
346 }
347