• 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             ppir_node *succ = ppir_node_first_succ(node);
190             ppir_src *src = NULL;
191             for (int s = 0; s < ppir_node_get_src_num(succ); s++) {
192                src = ppir_node_get_src(succ, s);
193                if (src->node == node)
194                   break;
195             }
196             assert(src->node == node);
197 
198             instr->constant[i] = ic;
199             ppir_update_src_pipeline(ppir_pipeline_reg_const0 + i, src,
200                                      &c->dest, swizzle);
201             break;
202          }
203       }
204 
205       /* no const slot can insert */
206       if (i == 2)
207          return false;
208 
209       return true;
210    }
211    else {
212       int *slots = ppir_op_infos[node->op].slots;
213       for (int i = 0; slots[i] != PPIR_INSTR_SLOT_END; i++) {
214          int pos = slots[i];
215 
216          if (instr->slots[pos]) {
217             /* node already in this instr, i.e. load_uniform */
218             if (instr->slots[pos] == node)
219                return true;
220             else
221                continue;
222          }
223 
224          /* ^fmul dests (e.g. condition for select) can only be
225           * scheduled to ALU_SCL_MUL */
226          if (pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {
227             ppir_dest *dest = ppir_node_get_dest(node);
228             if (dest && dest->type == ppir_target_pipeline &&
229                 dest->pipeline == ppir_pipeline_reg_fmul)
230             continue;
231          }
232 
233          if (pos == PPIR_INSTR_SLOT_ALU_SCL_MUL ||
234              pos == PPIR_INSTR_SLOT_ALU_SCL_ADD) {
235             ppir_dest *dest = ppir_node_get_dest(node);
236             if (!ppir_target_is_scalar(dest))
237                continue;
238          }
239 
240          instr->slots[pos] = node;
241          node->instr = instr;
242          node->instr_pos = pos;
243 
244          if ((node->op == ppir_op_load_uniform) || (node->op == ppir_op_load_temp)) {
245             ppir_load_node *l = ppir_node_to_load(node);
246             ppir_instr_update_src_pipeline(
247                instr, ppir_pipeline_reg_uniform, &l->dest, NULL);
248          }
249 
250          return true;
251       }
252 
253       return false;
254    }
255 }
256 
257 static struct {
258    int len;
259    char *name;
260 } ppir_instr_fields[] = {
261    [PPIR_INSTR_SLOT_VARYING] = { 4, "vary" },
262    [PPIR_INSTR_SLOT_TEXLD] = { 4, "texl"},
263    [PPIR_INSTR_SLOT_UNIFORM] = { 4, "unif" },
264    [PPIR_INSTR_SLOT_ALU_VEC_MUL] = { 4, "vmul" },
265    [PPIR_INSTR_SLOT_ALU_SCL_MUL] = { 4, "smul" },
266    [PPIR_INSTR_SLOT_ALU_VEC_ADD] = { 4, "vadd" },
267    [PPIR_INSTR_SLOT_ALU_SCL_ADD] = { 4, "sadd" },
268    [PPIR_INSTR_SLOT_ALU_COMBINE] = { 4, "comb" },
269    [PPIR_INSTR_SLOT_STORE_TEMP] = { 4, "stor" },
270    [PPIR_INSTR_SLOT_BRANCH] = { 4, "brch" },
271 };
272 
ppir_instr_print_list(ppir_compiler * comp)273 void ppir_instr_print_list(ppir_compiler *comp)
274 {
275    if (!(lima_debug & LIMA_DEBUG_PP))
276       return;
277 
278    printf("======ppir instr list======\n");
279    printf("      ");
280    for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++)
281       printf("%-*s ", ppir_instr_fields[i].len, ppir_instr_fields[i].name);
282    printf("const0|1\n");
283 
284    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
285       printf("-------block %3d-------\n", block->index);
286       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
287          printf("%c%03d: ", instr->is_end ? '*' : ' ', instr->index);
288          for (int i = 0; i < PPIR_INSTR_SLOT_NUM; i++) {
289             ppir_node *node = instr->slots[i];
290             if (node)
291                printf("%-*d ", ppir_instr_fields[i].len, node->index);
292             else
293                printf("%-*s ", ppir_instr_fields[i].len, "null");
294          }
295          for (int i = 0; i < 2; i++) {
296             if (i)
297                printf("| ");
298 
299             for (int j = 0; j < instr->constant[i].num; j++)
300                printf("%f ", instr->constant[i].value[j].f);
301          }
302          printf("\n");
303       }
304    }
305    printf("===========================\n");
306 }
307 
ppir_instr_print_sub(ppir_instr * instr)308 static void ppir_instr_print_sub(ppir_instr *instr)
309 {
310    printf("[%s%d",
311           instr->printed && !ppir_instr_is_leaf(instr) ? "+" : "",
312           instr->index);
313 
314    if (!instr->printed) {
315       ppir_instr_foreach_pred(instr, dep) {
316          ppir_instr_print_sub(dep->pred);
317       }
318 
319       instr->printed = true;
320    }
321 
322    printf("]");
323 }
324 
ppir_instr_print_dep(ppir_compiler * comp)325 void ppir_instr_print_dep(ppir_compiler *comp)
326 {
327    if (!(lima_debug & LIMA_DEBUG_PP))
328       return;
329 
330    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
331       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
332          instr->printed = false;
333       }
334    }
335 
336    printf("======ppir instr depend======\n");
337    list_for_each_entry(ppir_block, block, &comp->block_list, list) {
338       printf("-------block %3d-------\n", block->index);
339       list_for_each_entry(ppir_instr, instr, &block->instr_list, list) {
340          if (ppir_instr_is_root(instr)) {
341             ppir_instr_print_sub(instr);
342             printf("\n");
343          }
344       }
345    }
346    printf("=============================\n");
347 }
348