1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright 2011 Christoph Bumiller
3bf215546Sopenharmony_ci *           2014 Red Hat Inc.
4bf215546Sopenharmony_ci *
5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
10bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci *
12bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
13bf215546Sopenharmony_ci * all copies or substantial portions of the Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "nv50_ir.h"
25bf215546Sopenharmony_ci#include "nv50_ir_build_util.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ci#include "nv50_ir_target_nvc0.h"
28bf215546Sopenharmony_ci#include "nv50_ir_lowering_gm107.h"
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include <limits>
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cinamespace nv50_ir {
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci#define QOP_ADD  0
35bf215546Sopenharmony_ci#define QOP_SUBR 1
36bf215546Sopenharmony_ci#define QOP_SUB  2
37bf215546Sopenharmony_ci#define QOP_MOV2 3
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci//             UL UR LL LR
40bf215546Sopenharmony_ci#define QUADOP(q, r, s, t)                      \
41bf215546Sopenharmony_ci   ((QOP_##q << 6) | (QOP_##r << 4) |           \
42bf215546Sopenharmony_ci    (QOP_##s << 2) | (QOP_##t << 0))
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci#define SHFL_BOUND_QUAD 0x1c03
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_civoid
47bf215546Sopenharmony_ciGM107LegalizeSSA::handlePFETCH(Instruction *i)
48bf215546Sopenharmony_ci{
49bf215546Sopenharmony_ci   Value *src0;
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   if (i->src(0).getFile() == FILE_GPR && !i->srcExists(1))
52bf215546Sopenharmony_ci      return;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   bld.setPosition(i, false);
55bf215546Sopenharmony_ci   src0 = bld.getSSA();
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci   if (i->srcExists(1))
58bf215546Sopenharmony_ci      bld.mkOp2(OP_ADD , TYPE_U32, src0, i->getSrc(0), i->getSrc(1));
59bf215546Sopenharmony_ci   else
60bf215546Sopenharmony_ci      bld.mkOp1(OP_MOV , TYPE_U32, src0, i->getSrc(0));
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci   i->setSrc(0, src0);
63bf215546Sopenharmony_ci   i->setSrc(1, NULL);
64bf215546Sopenharmony_ci}
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_civoid
67bf215546Sopenharmony_ciGM107LegalizeSSA::handleLOAD(Instruction *i)
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   if (i->src(0).getFile() != FILE_MEMORY_CONST)
70bf215546Sopenharmony_ci      return;
71bf215546Sopenharmony_ci   if (i->src(0).isIndirect(0))
72bf215546Sopenharmony_ci      return;
73bf215546Sopenharmony_ci   if (typeSizeof(i->dType) != 4)
74bf215546Sopenharmony_ci      return;
75bf215546Sopenharmony_ci
76bf215546Sopenharmony_ci   i->op = OP_MOV;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_civoid
80bf215546Sopenharmony_ciGM107LegalizeSSA::handleQUADON(Instruction *i)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci   i->setDef(0, NULL);
83bf215546Sopenharmony_ci}
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_civoid
86bf215546Sopenharmony_ciGM107LegalizeSSA::handleQUADPOP(Instruction *i)
87bf215546Sopenharmony_ci{
88bf215546Sopenharmony_ci   i->setSrc(0, NULL);
89bf215546Sopenharmony_ci}
90bf215546Sopenharmony_ci
91bf215546Sopenharmony_cibool
92bf215546Sopenharmony_ciGM107LegalizeSSA::visit(Instruction *i)
93bf215546Sopenharmony_ci{
94bf215546Sopenharmony_ci   switch (i->op) {
95bf215546Sopenharmony_ci   case OP_QUADON:
96bf215546Sopenharmony_ci      handleQUADON(i);
97bf215546Sopenharmony_ci      break;
98bf215546Sopenharmony_ci   case OP_QUADPOP:
99bf215546Sopenharmony_ci      handleQUADPOP(i);
100bf215546Sopenharmony_ci      break;
101bf215546Sopenharmony_ci   case OP_PFETCH:
102bf215546Sopenharmony_ci      handlePFETCH(i);
103bf215546Sopenharmony_ci      break;
104bf215546Sopenharmony_ci   case OP_LOAD:
105bf215546Sopenharmony_ci      handleLOAD(i);
106bf215546Sopenharmony_ci      break;
107bf215546Sopenharmony_ci   default:
108bf215546Sopenharmony_ci      break;
109bf215546Sopenharmony_ci   }
110bf215546Sopenharmony_ci   return true;
111bf215546Sopenharmony_ci}
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_cibool
114bf215546Sopenharmony_ciGM107LoweringPass::handleManualTXD(TexInstruction *i)
115bf215546Sopenharmony_ci{
116bf215546Sopenharmony_ci   // See NVC0LoweringPass::handleManualTXD for rationale. This function
117bf215546Sopenharmony_ci   // implements the same logic, but using SM50-friendly primitives.
118bf215546Sopenharmony_ci   static const uint8_t qOps[2] =
119bf215546Sopenharmony_ci      { QUADOP(MOV2, ADD,  MOV2, ADD),  QUADOP(MOV2, MOV2, ADD,  ADD) };
120bf215546Sopenharmony_ci   Value *def[4][4];
121bf215546Sopenharmony_ci   Value *crd[3], *arr, *shadow;
122bf215546Sopenharmony_ci   Value *tmp;
123bf215546Sopenharmony_ci   Instruction *tex, *add;
124bf215546Sopenharmony_ci   Value *quad = bld.mkImm(SHFL_BOUND_QUAD);
125bf215546Sopenharmony_ci   int l, c;
126bf215546Sopenharmony_ci   const int dim = i->tex.target.getDim() + i->tex.target.isCube();
127bf215546Sopenharmony_ci   const int array = i->tex.target.isArray();
128bf215546Sopenharmony_ci   const int indirect = i->tex.rIndirectSrc >= 0;
129bf215546Sopenharmony_ci
130bf215546Sopenharmony_ci   i->op = OP_TEX; // no need to clone dPdx/dPdy later
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   for (c = 0; c < dim; ++c)
133bf215546Sopenharmony_ci      crd[c] = bld.getScratch();
134bf215546Sopenharmony_ci   arr = bld.getScratch();
135bf215546Sopenharmony_ci   shadow = bld.getScratch();
136bf215546Sopenharmony_ci   tmp = bld.getScratch();
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   for (l = 0; l < 4; ++l) {
139bf215546Sopenharmony_ci      Value *bar = bld.getSSA(4, FILE_BARRIER);
140bf215546Sopenharmony_ci      Value *src[3], *val;
141bf215546Sopenharmony_ci      Value *lane = bld.mkImm(l);
142bf215546Sopenharmony_ci      bld.mkOp(OP_QUADON, TYPE_U32, bar);
143bf215546Sopenharmony_ci      // Make sure lane 0 has the appropriate array/depth compare values
144bf215546Sopenharmony_ci      if (l != 0) {
145bf215546Sopenharmony_ci         if (array)
146bf215546Sopenharmony_ci            bld.mkOp3(OP_SHFL, TYPE_F32, arr, i->getSrc(0), lane, quad);
147bf215546Sopenharmony_ci         if (i->tex.target.isShadow())
148bf215546Sopenharmony_ci            bld.mkOp3(OP_SHFL, TYPE_F32, shadow, i->getSrc(array + dim + indirect), lane, quad);
149bf215546Sopenharmony_ci      }
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci      // mov coordinates from lane l to all lanes
152bf215546Sopenharmony_ci      for (c = 0; c < dim; ++c) {
153bf215546Sopenharmony_ci         bld.mkOp3(OP_SHFL, TYPE_F32, crd[c], i->getSrc(c + array), lane, quad);
154bf215546Sopenharmony_ci      }
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci      // add dPdx from lane l to lanes dx
157bf215546Sopenharmony_ci      for (c = 0; c < dim; ++c) {
158bf215546Sopenharmony_ci         bld.mkOp3(OP_SHFL, TYPE_F32, tmp, i->dPdx[c].get(), lane, quad);
159bf215546Sopenharmony_ci         add = bld.mkOp2(OP_QUADOP, TYPE_F32, crd[c], tmp, crd[c]);
160bf215546Sopenharmony_ci         add->subOp = qOps[0];
161bf215546Sopenharmony_ci         add->lanes = 1; /* abused for .ndv */
162bf215546Sopenharmony_ci      }
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci      // add dPdy from lane l to lanes dy
165bf215546Sopenharmony_ci      for (c = 0; c < dim; ++c) {
166bf215546Sopenharmony_ci         bld.mkOp3(OP_SHFL, TYPE_F32, tmp, i->dPdy[c].get(), lane, quad);
167bf215546Sopenharmony_ci         add = bld.mkOp2(OP_QUADOP, TYPE_F32, crd[c], tmp, crd[c]);
168bf215546Sopenharmony_ci         add->subOp = qOps[1];
169bf215546Sopenharmony_ci         add->lanes = 1; /* abused for .ndv */
170bf215546Sopenharmony_ci      }
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci      // normalize cube coordinates if necessary
173bf215546Sopenharmony_ci      if (i->tex.target.isCube()) {
174bf215546Sopenharmony_ci         for (c = 0; c < 3; ++c)
175bf215546Sopenharmony_ci            src[c] = bld.mkOp1v(OP_ABS, TYPE_F32, bld.getSSA(), crd[c]);
176bf215546Sopenharmony_ci         val = bld.getScratch();
177bf215546Sopenharmony_ci         bld.mkOp2(OP_MAX, TYPE_F32, val, src[0], src[1]);
178bf215546Sopenharmony_ci         bld.mkOp2(OP_MAX, TYPE_F32, val, src[2], val);
179bf215546Sopenharmony_ci         bld.mkOp1(OP_RCP, TYPE_F32, val, val);
180bf215546Sopenharmony_ci         for (c = 0; c < 3; ++c)
181bf215546Sopenharmony_ci            src[c] = bld.mkOp2v(OP_MUL, TYPE_F32, bld.getSSA(), crd[c], val);
182bf215546Sopenharmony_ci      } else {
183bf215546Sopenharmony_ci         for (c = 0; c < dim; ++c)
184bf215546Sopenharmony_ci            src[c] = crd[c];
185bf215546Sopenharmony_ci      }
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci      // texture
188bf215546Sopenharmony_ci      bld.insert(tex = cloneForward(func, i));
189bf215546Sopenharmony_ci      if (l != 0) {
190bf215546Sopenharmony_ci         if (array)
191bf215546Sopenharmony_ci            tex->setSrc(0, arr);
192bf215546Sopenharmony_ci         if (i->tex.target.isShadow())
193bf215546Sopenharmony_ci            tex->setSrc(array + dim + indirect, shadow);
194bf215546Sopenharmony_ci      }
195bf215546Sopenharmony_ci      for (c = 0; c < dim; ++c)
196bf215546Sopenharmony_ci         tex->setSrc(c + array, src[c]);
197bf215546Sopenharmony_ci      // broadcast results from lane 0 to all lanes
198bf215546Sopenharmony_ci      if (l != 0)
199bf215546Sopenharmony_ci         for (c = 0; i->defExists(c); ++c)
200bf215546Sopenharmony_ci            bld.mkOp3(OP_SHFL, TYPE_F32, tex->getDef(c), tex->getDef(c), bld.mkImm(0), quad);
201bf215546Sopenharmony_ci      bld.mkOp1(OP_QUADPOP, TYPE_U32, NULL, bar)->fixed = 1;
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci      // save results
204bf215546Sopenharmony_ci      for (c = 0; i->defExists(c); ++c) {
205bf215546Sopenharmony_ci         Instruction *mov;
206bf215546Sopenharmony_ci         def[c][l] = bld.getSSA();
207bf215546Sopenharmony_ci         mov = bld.mkMov(def[c][l], tex->getDef(c));
208bf215546Sopenharmony_ci         mov->fixed = 1;
209bf215546Sopenharmony_ci         mov->lanes = 1 << l;
210bf215546Sopenharmony_ci      }
211bf215546Sopenharmony_ci   }
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   for (c = 0; i->defExists(c); ++c) {
214bf215546Sopenharmony_ci      Instruction *u = bld.mkOp(OP_UNION, TYPE_U32, i->getDef(c));
215bf215546Sopenharmony_ci      for (l = 0; l < 4; ++l)
216bf215546Sopenharmony_ci         u->setSrc(l, def[c][l]);
217bf215546Sopenharmony_ci   }
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci   i->bb->remove(i);
220bf215546Sopenharmony_ci   return true;
221bf215546Sopenharmony_ci}
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_cibool
224bf215546Sopenharmony_ciGM107LoweringPass::handleDFDX(Instruction *insn)
225bf215546Sopenharmony_ci{
226bf215546Sopenharmony_ci   Instruction *shfl;
227bf215546Sopenharmony_ci   int qop = 0, xid = 0;
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   switch (insn->op) {
230bf215546Sopenharmony_ci   case OP_DFDX:
231bf215546Sopenharmony_ci      qop = QUADOP(SUB, SUBR, SUB, SUBR);
232bf215546Sopenharmony_ci      xid = 1;
233bf215546Sopenharmony_ci      break;
234bf215546Sopenharmony_ci   case OP_DFDY:
235bf215546Sopenharmony_ci      qop = QUADOP(SUB, SUB, SUBR, SUBR);
236bf215546Sopenharmony_ci      xid = 2;
237bf215546Sopenharmony_ci      break;
238bf215546Sopenharmony_ci   default:
239bf215546Sopenharmony_ci      assert(!"invalid dfdx opcode");
240bf215546Sopenharmony_ci      break;
241bf215546Sopenharmony_ci   }
242bf215546Sopenharmony_ci
243bf215546Sopenharmony_ci   shfl = bld.mkOp3(OP_SHFL, TYPE_F32, bld.getScratch(), insn->getSrc(0),
244bf215546Sopenharmony_ci                    bld.mkImm(xid), bld.mkImm(SHFL_BOUND_QUAD));
245bf215546Sopenharmony_ci   shfl->subOp = NV50_IR_SUBOP_SHFL_BFLY;
246bf215546Sopenharmony_ci   insn->op = OP_QUADOP;
247bf215546Sopenharmony_ci   insn->subOp = qop;
248bf215546Sopenharmony_ci   insn->lanes = 0; /* abused for !.ndv */
249bf215546Sopenharmony_ci   insn->setSrc(1, insn->getSrc(0));
250bf215546Sopenharmony_ci   insn->setSrc(0, shfl->getDef(0));
251bf215546Sopenharmony_ci   return true;
252bf215546Sopenharmony_ci}
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_cibool
255bf215546Sopenharmony_ciGM107LoweringPass::handlePFETCH(Instruction *i)
256bf215546Sopenharmony_ci{
257bf215546Sopenharmony_ci   Value *tmp0 = bld.getScratch();
258bf215546Sopenharmony_ci   Value *tmp1 = bld.getScratch();
259bf215546Sopenharmony_ci   Value *tmp2 = bld.getScratch();
260bf215546Sopenharmony_ci   bld.mkOp1(OP_RDSV, TYPE_U32, tmp0, bld.mkSysVal(SV_INVOCATION_INFO, 0));
261bf215546Sopenharmony_ci   bld.mkOp3(OP_PERMT, TYPE_U32, tmp1, tmp0, bld.mkImm(0x4442), bld.mkImm(0));
262bf215546Sopenharmony_ci   bld.mkOp3(OP_PERMT, TYPE_U32, tmp0, tmp0, bld.mkImm(0x4440), bld.mkImm(0));
263bf215546Sopenharmony_ci   if (i->getSrc(1))
264bf215546Sopenharmony_ci      bld.mkOp2(OP_ADD , TYPE_U32, tmp2, i->getSrc(0), i->getSrc(1));
265bf215546Sopenharmony_ci   else
266bf215546Sopenharmony_ci      bld.mkOp1(OP_MOV , TYPE_U32, tmp2, i->getSrc(0));
267bf215546Sopenharmony_ci   bld.mkOp3(OP_MAD , TYPE_U32, tmp0, tmp0, tmp1, tmp2);
268bf215546Sopenharmony_ci   i->setSrc(0, tmp0);
269bf215546Sopenharmony_ci   i->setSrc(1, NULL);
270bf215546Sopenharmony_ci   return true;
271bf215546Sopenharmony_ci}
272bf215546Sopenharmony_ci
273bf215546Sopenharmony_cibool
274bf215546Sopenharmony_ciGM107LoweringPass::handlePOPCNT(Instruction *i)
275bf215546Sopenharmony_ci{
276bf215546Sopenharmony_ci   Value *tmp = bld.mkOp2v(OP_AND, i->sType, bld.getScratch(),
277bf215546Sopenharmony_ci                           i->getSrc(0), i->getSrc(1));
278bf215546Sopenharmony_ci   i->setSrc(0, tmp);
279bf215546Sopenharmony_ci   i->setSrc(1, NULL);
280bf215546Sopenharmony_ci   return true;
281bf215546Sopenharmony_ci}
282bf215546Sopenharmony_ci
283bf215546Sopenharmony_cibool
284bf215546Sopenharmony_ciGM107LoweringPass::handleSUQ(TexInstruction *suq)
285bf215546Sopenharmony_ci{
286bf215546Sopenharmony_ci   Value *ind = suq->getIndirectR();
287bf215546Sopenharmony_ci   Value *handle;
288bf215546Sopenharmony_ci   const int slot = suq->tex.r;
289bf215546Sopenharmony_ci   const int mask = suq->tex.mask;
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   if (suq->tex.bindless)
292bf215546Sopenharmony_ci      handle = ind;
293bf215546Sopenharmony_ci   else
294bf215546Sopenharmony_ci      handle = loadTexHandle(ind, slot + 32);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   suq->tex.r = 0xff;
297bf215546Sopenharmony_ci   suq->tex.s = 0x1f;
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_ci   suq->setIndirectR(NULL);
300bf215546Sopenharmony_ci   suq->setSrc(0, handle);
301bf215546Sopenharmony_ci   suq->tex.rIndirectSrc = 0;
302bf215546Sopenharmony_ci   suq->setSrc(1, bld.loadImm(NULL, 0));
303bf215546Sopenharmony_ci   suq->tex.query = TXQ_DIMS;
304bf215546Sopenharmony_ci   suq->op = OP_TXQ;
305bf215546Sopenharmony_ci
306bf215546Sopenharmony_ci   // We store CUBE / CUBE_ARRAY as a 2D ARRAY. Make sure that depth gets
307bf215546Sopenharmony_ci   // divided by 6.
308bf215546Sopenharmony_ci   if (mask & 0x4 && suq->tex.target.isCube()) {
309bf215546Sopenharmony_ci      int d = util_bitcount(mask & 0x3);
310bf215546Sopenharmony_ci      bld.setPosition(suq, true);
311bf215546Sopenharmony_ci      bld.mkOp2(OP_DIV, TYPE_U32, suq->getDef(d), suq->getDef(d),
312bf215546Sopenharmony_ci                bld.loadImm(NULL, 6));
313bf215546Sopenharmony_ci   }
314bf215546Sopenharmony_ci
315bf215546Sopenharmony_ci   // Samples come from a different query. If we want both samples and dims,
316bf215546Sopenharmony_ci   // create a second suq.
317bf215546Sopenharmony_ci   if (mask & 0x8) {
318bf215546Sopenharmony_ci      int d = util_bitcount(mask & 0x7);
319bf215546Sopenharmony_ci      Value *dst = suq->getDef(d);
320bf215546Sopenharmony_ci      TexInstruction *samples = suq;
321bf215546Sopenharmony_ci      assert(dst);
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci      if (mask != 0x8) {
324bf215546Sopenharmony_ci         suq->setDef(d, NULL);
325bf215546Sopenharmony_ci         suq->tex.mask &= 0x7;
326bf215546Sopenharmony_ci         samples = cloneShallow(func, suq);
327bf215546Sopenharmony_ci         for (int i = 0; i < d; i++)
328bf215546Sopenharmony_ci            samples->setDef(d, NULL);
329bf215546Sopenharmony_ci         samples->setDef(0, dst);
330bf215546Sopenharmony_ci         suq->bb->insertAfter(suq, samples);
331bf215546Sopenharmony_ci      }
332bf215546Sopenharmony_ci      samples->tex.mask = 0x4;
333bf215546Sopenharmony_ci      samples->tex.query = TXQ_TYPE;
334bf215546Sopenharmony_ci   }
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci   if (suq->tex.target.isMS()) {
337bf215546Sopenharmony_ci      bld.setPosition(suq, true);
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci      if (mask & 0x1)
340bf215546Sopenharmony_ci         bld.mkOp2(OP_SHR, TYPE_U32, suq->getDef(0), suq->getDef(0),
341bf215546Sopenharmony_ci                   loadMsAdjInfo32(suq->tex.target, 0, slot, ind, suq->tex.bindless));
342bf215546Sopenharmony_ci      if (mask & 0x2) {
343bf215546Sopenharmony_ci         int d = util_bitcount(mask & 0x1);
344bf215546Sopenharmony_ci         bld.mkOp2(OP_SHR, TYPE_U32, suq->getDef(d), suq->getDef(d),
345bf215546Sopenharmony_ci                   loadMsAdjInfo32(suq->tex.target, 1, slot, ind, suq->tex.bindless));
346bf215546Sopenharmony_ci      }
347bf215546Sopenharmony_ci   }
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci   return true;
350bf215546Sopenharmony_ci}
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_ci//
353bf215546Sopenharmony_ci// - add quadop dance for texturing
354bf215546Sopenharmony_ci// - put FP outputs in GPRs
355bf215546Sopenharmony_ci// - convert instruction sequences
356bf215546Sopenharmony_ci//
357bf215546Sopenharmony_cibool
358bf215546Sopenharmony_ciGM107LoweringPass::visit(Instruction *i)
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci   bld.setPosition(i, false);
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci   if (i->cc != CC_ALWAYS)
363bf215546Sopenharmony_ci      checkPredicate(i);
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_ci   switch (i->op) {
366bf215546Sopenharmony_ci   case OP_PFETCH:
367bf215546Sopenharmony_ci      return handlePFETCH(i);
368bf215546Sopenharmony_ci   case OP_DFDX:
369bf215546Sopenharmony_ci   case OP_DFDY:
370bf215546Sopenharmony_ci      return handleDFDX(i);
371bf215546Sopenharmony_ci   case OP_POPCNT:
372bf215546Sopenharmony_ci      return handlePOPCNT(i);
373bf215546Sopenharmony_ci   case OP_SUQ:
374bf215546Sopenharmony_ci      return handleSUQ(i->asTex());
375bf215546Sopenharmony_ci   default:
376bf215546Sopenharmony_ci      return NVC0LoweringPass::visit(i);
377bf215546Sopenharmony_ci   }
378bf215546Sopenharmony_ci}
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci} // namespace nv50_ir
381