1 //===-- SIInstrInfo.td - SI Instruction Infos -------------*- tablegen -*--===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 //===----------------------------------------------------------------------===//
12 //===----------------------------------------------------------------------===//
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>]>
19 def SIload_constant : SDNode<"AMDGPUISD::LOAD_CONSTANT",
20 SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisVT<1, i128>, SDTCisVT<2, i32>]>,
21 [SDNPMayLoad, SDNPMemOperand]
24 def SIload_input : SDNode<"AMDGPUISD::LOAD_INPUT",
25 SDTypeProfile<1, 3, [SDTCisVT<0, v4f32>, SDTCisVT<1, i128>, SDTCisVT<2, i16>,
29 class SDSample<string opcode> : SDNode <opcode,
30 SDTypeProfile<1, 4, [SDTCisVT<0, v4f32>, SDTCisVT<2, v32i8>,
31 SDTCisVT<3, i128>, SDTCisVT<4, i32>]>
34 def SIsample : SDSample<"AMDGPUISD::SAMPLE">;
35 def SIsampleb : SDSample<"AMDGPUISD::SAMPLEB">;
36 def SIsampled : SDSample<"AMDGPUISD::SAMPLED">;
37 def SIsamplel : SDSample<"AMDGPUISD::SAMPLEL">;
39 // Transformation function, extract the lower 32bit of a 64bit immediate
40 def LO32 : SDNodeXForm<imm, [{
41 return CurDAG->getTargetConstant(N->getZExtValue() & 0xffffffff, MVT::i32);
44 def LO32f : SDNodeXForm<fpimm, [{
45 APInt V = N->getValueAPF().bitcastToAPInt().trunc(32);
46 return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
49 // Transformation function, extract the upper 32bit of a 64bit immediate
50 def HI32 : SDNodeXForm<imm, [{
51 return CurDAG->getTargetConstant(N->getZExtValue() >> 32, MVT::i32);
54 def HI32f : SDNodeXForm<fpimm, [{
55 APInt V = N->getValueAPF().bitcastToAPInt().lshr(32).trunc(32);
56 return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
59 def IMM8bitDWORD : ImmLeaf <
61 return (Imm & ~0x3FC) == 0;
62 }], SDNodeXForm<imm, [{
63 return CurDAG->getTargetConstant(
64 N->getZExtValue() >> 2, MVT::i32);
68 def as_i16imm : SDNodeXForm<imm, [{
69 return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i16);
72 def IMM12bit : PatLeaf <(imm),
73 [{return isUInt<12>(N->getZExtValue());}]
76 class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
78 (*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0;
81 class SGPRImm <dag frag> : PatLeaf<frag, [{
82 if (TM.getSubtarget<AMDGPUSubtarget>().getGeneration() <
83 AMDGPUSubtarget::SOUTHERN_ISLANDS) {
86 const SIRegisterInfo *SIRI =
87 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
88 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
90 if (SIRI->isSGPRClass(getOperandRegClass(*U, U.getOperandNo()))) {
97 //===----------------------------------------------------------------------===//
98 // SI assembler operands
99 //===----------------------------------------------------------------------===//
106 include "SIInstrFormats.td"
108 //===----------------------------------------------------------------------===//
110 // SI Instruction multiclass helpers.
112 // Instructions with _32 take 32-bit operands.
113 // Instructions with _64 take 64-bit operands.
115 // VOP_* instructions can use either a 32-bit or 64-bit encoding. The 32-bit
116 // encoding is the standard encoding, but instruction that make use of
117 // any of the instruction modifiers must use the 64-bit encoding.
119 // Instructions with _e32 use the 32-bit encoding.
120 // Instructions with _e64 use the 64-bit encoding.
122 //===----------------------------------------------------------------------===//
124 //===----------------------------------------------------------------------===//
126 //===----------------------------------------------------------------------===//
128 class SOP1_32 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
129 op, (outs SReg_32:$dst), (ins SSrc_32:$src0),
130 opName#" $dst, $src0", pattern
133 class SOP1_64 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
134 op, (outs SReg_64:$dst), (ins SSrc_64:$src0),
135 opName#" $dst, $src0", pattern
138 class SOP2_32 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
139 op, (outs SReg_32:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
140 opName#" $dst, $src0, $src1", pattern
143 class SOP2_64 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
144 op, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
145 opName#" $dst, $src0, $src1", pattern
148 class SOPC_32 <bits<7> op, string opName, list<dag> pattern> : SOPC <
149 op, (outs SCCReg:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
150 opName#" $dst, $src0, $src1", pattern
153 class SOPC_64 <bits<7> op, string opName, list<dag> pattern> : SOPC <
154 op, (outs SCCReg:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
155 opName#" $dst, $src0, $src1", pattern
158 class SOPK_32 <bits<5> op, string opName, list<dag> pattern> : SOPK <
159 op, (outs SReg_32:$dst), (ins i16imm:$src0),
160 opName#" $dst, $src0", pattern
163 class SOPK_64 <bits<5> op, string opName, list<dag> pattern> : SOPK <
164 op, (outs SReg_64:$dst), (ins i16imm:$src0),
165 opName#" $dst, $src0", pattern
168 multiclass SMRD_Helper <bits<5> op, string asm, RegisterClass baseClass,
169 RegisterClass dstClass> {
171 op, 1, (outs dstClass:$dst),
172 (ins baseClass:$sbase, i32imm:$offset),
173 asm#" $dst, $sbase, $offset", []
177 op, 0, (outs dstClass:$dst),
178 (ins baseClass:$sbase, SReg_32:$soff),
179 asm#" $dst, $sbase, $soff", []
183 //===----------------------------------------------------------------------===//
184 // Vector ALU classes
185 //===----------------------------------------------------------------------===//
187 class VOP <string opName> {
188 string OpName = opName;
191 class VOP2_REV <string revOp, bit isOrig> {
192 string RevOp = revOp;
196 multiclass VOP1_Helper <bits<8> op, RegisterClass drc, RegisterClass src,
197 string opName, list<dag> pattern> {
200 op, (outs drc:$dst), (ins src:$src0),
201 opName#"_e32 $dst, $src0", pattern
205 {1, 1, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
208 i32imm:$abs, i32imm:$clamp,
209 i32imm:$omod, i32imm:$neg),
210 opName#"_e64 $dst, $src0, $abs, $clamp, $omod, $neg", []
212 let src1 = SIOperand.ZERO;
213 let src2 = SIOperand.ZERO;
217 multiclass VOP1_32 <bits<8> op, string opName, list<dag> pattern>
218 : VOP1_Helper <op, VReg_32, VSrc_32, opName, pattern>;
220 multiclass VOP1_64 <bits<8> op, string opName, list<dag> pattern>
221 : VOP1_Helper <op, VReg_64, VSrc_64, opName, pattern>;
223 multiclass VOP1_32_64 <bits<8> op, string opName, list<dag> pattern>
224 : VOP1_Helper <op, VReg_32, VSrc_64, opName, pattern>;
226 multiclass VOP1_64_32 <bits<8> op, string opName, list<dag> pattern>
227 : VOP1_Helper <op, VReg_64, VSrc_32, opName, pattern>;
229 multiclass VOP2_Helper <bits<6> op, RegisterClass vrc, RegisterClass arc,
230 string opName, list<dag> pattern, string revOp> {
232 op, (outs vrc:$dst), (ins arc:$src0, vrc:$src1),
233 opName#"_e32 $dst, $src0, $src1", pattern
234 >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
237 {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
239 (ins arc:$src0, arc:$src1,
240 i32imm:$abs, i32imm:$clamp,
241 i32imm:$omod, i32imm:$neg),
242 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
243 >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
244 let src2 = SIOperand.ZERO;
248 multiclass VOP2_32 <bits<6> op, string opName, list<dag> pattern,
249 string revOp = opName>
250 : VOP2_Helper <op, VReg_32, VSrc_32, opName, pattern, revOp>;
252 multiclass VOP2_64 <bits<6> op, string opName, list<dag> pattern,
253 string revOp = opName>
254 : VOP2_Helper <op, VReg_64, VSrc_64, opName, pattern, revOp>;
256 multiclass VOP2b_32 <bits<6> op, string opName, list<dag> pattern,
257 string revOp = opName> {
260 op, (outs VReg_32:$dst), (ins VSrc_32:$src0, VReg_32:$src1),
261 opName#"_e32 $dst, $src0, $src1", pattern
262 >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
265 {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
267 (ins VSrc_32:$src0, VSrc_32:$src1,
268 i32imm:$abs, i32imm:$clamp,
269 i32imm:$omod, i32imm:$neg),
270 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
271 >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
272 let src2 = SIOperand.ZERO;
273 /* the VOP2 variant puts the carry out into VCC, the VOP3 variant
274 can write it into any SGPR. We currently don't use the carry out,
275 so for now hardcode it to VCC as well */
276 let sdst = SIOperand.VCC;
280 multiclass VOPC_Helper <bits<8> op, RegisterClass vrc, RegisterClass arc,
281 string opName, ValueType vt, PatLeaf cond> {
284 op, (ins arc:$src0, vrc:$src1),
285 opName#"_e32 $dst, $src0, $src1", []
289 {0, op{7}, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
291 (ins arc:$src0, arc:$src1,
292 InstFlag:$abs, InstFlag:$clamp,
293 InstFlag:$omod, InstFlag:$neg),
294 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg",
295 !if(!eq(!cast<string>(cond), "COND_NULL"), []<dag>,
296 [(set SReg_64:$dst, (i1 (setcc (vt arc:$src0), arc:$src1, cond)))]
299 let src2 = SIOperand.ZERO;
303 multiclass VOPC_32 <bits<8> op, string opName,
304 ValueType vt = untyped, PatLeaf cond = COND_NULL>
305 : VOPC_Helper <op, VReg_32, VSrc_32, opName, vt, cond>;
307 multiclass VOPC_64 <bits<8> op, string opName,
308 ValueType vt = untyped, PatLeaf cond = COND_NULL>
309 : VOPC_Helper <op, VReg_64, VSrc_64, opName, vt, cond>;
311 class VOP3_32 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
312 op, (outs VReg_32:$dst),
313 (ins VSrc_32:$src0, VSrc_32:$src1, VSrc_32:$src2,
314 InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
315 opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
318 class VOP3_64_Shift <bits <9> op, string opName, list<dag> pattern> : VOP3 <
319 op, (outs VReg_64:$dst),
320 (ins VSrc_64:$src0, VSrc_32:$src1),
321 opName#" $dst, $src0, $src1", pattern
324 let src2 = SIOperand.ZERO;
331 class VOP3_64 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
332 op, (outs VReg_64:$dst),
333 (ins VSrc_64:$src0, VSrc_64:$src1, VSrc_64:$src2,
334 InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
335 opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
338 //===----------------------------------------------------------------------===//
339 // Vector I/O classes
340 //===----------------------------------------------------------------------===//
342 class DS_Load_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
344 (outs regClass:$vdst),
345 (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
346 i8imm:$offset0, i8imm:$offset1),
347 asm#" $vdst, $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
353 class DS_Store_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
356 (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
357 i8imm:$offset0, i8imm:$offset1),
358 asm#" $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
365 class MTBUF_Store_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
368 (ins regClass:$vdata, i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
369 i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr,
370 SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
371 asm#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
372 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
378 multiclass MUBUF_Load_Helper <bits<7> op, string asm, RegisterClass regClass> {
380 let glc = 0, lds = 0, slc = 0, tfe = 0, soffset = 128 /* ZERO */,
383 let offen = 1, idxen = 0, addr64 = 0, offset = 0 in {
384 def _OFFEN : MUBUF <op, (outs regClass:$vdata),
385 (ins SReg_128:$srsrc, VReg_32:$vaddr),
386 asm#" $vdata, $srsrc + $vaddr", []>;
389 let offen = 0, idxen = 1, addr64 = 0 in {
390 def _IDXEN : MUBUF <op, (outs regClass:$vdata),
391 (ins SReg_128:$srsrc, VReg_32:$vaddr, i16imm:$offset),
392 asm#" $vdata, $srsrc[$vaddr] + $offset", []>;
395 let offen = 0, idxen = 0, addr64 = 1 in {
396 def _ADDR64 : MUBUF <op, (outs regClass:$vdata),
397 (ins SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
398 asm#" $vdata, $srsrc + $vaddr + $offset", []>;
403 class MUBUF_Store_Helper <bits<7> op, string name, RegisterClass vdataClass> :
404 MUBUF <op, (outs), (ins vdataClass:$vdata, SReg_128:$srsrc, VReg_64:$vaddr,
406 name#" $vdata, $srsrc + $vaddr + $offset",
420 let soffset = 128; // ZERO
423 class MTBUF_Load_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
425 (outs regClass:$dst),
426 (ins i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
427 i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr, SReg_128:$srsrc,
428 i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
429 asm#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
430 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
436 class MIMG_NoSampler_Helper <bits<7> op, string asm,
437 RegisterClass src_rc> : MIMG <
439 (outs VReg_128:$vdata),
440 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
441 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
443 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
444 #" $tfe, $lwe, $slc, $vaddr, $srsrc",
449 let hasPostISelHook = 1;
452 multiclass MIMG_NoSampler <bits<7> op, string asm> {
453 def _V1 : MIMG_NoSampler_Helper <op, asm, VReg_32>;
454 def _V2 : MIMG_NoSampler_Helper <op, asm, VReg_64>;
455 def _V4 : MIMG_NoSampler_Helper <op, asm, VReg_128>;
458 class MIMG_Sampler_Helper <bits<7> op, string asm,
459 RegisterClass src_rc> : MIMG <
461 (outs VReg_128:$vdata),
462 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
463 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
464 SReg_256:$srsrc, SReg_128:$ssamp),
465 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
466 #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
470 let hasPostISelHook = 1;
473 multiclass MIMG_Sampler <bits<7> op, string asm> {
474 def _V1 : MIMG_Sampler_Helper <op, asm, VReg_32>;
475 def _V2 : MIMG_Sampler_Helper <op, asm, VReg_64>;
476 def _V4 : MIMG_Sampler_Helper <op, asm, VReg_128>;
477 def _V8 : MIMG_Sampler_Helper <op, asm, VReg_256>;
478 def _V16 : MIMG_Sampler_Helper <op, asm, VReg_512>;
481 //===----------------------------------------------------------------------===//
482 // Vector instruction mappings
483 //===----------------------------------------------------------------------===//
485 // Maps an opcode in e32 form to its e64 equivalent
486 def getVOPe64 : InstrMapping {
487 let FilterClass = "VOP";
488 let RowFields = ["OpName"];
489 let ColFields = ["Size"];
491 let ValueCols = [["8"]];
494 // Maps an original opcode to its commuted version
495 def getCommuteRev : InstrMapping {
496 let FilterClass = "VOP2_REV";
497 let RowFields = ["RevOp"];
498 let ColFields = ["IsOrig"];
500 let ValueCols = [["0"]];
503 // Maps an commuted opcode to its original version
504 def getCommuteOrig : InstrMapping {
505 let FilterClass = "VOP2_REV";
506 let RowFields = ["RevOp"];
507 let ColFields = ["IsOrig"];
509 let ValueCols = [["1"]];
512 include "SIInstructions.td"