xref: /aosp_15_r20/external/mesa3d/src/nouveau/codegen/nv50_ir_build_util.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 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.
21  */
22 
23 #ifndef __NV50_IR_BUILD_UTIL__
24 #define __NV50_IR_BUILD_UTIL__
25 
26 namespace nv50_ir {
27 
28 class BuildUtil
29 {
30 public:
31    BuildUtil();
32    BuildUtil(Program *);
33 
34    inline void setProgram(Program *);
getProgram()35    inline Program *getProgram() const { return prog; }
getFunction()36    inline Function *getFunction() const { return func; }
37 
38    // keeps inserting at head/tail of block
39    inline void setPosition(BasicBlock *, bool tail);
40    // position advances only if @after is true
41    inline void setPosition(Instruction *, bool after);
42 
getBB()43    inline BasicBlock *getBB() { return bb; }
44 
45    inline void insert(Instruction *);
remove(Instruction * i)46    inline void remove(Instruction *i) { assert(i->bb == bb); bb->remove(i); }
47 
48    inline LValue *getScratch(int size = 4, DataFile = FILE_GPR);
49    // scratch value for a single assignment:
50    inline LValue *getSSA(int size = 4, DataFile = FILE_GPR);
51 
52    inline Instruction *mkOp(operation, DataType, Value *);
53    Instruction *mkOp1(operation, DataType, Value *, Value *);
54    Instruction *mkOp2(operation, DataType, Value *, Value *, Value *);
55    Instruction *mkOp3(operation, DataType, Value *, Value *, Value *, Value *);
56 
57    LValue *mkOp1v(operation, DataType, Value *, Value *);
58    LValue *mkOp2v(operation, DataType, Value *, Value *, Value *);
59    LValue *mkOp3v(operation, DataType, Value *, Value *, Value *, Value *);
60 
61    Instruction *mkLoad(DataType, Value *dst, Symbol *, Value *ptr);
62    Instruction *mkStore(operation, DataType, Symbol *, Value *ptr, Value *val);
63 
64    LValue *mkLoadv(DataType, Symbol *, Value *ptr);
65 
66    Instruction *mkMov(Value *, Value *, DataType = TYPE_U32);
67    Instruction *mkMovToReg(int id, Value *);
68    Instruction *mkMovFromReg(Value *, int id);
69    inline Instruction *mkBMov(Value *, Value *);
70 
71    Instruction *mkInterp(unsigned mode, Value *, int32_t offset, Value *rel);
72    Instruction *mkFetch(Value *, DataType, DataFile, int32_t offset,
73                         Value *attrRel, Value *primRel);
74 
75    Instruction *mkCvt(operation, DataType, Value *, DataType, Value *);
76    CmpInstruction *mkCmp(operation, CondCode, DataType,
77                          Value *,
78                          DataType, Value *, Value *, Value * = NULL);
79    TexInstruction *mkTex(operation, TexTarget,
80                          uint16_t tic, uint16_t tsc,
81                          const std::vector<Value *> &def,
82                          const std::vector<Value *> &src);
83    Instruction *mkQuadop(uint8_t qop, Value *, uint8_t l, Value *, Value *);
84 
85    FlowInstruction *mkFlow(operation, void *target, CondCode, Value *pred);
86 
87    Instruction *mkSelect(Value *pred, Value *dst, Value *trSrc, Value *flSrc);
88 
89    Instruction *mkSplit(Value *half[2], uint8_t halfSize, Value *);
90 
91    void mkClobber(DataFile file, uint32_t regMask, int regUnitLog2);
92 
93    ImmediateValue *mkImm(float);
94    ImmediateValue *mkImm(double);
95    ImmediateValue *mkImm(uint16_t);
96    ImmediateValue *mkImm(uint32_t);
97    ImmediateValue *mkImm(uint64_t);
98 
mkImm(int i)99    ImmediateValue *mkImm(int i) { return mkImm((uint32_t)i); }
100 
101    Value *loadImm(Value *dst, float);
102    Value *loadImm(Value *dst, double);
103    Value *loadImm(Value *dst, uint16_t);
104    Value *loadImm(Value *dst, uint32_t);
105    Value *loadImm(Value *dst, uint64_t);
106 
loadImm(Value * dst,int i)107    Value *loadImm(Value *dst, int i) { return loadImm(dst, (uint32_t)i); }
108 
109    // returns high part of the operation
110    static Instruction *split64BitOpPostRA(Function *, Instruction *,
111                                           Value *zero, Value *carry);
112 
113    Symbol *mkSymbol(DataFile file, int8_t fileIndex,
114                     DataType ty, uint32_t baseAddress);
115 
116    Symbol *mkSysVal(SVSemantic svName, uint32_t svIndex);
117    Symbol *mkTSVal(TSSemantic tsName);
118 
119 private:
120    void init(Program *);
121    void addImmediate(ImmediateValue *);
122    inline unsigned int u32Hash(uint32_t);
123 
124 protected:
125    Program *prog;
126    Function *func;
127    Instruction *pos;
128    BasicBlock *bb;
129    bool tail;
130 
131 #define NV50_IR_BUILD_IMM_HT_SIZE 256
132 
133    ImmediateValue *imms[NV50_IR_BUILD_IMM_HT_SIZE];
134    unsigned int immCount;
135 };
136 
u32Hash(uint32_t u)137 unsigned int BuildUtil::u32Hash(uint32_t u)
138 {
139    return (u % 273) % NV50_IR_BUILD_IMM_HT_SIZE;
140 }
141 
setProgram(Program * program)142 void BuildUtil::setProgram(Program *program)
143 {
144    prog = program;
145 }
146 
147 void
setPosition(BasicBlock * block,bool atTail)148 BuildUtil::setPosition(BasicBlock *block, bool atTail)
149 {
150    bb = block;
151    prog = bb->getProgram();
152    func = bb->getFunction();
153    pos = NULL;
154    tail = atTail;
155 }
156 
157 void
setPosition(Instruction * i,bool after)158 BuildUtil::setPosition(Instruction *i, bool after)
159 {
160    bb = i->bb;
161    prog = bb->getProgram();
162    func = bb->getFunction();
163    pos = i;
164    tail = after;
165    assert(bb);
166 }
167 
168 LValue *
getScratch(int size,DataFile f)169 BuildUtil::getScratch(int size, DataFile f)
170 {
171    LValue *lval = new_LValue(func, f);
172    lval->reg.size = size;
173    return lval;
174 }
175 
176 LValue *
getSSA(int size,DataFile f)177 BuildUtil::getSSA(int size, DataFile f)
178 {
179    LValue *lval = new_LValue(func, f);
180    lval->ssa = 1;
181    lval->reg.size = size;
182    return lval;
183 }
184 
insert(Instruction * i)185 void BuildUtil::insert(Instruction *i)
186 {
187    if (!pos) {
188       tail ? bb->insertTail(i) : bb->insertHead(i);
189    } else {
190       if (tail) {
191          bb->insertAfter(pos, i);
192          pos = i;
193       } else {
194          bb->insertBefore(pos, i);
195       }
196    }
197 }
198 
199 Instruction *
mkOp(operation op,DataType ty,Value * dst)200 BuildUtil::mkOp(operation op, DataType ty, Value *dst)
201 {
202    Instruction *insn = new_Instruction(func, op, ty);
203    insn->setDef(0, dst);
204    insert(insn);
205    if (op == OP_DISCARD || op == OP_EXIT ||
206        op == OP_JOIN ||
207        op == OP_QUADON || op == OP_QUADPOP ||
208        op == OP_EMIT || op == OP_RESTART)
209       insn->fixed = 1;
210    return insn;
211 }
212 
213 inline LValue *
mkOp1v(operation op,DataType ty,Value * dst,Value * src)214 BuildUtil::mkOp1v(operation op, DataType ty, Value *dst, Value *src)
215 {
216    mkOp1(op, ty, dst, src);
217    return dst->asLValue();
218 }
219 
220 inline LValue *
mkOp2v(operation op,DataType ty,Value * dst,Value * src0,Value * src1)221 BuildUtil::mkOp2v(operation op, DataType ty, Value *dst,
222                   Value *src0, Value *src1)
223 {
224    mkOp2(op, ty, dst, src0, src1);
225    return dst->asLValue();
226 }
227 
228 inline LValue *
mkOp3v(operation op,DataType ty,Value * dst,Value * src0,Value * src1,Value * src2)229 BuildUtil::mkOp3v(operation op, DataType ty, Value *dst,
230                   Value *src0, Value *src1, Value *src2)
231 {
232    mkOp3(op, ty, dst, src0, src1, src2);
233    return dst->asLValue();
234 }
235 
236 inline LValue *
mkLoadv(DataType ty,Symbol * mem,Value * ptr)237 BuildUtil::mkLoadv(DataType ty, Symbol *mem, Value *ptr)
238 {
239    LValue *dst = getScratch(typeSizeof(ty));
240    mkLoad(ty, dst, mem, ptr);
241    return dst;
242 }
243 
244 inline Instruction *
mkBMov(Value * dst,Value * src)245 BuildUtil::mkBMov(Value *dst, Value *src)
246 {
247    return mkCvt(OP_CVT, TYPE_U32, dst, TYPE_U32, src);
248 }
249 
250 } // namespace nv50_ir
251 
252 #endif // __NV50_IR_BUILD_UTIL_H__
253