nv50/ir/tgsi: handle inferSrcType(NOT) to be u32
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir.cpp
1 /*
2 * Copyright 2011 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 #include "nv50_ir.h"
24 #include "nv50_ir_target.h"
25 #include "nv50_ir_driver.h"
26
27 extern "C" {
28 #include "nv50/nv50_program.h"
29 #include "nv50/nv50_debug.h"
30 }
31
32 namespace nv50_ir {
33
34 Modifier::Modifier(operation op)
35 {
36 switch (op) {
37 case OP_NEG: bits = NV50_IR_MOD_NEG; break;
38 case OP_ABS: bits = NV50_IR_MOD_ABS; break;
39 case OP_SAT: bits = NV50_IR_MOD_SAT; break;
40 case OP_NOT: bits = NV50_IR_MOD_NOT; break;
41 default:
42 bits = 0;
43 break;
44 }
45 }
46
47 Modifier Modifier::operator*(const Modifier m) const
48 {
49 unsigned int a, b, c;
50
51 b = m.bits;
52 if (this->bits & NV50_IR_MOD_ABS)
53 b &= ~NV50_IR_MOD_NEG;
54
55 a = (this->bits ^ b) & (NV50_IR_MOD_NOT | NV50_IR_MOD_NEG);
56 c = (this->bits | m.bits) & (NV50_IR_MOD_ABS | NV50_IR_MOD_SAT);
57
58 return Modifier(a | c);
59 }
60
61 ValueRef::ValueRef() : value(0), insn(0), next(this), prev(this)
62 {
63 indirect[0] = -1;
64 indirect[1] = -1;
65 usedAsPtr = false;
66 }
67
68 ValueRef::~ValueRef()
69 {
70 this->set(NULL);
71 }
72
73 ImmediateValue *ValueRef::getImmediate() const
74 {
75 Value *src = value;
76
77 while (src) {
78 if (src->reg.file == FILE_IMMEDIATE)
79 return src->asImm();
80
81 Instruction *insn = src->getUniqueInsn();
82
83 src = (insn && insn->op == OP_MOV) ? insn->getSrc(0) : NULL;
84 }
85 return NULL;
86 }
87
88 ValueDef::ValueDef() : value(0), insn(0), next(this), prev(this)
89 {
90 // nothing to do
91 }
92
93 ValueDef::~ValueDef()
94 {
95 this->set(NULL);
96 }
97
98 void
99 ValueRef::set(const ValueRef &ref)
100 {
101 this->set(ref.get());
102 mod = ref.mod;
103 indirect[0] = ref.indirect[0];
104 indirect[1] = ref.indirect[1];
105 }
106
107 void
108 ValueRef::set(Value *refVal)
109 {
110 if (value == refVal)
111 return;
112 if (value) {
113 if (value->uses == this)
114 value->uses = (next == this) ? NULL : next;
115 value->unref();
116 DLLIST_DEL(this);
117 }
118
119 if (refVal) {
120 if (refVal->uses)
121 DLLIST_ADDTAIL(refVal->uses, this);
122 else
123 refVal->uses = this;
124 refVal->ref();
125 }
126 value = refVal;
127 }
128
129 void
130 ValueDef::set(Value *defVal)
131 {
132 assert(next != this || prev == this); // check that SSA hack isn't active
133
134 if (value == defVal)
135 return;
136 if (value) {
137 if (value->defs == this)
138 value->defs = (next == this) ? NULL : next;
139 DLLIST_DEL(this);
140 }
141
142 if (defVal) {
143 if (defVal->defs)
144 DLLIST_ADDTAIL(defVal->defs, this);
145 else
146 defVal->defs = this;
147 }
148 value = defVal;
149 }
150
151 // TODO: make me faster by using a safe iterator
152 void
153 ValueDef::replace(Value *repVal, bool doSet)
154 {
155 ValueRef **refs = new ValueRef * [value->refCount()];
156 int n = 0;
157
158 if (!refs && value->refCount())
159 FATAL("memory allocation failed");
160
161 for (ValueRef::Iterator iter = value->uses->iterator(); !iter.end();
162 iter.next()) {
163 assert(n < value->refCount());
164 refs[n++] = iter.get();
165 }
166 while (n)
167 refs[--n]->set(repVal);
168
169 if (doSet)
170 this->set(repVal);
171
172 if (refs)
173 delete[] refs;
174 }
175
176 void
177 ValueDef::mergeDefs(ValueDef *join)
178 {
179 DLLIST_MERGE(this, join, ValueDef *);
180 }
181
182 Value::Value()
183 {
184 refCnt = 0;
185 uses = NULL;
186 defs = NULL;
187 join = this;
188
189 memset(&reg, 0, sizeof(reg));
190 reg.size = 4;
191 }
192
193 bool
194 Value::coalesce(Value *jval, bool force)
195 {
196 Value *repr = this->join; // new representative
197 Value *jrep = jval->join;
198
199 if (reg.file != jval->reg.file || reg.size != jval->reg.size) {
200 if (!force)
201 return false;
202 ERROR("forced coalescing of values of different sizes/files");
203 }
204
205 if (!force && (repr->reg.data.id != jrep->reg.data.id)) {
206 if (repr->reg.data.id >= 0 &&
207 jrep->reg.data.id >= 0)
208 return false;
209 if (jrep->reg.data.id >= 0) {
210 repr = jval->join;
211 jrep = this->join;
212 jval = this;
213 }
214
215 // need to check all fixed register values of the program for overlap
216 Function *func = defs->getInsn()->bb->getFunction();
217
218 // TODO: put values in by register-id bins per function
219 ArrayList::Iterator iter = func->allLValues.iterator();
220 for (; !iter.end(); iter.next()) {
221 Value *fixed = reinterpret_cast<Value *>(iter.get());
222 assert(fixed);
223 if (fixed->reg.data.id == repr->reg.data.id)
224 if (fixed->livei.overlaps(jrep->livei))
225 return false;
226 }
227 }
228 if (repr->livei.overlaps(jrep->livei)) {
229 if (!force)
230 return false;
231 // do we really want this ? if at all, only for constraint ops
232 INFO("NOTE: forced coalescing with live range overlap\n");
233 }
234
235 ValueDef::Iterator iter = jrep->defs->iterator();
236 for (; !iter.end(); iter.next())
237 iter.get()->get()->join = repr;
238
239 repr->defs->mergeDefs(jrep->defs);
240 repr->livei.unify(jrep->livei);
241
242 assert(repr->join == repr && jval->join == repr);
243 return true;
244 }
245
246 LValue::LValue(Function *fn, DataFile file)
247 {
248 reg.file = file;
249 reg.size = (file != FILE_PREDICATE) ? 4 : 1;
250 reg.data.id = -1;
251
252 affinity = -1;
253
254 fn->add(this, this->id);
255 }
256
257 LValue::LValue(Function *fn, LValue *lval)
258 {
259 assert(lval);
260
261 reg.file = lval->reg.file;
262 reg.size = lval->reg.size;
263 reg.data.id = -1;
264
265 affinity = -1;
266
267 fn->add(this, this->id);
268 }
269
270 Value *LValue::clone(Function *func) const
271 {
272 LValue *that = new_LValue(func, reg.file);
273
274 that->reg.size = this->reg.size;
275 that->reg.type = this->reg.type;
276 that->reg.data = this->reg.data;
277
278 return that;
279 }
280
281 Symbol::Symbol(Program *prog, DataFile f, ubyte fidx)
282 {
283 baseSym = NULL;
284
285 reg.file = f;
286 reg.fileIndex = fidx;
287 reg.data.offset = 0;
288
289 prog->add(this, this->id);
290 }
291
292 Value *
293 Symbol::clone(Function *func) const
294 {
295 Program *prog = func->getProgram();
296
297 Symbol *that = new_Symbol(prog, reg.file, reg.fileIndex);
298
299 that->reg.size = this->reg.size;
300 that->reg.type = this->reg.type;
301 that->reg.data = this->reg.data;
302
303 that->baseSym = this->baseSym;
304
305 return that;
306 }
307
308 ImmediateValue::ImmediateValue(Program *prog, uint32_t uval)
309 {
310 memset(&reg, 0, sizeof(reg));
311
312 reg.file = FILE_IMMEDIATE;
313 reg.size = 4;
314 reg.type = TYPE_U32;
315
316 reg.data.u32 = uval;
317
318 prog->add(this, this->id);
319 }
320
321 ImmediateValue::ImmediateValue(Program *prog, float fval)
322 {
323 memset(&reg, 0, sizeof(reg));
324
325 reg.file = FILE_IMMEDIATE;
326 reg.size = 4;
327 reg.type = TYPE_F32;
328
329 reg.data.f32 = fval;
330
331 prog->add(this, this->id);
332 }
333
334 ImmediateValue::ImmediateValue(Program *prog, double dval)
335 {
336 memset(&reg, 0, sizeof(reg));
337
338 reg.file = FILE_IMMEDIATE;
339 reg.size = 8;
340 reg.type = TYPE_F64;
341
342 reg.data.f64 = dval;
343
344 prog->add(this, this->id);
345 }
346
347 ImmediateValue::ImmediateValue(const ImmediateValue *proto, DataType ty)
348 {
349 reg = proto->reg;
350
351 reg.type = ty;
352 reg.size = typeSizeof(ty);
353 }
354
355 bool
356 ImmediateValue::isInteger(const int i) const
357 {
358 switch (reg.type) {
359 case TYPE_S8:
360 return reg.data.s8 == i;
361 case TYPE_U8:
362 return reg.data.u8 == i;
363 case TYPE_S16:
364 return reg.data.s16 == i;
365 case TYPE_U16:
366 return reg.data.u16 == i;
367 case TYPE_S32:
368 case TYPE_U32:
369 return reg.data.s32 == i; // as if ...
370 case TYPE_F32:
371 return reg.data.f32 == static_cast<float>(i);
372 case TYPE_F64:
373 return reg.data.f64 == static_cast<double>(i);
374 default:
375 return false;
376 }
377 }
378
379 bool
380 ImmediateValue::isNegative() const
381 {
382 switch (reg.type) {
383 case TYPE_S8: return reg.data.s8 < 0;
384 case TYPE_S16: return reg.data.s16 < 0;
385 case TYPE_S32:
386 case TYPE_U32: return reg.data.s32 < 0;
387 case TYPE_F32: return reg.data.u32 & (1 << 31);
388 case TYPE_F64: return reg.data.u64 & (1ULL << 63);
389 default:
390 return false;
391 }
392 }
393
394 bool
395 ImmediateValue::isPow2() const
396 {
397 switch (reg.type) {
398 case TYPE_U8:
399 case TYPE_U16:
400 case TYPE_U32: return util_is_power_of_two(reg.data.u32);
401 default:
402 return false;
403 }
404 }
405
406 void
407 ImmediateValue::applyLog2()
408 {
409 switch (reg.type) {
410 case TYPE_S8:
411 case TYPE_S16:
412 case TYPE_S32:
413 assert(!this->isNegative());
414 // fall through
415 case TYPE_U8:
416 case TYPE_U16:
417 case TYPE_U32:
418 reg.data.u32 = util_logbase2(reg.data.u32);
419 break;
420 case TYPE_F32:
421 reg.data.f32 = log2f(reg.data.f32);
422 break;
423 case TYPE_F64:
424 reg.data.f64 = log2(reg.data.f64);
425 break;
426 default:
427 assert(0);
428 break;
429 }
430 }
431
432 bool
433 ImmediateValue::compare(CondCode cc, float fval) const
434 {
435 if (reg.type != TYPE_F32)
436 ERROR("immediate value is not of type f32");
437
438 switch (static_cast<CondCode>(cc & 7)) {
439 case CC_TR: return true;
440 case CC_FL: return false;
441 case CC_LT: return reg.data.f32 < fval;
442 case CC_LE: return reg.data.f32 <= fval;
443 case CC_GT: return reg.data.f32 > fval;
444 case CC_GE: return reg.data.f32 >= fval;
445 case CC_EQ: return reg.data.f32 == fval;
446 case CC_NE: return reg.data.f32 != fval;
447 default:
448 assert(0);
449 return false;
450 }
451 }
452
453 bool
454 Value::interfers(const Value *that) const
455 {
456 uint32_t idA, idB;
457
458 if (that->reg.file != reg.file || that->reg.fileIndex != reg.fileIndex)
459 return false;
460 if (this->asImm())
461 return false;
462
463 if (this->asSym()) {
464 idA = this->join->reg.data.offset;
465 idB = that->join->reg.data.offset;
466 } else {
467 idA = this->join->reg.data.id * this->reg.size;
468 idB = that->join->reg.data.id * that->reg.size;
469 }
470
471 if (idA < idB)
472 return (idA + this->reg.size > idB);
473 else
474 if (idA > idB)
475 return (idB + that->reg.size > idA);
476 else
477 return (idA == idB);
478 }
479
480 bool
481 Value::equals(const Value *that, bool strict) const
482 {
483 that = that->join;
484
485 if (strict)
486 return this == that;
487
488 if (that->reg.file != reg.file || that->reg.fileIndex != reg.fileIndex)
489 return false;
490 if (that->reg.size != this->reg.size)
491 return false;
492
493 if (that->reg.data.id != this->reg.data.id)
494 return false;
495
496 return true;
497 }
498
499 bool
500 ImmediateValue::equals(const Value *that, bool strict) const
501 {
502 const ImmediateValue *imm = that->asImm();
503 if (!imm)
504 return false;
505 return reg.data.u64 == imm->reg.data.u64;
506 }
507
508 bool
509 Symbol::equals(const Value *that, bool strict) const
510 {
511 if (reg.file != that->reg.file || reg.fileIndex != that->reg.fileIndex)
512 return false;
513 assert(that->asSym());
514
515 if (this->baseSym != that->asSym()->baseSym)
516 return false;
517
518 return this->reg.data.offset == that->reg.data.offset;
519 }
520
521 void Instruction::init()
522 {
523 next = prev = 0;
524
525 cc = CC_ALWAYS;
526 rnd = ROUND_N;
527 cache = CACHE_CA;
528 subOp = 0;
529
530 saturate = 0;
531 join = terminator = 0;
532 ftz = dnz = 0;
533 atomic = 0;
534 perPatch = 0;
535 fixed = 0;
536 encSize = 0;
537 ipa = 0;
538
539 lanes = 0xf;
540
541 postFactor = 0;
542
543 for (int p = 0; p < NV50_IR_MAX_DEFS; ++p)
544 def[p].setInsn(this);
545 for (int p = 0; p < NV50_IR_MAX_SRCS; ++p)
546 src[p].setInsn(this);
547
548 predSrc = -1;
549 flagsDef = -1;
550 flagsSrc = -1;
551 }
552
553 Instruction::Instruction()
554 {
555 init();
556
557 op = OP_NOP;
558 dType = sType = TYPE_F32;
559
560 id = -1;
561 bb = 0;
562 }
563
564 Instruction::Instruction(Function *fn, operation opr, DataType ty)
565 {
566 init();
567
568 op = opr;
569 dType = sType = ty;
570
571 fn->add(this, id);
572 }
573
574 Instruction::~Instruction()
575 {
576 if (bb) {
577 Function *fn = bb->getFunction();
578 bb->remove(this);
579 fn->allInsns.remove(id);
580 }
581
582 for (int s = 0; srcExists(s); ++s)
583 setSrc(s, NULL);
584 // must unlink defs too since the list pointers will get deallocated
585 for (int d = 0; defExists(d); ++d)
586 setDef(d, NULL);
587 }
588
589 void
590 Instruction::setSrc(int s, ValueRef& ref)
591 {
592 setSrc(s, ref.get());
593 src[s].mod = ref.mod;
594 }
595
596 void
597 Instruction::swapSources(int a, int b)
598 {
599 Value *value = src[a].get();
600 Modifier m = src[a].mod;
601
602 setSrc(a, src[b]);
603
604 src[b].set(value);
605 src[b].mod = m;
606 }
607
608 void
609 Instruction::takeExtraSources(int s, Value *values[3])
610 {
611 values[0] = getIndirect(s, 0);
612 if (values[0])
613 setIndirect(s, 0, NULL);
614
615 values[1] = getIndirect(s, 1);
616 if (values[1])
617 setIndirect(s, 1, NULL);
618
619 values[2] = getPredicate();
620 if (values[2])
621 setPredicate(cc, NULL);
622 }
623
624 void
625 Instruction::putExtraSources(int s, Value *values[3])
626 {
627 if (values[0])
628 setIndirect(s, 0, values[0]);
629 if (values[1])
630 setIndirect(s, 1, values[1]);
631 if (values[2])
632 setPredicate(cc, values[2]);
633 }
634
635 Instruction *
636 Instruction::clone(bool deep) const
637 {
638 Instruction *insn = new_Instruction(bb->getFunction(), op, dType);
639 assert(!asCmp() && !asFlow());
640 cloneBase(insn, deep);
641 return insn;
642 }
643
644 void
645 Instruction::cloneBase(Instruction *insn, bool deep) const
646 {
647 insn->sType = this->sType;
648
649 insn->cc = this->cc;
650 insn->rnd = this->rnd;
651 insn->cache = this->cache;
652 insn->subOp = this->subOp;
653
654 insn->saturate = this->saturate;
655 insn->atomic = this->atomic;
656 insn->ftz = this->ftz;
657 insn->dnz = this->dnz;
658 insn->ipa = this->ipa;
659 insn->lanes = this->lanes;
660 insn->perPatch = this->perPatch;
661
662 insn->postFactor = this->postFactor;
663
664 if (deep) {
665 if (!bb)
666 return;
667 Function *fn = bb->getFunction();
668 for (int d = 0; this->defExists(d); ++d)
669 insn->setDef(d, this->getDef(d)->clone(fn));
670 } else {
671 for (int d = 0; this->defExists(d); ++d)
672 insn->setDef(d, this->getDef(d));
673 }
674
675 for (int s = 0; this->srcExists(s); ++s)
676 insn->src[s].set(this->src[s]);
677
678 insn->predSrc = this->predSrc;
679 insn->flagsDef = this->flagsDef;
680 insn->flagsSrc = this->flagsSrc;
681 }
682
683 unsigned int
684 Instruction::defCount(unsigned int mask) const
685 {
686 unsigned int i, n;
687
688 for (n = 0, i = 0; this->defExists(i); ++i, mask >>= 1)
689 n += mask & 1;
690 return n;
691 }
692
693 unsigned int
694 Instruction::srcCount(unsigned int mask) const
695 {
696 unsigned int i, n;
697
698 for (n = 0, i = 0; this->srcExists(i); ++i, mask >>= 1)
699 n += mask & 1;
700 return n;
701 }
702
703 bool
704 Instruction::setIndirect(int s, int dim, Value *value)
705 {
706 int p = src[s].indirect[dim];
707
708 assert(this->srcExists(s));
709 if (p < 0) {
710 if (!value)
711 return true;
712 for (p = s + 1; this->srcExists(p); ++p);
713 }
714 assert(p < NV50_IR_MAX_SRCS);
715
716 src[p] = value;
717 src[p].usedAsPtr = (value != 0);
718 src[s].indirect[dim] = value ? p : -1;
719 return true;
720 }
721
722 bool
723 Instruction::setPredicate(CondCode ccode, Value *value)
724 {
725 cc = ccode;
726
727 if (!value) {
728 if (predSrc >= 0) {
729 src[predSrc] = 0;
730 predSrc = -1;
731 }
732 return true;
733 }
734
735 if (predSrc < 0) {
736 int s;
737 for (s = 0; this->srcExists(s); ++s)
738 assert(s < NV50_IR_MAX_SRCS);
739 predSrc = s;
740 }
741 src[predSrc] = value;
742 return true;
743 }
744
745 bool
746 Instruction::writesPredicate() const
747 {
748 for (int d = 0; d < 2 && def[d].exists(); ++d)
749 if (def[d].exists() &&
750 (getDef(d)->inFile(FILE_PREDICATE) || getDef(d)->inFile(FILE_FLAGS)))
751 return true;
752 return false;
753 }
754
755 static bool
756 insnCheckCommutation(const Instruction *a, const Instruction *b)
757 {
758 for (int d = 0; a->defExists(d); ++d)
759 for (int s = 0; b->srcExists(s); ++s)
760 if (a->getDef(d)->interfers(b->getSrc(s)))
761 return false;
762 return true;
763 }
764
765 bool
766 Instruction::isCommutationLegal(const Instruction *i) const
767 {
768 bool ret = true;
769 ret = ret && insnCheckCommutation(this, i);
770 ret = ret && insnCheckCommutation(i, this);
771 return ret;
772 }
773
774 TexInstruction::TexInstruction(Function *fn, operation op)
775 : Instruction(fn, op, TYPE_F32)
776 {
777 memset(&tex, 0, sizeof(tex));
778
779 tex.rIndirectSrc = -1;
780 tex.sIndirectSrc = -1;
781 }
782
783 TexInstruction::~TexInstruction()
784 {
785 for (int c = 0; c < 3; ++c) {
786 dPdx[c].set(NULL);
787 dPdy[c].set(NULL);
788 }
789 }
790
791 Instruction *
792 TexInstruction::clone(bool deep) const
793 {
794 TexInstruction *tex = new_TexInstruction(bb->getFunction(), op);
795 cloneBase(tex, deep);
796
797 tex->tex = this->tex;
798
799 if (op == OP_TXD) {
800 for (unsigned int c = 0; c < tex->tex.target.getDim(); ++c) {
801 tex->dPdx[c].set(dPdx[c]);
802 tex->dPdy[c].set(dPdy[c]);
803 }
804 }
805
806 return tex;
807 }
808
809 const struct TexInstruction::Target::Desc TexInstruction::Target::descTable[] =
810 {
811 { "1D", 1, 1, false, false, false },
812 { "2D", 2, 2, false, false, false },
813 { "2D_MS", 2, 2, false, false, false },
814 { "3D", 3, 3, false, false, false },
815 { "CUBE", 2, 3, false, true, false },
816 { "1D_SHADOW", 1, 1, false, false, true },
817 { "2D_SHADOW", 2, 2, false, false, true },
818 { "CUBE_SHADOW", 2, 3, false, true, true },
819 { "1D_ARRAY", 1, 2, true, false, false },
820 { "2D_ARRAY", 2, 3, true, false, false },
821 { "2D_MS_ARRAY", 2, 3, true, false, false },
822 { "CUBE_ARRAY", 2, 4, true, true, false },
823 { "1D_ARRAY_SHADOW", 1, 2, true, false, true },
824 { "2D_ARRAY_SHADOW", 2, 3, true, false, true },
825 { "RECT", 2, 2, false, false, false },
826 { "RECT_SHADOW", 2, 2, false, false, true },
827 { "CUBE_ARRAY_SHADOW", 2, 4, true, true, true },
828 { "BUFFER", 1, 1, false, false, false },
829 };
830
831 CmpInstruction::CmpInstruction(Function *fn, operation op)
832 : Instruction(fn, op, TYPE_F32)
833 {
834 setCond = CC_ALWAYS;
835 }
836
837 Instruction *
838 CmpInstruction::clone(bool deep) const
839 {
840 CmpInstruction *cmp = new_CmpInstruction(bb->getFunction(), op);
841 cloneBase(cmp, deep);
842 cmp->setCond = setCond;
843 cmp->dType = dType;
844 return cmp;
845 }
846
847 FlowInstruction::FlowInstruction(Function *fn, operation op,
848 BasicBlock *targ)
849 : Instruction(fn, op, TYPE_NONE)
850 {
851 target.bb = targ;
852
853 if (op == OP_BRA ||
854 op == OP_CONT || op == OP_BREAK ||
855 op == OP_RET || op == OP_EXIT)
856 terminator = 1;
857 else
858 if (op == OP_JOIN)
859 terminator = targ ? 1 : 0;
860
861 allWarp = absolute = limit = 0;
862 }
863
864 Program::Program(Type type, Target *arch)
865 : progType(type),
866 target(arch),
867 mem_Instruction(sizeof(Instruction), 6),
868 mem_CmpInstruction(sizeof(CmpInstruction), 4),
869 mem_TexInstruction(sizeof(TexInstruction), 4),
870 mem_FlowInstruction(sizeof(FlowInstruction), 4),
871 mem_LValue(sizeof(LValue), 8),
872 mem_Symbol(sizeof(Symbol), 7),
873 mem_ImmediateValue(sizeof(ImmediateValue), 7)
874 {
875 code = NULL;
876 binSize = 0;
877
878 maxGPR = -1;
879
880 main = new Function(this, "MAIN");
881
882 dbgFlags = 0;
883 }
884
885 Program::~Program()
886 {
887 if (main)
888 delete main;
889 }
890
891 void Program::releaseInstruction(Instruction *insn)
892 {
893 // TODO: make this not suck so much
894
895 insn->~Instruction();
896
897 if (insn->asCmp())
898 mem_CmpInstruction.release(insn);
899 else
900 if (insn->asTex())
901 mem_TexInstruction.release(insn);
902 else
903 if (insn->asFlow())
904 mem_FlowInstruction.release(insn);
905 else
906 mem_Instruction.release(insn);
907 }
908
909 void Program::releaseValue(Value *value)
910 {
911 if (value->asLValue())
912 mem_LValue.release(value);
913 else
914 if (value->asImm())
915 mem_ImmediateValue.release(value);
916 else
917 if (value->asSym())
918 mem_Symbol.release(value);
919 }
920
921
922 } // namespace nv50_ir
923
924 extern "C" {
925
926 static void
927 nv50_ir_init_prog_info(struct nv50_ir_prog_info *info)
928 {
929 #if defined(PIPE_SHADER_HULL) && defined(PIPE_SHADER_DOMAIN)
930 if (info->type == PIPE_SHADER_HULL || info->type == PIPE_SHADER_DOMAIN) {
931 info->prop.tp.domain = PIPE_PRIM_MAX;
932 info->prop.tp.outputPrim = PIPE_PRIM_MAX;
933 }
934 #endif
935 if (info->type == PIPE_SHADER_GEOMETRY) {
936 info->prop.gp.instanceCount = 1;
937 info->prop.gp.maxVertices = 1;
938 }
939 info->io.clipDistance = 0xff;
940 info->io.pointSize = 0xff;
941 info->io.vertexId = 0xff;
942 info->io.edgeFlagIn = 0xff;
943 info->io.edgeFlagOut = 0xff;
944 info->io.fragDepth = 0xff;
945 info->io.sampleMask = 0xff;
946 info->io.backFaceColor[0] = info->io.backFaceColor[1] = 0xff;
947 }
948
949 int
950 nv50_ir_generate_code(struct nv50_ir_prog_info *info)
951 {
952 int ret = 0;
953
954 nv50_ir::Program::Type type;
955
956 nv50_ir_init_prog_info(info);
957
958 #define PROG_TYPE_CASE(a, b) \
959 case PIPE_SHADER_##a: type = nv50_ir::Program::TYPE_##b; break
960
961 switch (info->type) {
962 PROG_TYPE_CASE(VERTEX, VERTEX);
963 // PROG_TYPE_CASE(HULL, TESSELLATION_CONTROL);
964 // PROG_TYPE_CASE(DOMAIN, TESSELLATION_EVAL);
965 PROG_TYPE_CASE(GEOMETRY, GEOMETRY);
966 PROG_TYPE_CASE(FRAGMENT, FRAGMENT);
967 default:
968 type = nv50_ir::Program::TYPE_COMPUTE;
969 break;
970 }
971 INFO_DBG(info->dbgFlags, VERBOSE, "translating program of type %u\n", type);
972
973 nv50_ir::Target *targ = nv50_ir::Target::create(info->target);
974 if (!targ)
975 return -1;
976
977 nv50_ir::Program *prog = new nv50_ir::Program(type, targ);
978 if (!prog)
979 return -1;
980 prog->dbgFlags = info->dbgFlags;
981
982 switch (info->bin.sourceRep) {
983 #if 0
984 case PIPE_IR_LLVM:
985 case PIPE_IR_GLSL:
986 return -1;
987 case PIPE_IR_SM4:
988 ret = prog->makeFromSM4(info) ? 0 : -2;
989 break;
990 case PIPE_IR_TGSI:
991 #endif
992 default:
993 ret = prog->makeFromTGSI(info) ? 0 : -2;
994 break;
995 }
996 if (ret < 0)
997 goto out;
998 if (prog->dbgFlags & NV50_IR_DEBUG_VERBOSE)
999 prog->print();
1000
1001 prog->getTarget()->runLegalizePass(prog, nv50_ir::CG_STAGE_PRE_SSA);
1002
1003 prog->convertToSSA();
1004
1005 if (prog->dbgFlags & NV50_IR_DEBUG_VERBOSE)
1006 prog->print();
1007
1008 prog->optimizeSSA(info->optLevel);
1009 prog->getTarget()->runLegalizePass(prog, nv50_ir::CG_STAGE_SSA);
1010
1011 if (prog->dbgFlags & NV50_IR_DEBUG_BASIC)
1012 prog->print();
1013
1014 if (!prog->registerAllocation()) {
1015 ret = -4;
1016 goto out;
1017 }
1018 prog->getTarget()->runLegalizePass(prog, nv50_ir::CG_STAGE_POST_RA);
1019
1020 prog->optimizePostRA(info->optLevel);
1021
1022 if (!prog->emitBinary(info)) {
1023 ret = -5;
1024 goto out;
1025 }
1026
1027 out:
1028 INFO_DBG(prog->dbgFlags, VERBOSE, "nv50_ir_generate_code: ret = %i\n", ret);
1029
1030 info->bin.maxGPR = prog->maxGPR;
1031 info->bin.code = prog->code;
1032 info->bin.codeSize = prog->binSize;
1033
1034 delete prog;
1035 nv50_ir::Target::destroy(targ);
1036
1037 return ret;
1038 }
1039
1040 } // extern "C"