R600/SI: Prefer SALU instructions for bit shift operations
[oota-llvm.git] / lib / Target / R600 / SIInstrInfo.td
1 //===-- SIInstrInfo.td - SI Instruction Infos -------------*- tablegen -*--===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 // SI DAG Nodes
12 //===----------------------------------------------------------------------===//
13
14 // SMRD takes a 64bit memory address and can only add an 32bit offset
15 def SIadd64bit32bit : SDNode<"ISD::ADD",
16   SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>, SDTCisVT<0, i64>, SDTCisVT<2, i32>]>
17 >;
18
19 def SIload_constant : SDNode<"AMDGPUISD::LOAD_CONSTANT",
20   SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisVT<1, i128>, SDTCisVT<2, i32>]>,
21                       [SDNPMayLoad, SDNPMemOperand]
22 >;
23
24 def SItbuffer_store : SDNode<"AMDGPUISD::TBUFFER_STORE_FORMAT",
25   SDTypeProfile<0, 13,
26     [SDTCisVT<0, i128>,   // rsrc(SGPR)
27      SDTCisVT<1, iAny>,   // vdata(VGPR)
28      SDTCisVT<2, i32>,    // num_channels(imm)
29      SDTCisVT<3, i32>,    // vaddr(VGPR)
30      SDTCisVT<4, i32>,    // soffset(SGPR)
31      SDTCisVT<5, i32>,    // inst_offset(imm)
32      SDTCisVT<6, i32>,    // dfmt(imm)
33      SDTCisVT<7, i32>,    // nfmt(imm)
34      SDTCisVT<8, i32>,    // offen(imm)
35      SDTCisVT<9, i32>,    // idxen(imm)
36      SDTCisVT<10, i32>,   // glc(imm)
37      SDTCisVT<11, i32>,   // slc(imm)
38      SDTCisVT<12, i32>    // tfe(imm)
39     ]>,
40   [SDNPMayStore, SDNPMemOperand, SDNPHasChain]
41 >;
42
43 def SIload_input : SDNode<"AMDGPUISD::LOAD_INPUT",
44   SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisVT<1, i128>, SDTCisVT<2, i16>,
45                        SDTCisVT<3, i32>]>
46 >;
47
48 class SDSample<string opcode> : SDNode <opcode,
49   SDTypeProfile<1, 4, [SDTCisVT<0, v4f32>, SDTCisVT<2, v32i8>,
50                        SDTCisVT<3, i128>, SDTCisVT<4, i32>]>
51 >;
52
53 def SIsample : SDSample<"AMDGPUISD::SAMPLE">;
54 def SIsampleb : SDSample<"AMDGPUISD::SAMPLEB">;
55 def SIsampled : SDSample<"AMDGPUISD::SAMPLED">;
56 def SIsamplel : SDSample<"AMDGPUISD::SAMPLEL">;
57
58 // Transformation function, extract the lower 32bit of a 64bit immediate
59 def LO32 : SDNodeXForm<imm, [{
60   return CurDAG->getTargetConstant(N->getZExtValue() & 0xffffffff, MVT::i32);
61 }]>;
62
63 def LO32f : SDNodeXForm<fpimm, [{
64   APInt V = N->getValueAPF().bitcastToAPInt().trunc(32);
65   return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
66 }]>;
67
68 // Transformation function, extract the upper 32bit of a 64bit immediate
69 def HI32 : SDNodeXForm<imm, [{
70   return CurDAG->getTargetConstant(N->getZExtValue() >> 32, MVT::i32);
71 }]>;
72
73 def HI32f : SDNodeXForm<fpimm, [{
74   APInt V = N->getValueAPF().bitcastToAPInt().lshr(32).trunc(32);
75   return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
76 }]>;
77
78 def IMM8bitDWORD : ImmLeaf <
79   i32, [{
80     return (Imm & ~0x3FC) == 0;
81   }], SDNodeXForm<imm, [{
82     return CurDAG->getTargetConstant(
83       N->getZExtValue() >> 2, MVT::i32);
84   }]>
85 >;
86
87 def as_i1imm : SDNodeXForm<imm, [{
88   return CurDAG->getTargetConstant(N->getZExtValue(), MVT::i1);
89 }]>;
90
91 def as_i8imm : SDNodeXForm<imm, [{
92   return CurDAG->getTargetConstant(N->getZExtValue(), MVT::i8);
93 }]>;
94
95 def as_i16imm : SDNodeXForm<imm, [{
96   return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i16);
97 }]>;
98
99 def IMM12bit : PatLeaf <(imm),
100   [{return isUInt<12>(N->getZExtValue());}]
101 >;
102
103 class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
104   return
105     (*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0;
106 }]>;
107
108 class SGPRImm <dag frag> : PatLeaf<frag, [{
109   if (TM.getSubtarget<AMDGPUSubtarget>().getGeneration() <
110       AMDGPUSubtarget::SOUTHERN_ISLANDS) {
111     return false;
112   }
113   const SIRegisterInfo *SIRI =
114                        static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
115   for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
116                                                 U != E; ++U) {
117     if (SIRI->isSGPRClass(getOperandRegClass(*U, U.getOperandNo()))) {
118       return true;
119     }
120   }
121   return false;
122 }]>;
123
124 //===----------------------------------------------------------------------===//
125 // SI assembler operands
126 //===----------------------------------------------------------------------===//
127
128 def SIOperand {
129   int ZERO = 0x80;
130   int VCC = 0x6A;
131 }
132
133 include "SIInstrFormats.td"
134
135 //===----------------------------------------------------------------------===//
136 //
137 // SI Instruction multiclass helpers.
138 //
139 // Instructions with _32 take 32-bit operands.
140 // Instructions with _64 take 64-bit operands.
141 //
142 // VOP_* instructions can use either a 32-bit or 64-bit encoding.  The 32-bit
143 // encoding is the standard encoding, but instruction that make use of
144 // any of the instruction modifiers must use the 64-bit encoding.
145 //
146 // Instructions with _e32 use the 32-bit encoding.
147 // Instructions with _e64 use the 64-bit encoding.
148 //
149 //===----------------------------------------------------------------------===//
150
151 //===----------------------------------------------------------------------===//
152 // Scalar classes
153 //===----------------------------------------------------------------------===//
154
155 class SOP1_32 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
156   op, (outs SReg_32:$dst), (ins SSrc_32:$src0),
157   opName#" $dst, $src0", pattern
158 >;
159
160 class SOP1_64 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
161   op, (outs SReg_64:$dst), (ins SSrc_64:$src0),
162   opName#" $dst, $src0", pattern
163 >;
164
165 class SOP2_32 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
166   op, (outs SReg_32:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
167   opName#" $dst, $src0, $src1", pattern
168 >;
169
170 class SOP2_64 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
171   op, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
172   opName#" $dst, $src0, $src1", pattern
173 >;
174
175 class SOP2_SHIFT_64 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
176   op, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_32:$src1),
177   opName#" $dst, $src0, $src1", pattern
178 >;
179
180 class SOPC_32 <bits<7> op, string opName, list<dag> pattern> : SOPC <
181   op, (outs SCCReg:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
182   opName#" $dst, $src0, $src1", pattern
183 >;
184
185 class SOPC_64 <bits<7> op, string opName, list<dag> pattern> : SOPC <
186   op, (outs SCCReg:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
187   opName#" $dst, $src0, $src1", pattern
188 >;
189
190 class SOPK_32 <bits<5> op, string opName, list<dag> pattern> : SOPK <
191   op, (outs SReg_32:$dst), (ins i16imm:$src0),
192   opName#" $dst, $src0", pattern
193 >;
194
195 class SOPK_64 <bits<5> op, string opName, list<dag> pattern> : SOPK <
196   op, (outs SReg_64:$dst), (ins i16imm:$src0),
197   opName#" $dst, $src0", pattern
198 >;
199
200 multiclass SMRD_Helper <bits<5> op, string asm, RegisterClass baseClass,
201                         RegisterClass dstClass> {
202   def _IMM : SMRD <
203     op, 1, (outs dstClass:$dst),
204     (ins baseClass:$sbase, i32imm:$offset),
205     asm#" $dst, $sbase, $offset", []
206   >;
207
208   def _SGPR : SMRD <
209     op, 0, (outs dstClass:$dst),
210     (ins baseClass:$sbase, SReg_32:$soff),
211     asm#" $dst, $sbase, $soff", []
212   >;
213 }
214
215 //===----------------------------------------------------------------------===//
216 // Vector ALU classes
217 //===----------------------------------------------------------------------===//
218
219 class VOP <string opName> {
220   string OpName = opName;
221 }
222
223 class VOP2_REV <string revOp, bit isOrig> {
224   string RevOp = revOp;
225   bit IsOrig = isOrig;
226 }
227
228 multiclass VOP1_Helper <bits<8> op, RegisterClass drc, RegisterClass src,
229                         string opName, list<dag> pattern> {
230
231   def _e32 : VOP1 <
232     op, (outs drc:$dst), (ins src:$src0),
233     opName#"_e32 $dst, $src0", pattern
234   >, VOP <opName>;
235
236   def _e64 : VOP3 <
237     {1, 1, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
238     (outs drc:$dst),
239     (ins src:$src0,
240          i32imm:$abs, i32imm:$clamp,
241          i32imm:$omod, i32imm:$neg),
242     opName#"_e64 $dst, $src0, $abs, $clamp, $omod, $neg", []
243   >, VOP <opName> {
244     let src1 = SIOperand.ZERO;
245     let src2 = SIOperand.ZERO;
246   }
247 }
248
249 multiclass VOP1_32 <bits<8> op, string opName, list<dag> pattern>
250   : VOP1_Helper <op, VReg_32, VSrc_32, opName, pattern>;
251
252 multiclass VOP1_64 <bits<8> op, string opName, list<dag> pattern>
253   : VOP1_Helper <op, VReg_64, VSrc_64, opName, pattern>;
254
255 multiclass VOP1_32_64 <bits<8> op, string opName, list<dag> pattern>
256   : VOP1_Helper <op, VReg_32, VSrc_64, opName, pattern>;
257
258 multiclass VOP1_64_32 <bits<8> op, string opName, list<dag> pattern>
259   : VOP1_Helper <op, VReg_64, VSrc_32, opName, pattern>;
260
261 multiclass VOP2_Helper <bits<6> op, RegisterClass vrc, RegisterClass arc,
262                         string opName, list<dag> pattern, string revOp> {
263   def _e32 : VOP2 <
264     op, (outs vrc:$dst), (ins arc:$src0, vrc:$src1),
265     opName#"_e32 $dst, $src0, $src1", pattern
266   >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
267
268   def _e64 : VOP3 <
269     {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
270     (outs vrc:$dst),
271     (ins arc:$src0, arc:$src1,
272          i32imm:$abs, i32imm:$clamp,
273          i32imm:$omod, i32imm:$neg),
274     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
275   >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
276     let src2 = SIOperand.ZERO;
277   }
278 }
279
280 multiclass VOP2_32 <bits<6> op, string opName, list<dag> pattern,
281                     string revOp = opName>
282   : VOP2_Helper <op, VReg_32, VSrc_32, opName, pattern, revOp>;
283
284 multiclass VOP2_64 <bits<6> op, string opName, list<dag> pattern,
285                     string revOp = opName>
286   : VOP2_Helper <op, VReg_64, VSrc_64, opName, pattern, revOp>;
287
288 multiclass VOP2b_32 <bits<6> op, string opName, list<dag> pattern,
289                      string revOp = opName> {
290
291   def _e32 : VOP2 <
292     op, (outs VReg_32:$dst), (ins VSrc_32:$src0, VReg_32:$src1),
293     opName#"_e32 $dst, $src0, $src1", pattern
294   >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
295
296   def _e64 : VOP3b <
297     {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
298     (outs VReg_32:$dst),
299     (ins VSrc_32:$src0, VSrc_32:$src1,
300          i32imm:$abs, i32imm:$clamp,
301          i32imm:$omod, i32imm:$neg),
302     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
303   >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
304     let src2 = SIOperand.ZERO;
305     /* the VOP2 variant puts the carry out into VCC, the VOP3 variant
306        can write it into any SGPR. We currently don't use the carry out,
307        so for now hardcode it to VCC as well */
308     let sdst = SIOperand.VCC;
309   }
310 }
311
312 multiclass VOPC_Helper <bits<8> op, RegisterClass vrc, RegisterClass arc,
313                         string opName, ValueType vt, PatLeaf cond> {
314
315   def _e32 : VOPC <
316     op, (ins arc:$src0, vrc:$src1),
317     opName#"_e32 $dst, $src0, $src1", []
318   >, VOP <opName>;
319
320   def _e64 : VOP3 <
321     {0, op{7}, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
322     (outs SReg_64:$dst),
323     (ins arc:$src0, arc:$src1,
324          InstFlag:$abs, InstFlag:$clamp,
325          InstFlag:$omod, InstFlag:$neg),
326     opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg",
327     !if(!eq(!cast<string>(cond), "COND_NULL"), []<dag>,
328       [(set SReg_64:$dst, (i1 (setcc (vt arc:$src0), arc:$src1, cond)))]
329     )
330   >, VOP <opName> {
331     let src2 = SIOperand.ZERO;
332   }
333 }
334
335 multiclass VOPC_32 <bits<8> op, string opName,
336   ValueType vt = untyped, PatLeaf cond = COND_NULL>
337   : VOPC_Helper <op, VReg_32, VSrc_32, opName, vt, cond>;
338
339 multiclass VOPC_64 <bits<8> op, string opName,
340   ValueType vt = untyped, PatLeaf cond = COND_NULL>
341   : VOPC_Helper <op, VReg_64, VSrc_64, opName, vt, cond>;
342
343 class VOP3_32 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
344   op, (outs VReg_32:$dst),
345   (ins VSrc_32:$src0, VSrc_32:$src1, VSrc_32:$src2,
346    InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
347   opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
348 >, VOP <opName>;
349
350 class VOP3_64_Shift <bits <9> op, string opName, list<dag> pattern> : VOP3 <
351   op, (outs VReg_64:$dst),
352   (ins VSrc_64:$src0, VSrc_32:$src1),
353   opName#" $dst, $src0, $src1", pattern
354 >, VOP <opName> {
355
356   let src2 = SIOperand.ZERO;
357   let abs = 0;
358   let clamp = 0;
359   let omod = 0;
360   let neg = 0;
361 }
362
363 class VOP3_64 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
364   op, (outs VReg_64:$dst),
365   (ins VSrc_64:$src0, VSrc_64:$src1, VSrc_64:$src2,
366    InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
367   opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
368 >, VOP <opName>;
369
370 //===----------------------------------------------------------------------===//
371 // Vector I/O classes
372 //===----------------------------------------------------------------------===//
373
374 class DS_Load_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
375   op,
376   (outs regClass:$vdst),
377   (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
378        i8imm:$offset0, i8imm:$offset1),
379   asm#" $vdst, $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
380   []> {
381   let mayLoad = 1;
382   let mayStore = 0;
383 }
384
385 class DS_Store_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
386   op,
387   (outs),
388   (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
389        i8imm:$offset0, i8imm:$offset1),
390   asm#" $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
391   []> {
392   let mayStore = 1;
393   let mayLoad = 0;
394   let vdst = 0;
395 }
396
397 class DS_1A1D_RET <bits<8> op, string asm, RegisterClass rc> : DS <
398   op,
399   (outs rc:$vdst),
400   (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, i8imm:$offset0,
401        i8imm:$offset1),
402   asm#" $gds, $vdst, $addr, $data0, $offset0, $offset1, [M0]",
403   []> {
404   let mayStore = 1;
405   let mayLoad = 1;
406   let data1 = 0;
407 }
408
409 class MTBUF_Store_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
410   op,
411   (outs),
412   (ins regClass:$vdata, i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
413    i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr,
414    SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
415   asm#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
416      #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
417   []> {
418   let mayStore = 1;
419   let mayLoad = 0;
420 }
421
422 multiclass MUBUF_Load_Helper <bits<7> op, string asm, RegisterClass regClass> {
423
424   let glc = 0, lds = 0, slc = 0, tfe = 0, soffset = 128 /* ZERO */,
425                                           mayLoad = 1 in {
426
427   let offen = 1, idxen = 0, addr64 = 0, offset = 0 in {
428     def _OFFEN  : MUBUF <op, (outs regClass:$vdata),
429                          (ins SReg_128:$srsrc, VReg_32:$vaddr),
430                          asm#" $vdata, $srsrc + $vaddr", []>;
431   }
432
433   let offen = 0, idxen = 1, addr64 = 0 in {
434     def _IDXEN  : MUBUF <op, (outs regClass:$vdata),
435                          (ins SReg_128:$srsrc, VReg_32:$vaddr, i16imm:$offset),
436                          asm#" $vdata, $srsrc[$vaddr] + $offset", []>;
437   }
438
439   let offen = 0, idxen = 0, addr64 = 1 in {
440     def _ADDR64 : MUBUF <op, (outs regClass:$vdata),
441                          (ins SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
442                          asm#" $vdata, $srsrc + $vaddr + $offset", []>;
443   }
444   }
445 }
446
447 class MUBUF_Store_Helper <bits<7> op, string name, RegisterClass vdataClass> :
448     MUBUF <op, (outs), (ins vdataClass:$vdata, SReg_128:$srsrc, VReg_64:$vaddr,
449                             i16imm:$offset),
450           name#" $vdata, $srsrc + $vaddr + $offset",
451          []> {
452
453   let mayLoad = 0;
454   let mayStore = 1;
455
456   // Encoding
457   let offen = 0;
458   let idxen = 0;
459   let glc = 0;
460   let addr64 = 1;
461   let lds = 0;
462   let slc = 0;
463   let tfe = 0;
464   let soffset = 128; // ZERO
465 }
466
467 class MTBUF_Load_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
468   op,
469   (outs regClass:$dst),
470   (ins i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
471        i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr, SReg_128:$srsrc,
472        i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
473   asm#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
474      #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
475   []> {
476   let mayLoad = 1;
477   let mayStore = 0;
478 }
479
480 class MIMG_Mask <string op, int channels> {
481   string Op = op;
482   int Channels = channels;
483 }
484
485 class MIMG_NoSampler_Helper <bits<7> op, string asm,
486                              RegisterClass dst_rc,
487                              RegisterClass src_rc> : MIMG <
488   op,
489   (outs dst_rc:$vdata),
490   (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
491        i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
492        SReg_256:$srsrc),
493   asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
494      #" $tfe, $lwe, $slc, $vaddr, $srsrc",
495   []> {
496   let SSAMP = 0;
497   let mayLoad = 1;
498   let mayStore = 0;
499   let hasPostISelHook = 1;
500 }
501
502 multiclass MIMG_NoSampler_Src_Helper <bits<7> op, string asm,
503                                       RegisterClass dst_rc,
504                                       int channels> {
505   def _V1 : MIMG_NoSampler_Helper <op, asm, dst_rc, VReg_32>,
506             MIMG_Mask<asm#"_V1", channels>;
507   def _V2 : MIMG_NoSampler_Helper <op, asm, dst_rc, VReg_64>,
508             MIMG_Mask<asm#"_V2", channels>;
509   def _V4 : MIMG_NoSampler_Helper <op, asm, dst_rc, VReg_128>,
510             MIMG_Mask<asm#"_V4", channels>;
511 }
512
513 multiclass MIMG_NoSampler <bits<7> op, string asm> {
514   defm _V1 : MIMG_NoSampler_Src_Helper <op, asm, VReg_32, 1>;
515   defm _V2 : MIMG_NoSampler_Src_Helper <op, asm, VReg_64, 2>;
516   defm _V3 : MIMG_NoSampler_Src_Helper <op, asm, VReg_96, 3>;
517   defm _V4 : MIMG_NoSampler_Src_Helper <op, asm, VReg_128, 4>;
518 }
519
520 class MIMG_Sampler_Helper <bits<7> op, string asm,
521                            RegisterClass dst_rc,
522                            RegisterClass src_rc> : MIMG <
523   op,
524   (outs dst_rc:$vdata),
525   (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
526        i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
527        SReg_256:$srsrc, SReg_128:$ssamp),
528   asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
529      #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
530   []> {
531   let mayLoad = 1;
532   let mayStore = 0;
533   let hasPostISelHook = 1;
534 }
535
536 multiclass MIMG_Sampler_Src_Helper <bits<7> op, string asm,
537                                     RegisterClass dst_rc,
538                                     int channels> {
539   def _V1 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_32>,
540             MIMG_Mask<asm#"_V1", channels>;
541   def _V2 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_64>,
542             MIMG_Mask<asm#"_V2", channels>;
543   def _V4 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_128>,
544             MIMG_Mask<asm#"_V4", channels>;
545   def _V8 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_256>,
546             MIMG_Mask<asm#"_V8", channels>;
547   def _V16 : MIMG_Sampler_Helper <op, asm, dst_rc, VReg_512>,
548             MIMG_Mask<asm#"_V16", channels>;
549 }
550
551 multiclass MIMG_Sampler <bits<7> op, string asm> {
552   defm _V1 : MIMG_Sampler_Src_Helper<op, asm, VReg_32, 1>;
553   defm _V2 : MIMG_Sampler_Src_Helper<op, asm, VReg_64, 2>;
554   defm _V3 : MIMG_Sampler_Src_Helper<op, asm, VReg_96, 3>;
555   defm _V4 : MIMG_Sampler_Src_Helper<op, asm, VReg_128, 4>;
556 }
557
558 //===----------------------------------------------------------------------===//
559 // Vector instruction mappings
560 //===----------------------------------------------------------------------===//
561
562 // Maps an opcode in e32 form to its e64 equivalent
563 def getVOPe64 : InstrMapping {
564   let FilterClass = "VOP";
565   let RowFields = ["OpName"];
566   let ColFields = ["Size"];
567   let KeyCol = ["4"];
568   let ValueCols = [["8"]];
569 }
570
571 // Maps an original opcode to its commuted version
572 def getCommuteRev : InstrMapping {
573   let FilterClass = "VOP2_REV";
574   let RowFields = ["RevOp"];
575   let ColFields = ["IsOrig"];
576   let KeyCol = ["1"];
577   let ValueCols = [["0"]];
578 }
579
580 def getMaskedMIMGOp : InstrMapping {
581   let FilterClass = "MIMG_Mask";
582   let RowFields = ["Op"];
583   let ColFields = ["Channels"];
584   let KeyCol = ["4"];
585   let ValueCols = [["1"], ["2"], ["3"] ];
586 }
587
588 // Maps an commuted opcode to its original version
589 def getCommuteOrig : InstrMapping {
590   let FilterClass = "VOP2_REV";
591   let RowFields = ["RevOp"];
592   let ColFields = ["IsOrig"];
593   let KeyCol = ["0"];
594   let ValueCols = [["1"]];
595 }
596
597 include "SIInstructions.td"