nv50: prepare for having multiple functions
[profile/ivi/mesa.git] / src / gallium / drivers / nv50 / nv50_pc_optimize.c
1 /*
2  * Copyright 2010 Christoph Bumiller
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, sublicense,
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 shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22
23 /* #define NV50PC_DEBUG */
24
25 #include "nv50_pc.h"
26
27 #define DESCEND_ARBITRARY(j, f)                                 \
28 do {                                                            \
29    b->pass_seq = ctx->pc->pass_seq;                             \
30                                                                 \
31    for (j = 0; j < 2; ++j)                                      \
32       if (b->out[j] && b->out[j]->pass_seq < ctx->pc->pass_seq) \
33          f(ctx, b->out[j]);                                       \
34 } while (0)
35
36 extern unsigned nv50_inst_min_size(struct nv_instruction *);
37
38 struct nv_pc_pass {
39    struct nv_pc *pc;
40 };
41
42 static INLINE boolean
43 values_equal(struct nv_value *a, struct nv_value *b)
44 {
45    /* XXX: sizes */
46    return (a->reg.file == b->reg.file && a->join->reg.id == b->join->reg.id);
47 }
48
49 static INLINE boolean
50 inst_commutation_check(struct nv_instruction *a,
51                        struct nv_instruction *b)
52 {
53    int si, di;
54
55    for (di = 0; di < 4; ++di) {
56       if (!a->def[di])
57          break;
58       for (si = 0; si < 5; ++si) {
59          if (!b->src[si])
60             continue;
61          if (values_equal(a->def[di], b->src[si]->value))
62             return FALSE;
63       }
64    }
65
66    if (b->flags_src && b->flags_src->value == a->flags_def)
67       return FALSE;
68
69    return TRUE;
70 }
71
72 /* Check whether we can swap the order of the instructions,
73  * where a & b may be either the earlier or the later one.
74  */
75 static boolean
76 inst_commutation_legal(struct nv_instruction *a,
77                        struct nv_instruction *b)
78 {
79    return inst_commutation_check(a, b) && inst_commutation_check(b, a);
80 }
81
82 static INLINE boolean
83 inst_cullable(struct nv_instruction *nvi)
84 {
85    return (!(nvi->is_terminator || nvi->is_join ||
86              nvi->target ||
87              nvi->fixed ||
88              nv_nvi_refcount(nvi)));
89 }
90
91 static INLINE boolean
92 nvi_isnop(struct nv_instruction *nvi)
93 {
94    if (nvi->opcode == NV_OP_EXPORT || nvi->opcode == NV_OP_UNDEF)
95       return TRUE;
96
97    /* NOTE: 'fixed' now only means that it shouldn't be optimized away,
98     *  but we can still remove it if it is a no-op move.
99     */
100    if (/* nvi->fixed || */
101        /* nvi->flags_src || */ /* cond. MOV to same register is still NOP */
102        nvi->flags_def ||
103        nvi->is_terminator ||
104        nvi->is_join)
105       return FALSE;
106
107    if (nvi->def[0] && nvi->def[0]->join->reg.id < 0)
108       return TRUE;
109
110    if (nvi->opcode != NV_OP_MOV && nvi->opcode != NV_OP_SELECT)
111       return FALSE;
112
113    if (nvi->def[0]->reg.file != nvi->src[0]->value->reg.file)
114       return FALSE;
115
116    if (nvi->src[0]->value->join->reg.id < 0) {
117       NV50_DBGMSG("nvi_isnop: orphaned value detected\n");
118       return TRUE;
119    }
120
121    if (nvi->opcode == NV_OP_SELECT)
122       if (!values_equal(nvi->def[0], nvi->src[1]->value))
123          return FALSE;
124
125    return values_equal(nvi->def[0], nvi->src[0]->value);
126 }
127
128 struct nv_pass {
129    struct nv_pc *pc;
130    int n;
131    void *priv;
132 };
133
134 static int
135 nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b);
136
137 static void
138 nv_pc_pass_pre_emission(void *priv, struct nv_basic_block *b)
139 {
140    struct nv_pc *pc = (struct nv_pc *)priv;
141    struct nv_basic_block *in;
142    struct nv_instruction *nvi, *next;
143    int j;
144    uint size, n32 = 0;
145
146    for (j = pc->num_blocks - 1; j >= 0 && !pc->bb_list[j]->bin_size; --j);
147    if (j >= 0) {
148       in = pc->bb_list[j];
149
150       /* check for no-op branches (BRA $PC+8) */
151       if (in->exit && in->exit->opcode == NV_OP_BRA && in->exit->target == b) {
152          in->bin_size -= 8;
153          pc->bin_size -= 8;
154
155          for (++j; j < pc->num_blocks; ++j)
156             pc->bb_list[j]->bin_pos -= 8;
157
158          nv_nvi_delete(in->exit);
159       }
160       b->bin_pos = in->bin_pos + in->bin_size;
161    }
162
163    pc->bb_list[pc->num_blocks++] = b;
164
165    /* visit node */
166
167    for (nvi = b->entry; nvi; nvi = next) {
168       next = nvi->next;
169       if (nvi_isnop(nvi))
170          nv_nvi_delete(nvi);
171    }
172
173    for (nvi = b->entry; nvi; nvi = next) {
174       next = nvi->next;
175
176       size = nv50_inst_min_size(nvi);
177       if (nvi->next && size < 8)
178          ++n32;
179       else
180       if ((n32 & 1) && nvi->next &&
181           nv50_inst_min_size(nvi->next) == 4 &&
182           inst_commutation_legal(nvi, nvi->next)) {
183          ++n32;
184          nv_nvi_permute(nvi, nvi->next);
185          next = nvi;
186       } else {
187          nvi->is_long = 1;
188
189          b->bin_size += n32 & 1;
190          if (n32 & 1)
191             nvi->prev->is_long = 1;
192          n32 = 0;
193       }
194       b->bin_size += 1 + nvi->is_long;
195    }
196
197    if (!b->entry) {
198       NV50_DBGMSG("block %p is now empty\n", b);
199    } else
200    if (!b->exit->is_long) {
201       assert(n32);
202       b->exit->is_long = 1;
203       b->bin_size += 1;
204
205       /* might have del'd a hole tail of instructions */
206       if (!b->exit->prev->is_long && !(n32 & 1)) {
207          b->bin_size += 1;
208          b->exit->prev->is_long = 1;
209       }
210    }
211    assert(!b->entry || (b->exit && b->exit->is_long));
212
213    pc->bin_size += b->bin_size *= 4;
214 }
215
216 static int
217 nv_pc_pass2(struct nv_pc *pc, struct nv_basic_block *root)
218 {
219    struct nv_pass pass;
220
221    pass.pc = pc;
222
223    pc->pass_seq++;
224
225    nv_pass_flatten(&pass, root);
226
227    nv_pc_pass_in_order(root, nv_pc_pass_pre_emission, pc);
228
229    return 0;
230 }
231
232 int
233 nv_pc_exec_pass2(struct nv_pc *pc)
234 {
235    int i, ret;
236
237    NV50_DBGMSG("preparing %u blocks for emission\n", pc->num_blocks);
238
239    pc->bb_list = CALLOC(pc->num_blocks, sizeof(pc->bb_list[0]));
240
241    pc->num_blocks = 0;
242
243    for (i = 0; i < pc->num_subroutines + 1; ++i)
244       if (pc->root[i] && (ret = nv_pc_pass2(pc, pc->root[i])))
245          return ret;
246    return 0;
247 }
248
249 static INLINE boolean
250 is_cmem_load(struct nv_instruction *nvi)
251 {
252    return (nvi->opcode == NV_OP_LDA &&
253            nvi->src[0]->value->reg.file >= NV_FILE_MEM_C(0) &&
254            nvi->src[0]->value->reg.file <= NV_FILE_MEM_C(15));
255 }
256
257 static INLINE boolean
258 is_smem_load(struct nv_instruction *nvi)
259 {
260    return (nvi->opcode == NV_OP_LDA &&
261            (nvi->src[0]->value->reg.file == NV_FILE_MEM_S ||
262             nvi->src[0]->value->reg.file <= NV_FILE_MEM_P));
263 }
264
265 static INLINE boolean
266 is_immd_move(struct nv_instruction *nvi)
267 {
268    return (nvi->opcode == NV_OP_MOV &&
269            nvi->src[0]->value->reg.file == NV_FILE_IMM);
270 }
271
272 static INLINE void
273 check_swap_src_0_1(struct nv_instruction *nvi)
274 {
275    static const ubyte cc_swapped[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
276
277    struct nv_ref *src0 = nvi->src[0], *src1 = nvi->src[1];
278
279    if (!nv_op_commutative(nvi->opcode))
280       return;
281    assert(src0 && src1);
282
283    if (src1->value->reg.file == NV_FILE_IMM)
284       return;
285
286    if (is_cmem_load(src0->value->insn)) {
287       if (!is_cmem_load(src1->value->insn)) {
288          nvi->src[0] = src1;
289          nvi->src[1] = src0;
290          /* debug_printf("swapping cmem load to 1\n"); */
291       }
292    } else
293    if (is_smem_load(src1->value->insn)) {
294       if (!is_smem_load(src0->value->insn)) {
295          nvi->src[0] = src1;
296          nvi->src[1] = src0;
297          /* debug_printf("swapping smem load to 0\n"); */
298       }
299    }
300
301    if (nvi->opcode == NV_OP_SET && nvi->src[0] != src0)
302       nvi->set_cond = cc_swapped[nvi->set_cond];
303 }
304
305 static int
306 nv_pass_fold_stores(struct nv_pass *ctx, struct nv_basic_block *b)
307 {
308    struct nv_instruction *nvi, *sti, *next;
309    int j;
310
311    for (sti = b->entry; sti; sti = next) {
312       next = sti->next;
313
314       /* only handling MOV to $oX here */
315       if (!sti->def[0] || sti->def[0]->reg.file != NV_FILE_OUT)
316          continue;
317       if (sti->opcode != NV_OP_MOV && sti->opcode != NV_OP_STA)
318          continue;
319
320       nvi = sti->src[0]->value->insn;
321       if (!nvi || nvi->opcode == NV_OP_PHI || nv_is_vector_op(nvi->opcode))
322          continue;
323       assert(nvi->def[0] == sti->src[0]->value);
324
325       if (nvi->def[0]->refc > 1)
326          continue;
327
328       /* cannot write to $oX when using immediate */
329       for (j = 0; j < 4 && nvi->src[j]; ++j)
330          if (nvi->src[j]->value->reg.file == NV_FILE_IMM)
331             break;
332       if (j < 4 && nvi->src[j])
333          continue;
334
335       nvi->def[0] = sti->def[0];
336       nvi->fixed = sti->fixed;
337
338       nv_nvi_delete(sti);
339    }
340    DESCEND_ARBITRARY(j, nv_pass_fold_stores);
341
342    return 0;
343 }
344
345 static int
346 nv_pass_fold_loads(struct nv_pass *ctx, struct nv_basic_block *b)
347 {
348    struct nv_instruction *nvi, *ld;
349    int j;
350
351    for (nvi = b->entry; nvi; nvi = nvi->next) {
352       check_swap_src_0_1(nvi);
353
354       for (j = 0; j < 3; ++j) {
355          if (!nvi->src[j])
356             break;
357          ld = nvi->src[j]->value->insn;
358          if (!ld)
359             continue;
360
361          if (is_immd_move(ld) && nv50_nvi_can_use_imm(nvi, j)) {
362             nv_reference(ctx->pc, &nvi->src[j], ld->src[0]->value);
363             continue;
364          }
365
366          if (ld->opcode != NV_OP_LDA)
367             continue;
368          if (!nv50_nvi_can_load(nvi, j, ld->src[0]->value))
369             continue;
370
371          if (j == 0 && ld->src[4]) /* can't load shared mem */
372             continue;
373
374          /* fold it ! */ /* XXX: ref->insn */
375          nv_reference(ctx->pc, &nvi->src[j], ld->src[0]->value);
376          if (ld->src[4])
377             nv_reference(ctx->pc, &nvi->src[4], ld->src[4]->value);
378
379          if (!nv_nvi_refcount(ld))
380             nv_nvi_delete(ld);
381       }
382    }
383    DESCEND_ARBITRARY(j, nv_pass_fold_loads);
384
385    return 0;
386 }
387
388 static int
389 nv_pass_lower_mods(struct nv_pass *ctx, struct nv_basic_block *b)
390 {
391    int j;
392    struct nv_instruction *nvi, *mi, *next;
393    ubyte mod;
394
395    for (nvi = b->entry; nvi; nvi = next) {
396       next = nvi->next;
397       if (nvi->opcode == NV_OP_SUB) {
398          nvi->opcode = NV_OP_ADD;
399          nvi->src[1]->mod ^= NV_MOD_NEG;
400       }
401
402       /* should not put any modifiers on NEG and ABS */
403       assert(nvi->opcode != NV_MOD_NEG || !nvi->src[0]->mod);
404       assert(nvi->opcode != NV_MOD_ABS || !nvi->src[0]->mod);
405
406       for (j = 0; j < 4; ++j) {
407          if (!nvi->src[j])
408             break;
409
410          mi = nvi->src[j]->value->insn;
411          if (!mi)
412             continue;
413          if (mi->def[0]->refc > 1)
414             continue;
415
416          if (mi->opcode == NV_OP_NEG) mod = NV_MOD_NEG;
417          else
418          if (mi->opcode == NV_OP_ABS) mod = NV_MOD_ABS;
419          else
420             continue;
421
422          if (nvi->opcode == NV_OP_ABS)
423             mod &= ~(NV_MOD_NEG | NV_MOD_ABS);
424          else
425          if (nvi->opcode == NV_OP_NEG && mod == NV_MOD_NEG) {
426             nvi->opcode = NV_OP_MOV;
427             mod = 0;
428          }
429
430          if (!(nv50_supported_src_mods(nvi->opcode, j) & mod))
431             continue;
432
433          nv_reference(ctx->pc, &nvi->src[j], mi->src[0]->value);
434
435          nvi->src[j]->mod ^= mod;
436       }
437
438       if (nvi->opcode == NV_OP_SAT) {
439          mi = nvi->src[0]->value->insn;
440
441          if ((mi->opcode == NV_OP_MAD) && !mi->flags_def) {
442             mi->saturate = 1;
443             mi->def[0] = nvi->def[0];
444             nv_nvi_delete(nvi);
445          }
446       }
447    }
448    DESCEND_ARBITRARY(j, nv_pass_lower_mods);
449
450    return 0;
451 }
452
453 #define SRC_IS_MUL(s) ((s)->insn && (s)->insn->opcode == NV_OP_MUL)
454
455 static void
456 modifiers_apply(uint32_t *val, ubyte type, ubyte mod)
457 {
458    if (mod & NV_MOD_ABS) {
459       if (type == NV_TYPE_F32)
460          *val &= 0x7fffffff;
461       else
462       if ((*val) & (1 << 31))
463          *val = ~(*val) + 1;
464    }
465    if (mod & NV_MOD_NEG) {
466       if (type == NV_TYPE_F32)
467          *val ^= 0x80000000;
468       else
469          *val = ~(*val) + 1;
470    }
471 }
472
473 static INLINE uint
474 modifiers_opcode(ubyte mod)
475 {
476    switch (mod) {
477    case NV_MOD_NEG: return NV_OP_NEG;
478    case NV_MOD_ABS: return NV_OP_ABS;
479    case 0:
480       return NV_OP_MOV;
481    default:
482       return NV_OP_NOP;
483    }
484 }
485
486 static void
487 constant_expression(struct nv_pc *pc, struct nv_instruction *nvi,
488                     struct nv_value *src0, struct nv_value *src1)
489 {
490    struct nv_value *val;
491    union {
492       float f32;
493       uint32_t u32;
494       int32_t s32;
495    } u0, u1, u;
496    ubyte type;
497
498    if (!nvi->def[0])
499       return;
500    type = nvi->def[0]->reg.type;
501
502    u.u32 = 0;
503    u0.u32 = src0->reg.imm.u32;
504    u1.u32 = src1->reg.imm.u32;
505
506    modifiers_apply(&u0.u32, type, nvi->src[0]->mod);
507    modifiers_apply(&u1.u32, type, nvi->src[1]->mod);
508
509    switch (nvi->opcode) {
510    case NV_OP_MAD:
511       if (nvi->src[2]->value->reg.file != NV_FILE_GPR)
512          return;
513       /* fall through */
514    case NV_OP_MUL:
515       switch (type) {
516       case NV_TYPE_F32: u.f32 = u0.f32 * u1.f32; break;
517       case NV_TYPE_U32: u.u32 = u0.u32 * u1.u32; break;
518       case NV_TYPE_S32: u.s32 = u0.s32 * u1.s32; break;
519       default:
520          assert(0);
521          break;
522       }
523       break;
524    case NV_OP_ADD:
525       switch (type) {
526       case NV_TYPE_F32: u.f32 = u0.f32 + u1.f32; break;
527       case NV_TYPE_U32: u.u32 = u0.u32 + u1.u32; break;
528       case NV_TYPE_S32: u.s32 = u0.s32 + u1.s32; break;
529       default:
530          assert(0);
531          break;
532       }
533       break;
534    case NV_OP_SUB:
535       switch (type) {
536       case NV_TYPE_F32: u.f32 = u0.f32 - u1.f32; break;
537       case NV_TYPE_U32: u.u32 = u0.u32 - u1.u32; break;
538       case NV_TYPE_S32: u.s32 = u0.s32 - u1.s32; break;
539       default:
540          assert(0);
541          break;
542       }
543       break;
544    default:
545       return;
546    }
547
548    nvi->opcode = NV_OP_MOV;
549
550    val = new_value(pc, NV_FILE_IMM, type);
551
552    val->reg.imm.u32 = u.u32;
553
554    nv_reference(pc, &nvi->src[1], NULL);
555    nv_reference(pc, &nvi->src[0], val);
556
557    if (nvi->src[2]) { /* from MAD */
558       nvi->src[1] = nvi->src[0];
559       nvi->src[0] = nvi->src[2];
560       nvi->src[2] = NULL;
561       nvi->opcode = NV_OP_ADD;
562    }
563 }
564
565 static void
566 constant_operand(struct nv_pc *pc,
567                  struct nv_instruction *nvi, struct nv_value *val, int s)
568 {
569    union {
570       float f32;
571       uint32_t u32;
572       int32_t s32;
573    } u;
574    int t = s ? 0 : 1;
575    uint op;
576    ubyte type;
577
578    if (!nvi->def[0])
579       return;
580    type = nvi->def[0]->reg.type;
581
582    u.u32 = val->reg.imm.u32;
583    modifiers_apply(&u.u32, type, nvi->src[s]->mod);
584
585    switch (nvi->opcode) {
586    case NV_OP_MUL:
587       if ((type == NV_TYPE_F32 && u.f32 == 1.0f) ||
588           (NV_TYPE_ISINT(type) && u.u32 == 1)) {
589          if ((op = modifiers_opcode(nvi->src[t]->mod)) == NV_OP_NOP)
590             break;
591          nvi->opcode = op;
592          nv_reference(pc, &nvi->src[s], NULL);
593          nvi->src[0] = nvi->src[t];
594          nvi->src[1] = NULL;
595       } else
596       if ((type == NV_TYPE_F32 && u.f32 == 2.0f) ||
597           (NV_TYPE_ISINT(type) && u.u32 == 2)) {
598          nvi->opcode = NV_OP_ADD;
599          nv_reference(pc, &nvi->src[s], nvi->src[t]->value);
600          nvi->src[s]->mod = nvi->src[t]->mod;
601       } else
602       if (type == NV_TYPE_F32 && u.f32 == -1.0f) {
603          if (nvi->src[t]->mod & NV_MOD_NEG)
604             nvi->opcode = NV_OP_MOV;
605          else
606             nvi->opcode = NV_OP_NEG;
607          nv_reference(pc, &nvi->src[s], NULL);
608          nvi->src[0] = nvi->src[t];
609          nvi->src[1] = NULL;
610       } else
611       if (type == NV_TYPE_F32 && u.f32 == -2.0f) {
612          nvi->opcode = NV_OP_ADD;
613          nv_reference(pc, &nvi->src[s], nvi->src[t]->value);
614          nvi->src[s]->mod = (nvi->src[t]->mod ^= NV_MOD_NEG);
615       } else
616       if (u.u32 == 0) {
617          nvi->opcode = NV_OP_MOV;
618          nv_reference(pc, &nvi->src[t], NULL);
619          if (s) {
620             nvi->src[0] = nvi->src[1];
621             nvi->src[1] = NULL;
622          }
623       }
624       break;
625    case NV_OP_ADD:
626       if (u.u32 == 0) {
627          if ((op = modifiers_opcode(nvi->src[t]->mod)) == NV_OP_NOP)
628             break;
629          nvi->opcode = op;
630          nv_reference(pc, &nvi->src[s], NULL);
631          nvi->src[0] = nvi->src[t];
632          nvi->src[1] = NULL;
633       }
634       break;
635    case NV_OP_RCP:
636       u.f32 = 1.0f / u.f32;
637       (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32;
638       nvi->opcode = NV_OP_MOV;
639       assert(s == 0);
640       nv_reference(pc, &nvi->src[0], val);
641       break;
642    case NV_OP_RSQ:
643       u.f32 = 1.0f / sqrtf(u.f32);
644       (val = new_value(pc, NV_FILE_IMM, NV_TYPE_F32))->reg.imm.f32 = u.f32;
645       nvi->opcode = NV_OP_MOV;
646       assert(s == 0);
647       nv_reference(pc, &nvi->src[0], val);
648       break;
649    default:
650       break;
651    }
652
653    if (nvi->opcode == NV_OP_MOV && nvi->flags_def) {
654       struct nv_instruction *cvt = new_instruction_at(pc, nvi, NV_OP_CVT);
655
656       nv_reference(pc, &cvt->src[0], nvi->def[0]);
657
658       cvt->flags_def = nvi->flags_def;
659       nvi->flags_def = NULL;
660    }
661 }
662
663 static int
664 nv_pass_lower_arith(struct nv_pass *ctx, struct nv_basic_block *b)
665 {
666    struct nv_instruction *nvi, *next;
667    int j;
668
669    for (nvi = b->entry; nvi; nvi = next) {
670       struct nv_value *src0, *src1, *src;
671       int mod;
672
673       next = nvi->next;
674
675       src0 = nvcg_find_immediate(nvi->src[0]);
676       src1 = nvcg_find_immediate(nvi->src[1]);
677
678       if (src0 && src1)
679          constant_expression(ctx->pc, nvi, src0, src1);
680       else {
681          if (src0)
682             constant_operand(ctx->pc, nvi, src0, 0);
683          else
684          if (src1)
685             constant_operand(ctx->pc, nvi, src1, 1);
686       }
687
688       /* try to combine MUL, ADD into MAD */
689       if (nvi->opcode != NV_OP_ADD)
690          continue;
691
692       src0 = nvi->src[0]->value;
693       src1 = nvi->src[1]->value;
694
695       if (SRC_IS_MUL(src0) && src0->refc == 1)
696          src = src0;
697       else
698       if (SRC_IS_MUL(src1) && src1->refc == 1)
699          src = src1;
700       else
701          continue;
702
703       nvi->opcode = NV_OP_MAD;
704       mod = nvi->src[(src == src0) ? 0 : 1]->mod;
705       nv_reference(ctx->pc, &nvi->src[(src == src0) ? 0 : 1], NULL);
706       nvi->src[2] = nvi->src[(src == src0) ? 1 : 0];
707
708       assert(!(mod & ~NV_MOD_NEG));
709       nvi->src[0] = new_ref(ctx->pc, src->insn->src[0]->value);
710       nvi->src[1] = new_ref(ctx->pc, src->insn->src[1]->value);
711       nvi->src[0]->mod = src->insn->src[0]->mod ^ mod;
712       nvi->src[1]->mod = src->insn->src[1]->mod;
713    }
714    DESCEND_ARBITRARY(j, nv_pass_lower_arith);
715
716    return 0;
717 }
718
719 /* TODO: redundant store elimination */
720
721 struct load_record {
722    struct load_record *next;
723    uint64_t data;
724    struct nv_value *value;
725 };
726
727 #define LOAD_RECORD_POOL_SIZE 1024
728
729 struct nv_pass_reld_elim {
730    struct nv_pc *pc;
731
732    struct load_record *imm;
733    struct load_record *mem_s;
734    struct load_record *mem_v;
735    struct load_record *mem_c[16];
736    struct load_record *mem_l;
737
738    struct load_record pool[LOAD_RECORD_POOL_SIZE];
739    int alloc;
740 };
741
742 static int
743 nv_pass_reload_elim(struct nv_pass_reld_elim *ctx, struct nv_basic_block *b)
744 {
745    struct load_record **rec, *it;
746    struct nv_instruction *ld, *next;
747    uint64_t data;
748    struct nv_value *val;
749    int j;
750
751    for (ld = b->entry; ld; ld = next) {
752       next = ld->next;
753       if (!ld->src[0])
754          continue;
755       val = ld->src[0]->value;
756       rec = NULL;
757
758       if (ld->opcode == NV_OP_LINTERP || ld->opcode == NV_OP_PINTERP) {
759          data = val->reg.id;
760          rec = &ctx->mem_v;
761       } else
762       if (ld->opcode == NV_OP_LDA) {
763          data = val->reg.id;
764          if (val->reg.file >= NV_FILE_MEM_C(0) &&
765              val->reg.file <= NV_FILE_MEM_C(15))
766             rec = &ctx->mem_c[val->reg.file - NV_FILE_MEM_C(0)];
767          else
768          if (val->reg.file == NV_FILE_MEM_S)
769             rec = &ctx->mem_s;
770          else
771          if (val->reg.file == NV_FILE_MEM_L)
772             rec = &ctx->mem_l;
773       } else
774       if ((ld->opcode == NV_OP_MOV) && (val->reg.file == NV_FILE_IMM)) {
775          data = val->reg.imm.u32;
776          rec = &ctx->imm;
777       }
778
779       if (!rec || !ld->def[0]->refc)
780          continue;
781
782       for (it = *rec; it; it = it->next)
783          if (it->data == data)
784             break;
785
786       if (it) {
787          if (ld->def[0]->reg.id >= 0)
788             it->value = ld->def[0];
789          else
790          if (!ld->fixed)
791             nvcg_replace_value(ctx->pc, ld->def[0], it->value);
792       } else {
793          if (ctx->alloc == LOAD_RECORD_POOL_SIZE)
794             continue;
795          it = &ctx->pool[ctx->alloc++];
796          it->next = *rec;
797          it->data = data;
798          it->value = ld->def[0];
799          *rec = it;
800       }
801    }
802
803    ctx->imm = NULL;
804    ctx->mem_s = NULL;
805    ctx->mem_v = NULL;
806    for (j = 0; j < 16; ++j)
807       ctx->mem_c[j] = NULL;
808    ctx->mem_l = NULL;
809    ctx->alloc = 0;
810
811    DESCEND_ARBITRARY(j, nv_pass_reload_elim);
812
813    return 0;
814 }
815
816 static int
817 nv_pass_tex_mask(struct nv_pass *ctx, struct nv_basic_block *b)
818 {
819    int i, c, j;
820
821    for (i = 0; i < ctx->pc->num_instructions; ++i) {
822       struct nv_instruction *nvi = &ctx->pc->instructions[i];
823       struct nv_value *def[4];
824
825       if (!nv_is_vector_op(nvi->opcode))
826          continue;
827       nvi->tex_mask = 0;
828
829       for (c = 0; c < 4; ++c) {
830          if (nvi->def[c]->refc)
831             nvi->tex_mask |= 1 << c;
832          def[c] = nvi->def[c];
833       }
834
835       j = 0;
836       for (c = 0; c < 4; ++c)
837          if (nvi->tex_mask & (1 << c))
838             nvi->def[j++] = def[c];
839       for (c = 0; c < 4; ++c)
840          if (!(nvi->tex_mask & (1 << c)))
841            nvi->def[j++] = def[c];
842       assert(j == 4);
843    }
844    return 0;
845 }
846
847 struct nv_pass_dce {
848    struct nv_pc *pc;
849    uint removed;
850 };
851
852 static int
853 nv_pass_dce(struct nv_pass_dce *ctx, struct nv_basic_block *b)
854 {
855    int j;
856    struct nv_instruction *nvi, *next;
857
858    for (nvi = b->phi ? b->phi : b->entry; nvi; nvi = next) {
859       next = nvi->next;
860
861       if (inst_cullable(nvi)) {
862          nv_nvi_delete(nvi);
863
864          ++ctx->removed;
865       }
866    }
867    DESCEND_ARBITRARY(j, nv_pass_dce);
868
869    return 0;
870 }
871
872 /* Register allocation inserted ELSE blocks for all IF/ENDIF without ELSE.
873  * Returns TRUE if @bb initiates an IF/ELSE/ENDIF clause, or is an IF with
874  * BREAK and dummy ELSE block.
875  */
876 static INLINE boolean
877 bb_is_if_else_endif(struct nv_basic_block *bb)
878 {
879    if (!bb->out[0] || !bb->out[1])
880       return FALSE;
881
882    if (bb->out[0]->out_kind[0] == CFG_EDGE_LOOP_LEAVE) {
883       return (bb->out[0]->out[1] == bb->out[1]->out[0] &&
884               !bb->out[1]->out[1]);
885    } else {
886       return (bb->out[0]->out[0] == bb->out[1]->out[0] &&
887               !bb->out[0]->out[1] &&
888               !bb->out[1]->out[1]);
889    }
890 }
891
892 /* predicate instructions and remove branch at the end */
893 static void
894 predicate_instructions(struct nv_pc *pc, struct nv_basic_block *b,
895                        struct nv_value *p, ubyte cc)
896 {
897    struct nv_instruction *nvi;
898
899    if (!b->entry)
900       return;
901    for (nvi = b->entry; nvi->next; nvi = nvi->next) {
902       if (!nvi_isnop(nvi)) {
903          nvi->cc = cc;
904          nv_reference(pc, &nvi->flags_src, p);
905       }
906    }
907
908    if (nvi->opcode == NV_OP_BRA)
909       nv_nvi_delete(nvi);
910    else
911    if (!nvi_isnop(nvi)) {
912       nvi->cc = cc;
913       nv_reference(pc, &nvi->flags_src, p);
914    }
915 }
916
917 /* NOTE: Run this after register allocation, we can just cut out the cflow
918  * instructions and hook the predicates to the conditional OPs if they are
919  * not using immediates; better than inserting SELECT to join definitions.
920  *
921  * NOTE: Should adapt prior optimization to make this possible more often.
922  */
923 static int
924 nv_pass_flatten(struct nv_pass *ctx, struct nv_basic_block *b)
925 {
926    struct nv_instruction *nvi;
927    struct nv_value *pred;
928    int i;
929    int n0 = 0, n1 = 0;
930
931    if (bb_is_if_else_endif(b)) {
932
933       NV50_DBGMSG("pass_flatten: IF/ELSE/ENDIF construct at BB:%i\n", b->id);
934
935       for (n0 = 0, nvi = b->out[0]->entry; nvi; nvi = nvi->next, ++n0)
936          if (!nv50_nvi_can_predicate(nvi))
937             break;
938       if (!nvi) {
939          for (n1 = 0, nvi = b->out[1]->entry; nvi; nvi = nvi->next, ++n1)
940             if (!nv50_nvi_can_predicate(nvi))
941                break;
942 #ifdef NV50_PC_DEBUG
943          if (nvi) {
944             debug_printf("cannot predicate: "); nv_print_instruction(nvi);
945          }
946       } else {
947          debug_printf("cannot predicate: "); nv_print_instruction(nvi);
948 #endif
949       }
950
951       if (!nvi && n0 < 12 && n1 < 12) { /* 12 as arbitrary limit */
952          assert(b->exit && b->exit->flags_src);
953          pred = b->exit->flags_src->value;
954
955          predicate_instructions(ctx->pc, b->out[0], pred, NV_CC_NE | NV_CC_U);
956          predicate_instructions(ctx->pc, b->out[1], pred, NV_CC_EQ);
957
958          assert(b->exit && b->exit->opcode == NV_OP_BRA);
959          nv_nvi_delete(b->exit);
960
961          if (b->exit && b->exit->opcode == NV_OP_JOINAT)
962             nv_nvi_delete(b->exit);
963
964          i = (b->out[0]->out_kind[0] == CFG_EDGE_LOOP_LEAVE) ? 1 : 0;
965
966          if ((nvi = b->out[0]->out[i]->entry)) {
967             nvi->is_join = 0;
968             if (nvi->opcode == NV_OP_JOIN)
969                nv_nvi_delete(nvi);
970          }
971       }
972    }
973    DESCEND_ARBITRARY(i, nv_pass_flatten);
974
975    return 0;
976 }
977
978 /* local common subexpression elimination, stupid O(n^2) implementation */
979 static int
980 nv_pass_cse(struct nv_pass *ctx, struct nv_basic_block *b)
981 {
982    struct nv_instruction *ir, *ik, *next;
983    struct nv_instruction *entry = b->phi ? b->phi : b->entry;
984    int s;
985    unsigned int reps;
986
987    do {
988       reps = 0;
989       for (ir = entry; ir; ir = next) {
990          next = ir->next;
991          for (ik = entry; ik != ir; ik = ik->next) {
992             if (ir->opcode != ik->opcode || ir->fixed)
993                continue;
994
995             if (!ir->def[0] || !ik->def[0] ||
996                 ik->opcode == NV_OP_LDA ||
997                 ik->opcode == NV_OP_STA ||
998                 ik->opcode == NV_OP_MOV ||
999                 nv_is_vector_op(ik->opcode))
1000                continue; /* ignore loads, stores & moves */
1001
1002             if (ik->src[4] || ir->src[4])
1003                continue; /* don't mess with address registers */
1004
1005             if (ik->flags_src || ir->flags_src ||
1006                 ik->flags_def || ir->flags_def)
1007                continue; /* and also not with flags, for now */
1008
1009             if (ik->def[0]->reg.file == NV_FILE_OUT ||
1010                 ir->def[0]->reg.file == NV_FILE_OUT ||
1011                 !values_equal(ik->def[0], ir->def[0]))
1012                continue;
1013
1014             for (s = 0; s < 3; ++s) {
1015                struct nv_value *a, *b;
1016
1017                if (!ik->src[s]) {
1018                   if (ir->src[s])
1019                      break;
1020                   continue;
1021                }
1022                if (ik->src[s]->mod != ir->src[s]->mod)
1023                   break;
1024                a = ik->src[s]->value;
1025                b = ir->src[s]->value;
1026                if (a == b)
1027                   continue;
1028                if (a->reg.file != b->reg.file ||
1029                    a->reg.id < 0 ||
1030                    a->reg.id != b->reg.id)
1031                   break;
1032             }
1033             if (s == 3) {
1034                nv_nvi_delete(ir);
1035                ++reps;
1036                nvcg_replace_value(ctx->pc, ir->def[0], ik->def[0]);
1037                break;
1038             }
1039          }
1040       }
1041    } while(reps);
1042
1043    DESCEND_ARBITRARY(s, nv_pass_cse);
1044
1045    return 0;
1046 }
1047
1048 static int
1049 nv_pc_pass0(struct nv_pc *pc, struct nv_basic_block *root)
1050 {
1051    struct nv_pass_reld_elim *reldelim;
1052    struct nv_pass pass;
1053    struct nv_pass_dce dce;
1054    int ret;
1055
1056    pass.n = 0;
1057    pass.pc = pc;
1058
1059    /* Do this first, so we don't have to pay attention
1060     * to whether sources are supported memory loads.
1061     */
1062    pc->pass_seq++;
1063    ret = nv_pass_lower_arith(&pass, root);
1064    if (ret)
1065       return ret;
1066
1067    pc->pass_seq++;
1068    ret = nv_pass_fold_loads(&pass, root);
1069    if (ret)
1070       return ret;
1071
1072    pc->pass_seq++;
1073    ret = nv_pass_fold_stores(&pass, root);
1074    if (ret)
1075       return ret;
1076
1077    reldelim = CALLOC_STRUCT(nv_pass_reld_elim);
1078    reldelim->pc = pc;
1079    pc->pass_seq++;
1080    ret = nv_pass_reload_elim(reldelim, root);
1081    FREE(reldelim);
1082    if (ret)
1083       return ret;
1084
1085    pc->pass_seq++;
1086    ret = nv_pass_cse(&pass, root);
1087    if (ret)
1088       return ret;
1089
1090    pc->pass_seq++;
1091    ret = nv_pass_lower_mods(&pass, root);
1092    if (ret)
1093       return ret;
1094
1095    dce.pc = pc;
1096    do {
1097       dce.removed = 0;
1098       pc->pass_seq++;
1099       ret = nv_pass_dce(&dce, root);
1100       if (ret)
1101          return ret;
1102    } while (dce.removed);
1103
1104    ret = nv_pass_tex_mask(&pass, root);
1105    if (ret)
1106       return ret;
1107
1108    return ret;
1109 }
1110
1111 int
1112 nv_pc_exec_pass0(struct nv_pc *pc)
1113 {
1114    int i, ret;
1115
1116    for (i = 0; i < pc->num_subroutines + 1; ++i)
1117       if (pc->root[i] && (ret = nv_pc_pass0(pc, pc->root[i])))
1118          return ret;
1119    return 0;
1120 }