nv50,nvc0: hold references to the framebuffer surfaces
[mesa.git] / src / gallium / drivers / nv50 / codegen / nv50_ir.h
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 #ifndef __NV50_IR_H__
24 #define __NV50_IR_H__
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <stdint.h>
29
30 #include "nv50_ir_util.h"
31 #include "nv50_ir_graph.h"
32
33 #include "nv50_ir_driver.h"
34
35 namespace nv50_ir {
36
37 enum operation
38 {
39 OP_NOP = 0,
40 OP_PHI,
41 OP_UNION, // unify a new definition and several source values
42 OP_SPLIT, // $r0d -> { $r0, $r1 } ($r0d and $r0/$r1 will be coalesced)
43 OP_MERGE, // opposite of split, e.g. combine 2 32 bit into a 64 bit value
44 OP_CONSTRAINT, // copy values into consecutive registers
45 OP_MOV,
46 OP_LOAD,
47 OP_STORE,
48 OP_ADD,
49 OP_SUB,
50 OP_MUL,
51 OP_DIV,
52 OP_MOD,
53 OP_MAD,
54 OP_FMA,
55 OP_SAD, // abs(src0 - src1) + src2
56 OP_ABS,
57 OP_NEG,
58 OP_NOT,
59 OP_AND,
60 OP_OR,
61 OP_XOR,
62 OP_SHL,
63 OP_SHR,
64 OP_MAX,
65 OP_MIN,
66 OP_SAT, // CLAMP(f32, 0.0, 1.0)
67 OP_CEIL,
68 OP_FLOOR,
69 OP_TRUNC,
70 OP_CVT,
71 OP_SET_AND, // dst = (src0 CMP src1) & src2
72 OP_SET_OR,
73 OP_SET_XOR,
74 OP_SET,
75 OP_SELP, // dst = src2 ? src0 : src1
76 OP_SLCT, // dst = (src2 CMP 0) ? src0 : src1
77 OP_RCP,
78 OP_RSQ,
79 OP_LG2,
80 OP_SIN,
81 OP_COS,
82 OP_EX2,
83 OP_EXP, // exponential (base M_E)
84 OP_LOG, // natural logarithm
85 OP_PRESIN,
86 OP_PREEX2,
87 OP_SQRT,
88 OP_POW,
89 OP_BRA,
90 OP_CALL,
91 OP_RET,
92 OP_CONT,
93 OP_BREAK,
94 OP_PRERET,
95 OP_PRECONT,
96 OP_PREBREAK,
97 OP_BRKPT, // breakpoint (not related to loops)
98 OP_JOINAT, // push control flow convergence point
99 OP_JOIN, // converge
100 OP_DISCARD,
101 OP_EXIT,
102 OP_MEMBAR,
103 OP_VFETCH, // indirection 0 in attribute space, indirection 1 is vertex base
104 OP_PFETCH, // fetch base address of vertex src0 (immediate) [+ src1]
105 OP_EXPORT,
106 OP_LINTERP,
107 OP_PINTERP,
108 OP_EMIT, // emit vertex
109 OP_RESTART, // restart primitive
110 OP_TEX,
111 OP_TXB, // texture bias
112 OP_TXL, // texure lod
113 OP_TXF, // texel fetch
114 OP_TXQ, // texture size query
115 OP_TXD, // texture derivatives
116 OP_TXG, // texture gather
117 OP_TEXCSAA,
118 OP_SULD, // surface load
119 OP_SUST, // surface store
120 OP_DFDX,
121 OP_DFDY,
122 OP_RDSV, // read system value
123 OP_WRSV, // write system value
124 OP_PIXLD,
125 OP_QUADOP,
126 OP_QUADON,
127 OP_QUADPOP,
128 OP_POPCNT, // bitcount(src0 & src1)
129 OP_INSBF, // insert first src1[8:15] bits of src0 into src2 at src1[0:7]
130 OP_EXTBF,
131 OP_LAST
132 };
133
134 #define NV50_IR_SUBOP_MUL_HIGH 1
135 #define NV50_IR_SUBOP_EMIT_RESTART 1
136 #define NV50_IR_SUBOP_LDC_IL 1
137 #define NV50_IR_SUBOP_LDC_IS 2
138 #define NV50_IR_SUBOP_LDC_ISL 3
139 #define NV50_IR_SUBOP_SHIFT_WRAP 1
140
141 enum DataType
142 {
143 TYPE_NONE,
144 TYPE_U8,
145 TYPE_S8,
146 TYPE_U16,
147 TYPE_S16,
148 TYPE_U32,
149 TYPE_S32,
150 TYPE_U64, // 64 bit operations are only lowered after register allocation
151 TYPE_S64,
152 TYPE_F16,
153 TYPE_F32,
154 TYPE_F64,
155 TYPE_B96,
156 TYPE_B128
157 };
158
159 enum CondCode
160 {
161 CC_FL = 0,
162 CC_NEVER = CC_FL, // when used with FILE_FLAGS
163 CC_LT = 1,
164 CC_EQ = 2,
165 CC_NOT_P = CC_EQ, // when used with FILE_PREDICATE
166 CC_LE = 3,
167 CC_GT = 4,
168 CC_NE = 5,
169 CC_P = CC_NE,
170 CC_GE = 6,
171 CC_TR = 7,
172 CC_ALWAYS = CC_TR,
173 CC_U = 8,
174 CC_LTU = 9,
175 CC_EQU = 10,
176 CC_LEU = 11,
177 CC_GTU = 12,
178 CC_NEU = 13,
179 CC_GEU = 14,
180 CC_NO = 0x10,
181 CC_NC = 0x11,
182 CC_NS = 0x12,
183 CC_NA = 0x13,
184 CC_A = 0x14,
185 CC_S = 0x15,
186 CC_C = 0x16,
187 CC_O = 0x17
188 };
189
190 enum RoundMode
191 {
192 ROUND_N, // nearest
193 ROUND_M, // towards -inf
194 ROUND_Z, // towards 0
195 ROUND_P, // towards +inf
196 ROUND_NI, // nearest integer
197 ROUND_MI, // to integer towards -inf
198 ROUND_ZI, // to integer towards 0
199 ROUND_PI, // to integer towards +inf
200 };
201
202 enum CacheMode
203 {
204 CACHE_CA, // cache at all levels
205 CACHE_WB = CACHE_CA, // cache write back
206 CACHE_CG, // cache at global level
207 CACHE_CS, // cache streaming
208 CACHE_CV, // cache as volatile
209 CACHE_WT = CACHE_CV // cache write-through
210 };
211
212 enum DataFile
213 {
214 FILE_NULL = 0,
215 FILE_GPR,
216 FILE_PREDICATE, // boolean predicate
217 FILE_FLAGS, // zero/sign/carry/overflow bits
218 FILE_ADDRESS,
219 FILE_IMMEDIATE,
220 FILE_MEMORY_CONST,
221 FILE_SHADER_INPUT,
222 FILE_SHADER_OUTPUT,
223 FILE_MEMORY_GLOBAL,
224 FILE_MEMORY_SHARED,
225 FILE_MEMORY_LOCAL,
226 FILE_SYSTEM_VALUE,
227 DATA_FILE_COUNT
228 };
229
230 enum TexTarget
231 {
232 TEX_TARGET_1D,
233 TEX_TARGET_2D,
234 TEX_TARGET_2D_MS,
235 TEX_TARGET_3D,
236 TEX_TARGET_CUBE,
237 TEX_TARGET_1D_SHADOW,
238 TEX_TARGET_2D_SHADOW,
239 TEX_TARGET_CUBE_SHADOW,
240 TEX_TARGET_1D_ARRAY,
241 TEX_TARGET_2D_ARRAY,
242 TEX_TARGET_2D_MS_ARRAY,
243 TEX_TARGET_CUBE_ARRAY,
244 TEX_TARGET_1D_ARRAY_SHADOW,
245 TEX_TARGET_2D_ARRAY_SHADOW,
246 TEX_TARGET_RECT,
247 TEX_TARGET_RECT_SHADOW,
248 TEX_TARGET_CUBE_ARRAY_SHADOW,
249 TEX_TARGET_BUFFER,
250 TEX_TARGET_COUNT
251 };
252
253 enum SVSemantic
254 {
255 SV_POSITION, // WPOS
256 SV_VERTEX_ID,
257 SV_INSTANCE_ID,
258 SV_INVOCATION_ID,
259 SV_PRIMITIVE_ID,
260 SV_VERTEX_COUNT, // gl_PatchVerticesIn
261 SV_LAYER,
262 SV_VIEWPORT_INDEX,
263 SV_YDIR,
264 SV_FACE,
265 SV_POINT_SIZE,
266 SV_POINT_COORD,
267 SV_CLIP_DISTANCE,
268 SV_SAMPLE_INDEX,
269 SV_TESS_FACTOR,
270 SV_TESS_COORD,
271 SV_TID,
272 SV_CTAID,
273 SV_NTID,
274 SV_GRIDID,
275 SV_NCTAID,
276 SV_LANEID,
277 SV_PHYSID,
278 SV_NPHYSID,
279 SV_CLOCK,
280 SV_LBASE,
281 SV_SBASE,
282 SV_UNDEFINED,
283 SV_LAST
284 };
285
286 class Program;
287 class Function;
288 class BasicBlock;
289
290 class Target;
291
292 class Instruction;
293 class CmpInstruction;
294 class TexInstruction;
295 class FlowInstruction;
296
297 class Value;
298 class LValue;
299 class Symbol;
300 class ImmediateValue;
301
302 struct Storage
303 {
304 DataFile file;
305 int8_t fileIndex; // signed, may be indirect for CONST[]
306 uint8_t size; // this should match the Instruction type's size
307 DataType type; // mainly for pretty printing
308 union {
309 uint64_t u64; // immediate values
310 uint32_t u32;
311 uint16_t u16;
312 uint8_t u8;
313 int64_t s64;
314 int32_t s32;
315 int16_t s16;
316 int8_t s8;
317 float f32;
318 double f64;
319 int32_t offset; // offset from 0 (base of address space)
320 int32_t id; // register id (< 0 if virtual/unassigned)
321 struct {
322 SVSemantic sv;
323 int index;
324 } sv;
325 } data;
326 };
327
328 // precedence: NOT after SAT after NEG after ABS
329 #define NV50_IR_MOD_ABS (1 << 0)
330 #define NV50_IR_MOD_NEG (1 << 1)
331 #define NV50_IR_MOD_SAT (1 << 2)
332 #define NV50_IR_MOD_NOT (1 << 3)
333 #define NV50_IR_MOD_NEG_ABS (NV50_IR_MOD_NEG | NV50_IR_MOD_ABS)
334
335 #define NV50_IR_INTERP_MODE_MASK 0x3
336 #define NV50_IR_INTERP_LINEAR (0 << 0)
337 #define NV50_IR_INTERP_PERSPECTIVE (1 << 0)
338 #define NV50_IR_INTERP_FLAT (2 << 0)
339 #define NV50_IR_INTERP_SC (3 << 0) // what exactly is that ?
340 #define NV50_IR_INTERP_SAMPLE_MASK 0xc
341 #define NV50_IR_INTERP_DEFAULT (0 << 2)
342 #define NV50_IR_INTERP_CENTROID (1 << 2)
343 #define NV50_IR_INTERP_OFFSET (2 << 2)
344 #define NV50_IR_INTERP_SAMPLEID (3 << 2)
345
346 // do we really want this to be a class ?
347 class Modifier
348 {
349 public:
350 Modifier() : bits(0) { }
351 Modifier(unsigned int m) : bits(m) { }
352 Modifier(operation op);
353
354 // @return new Modifier applying a after b (asserts if unrepresentable)
355 Modifier operator*(const Modifier) const;
356 Modifier operator==(const Modifier m) const { return m.bits == bits; }
357 Modifier operator!=(const Modifier m) const { return m.bits != bits; }
358
359 inline Modifier operator&(const Modifier m) const { return bits & m.bits; }
360 inline Modifier operator|(const Modifier m) const { return bits | m.bits; }
361 inline Modifier operator^(const Modifier m) const { return bits ^ m.bits; }
362
363 operation getOp() const;
364
365 inline int neg() const { return (bits & NV50_IR_MOD_NEG) ? 1 : 0; }
366 inline int abs() const { return (bits & NV50_IR_MOD_ABS) ? 1 : 0; }
367
368 inline operator bool() { return bits ? true : false; }
369
370 void applyTo(ImmediateValue &imm) const;
371
372 int print(char *buf, size_t size) const;
373
374 private:
375 uint8_t bits;
376 };
377
378 class ValueRef
379 {
380 public:
381 ValueRef();
382 ~ValueRef();
383
384 inline ValueRef& operator=(Value *val) { this->set(val); return *this; }
385
386 inline bool exists() const { return value != NULL; }
387
388 void set(Value *);
389 void set(const ValueRef&);
390 inline Value *get() const { return value; }
391 inline Value *rep() const;
392
393 inline Instruction *getInsn() const { return insn; }
394 inline void setInsn(Instruction *inst) { insn = inst; }
395
396 inline bool isIndirect(int dim) const { return indirect[dim] >= 0; }
397 inline const ValueRef *getIndirect(int dim) const;
398
399 inline DataFile getFile() const;
400 inline unsigned getSize() const;
401
402 // SSA: return eventual (traverse MOVs) literal value, if it exists
403 ImmediateValue *getImmediate() const;
404
405 class Iterator
406 {
407 public:
408 Iterator(ValueRef *ref) : pos(ref), ini(ref) { }
409
410 inline ValueRef *get() const { return pos; }
411 inline bool end() const { return pos == NULL; }
412 inline void next() { pos = (pos->next != ini) ? pos->next : 0; }
413
414 private:
415 ValueRef *pos, *ini;
416 };
417
418 inline Iterator iterator() { return Iterator(this); }
419
420 public:
421 Modifier mod;
422 int8_t indirect[2]; // >= 0 if relative to lvalue in insn->src[indirect[i]]
423 uint8_t swizzle;
424
425 bool usedAsPtr; // for printing
426
427 private:
428 Value *value;
429 Instruction *insn;
430 ValueRef *next; // to link uses of the value
431 ValueRef *prev;
432 };
433
434 class ValueDef
435 {
436 public:
437 ValueDef();
438 ~ValueDef();
439
440 inline ValueDef& operator=(Value *val) { this->set(val); return *this; }
441
442 inline bool exists() const { return value != NULL; }
443
444 inline Value *get() const { return value; }
445 inline Value *rep() const;
446 void set(Value *);
447 void replace(Value *, bool doSet); // replace all uses of the old value
448
449 inline Instruction *getInsn() const { return insn; }
450 inline void setInsn(Instruction *inst) { insn = inst; }
451
452 inline DataFile getFile() const;
453 inline unsigned getSize() const;
454
455 // HACK: save the pre-SSA value in 'prev', in SSA we don't need the def list
456 // but we'll use it again for coalescing in register allocation
457 inline void setSSA(LValue *);
458 inline const LValue *preSSA() const;
459 inline void restoreDefList(); // after having been abused for SSA hack
460 void mergeDefs(ValueDef *);
461
462 class Iterator
463 {
464 public:
465 Iterator(ValueDef *def) : pos(def), ini(def) { }
466
467 inline ValueDef *get() const { return pos; }
468 inline bool end() const { return pos == NULL; }
469 inline void next() { pos = (pos->next != ini) ? pos->next : NULL; }
470
471 private:
472 ValueDef *pos, *ini;
473 };
474
475 inline Iterator iterator() { return Iterator(this); }
476
477 private:
478 Value *value; // should make this LValue * ...
479 Instruction *insn;
480 ValueDef *next; // circular list of all definitions of the same value
481 ValueDef *prev;
482 };
483
484 class Value
485 {
486 public:
487 Value();
488
489 virtual Value *clone(Function *) const { return NULL; }
490
491 virtual int print(char *, size_t, DataType ty = TYPE_NONE) const = 0;
492
493 virtual bool equals(const Value *, bool strict = false) const;
494 virtual bool interfers(const Value *) const;
495
496 inline Instruction *getUniqueInsn() const;
497 inline Instruction *getInsn() const; // use when uniqueness is certain
498
499 inline int refCount() { return refCnt; }
500 inline int ref() { return ++refCnt; }
501 inline int unref() { --refCnt; assert(refCnt >= 0); return refCnt; }
502
503 inline LValue *asLValue();
504 inline Symbol *asSym();
505 inline ImmediateValue *asImm();
506 inline const Symbol *asSym() const;
507 inline const ImmediateValue *asImm() const;
508
509 bool coalesce(Value *, bool force = false);
510
511 inline bool inFile(DataFile f) { return reg.file == f; }
512
513 static inline Value *get(Iterator&);
514
515 protected:
516 int refCnt;
517
518 friend class ValueDef;
519 friend class ValueRef;
520
521 public:
522 int id;
523 ValueRef *uses;
524 ValueDef *defs;
525 Storage reg;
526
527 // TODO: these should be in LValue:
528 Interval livei;
529 Value *join;
530 };
531
532 class LValue : public Value
533 {
534 public:
535 LValue(Function *, DataFile file);
536 LValue(Function *, LValue *);
537
538 virtual Value *clone(Function *) const;
539
540 virtual int print(char *, size_t, DataType ty = TYPE_NONE) const;
541
542 public:
543 unsigned ssa : 1;
544
545 int affinity;
546 };
547
548 class Symbol : public Value
549 {
550 public:
551 Symbol(Program *, DataFile file = FILE_MEMORY_CONST, ubyte fileIdx = 0);
552
553 virtual Value *clone(Function *) const;
554
555 virtual bool equals(const Value *that, bool strict) const;
556
557 virtual int print(char *, size_t, DataType ty = TYPE_NONE) const;
558
559 // print with indirect values
560 int print(char *, size_t, Value *, Value *, DataType ty = TYPE_NONE) const;
561
562 inline void setFile(DataFile file, ubyte fileIndex = 0)
563 {
564 reg.file = file;
565 reg.fileIndex = fileIndex;
566 }
567
568 inline void setOffset(int32_t offset);
569 inline void setAddress(Symbol *base, int32_t offset);
570 inline void setSV(SVSemantic sv, uint32_t idx = 0);
571
572 inline const Symbol *getBase() const { return baseSym; }
573
574 private:
575 Symbol *baseSym; // array base for Symbols representing array elements
576 };
577
578 class ImmediateValue : public Value
579 {
580 public:
581 ImmediateValue(Program *, uint32_t);
582 ImmediateValue(Program *, float);
583 ImmediateValue(Program *, double);
584
585 // NOTE: not added to program with
586 ImmediateValue(const ImmediateValue *, DataType ty);
587
588 virtual bool equals(const Value *that, bool strict) const;
589
590 // these only work if 'type' is valid (we mostly use untyped literals):
591 bool isInteger(const int ival) const; // ival is cast to this' type
592 bool isNegative() const;
593 bool isPow2() const;
594
595 void applyLog2();
596
597 // for constant folding:
598 ImmediateValue operator+(const ImmediateValue&) const;
599 ImmediateValue operator-(const ImmediateValue&) const;
600 ImmediateValue operator*(const ImmediateValue&) const;
601 ImmediateValue operator/(const ImmediateValue&) const;
602
603 bool compare(CondCode cc, float fval) const;
604
605 virtual int print(char *, size_t, DataType ty = TYPE_NONE) const;
606 };
607
608
609 #define NV50_IR_MAX_DEFS 4
610 #define NV50_IR_MAX_SRCS 8
611
612 class Instruction
613 {
614 public:
615 Instruction();
616 Instruction(Function *, operation, DataType);
617 virtual ~Instruction();
618
619 virtual Instruction *clone(bool deep) const;
620
621 inline void setDef(int i, Value *val) { def[i].set(val); }
622 inline void setSrc(int s, Value *val) { src[s].set(val); }
623 void setSrc(int s, ValueRef&);
624 void swapSources(int a, int b);
625 bool setIndirect(int s, int dim, Value *);
626
627 inline Value *getDef(int d) const { return def[d].get(); }
628 inline Value *getSrc(int s) const { return src[s].get(); }
629 inline Value *getIndirect(int s, int dim) const;
630
631 inline bool defExists(int d) const { return d < 4 && def[d].exists(); }
632 inline bool srcExists(int s) const { return s < 8 && src[s].exists(); }
633
634 inline bool constrainedDefs() const { return def[1].exists(); }
635
636 bool setPredicate(CondCode ccode, Value *);
637 inline Value *getPredicate() const;
638 bool writesPredicate() const;
639
640 unsigned int defCount(unsigned int mask) const;
641 unsigned int srcCount(unsigned int mask) const;
642
643 // save & remove / set indirect[0,1] and predicate source
644 void takeExtraSources(int s, Value *[3]);
645 void putExtraSources(int s, Value *[3]);
646
647 inline void setType(DataType type) { dType = sType = type; }
648
649 inline void setType(DataType dtype, DataType stype)
650 {
651 dType = dtype;
652 sType = stype;
653 }
654
655 inline bool isPseudo() const { return op < OP_MOV; }
656 bool isDead() const;
657 bool isNop() const;
658 bool isCommutationLegal(const Instruction *) const; // must be adjacent !
659 bool isActionEqual(const Instruction *) const;
660 bool isResultEqual(const Instruction *) const;
661
662 void print() const;
663
664 inline CmpInstruction *asCmp();
665 inline TexInstruction *asTex();
666 inline FlowInstruction *asFlow();
667 inline const TexInstruction *asTex() const;
668 inline const CmpInstruction *asCmp() const;
669 inline const FlowInstruction *asFlow() const;
670
671 public:
672 Instruction *next;
673 Instruction *prev;
674 int id;
675 int serial; // CFG order
676
677 operation op;
678 DataType dType; // destination or defining type
679 DataType sType; // source or secondary type
680 CondCode cc;
681 RoundMode rnd;
682 CacheMode cache;
683
684 uint8_t subOp; // quadop, 1 for mul-high, etc.
685
686 unsigned encSize : 4; // encoding size in bytes
687 unsigned saturate : 1; // to [0.0f, 1.0f]
688 unsigned join : 1; // converge control flow (use OP_JOIN until end)
689 unsigned fixed : 1; // prevent dead code elimination
690 unsigned terminator : 1; // end of basic block
691 unsigned atomic : 1;
692 unsigned ftz : 1; // flush denormal to zero
693 unsigned dnz : 1; // denormals, NaN are zero
694 unsigned ipa : 4; // interpolation mode
695 unsigned lanes : 4;
696 unsigned perPatch : 1;
697 unsigned exit : 1; // terminate program after insn
698
699 int8_t postFactor; // MUL/DIV(if < 0) by 1 << postFactor
700
701 int8_t predSrc;
702 int8_t flagsDef;
703 int8_t flagsSrc;
704
705 // NOTE: should make these pointers, saves space and work on shuffling
706 ValueDef def[NV50_IR_MAX_DEFS]; // no gaps !
707 ValueRef src[NV50_IR_MAX_SRCS]; // no gaps !
708
709 BasicBlock *bb;
710
711 // instruction specific methods:
712 // (don't want to subclass, would need more constructors and memory pools)
713 public:
714 inline void setInterpolate(unsigned int mode) { ipa = mode; }
715
716 unsigned int getInterpMode() const { return ipa & 0x3; }
717 unsigned int getSampleMode() const { return ipa & 0xc; }
718
719 private:
720 void init();
721 protected:
722 void cloneBase(Instruction *clone, bool deep) const;
723 };
724
725 enum TexQuery
726 {
727 TXQ_DIMS,
728 TXQ_TYPE,
729 TXQ_SAMPLE_POSITION,
730 TXQ_FILTER,
731 TXQ_LOD,
732 TXQ_WRAP,
733 TXQ_BORDER_COLOUR
734 };
735
736 class TexInstruction : public Instruction
737 {
738 public:
739 class Target
740 {
741 public:
742 Target(TexTarget targ = TEX_TARGET_2D) : target(targ) { }
743
744 const char *getName() const { return descTable[target].name; }
745 unsigned int getArgCount() const { return descTable[target].argc; }
746 unsigned int getDim() const { return descTable[target].dim; }
747 int isArray() const { return descTable[target].array ? 1 : 0; }
748 int isCube() const { return descTable[target].cube ? 1 : 0; }
749 int isShadow() const { return descTable[target].shadow ? 1 : 0; }
750
751 Target& operator=(TexTarget targ)
752 {
753 assert(targ < TEX_TARGET_COUNT);
754 return *this;
755 }
756
757 inline bool operator==(TexTarget targ) const { return target == targ; }
758
759 private:
760 struct Desc
761 {
762 char name[19];
763 uint8_t dim;
764 uint8_t argc;
765 bool array;
766 bool cube;
767 bool shadow;
768 };
769
770 static const struct Desc descTable[TEX_TARGET_COUNT];
771
772 private:
773 enum TexTarget target;
774 };
775
776 public:
777 TexInstruction(Function *, operation);
778 virtual ~TexInstruction();
779
780 virtual Instruction *clone(bool deep) const;
781
782 inline void setTexture(Target targ, uint8_t r, uint8_t s)
783 {
784 tex.r = r;
785 tex.s = s;
786 tex.target = targ;
787 }
788
789 inline Value *getIndirectR() const;
790 inline Value *getIndirectS() const;
791
792 public:
793 struct {
794 Target target;
795
796 uint8_t r;
797 int8_t rIndirectSrc;
798 uint8_t s;
799 int8_t sIndirectSrc;
800
801 uint8_t mask;
802 uint8_t gatherComp;
803
804 bool liveOnly; // only execute on live pixels of a quad (optimization)
805 bool levelZero;
806 bool derivAll;
807
808 int8_t useOffsets; // 0, 1, or 4 for textureGatherOffsets
809 int8_t offset[4][3];
810
811 enum TexQuery query;
812 } tex;
813
814 ValueRef dPdx[3];
815 ValueRef dPdy[3];
816 };
817
818 class CmpInstruction : public Instruction
819 {
820 public:
821 CmpInstruction(Function *, operation);
822
823 virtual Instruction *clone(bool deep) const;
824
825 void setCondition(CondCode cond) { setCond = cond; }
826 CondCode getCondition() const { return setCond; }
827
828 public:
829 CondCode setCond;
830 };
831
832 class FlowInstruction : public Instruction
833 {
834 public:
835 FlowInstruction(Function *, operation, BasicBlock *target);
836
837 public:
838 unsigned allWarp : 1;
839 unsigned absolute : 1;
840 unsigned limit : 1;
841 unsigned builtin : 1; // true for calls to emulation code
842
843 union {
844 BasicBlock *bb;
845 int builtin;
846 Function *fn;
847 } target;
848 };
849
850 class BasicBlock
851 {
852 public:
853 BasicBlock(Function *);
854 ~BasicBlock();
855
856 inline int getId() const { return id; }
857 inline unsigned int getInsnCount() const { return numInsns; }
858 inline bool isTerminated() const { return exit && exit->terminator; }
859
860 bool dominatedBy(BasicBlock *bb);
861 inline bool reachableBy(BasicBlock *by, BasicBlock *term);
862
863 // returns mask of conditional out blocks
864 // e.g. 3 for IF { .. } ELSE { .. } ENDIF, 1 for IF { .. } ENDIF
865 unsigned int initiatesSimpleConditional() const;
866
867 public:
868 Function *getFunction() const { return func; }
869 Program *getProgram() const { return program; }
870
871 Instruction *getEntry() const { return entry; } // first non-phi instruction
872 Instruction *getPhi() const { return phi; }
873 Instruction *getFirst() const { return phi ? phi : entry; }
874 Instruction *getExit() const { return exit; }
875
876 void insertHead(Instruction *);
877 void insertTail(Instruction *);
878 void insertBefore(Instruction *, Instruction *);
879 void insertAfter(Instruction *, Instruction *);
880 void remove(Instruction *);
881 void permuteAdjacent(Instruction *, Instruction *);
882
883 BasicBlock *idom() const;
884
885 DLList& getDF() { return df; }
886 DLList::Iterator iterDF() { return df.iterator(); }
887
888 static inline BasicBlock *get(Iterator&);
889 static inline BasicBlock *get(Graph::Node *);
890
891 public:
892 Graph::Node cfg; // first edge is branch *taken* (the ELSE branch)
893 Graph::Node dom;
894
895 BitSet liveSet;
896
897 uint32_t binPos;
898 uint32_t binSize;
899
900 Instruction *joinAt; // for quick reference
901
902 bool explicitCont; // loop headers: true if loop contains continue stmts
903
904 private:
905 int id;
906 DLList df;
907
908 Instruction *phi;
909 Instruction *entry;
910 Instruction *exit;
911
912 unsigned int numInsns;
913
914 private:
915 Function *func;
916 Program *program;
917 };
918
919 class Function
920 {
921 public:
922 Function(Program *, const char *name);
923 ~Function();
924
925 inline Program *getProgram() const { return prog; }
926 inline const char *getName() const { return name; }
927 inline int getId() const { return id; }
928
929 void print();
930 void printLiveIntervals() const;
931 void printCFGraph(const char *filePath);
932
933 bool setEntry(BasicBlock *);
934 bool setExit(BasicBlock *);
935
936 unsigned int orderInstructions(ArrayList&);
937
938 inline void add(BasicBlock *bb, int& id) { allBBlocks.insert(bb, id); }
939 inline void add(Instruction *insn, int& id) { allInsns.insert(insn, id); }
940 inline void add(LValue *lval, int& id) { allLValues.insert(lval, id); }
941
942 inline LValue *getLValue(int id);
943
944 bool convertToSSA();
945
946 public:
947 Graph cfg;
948 Graph::Node *cfgExit;
949 Graph *domTree;
950 Graph::Node call; // node in the call graph
951
952 BasicBlock **bbArray; // BBs in emission order
953 int bbCount;
954
955 unsigned int loopNestingBound;
956 int regClobberMax;
957
958 uint32_t binPos;
959 uint32_t binSize;
960
961 ArrayList allBBlocks;
962 ArrayList allInsns;
963 ArrayList allLValues;
964
965 private:
966 void buildLiveSetsPreSSA(BasicBlock *, const int sequence);
967
968 private:
969 int id;
970 const char *const name;
971 Program *prog;
972 };
973
974 enum CGStage
975 {
976 CG_STAGE_PRE_SSA,
977 CG_STAGE_SSA, // expected directly before register allocation
978 CG_STAGE_POST_RA
979 };
980
981 class Program
982 {
983 public:
984 enum Type
985 {
986 TYPE_VERTEX,
987 TYPE_TESSELLATION_CONTROL,
988 TYPE_TESSELLATION_EVAL,
989 TYPE_GEOMETRY,
990 TYPE_FRAGMENT,
991 TYPE_COMPUTE
992 };
993
994 Program(Type type, Target *targ);
995 ~Program();
996
997 void print();
998
999 Type getType() const { return progType; }
1000
1001 inline void add(Function *fn, int& id) { allFuncs.insert(fn, id); }
1002 inline void add(Value *rval, int& id) { allRValues.insert(rval, id); }
1003
1004 bool makeFromTGSI(struct nv50_ir_prog_info *);
1005 bool makeFromSM4(struct nv50_ir_prog_info *);
1006 bool convertToSSA();
1007 bool optimizeSSA(int level);
1008 bool optimizePostRA(int level);
1009 bool registerAllocation();
1010 bool emitBinary(struct nv50_ir_prog_info *);
1011
1012 const Target *getTarget() const { return target; }
1013
1014 private:
1015 Type progType;
1016 Target *target;
1017
1018 public:
1019 Function *main;
1020 Graph calls;
1021
1022 ArrayList allFuncs;
1023 ArrayList allRValues;
1024
1025 uint32_t *code;
1026 uint32_t binSize;
1027
1028 int maxGPR;
1029
1030 MemoryPool mem_Instruction;
1031 MemoryPool mem_CmpInstruction;
1032 MemoryPool mem_TexInstruction;
1033 MemoryPool mem_FlowInstruction;
1034 MemoryPool mem_LValue;
1035 MemoryPool mem_Symbol;
1036 MemoryPool mem_ImmediateValue;
1037
1038 uint32_t dbgFlags;
1039
1040 void releaseInstruction(Instruction *);
1041 void releaseValue(Value *);
1042 };
1043
1044 // TODO: add const version
1045 class Pass
1046 {
1047 public:
1048 bool run(Program *, bool ordered = false, bool skipPhi = false);
1049 bool run(Function *, bool ordered = false, bool skipPhi = false);
1050
1051 private:
1052 // return false to continue with next entity on next higher level
1053 virtual bool visit(Function *) { return true; }
1054 virtual bool visit(BasicBlock *) { return true; }
1055 virtual bool visit(Instruction *) { return false; }
1056
1057 bool doRun(Program *, bool ordered, bool skipPhi);
1058 bool doRun(Function *, bool ordered, bool skipPhi);
1059
1060 protected:
1061 bool err;
1062 Function *func;
1063 Program *prog;
1064 };
1065
1066 // =============================================================================
1067
1068 #include "nv50_ir_inlines.h"
1069
1070 } // namespace nv50_ir
1071
1072 #endif // __NV50_IR_H__