ae07d9672217b7600f0d01678717fbcd537c5f87
2 * Copyright 2011 Christoph Bumiller
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #include "codegen/nv50_ir.h"
24 #include "codegen/nv50_ir_target.h"
25 #include "codegen/nv50_ir_driver.h"
28 #include "nouveau_debug.h"
29 #include "nv50/nv50_program.h"
34 Modifier::Modifier(operation 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;
47 Modifier
Modifier::operator*(const Modifier m
) const
52 if (this->bits
& NV50_IR_MOD_ABS
)
53 b
&= ~NV50_IR_MOD_NEG
;
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
);
58 return Modifier(a
| c
);
61 ValueRef::ValueRef(Value
*v
) : value(NULL
), insn(NULL
)
69 ValueRef::ValueRef(const ValueRef
& ref
) : value(NULL
), insn(ref
.insn
)
72 usedAsPtr
= ref
.usedAsPtr
;
80 bool ValueRef::getImmediate(ImmediateValue
&imm
) const
82 const ValueRef
*src
= this;
84 DataType type
= src
->insn
->sType
;
88 if (src
->insn
->sType
!= type
)
92 if (src
->getFile() == FILE_IMMEDIATE
) {
93 imm
= *(src
->value
->asImm());
94 // The immediate's type isn't required to match its use, it's
95 // more of a hint; applying a modifier makes use of that hint.
101 Instruction
*insn
= src
->value
->getUniqueInsn();
103 if (insn
&& insn
->op
== OP_MOV
) {
106 WARN("OP_MOV with modifier encountered !\n");
114 ValueDef::ValueDef(Value
*v
) : value(NULL
), insn(NULL
)
119 ValueDef::ValueDef(const ValueDef
& def
) : value(NULL
), insn(NULL
)
124 ValueDef::~ValueDef()
130 ValueRef::set(const ValueRef
&ref
)
132 this->set(ref
.get());
134 indirect
[0] = ref
.indirect
[0];
135 indirect
[1] = ref
.indirect
[1];
139 ValueRef::set(Value
*refVal
)
144 value
->uses
.erase(this);
146 refVal
->uses
.insert(this);
152 ValueDef::set(Value
*defVal
)
157 value
->defs
.remove(this);
159 defVal
->defs
.push_back(this);
164 // Check if we can replace this definition's value by the value in @rep,
165 // including the source modifiers, i.e. make sure that all uses support
168 ValueDef::mayReplace(const ValueRef
&rep
)
173 if (!insn
|| !insn
->bb
) // Unbound instruction ?
176 const Target
*target
= insn
->bb
->getProgram()->getTarget();
178 for (Value::UseIterator it
= value
->uses
.begin(); it
!= value
->uses
.end();
180 Instruction
*insn
= (*it
)->getInsn();
183 for (int i
= 0; insn
->srcExists(i
); ++i
) {
184 if (insn
->src(i
).get() == value
) {
185 // If there are multiple references to us we'd have to check if the
186 // combination of mods is still supported, but just bail for now.
187 if (&insn
->src(i
) != (*it
))
192 assert(s
>= 0); // integrity of uses list
194 if (!target
->isModSupported(insn
, s
, rep
.mod
))
201 ValueDef::replace(const ValueRef
&repVal
, bool doSet
)
203 assert(mayReplace(repVal
));
205 if (value
== repVal
.get())
208 while (!value
->uses
.empty()) {
209 ValueRef
*ref
= *value
->uses
.begin();
210 ref
->set(repVal
.get());
211 ref
->mod
*= repVal
.mod
;
221 memset(®
, 0, sizeof(reg
));
225 LValue::LValue(Function
*fn
, DataFile file
)
228 reg
.size
= (file
!= FILE_PREDICATE
) ? 4 : 1;
237 fn
->add(this, this->id
);
240 LValue::LValue(Function
*fn
, LValue
*lval
)
244 reg
.file
= lval
->reg
.file
;
245 reg
.size
= lval
->reg
.size
;
254 fn
->add(this, this->id
);
258 LValue::clone(ClonePolicy
<Function
>& pol
) const
260 LValue
*that
= new_LValue(pol
.context(), reg
.file
);
262 pol
.set
<Value
>(this, that
);
264 that
->reg
.size
= this->reg
.size
;
265 that
->reg
.type
= this->reg
.type
;
266 that
->reg
.data
= this->reg
.data
;
272 LValue::isUniform() const
276 Instruction
*insn
= getInsn();
279 // let's not try too hard here for now ...
280 return !insn
->srcExists(1) && insn
->getSrc(0)->isUniform();
283 Symbol::Symbol(Program
*prog
, DataFile f
, ubyte fidx
)
288 reg
.fileIndex
= fidx
;
291 prog
->add(this, this->id
);
295 Symbol::clone(ClonePolicy
<Function
>& pol
) const
297 Program
*prog
= pol
.context()->getProgram();
299 Symbol
*that
= new_Symbol(prog
, reg
.file
, reg
.fileIndex
);
301 pol
.set
<Value
>(this, that
);
303 that
->reg
.size
= this->reg
.size
;
304 that
->reg
.type
= this->reg
.type
;
305 that
->reg
.data
= this->reg
.data
;
307 that
->baseSym
= this->baseSym
;
313 Symbol::isUniform() const
316 reg
.file
!= FILE_SYSTEM_VALUE
&&
317 reg
.file
!= FILE_MEMORY_LOCAL
&&
318 reg
.file
!= FILE_SHADER_INPUT
;
321 ImmediateValue::ImmediateValue(Program
*prog
, uint32_t uval
)
323 memset(®
, 0, sizeof(reg
));
325 reg
.file
= FILE_IMMEDIATE
;
331 prog
->add(this, this->id
);
334 ImmediateValue::ImmediateValue(Program
*prog
, float fval
)
336 memset(®
, 0, sizeof(reg
));
338 reg
.file
= FILE_IMMEDIATE
;
344 prog
->add(this, this->id
);
347 ImmediateValue::ImmediateValue(Program
*prog
, double dval
)
349 memset(®
, 0, sizeof(reg
));
351 reg
.file
= FILE_IMMEDIATE
;
357 prog
->add(this, this->id
);
360 ImmediateValue::ImmediateValue(const ImmediateValue
*proto
, DataType ty
)
365 reg
.size
= typeSizeof(ty
);
369 ImmediateValue::clone(ClonePolicy
<Function
>& pol
) const
371 Program
*prog
= pol
.context()->getProgram();
372 ImmediateValue
*that
= new_ImmediateValue(prog
, 0u);
374 pol
.set
<Value
>(this, that
);
376 that
->reg
.size
= this->reg
.size
;
377 that
->reg
.type
= this->reg
.type
;
378 that
->reg
.data
= this->reg
.data
;
384 ImmediateValue::isInteger(const int i
) const
388 return reg
.data
.s8
== i
;
390 return reg
.data
.u8
== i
;
392 return reg
.data
.s16
== i
;
394 return reg
.data
.u16
== i
;
397 return reg
.data
.s32
== i
; // as if ...
400 return reg
.data
.s64
== i
; // as if ...
402 return reg
.data
.f32
== static_cast<float>(i
);
404 return reg
.data
.f64
== static_cast<double>(i
);
411 ImmediateValue::isNegative() const
414 case TYPE_S8
: return reg
.data
.s8
< 0;
415 case TYPE_S16
: return reg
.data
.s16
< 0;
417 case TYPE_U32
: return reg
.data
.s32
< 0;
418 case TYPE_F32
: return reg
.data
.u32
& (1 << 31);
419 case TYPE_F64
: return reg
.data
.u64
& (1ULL << 63);
426 ImmediateValue::isPow2() const
428 if (reg
.type
== TYPE_U64
|| reg
.type
== TYPE_S64
)
429 return util_is_power_of_two_or_zero64(reg
.data
.u64
);
431 return util_is_power_of_two_or_zero(reg
.data
.u32
);
435 ImmediateValue::applyLog2()
441 assert(!this->isNegative());
446 reg
.data
.u32
= util_logbase2(reg
.data
.u32
);
449 assert(!this->isNegative());
452 reg
.data
.u64
= util_logbase2_64(reg
.data
.u64
);
455 reg
.data
.f32
= log2f(reg
.data
.f32
);
458 reg
.data
.f64
= log2(reg
.data
.f64
);
467 ImmediateValue::compare(CondCode cc
, float fval
) const
469 if (reg
.type
!= TYPE_F32
)
470 ERROR("immediate value is not of type f32");
472 switch (static_cast<CondCode
>(cc
& 7)) {
473 case CC_TR
: return true;
474 case CC_FL
: return false;
475 case CC_LT
: return reg
.data
.f32
< fval
;
476 case CC_LE
: return reg
.data
.f32
<= fval
;
477 case CC_GT
: return reg
.data
.f32
> fval
;
478 case CC_GE
: return reg
.data
.f32
>= fval
;
479 case CC_EQ
: return reg
.data
.f32
== fval
;
480 case CC_NE
: return reg
.data
.f32
!= fval
;
488 ImmediateValue::operator=(const ImmediateValue
&that
)
490 this->reg
= that
.reg
;
495 Value::interfers(const Value
*that
) const
499 if (that
->reg
.file
!= reg
.file
|| that
->reg
.fileIndex
!= reg
.fileIndex
)
505 idA
= this->join
->reg
.data
.offset
;
506 idB
= that
->join
->reg
.data
.offset
;
508 idA
= this->join
->reg
.data
.id
* MIN2(this->reg
.size
, 4);
509 idB
= that
->join
->reg
.data
.id
* MIN2(that
->reg
.size
, 4);
513 return (idA
+ this->reg
.size
> idB
);
516 return (idB
+ that
->reg
.size
> idA
);
522 Value::equals(const Value
*that
, bool strict
) const
527 if (that
->reg
.file
!= reg
.file
|| that
->reg
.fileIndex
!= reg
.fileIndex
)
529 if (that
->reg
.size
!= this->reg
.size
)
532 if (that
->reg
.data
.id
!= this->reg
.data
.id
)
539 ImmediateValue::equals(const Value
*that
, bool strict
) const
541 const ImmediateValue
*imm
= that
->asImm();
544 return reg
.data
.u64
== imm
->reg
.data
.u64
;
548 Symbol::equals(const Value
*that
, bool strict
) const
550 if (reg
.file
!= that
->reg
.file
|| reg
.fileIndex
!= that
->reg
.fileIndex
)
552 assert(that
->asSym());
554 if (this->baseSym
!= that
->asSym()->baseSym
)
557 if (reg
.file
== FILE_SYSTEM_VALUE
)
558 return (this->reg
.data
.sv
.sv
== that
->reg
.data
.sv
.sv
&&
559 this->reg
.data
.sv
.index
== that
->reg
.data
.sv
.index
);
560 return this->reg
.data
.offset
== that
->reg
.data
.offset
;
563 void Instruction::init()
594 Instruction::Instruction()
599 dType
= sType
= TYPE_F32
;
605 Instruction::Instruction(Function
*fn
, operation opr
, DataType ty
)
615 Instruction::~Instruction()
618 Function
*fn
= bb
->getFunction();
620 fn
->allInsns
.remove(id
);
623 for (int s
= 0; srcExists(s
); ++s
)
625 // must unlink defs too since the list pointers will get deallocated
626 for (int d
= 0; defExists(d
); ++d
)
631 Instruction::setDef(int i
, Value
*val
)
633 int size
= defs
.size();
637 defs
[size
++].setInsn(this);
643 Instruction::setSrc(int s
, Value
*val
)
645 int size
= srcs
.size();
649 srcs
[size
++].setInsn(this);
655 Instruction::setSrc(int s
, const ValueRef
& ref
)
657 setSrc(s
, ref
.get());
658 srcs
[s
].mod
= ref
.mod
;
662 Instruction::swapSources(int a
, int b
)
664 Value
*value
= srcs
[a
].get();
665 Modifier m
= srcs
[a
].mod
;
673 static inline void moveSourcesAdjustIndex(int8_t &index
, int s
, int delta
)
678 if ((delta
< 0) && (index
>= (s
+ delta
)))
682 // Moves sources [@s,last_source] by @delta.
683 // If @delta < 0, sources [@s - abs(@delta), @s) are erased.
685 Instruction::moveSources(const int s
, const int delta
)
689 assert(s
+ delta
>= 0);
693 for (k
= 0; srcExists(k
); ++k
) {
694 for (int i
= 0; i
< 2; ++i
)
695 moveSourcesAdjustIndex(src(k
).indirect
[i
], s
, delta
);
697 moveSourcesAdjustIndex(predSrc
, s
, delta
);
698 moveSourcesAdjustIndex(flagsSrc
, s
, delta
);
700 TexInstruction
*tex
= asTex();
701 moveSourcesAdjustIndex(tex
->tex
.rIndirectSrc
, s
, delta
);
702 moveSourcesAdjustIndex(tex
->tex
.sIndirectSrc
, s
, delta
);
707 for (int p
= k
+ delta
; k
>= s
; --k
, --p
)
711 for (p
= s
; p
< k
; ++p
)
712 setSrc(p
+ delta
, src(p
));
713 for (; (p
+ delta
) < k
; ++p
)
714 setSrc(p
+ delta
, NULL
);
719 Instruction::takeExtraSources(int s
, Value
*values
[3])
721 values
[0] = getIndirect(s
, 0);
723 setIndirect(s
, 0, NULL
);
725 values
[1] = getIndirect(s
, 1);
727 setIndirect(s
, 1, NULL
);
729 values
[2] = getPredicate();
731 setPredicate(cc
, NULL
);
735 Instruction::putExtraSources(int s
, Value
*values
[3])
738 setIndirect(s
, 0, values
[0]);
740 setIndirect(s
, 1, values
[1]);
742 setPredicate(cc
, values
[2]);
746 Instruction::clone(ClonePolicy
<Function
>& pol
, Instruction
*i
) const
749 i
= new_Instruction(pol
.context(), op
, dType
);
750 #ifndef NDEBUG // non-conformant assert, so this is required
751 assert(typeid(*i
) == typeid(*this));
754 pol
.set
<Instruction
>(this, i
);
762 i
->saturate
= saturate
;
770 i
->perPatch
= perPatch
;
772 i
->postFactor
= postFactor
;
774 for (int d
= 0; defExists(d
); ++d
)
775 i
->setDef(d
, pol
.get(getDef(d
)));
777 for (int s
= 0; srcExists(s
); ++s
) {
778 i
->setSrc(s
, pol
.get(getSrc(s
)));
779 i
->src(s
).mod
= src(s
).mod
;
783 i
->predSrc
= predSrc
;
784 i
->flagsDef
= flagsDef
;
785 i
->flagsSrc
= flagsSrc
;
791 Instruction::defCount(unsigned int mask
, bool singleFile
) const
796 unsigned int d
= ffs(mask
);
799 for (i
= d
--; defExists(i
); ++i
)
800 if (getDef(i
)->reg
.file
!= getDef(d
)->reg
.file
)
804 for (n
= 0, i
= 0; this->defExists(i
); ++i
, mask
>>= 1)
810 Instruction::srcCount(unsigned int mask
, bool singleFile
) const
815 unsigned int s
= ffs(mask
);
818 for (i
= s
--; srcExists(i
); ++i
)
819 if (getSrc(i
)->reg
.file
!= getSrc(s
)->reg
.file
)
823 for (n
= 0, i
= 0; this->srcExists(i
); ++i
, mask
>>= 1)
829 Instruction::setIndirect(int s
, int dim
, Value
*value
)
831 assert(this->srcExists(s
));
833 int p
= srcs
[s
].indirect
[dim
];
838 while (p
> 0 && !srcExists(p
- 1))
842 srcs
[p
].usedAsPtr
= (value
!= 0);
843 srcs
[s
].indirect
[dim
] = value
? p
: -1;
848 Instruction::setPredicate(CondCode ccode
, Value
*value
)
854 srcs
[predSrc
].set(NULL
);
861 predSrc
= srcs
.size();
862 while (predSrc
> 0 && !srcExists(predSrc
- 1))
866 setSrc(predSrc
, value
);
871 Instruction::writesPredicate() const
873 for (int d
= 0; defExists(d
); ++d
)
874 if (getDef(d
)->inFile(FILE_PREDICATE
) || getDef(d
)->inFile(FILE_FLAGS
))
880 Instruction::canCommuteDefSrc(const Instruction
*i
) const
882 for (int d
= 0; defExists(d
); ++d
)
883 for (int s
= 0; i
->srcExists(s
); ++s
)
884 if (getDef(d
)->interfers(i
->getSrc(s
)))
890 Instruction::canCommuteDefDef(const Instruction
*i
) const
892 for (int d
= 0; defExists(d
); ++d
)
893 for (int c
= 0; i
->defExists(c
); ++c
)
894 if (getDef(d
)->interfers(i
->getDef(c
)))
900 Instruction::isCommutationLegal(const Instruction
*i
) const
902 return canCommuteDefDef(i
) &&
903 canCommuteDefSrc(i
) &&
904 i
->canCommuteDefSrc(this);
907 TexInstruction::TexInstruction(Function
*fn
, operation op
)
908 : Instruction(fn
, op
, TYPE_F32
)
910 memset(&tex
, 0, sizeof(tex
));
912 tex
.rIndirectSrc
= -1;
913 tex
.sIndirectSrc
= -1;
919 TexInstruction::~TexInstruction()
921 for (int c
= 0; c
< 3; ++c
) {
925 for (int n
= 0; n
< 4; ++n
)
926 for (int c
= 0; c
< 3; ++c
)
927 offset
[n
][c
].set(NULL
);
931 TexInstruction::clone(ClonePolicy
<Function
>& pol
, Instruction
*i
) const
933 TexInstruction
*tex
= (i
? static_cast<TexInstruction
*>(i
) :
934 new_TexInstruction(pol
.context(), op
));
936 Instruction::clone(pol
, tex
);
938 tex
->tex
= this->tex
;
941 for (unsigned int c
= 0; c
< tex
->tex
.target
.getDim(); ++c
) {
942 tex
->dPdx
[c
].set(dPdx
[c
]);
943 tex
->dPdy
[c
].set(dPdy
[c
]);
947 for (int n
= 0; n
< tex
->tex
.useOffsets
; ++n
)
948 for (int c
= 0; c
< 3; ++c
)
949 tex
->offset
[n
][c
].set(offset
[n
][c
]);
954 const struct TexInstruction::Target::Desc
TexInstruction::Target::descTable
[] =
956 { "1D", 1, 1, false, false, false },
957 { "2D", 2, 2, false, false, false },
958 { "2D_MS", 2, 3, false, false, false },
959 { "3D", 3, 3, false, false, false },
960 { "CUBE", 2, 3, false, true, false },
961 { "1D_SHADOW", 1, 1, false, false, true },
962 { "2D_SHADOW", 2, 2, false, false, true },
963 { "CUBE_SHADOW", 2, 3, false, true, true },
964 { "1D_ARRAY", 1, 2, true, false, false },
965 { "2D_ARRAY", 2, 3, true, false, false },
966 { "2D_MS_ARRAY", 2, 4, true, false, false },
967 { "CUBE_ARRAY", 2, 4, true, true, false },
968 { "1D_ARRAY_SHADOW", 1, 2, true, false, true },
969 { "2D_ARRAY_SHADOW", 2, 3, true, false, true },
970 { "RECT", 2, 2, false, false, false },
971 { "RECT_SHADOW", 2, 2, false, false, true },
972 { "CUBE_ARRAY_SHADOW", 2, 4, true, true, true },
973 { "BUFFER", 1, 1, false, false, false },
976 const struct TexInstruction::ImgFormatDesc
TexInstruction::formatTable
[] =
978 { "NONE", 0, { 0, 0, 0, 0 }, UINT
},
980 { "RGBA32F", 4, { 32, 32, 32, 32 }, FLOAT
},
981 { "RGBA16F", 4, { 16, 16, 16, 16 }, FLOAT
},
982 { "RG32F", 2, { 32, 32, 0, 0 }, FLOAT
},
983 { "RG16F", 2, { 16, 16, 0, 0 }, FLOAT
},
984 { "R11G11B10F", 3, { 11, 11, 10, 0 }, FLOAT
},
985 { "R32F", 1, { 32, 0, 0, 0 }, FLOAT
},
986 { "R16F", 1, { 16, 0, 0, 0 }, FLOAT
},
988 { "RGBA32UI", 4, { 32, 32, 32, 32 }, UINT
},
989 { "RGBA16UI", 4, { 16, 16, 16, 16 }, UINT
},
990 { "RGB10A2UI", 4, { 10, 10, 10, 2 }, UINT
},
991 { "RGBA8UI", 4, { 8, 8, 8, 8 }, UINT
},
992 { "RG32UI", 2, { 32, 32, 0, 0 }, UINT
},
993 { "RG16UI", 2, { 16, 16, 0, 0 }, UINT
},
994 { "RG8UI", 2, { 8, 8, 0, 0 }, UINT
},
995 { "R32UI", 1, { 32, 0, 0, 0 }, UINT
},
996 { "R16UI", 1, { 16, 0, 0, 0 }, UINT
},
997 { "R8UI", 1, { 8, 0, 0, 0 }, UINT
},
999 { "RGBA32I", 4, { 32, 32, 32, 32 }, SINT
},
1000 { "RGBA16I", 4, { 16, 16, 16, 16 }, SINT
},
1001 { "RGBA8I", 4, { 8, 8, 8, 8 }, SINT
},
1002 { "RG32I", 2, { 32, 32, 0, 0 }, SINT
},
1003 { "RG16I", 2, { 16, 16, 0, 0 }, SINT
},
1004 { "RG8I", 2, { 8, 8, 0, 0 }, SINT
},
1005 { "R32I", 1, { 32, 0, 0, 0 }, SINT
},
1006 { "R16I", 1, { 16, 0, 0, 0 }, SINT
},
1007 { "R8I", 1, { 8, 0, 0, 0 }, SINT
},
1009 { "RGBA16", 4, { 16, 16, 16, 16 }, UNORM
},
1010 { "RGB10A2", 4, { 10, 10, 10, 2 }, UNORM
},
1011 { "RGBA8", 4, { 8, 8, 8, 8 }, UNORM
},
1012 { "RG16", 2, { 16, 16, 0, 0 }, UNORM
},
1013 { "RG8", 2, { 8, 8, 0, 0 }, UNORM
},
1014 { "R16", 1, { 16, 0, 0, 0 }, UNORM
},
1015 { "R8", 1, { 8, 0, 0, 0 }, UNORM
},
1017 { "RGBA16_SNORM", 4, { 16, 16, 16, 16 }, SNORM
},
1018 { "RGBA8_SNORM", 4, { 8, 8, 8, 8 }, SNORM
},
1019 { "RG16_SNORM", 2, { 16, 16, 0, 0 }, SNORM
},
1020 { "RG8_SNORM", 2, { 8, 8, 0, 0 }, SNORM
},
1021 { "R16_SNORM", 1, { 16, 0, 0, 0 }, SNORM
},
1022 { "R8_SNORM", 1, { 8, 0, 0, 0 }, SNORM
},
1024 { "BGRA8", 4, { 8, 8, 8, 8 }, UNORM
, true },
1028 TexInstruction::setIndirectR(Value
*v
)
1030 int p
= ((tex
.rIndirectSrc
< 0) && v
) ? srcs
.size() : tex
.rIndirectSrc
;
1032 tex
.rIndirectSrc
= p
;
1034 srcs
[p
].usedAsPtr
= !!v
;
1039 TexInstruction::setIndirectS(Value
*v
)
1041 int p
= ((tex
.sIndirectSrc
< 0) && v
) ? srcs
.size() : tex
.sIndirectSrc
;
1043 tex
.sIndirectSrc
= p
;
1045 srcs
[p
].usedAsPtr
= !!v
;
1049 CmpInstruction::CmpInstruction(Function
*fn
, operation op
)
1050 : Instruction(fn
, op
, TYPE_F32
)
1052 setCond
= CC_ALWAYS
;
1056 CmpInstruction::clone(ClonePolicy
<Function
>& pol
, Instruction
*i
) const
1058 CmpInstruction
*cmp
= (i
? static_cast<CmpInstruction
*>(i
) :
1059 new_CmpInstruction(pol
.context(), op
));
1061 Instruction::clone(pol
, cmp
);
1062 cmp
->setCond
= setCond
;
1066 FlowInstruction::FlowInstruction(Function
*fn
, operation op
, void *targ
)
1067 : Instruction(fn
, op
, TYPE_NONE
)
1070 target
.fn
= reinterpret_cast<Function
*>(targ
);
1072 target
.bb
= reinterpret_cast<BasicBlock
*>(targ
);
1075 op
== OP_CONT
|| op
== OP_BREAK
||
1076 op
== OP_RET
|| op
== OP_EXIT
)
1080 terminator
= targ
? 1 : 0;
1082 allWarp
= absolute
= limit
= builtin
= indirect
= 0;
1086 FlowInstruction::clone(ClonePolicy
<Function
>& pol
, Instruction
*i
) const
1088 FlowInstruction
*flow
= (i
? static_cast<FlowInstruction
*>(i
) :
1089 new_FlowInstruction(pol
.context(), op
, NULL
));
1091 Instruction::clone(pol
, flow
);
1092 flow
->allWarp
= allWarp
;
1093 flow
->absolute
= absolute
;
1094 flow
->limit
= limit
;
1095 flow
->builtin
= builtin
;
1098 flow
->target
.builtin
= target
.builtin
;
1101 flow
->target
.fn
= target
.fn
;
1104 flow
->target
.bb
= pol
.get
<BasicBlock
>(target
.bb
);
1109 Program::Program(Type type
, Target
*arch
)
1112 mem_Instruction(sizeof(Instruction
), 6),
1113 mem_CmpInstruction(sizeof(CmpInstruction
), 4),
1114 mem_TexInstruction(sizeof(TexInstruction
), 4),
1115 mem_FlowInstruction(sizeof(FlowInstruction
), 4),
1116 mem_LValue(sizeof(LValue
), 8),
1117 mem_Symbol(sizeof(Symbol
), 7),
1118 mem_ImmediateValue(sizeof(ImmediateValue
), 7)
1126 main
= new Function(this, "MAIN", ~0);
1127 calls
.insert(&main
->call
);
1137 for (ArrayList::Iterator it
= allFuncs
.iterator(); !it
.end(); it
.next())
1138 delete reinterpret_cast<Function
*>(it
.get());
1140 for (ArrayList::Iterator it
= allRValues
.iterator(); !it
.end(); it
.next())
1141 releaseValue(reinterpret_cast<Value
*>(it
.get()));
1144 void Program::releaseInstruction(Instruction
*insn
)
1146 // TODO: make this not suck so much
1148 insn
->~Instruction();
1151 mem_CmpInstruction
.release(insn
);
1154 mem_TexInstruction
.release(insn
);
1157 mem_FlowInstruction
.release(insn
);
1159 mem_Instruction
.release(insn
);
1162 void Program::releaseValue(Value
*value
)
1166 if (value
->asLValue())
1167 mem_LValue
.release(value
);
1170 mem_ImmediateValue
.release(value
);
1173 mem_Symbol
.release(value
);
1177 } // namespace nv50_ir
1182 nv50_ir_init_prog_info(struct nv50_ir_prog_info
*info
)
1184 if (info
->type
== PIPE_SHADER_TESS_CTRL
|| info
->type
== PIPE_SHADER_TESS_EVAL
) {
1185 info
->prop
.tp
.domain
= PIPE_PRIM_MAX
;
1186 info
->prop
.tp
.outputPrim
= PIPE_PRIM_MAX
;
1188 if (info
->type
== PIPE_SHADER_GEOMETRY
) {
1189 info
->prop
.gp
.instanceCount
= 1;
1190 info
->prop
.gp
.maxVertices
= 1;
1192 if (info
->type
== PIPE_SHADER_COMPUTE
) {
1193 info
->prop
.cp
.numThreads
[0] =
1194 info
->prop
.cp
.numThreads
[1] =
1195 info
->prop
.cp
.numThreads
[2] = 1;
1197 info
->io
.pointSize
= 0xff;
1198 info
->io
.instanceId
= 0xff;
1199 info
->io
.vertexId
= 0xff;
1200 info
->io
.edgeFlagIn
= 0xff;
1201 info
->io
.edgeFlagOut
= 0xff;
1202 info
->io
.fragDepth
= 0xff;
1203 info
->io
.sampleMask
= 0xff;
1204 info
->io
.backFaceColor
[0] = info
->io
.backFaceColor
[1] = 0xff;
1208 nv50_ir_generate_code(struct nv50_ir_prog_info
*info
)
1212 nv50_ir::Program::Type type
;
1214 nv50_ir_init_prog_info(info
);
1216 #define PROG_TYPE_CASE(a, b) \
1217 case PIPE_SHADER_##a: type = nv50_ir::Program::TYPE_##b; break
1219 switch (info
->type
) {
1220 PROG_TYPE_CASE(VERTEX
, VERTEX
);
1221 PROG_TYPE_CASE(TESS_CTRL
, TESSELLATION_CONTROL
);
1222 PROG_TYPE_CASE(TESS_EVAL
, TESSELLATION_EVAL
);
1223 PROG_TYPE_CASE(GEOMETRY
, GEOMETRY
);
1224 PROG_TYPE_CASE(FRAGMENT
, FRAGMENT
);
1225 PROG_TYPE_CASE(COMPUTE
, COMPUTE
);
1227 INFO_DBG(info
->dbgFlags
, VERBOSE
, "unsupported program type %u\n", info
->type
);
1230 INFO_DBG(info
->dbgFlags
, VERBOSE
, "translating program of type %u\n", type
);
1232 nv50_ir::Target
*targ
= nv50_ir::Target::create(info
->target
);
1236 nv50_ir::Program
*prog
= new nv50_ir::Program(type
, targ
);
1238 nv50_ir::Target::destroy(targ
);
1241 prog
->driver
= info
;
1242 prog
->dbgFlags
= info
->dbgFlags
;
1243 prog
->optLevel
= info
->optLevel
;
1245 switch (info
->bin
.sourceRep
) {
1246 case PIPE_SHADER_IR_NIR
:
1247 ret
= prog
->makeFromNIR(info
) ? 0 : -2;
1249 case PIPE_SHADER_IR_TGSI
:
1250 ret
= prog
->makeFromTGSI(info
) ? 0 : -2;
1258 if (prog
->dbgFlags
& NV50_IR_DEBUG_VERBOSE
)
1261 targ
->parseDriverInfo(info
);
1262 prog
->getTarget()->runLegalizePass(prog
, nv50_ir::CG_STAGE_PRE_SSA
);
1264 prog
->convertToSSA();
1266 if (prog
->dbgFlags
& NV50_IR_DEBUG_VERBOSE
)
1269 prog
->optimizeSSA(info
->optLevel
);
1270 prog
->getTarget()->runLegalizePass(prog
, nv50_ir::CG_STAGE_SSA
);
1272 if (prog
->dbgFlags
& NV50_IR_DEBUG_BASIC
)
1275 if (!prog
->registerAllocation()) {
1279 prog
->getTarget()->runLegalizePass(prog
, nv50_ir::CG_STAGE_POST_RA
);
1281 prog
->optimizePostRA(info
->optLevel
);
1283 if (!prog
->emitBinary(info
)) {
1289 INFO_DBG(prog
->dbgFlags
, VERBOSE
, "nv50_ir_generate_code: ret = %i\n", ret
);
1291 info
->bin
.maxGPR
= prog
->maxGPR
;
1292 info
->bin
.code
= prog
->code
;
1293 info
->bin
.codeSize
= prog
->binSize
;
1294 info
->bin
.tlsSpace
= prog
->tlsSize
;
1297 nv50_ir::Target::destroy(targ
);