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 DS_1A1D_RET <bits<8> op, string asm, RegisterClass rc> : DS <
368 (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, i8imm:$offset0,
370 asm#" $gds, $vdst, $addr, $data0, $offset0, $offset1, [M0]",
377 class MTBUF_Store_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
380 (ins regClass:$vdata, i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
381 i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr,
382 SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
383 asm#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
384 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
390 multiclass MUBUF_Load_Helper <bits<7> op, string asm, RegisterClass regClass> {
392 let glc = 0, lds = 0, slc = 0, tfe = 0, soffset = 128 /* ZERO */,
395 let offen = 1, idxen = 0, addr64 = 0, offset = 0 in {
396 def _OFFEN : MUBUF <op, (outs regClass:$vdata),
397 (ins SReg_128:$srsrc, VReg_32:$vaddr),
398 asm#" $vdata, $srsrc + $vaddr", []>;
401 let offen = 0, idxen = 1, addr64 = 0 in {
402 def _IDXEN : MUBUF <op, (outs regClass:$vdata),
403 (ins SReg_128:$srsrc, VReg_32:$vaddr, i16imm:$offset),
404 asm#" $vdata, $srsrc[$vaddr] + $offset", []>;
407 let offen = 0, idxen = 0, addr64 = 1 in {
408 def _ADDR64 : MUBUF <op, (outs regClass:$vdata),
409 (ins SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
410 asm#" $vdata, $srsrc + $vaddr + $offset", []>;
415 class MUBUF_Store_Helper <bits<7> op, string name, RegisterClass vdataClass> :
416 MUBUF <op, (outs), (ins vdataClass:$vdata, SReg_128:$srsrc, VReg_64:$vaddr,
418 name#" $vdata, $srsrc + $vaddr + $offset",
432 let soffset = 128; // ZERO
435 class MTBUF_Load_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
437 (outs regClass:$dst),
438 (ins i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
439 i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr, SReg_128:$srsrc,
440 i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
441 asm#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
442 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
448 class MIMG_NoSampler_Helper <bits<7> op, string asm,
449 RegisterClass src_rc> : MIMG <
451 (outs VReg_128:$vdata),
452 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
453 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
455 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
456 #" $tfe, $lwe, $slc, $vaddr, $srsrc",
461 let hasPostISelHook = 1;
464 multiclass MIMG_NoSampler <bits<7> op, string asm> {
465 def _V1 : MIMG_NoSampler_Helper <op, asm, VReg_32>;
466 def _V2 : MIMG_NoSampler_Helper <op, asm, VReg_64>;
467 def _V4 : MIMG_NoSampler_Helper <op, asm, VReg_128>;
470 class MIMG_Sampler_Helper <bits<7> op, string asm,
471 RegisterClass src_rc> : MIMG <
473 (outs VReg_128:$vdata),
474 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
475 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
476 SReg_256:$srsrc, SReg_128:$ssamp),
477 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
478 #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
482 let hasPostISelHook = 1;
485 multiclass MIMG_Sampler <bits<7> op, string asm> {
486 def _V1 : MIMG_Sampler_Helper <op, asm, VReg_32>;
487 def _V2 : MIMG_Sampler_Helper <op, asm, VReg_64>;
488 def _V4 : MIMG_Sampler_Helper <op, asm, VReg_128>;
489 def _V8 : MIMG_Sampler_Helper <op, asm, VReg_256>;
490 def _V16 : MIMG_Sampler_Helper <op, asm, VReg_512>;
493 //===----------------------------------------------------------------------===//
494 // Vector instruction mappings
495 //===----------------------------------------------------------------------===//
497 // Maps an opcode in e32 form to its e64 equivalent
498 def getVOPe64 : InstrMapping {
499 let FilterClass = "VOP";
500 let RowFields = ["OpName"];
501 let ColFields = ["Size"];
503 let ValueCols = [["8"]];
506 // Maps an original opcode to its commuted version
507 def getCommuteRev : InstrMapping {
508 let FilterClass = "VOP2_REV";
509 let RowFields = ["RevOp"];
510 let ColFields = ["IsOrig"];
512 let ValueCols = [["0"]];
515 // Maps an commuted opcode to its original version
516 def getCommuteOrig : InstrMapping {
517 let FilterClass = "VOP2_REV";
518 let RowFields = ["RevOp"];
519 let ColFields = ["IsOrig"];
521 let ValueCols = [["1"]];
524 include "SIInstructions.td"