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