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 // Transformation function, extract the lower 32bit of a 64bit immediate
20 def LO32 : SDNodeXForm<imm, [{
21 return CurDAG->getTargetConstant(N->getZExtValue() & 0xffffffff, MVT::i32);
24 def LO32f : SDNodeXForm<fpimm, [{
25 APInt V = N->getValueAPF().bitcastToAPInt().trunc(32);
26 return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
29 // Transformation function, extract the upper 32bit of a 64bit immediate
30 def HI32 : SDNodeXForm<imm, [{
31 return CurDAG->getTargetConstant(N->getZExtValue() >> 32, MVT::i32);
34 def HI32f : SDNodeXForm<fpimm, [{
35 APInt V = N->getValueAPF().bitcastToAPInt().lshr(32).trunc(32);
36 return CurDAG->getTargetConstantFP(APFloat(APFloat::IEEEsingle, V), MVT::f32);
39 def IMM8bitDWORD : ImmLeaf <
41 return (Imm & ~0x3FC) == 0;
42 }], SDNodeXForm<imm, [{
43 return CurDAG->getTargetConstant(
44 N->getZExtValue() >> 2, MVT::i32);
48 def as_i16imm : SDNodeXForm<imm, [{
49 return CurDAG->getTargetConstant(N->getSExtValue(), MVT::i16);
52 def IMM12bit : PatLeaf <(imm),
53 [{return isUInt<12>(N->getZExtValue());}]
56 class InlineImm <ValueType vt> : PatLeaf <(vt imm), [{
58 (*(const SITargetLowering *)getTargetLowering()).analyzeImmediate(N) == 0;
61 class SGPRImm <dag frag> : PatLeaf<frag, [{
62 if (TM.getSubtarget<AMDGPUSubtarget>().getGeneration() <
63 AMDGPUSubtarget::SOUTHERN_ISLANDS) {
66 const SIRegisterInfo *SIRI =
67 static_cast<const SIRegisterInfo*>(TM.getRegisterInfo());
68 for (SDNode::use_iterator U = N->use_begin(), E = SDNode::use_end();
70 if (SIRI->isSGPRClass(getOperandRegClass(*U, U.getOperandNo()))) {
77 //===----------------------------------------------------------------------===//
78 // SI assembler operands
79 //===----------------------------------------------------------------------===//
86 include "SIInstrFormats.td"
88 //===----------------------------------------------------------------------===//
90 // SI Instruction multiclass helpers.
92 // Instructions with _32 take 32-bit operands.
93 // Instructions with _64 take 64-bit operands.
95 // VOP_* instructions can use either a 32-bit or 64-bit encoding. The 32-bit
96 // encoding is the standard encoding, but instruction that make use of
97 // any of the instruction modifiers must use the 64-bit encoding.
99 // Instructions with _e32 use the 32-bit encoding.
100 // Instructions with _e64 use the 64-bit encoding.
102 //===----------------------------------------------------------------------===//
104 //===----------------------------------------------------------------------===//
106 //===----------------------------------------------------------------------===//
108 class SOP1_32 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
109 op, (outs SReg_32:$dst), (ins SSrc_32:$src0),
110 opName#" $dst, $src0", pattern
113 class SOP1_64 <bits<8> op, string opName, list<dag> pattern> : SOP1 <
114 op, (outs SReg_64:$dst), (ins SSrc_64:$src0),
115 opName#" $dst, $src0", pattern
118 class SOP2_32 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
119 op, (outs SReg_32:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
120 opName#" $dst, $src0, $src1", pattern
123 class SOP2_64 <bits<7> op, string opName, list<dag> pattern> : SOP2 <
124 op, (outs SReg_64:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
125 opName#" $dst, $src0, $src1", pattern
128 class SOPC_32 <bits<7> op, string opName, list<dag> pattern> : SOPC <
129 op, (outs SCCReg:$dst), (ins SSrc_32:$src0, SSrc_32:$src1),
130 opName#" $dst, $src0, $src1", pattern
133 class SOPC_64 <bits<7> op, string opName, list<dag> pattern> : SOPC <
134 op, (outs SCCReg:$dst), (ins SSrc_64:$src0, SSrc_64:$src1),
135 opName#" $dst, $src0, $src1", pattern
138 class SOPK_32 <bits<5> op, string opName, list<dag> pattern> : SOPK <
139 op, (outs SReg_32:$dst), (ins i16imm:$src0),
140 opName#" $dst, $src0", pattern
143 class SOPK_64 <bits<5> op, string opName, list<dag> pattern> : SOPK <
144 op, (outs SReg_64:$dst), (ins i16imm:$src0),
145 opName#" $dst, $src0", pattern
148 multiclass SMRD_Helper <bits<5> op, string asm, RegisterClass baseClass,
149 RegisterClass dstClass> {
151 op, 1, (outs dstClass:$dst),
152 (ins baseClass:$sbase, i32imm:$offset),
153 asm#" $dst, $sbase, $offset", []
157 op, 0, (outs dstClass:$dst),
158 (ins baseClass:$sbase, SReg_32:$soff),
159 asm#" $dst, $sbase, $soff", []
163 //===----------------------------------------------------------------------===//
164 // Vector ALU classes
165 //===----------------------------------------------------------------------===//
167 class VOP <string opName> {
168 string OpName = opName;
171 class VOP2_REV <string revOp, bit isOrig> {
172 string RevOp = revOp;
176 multiclass VOP1_Helper <bits<8> op, RegisterClass drc, RegisterClass src,
177 string opName, list<dag> pattern> {
180 op, (outs drc:$dst), (ins src:$src0),
181 opName#"_e32 $dst, $src0", pattern
185 {1, 1, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
188 i32imm:$abs, i32imm:$clamp,
189 i32imm:$omod, i32imm:$neg),
190 opName#"_e64 $dst, $src0, $abs, $clamp, $omod, $neg", []
192 let src1 = SIOperand.ZERO;
193 let src2 = SIOperand.ZERO;
197 multiclass VOP1_32 <bits<8> op, string opName, list<dag> pattern>
198 : VOP1_Helper <op, VReg_32, VSrc_32, opName, pattern>;
200 multiclass VOP1_64 <bits<8> op, string opName, list<dag> pattern>
201 : VOP1_Helper <op, VReg_64, VSrc_64, opName, pattern>;
203 multiclass VOP1_32_64 <bits<8> op, string opName, list<dag> pattern>
204 : VOP1_Helper <op, VReg_32, VSrc_64, opName, pattern>;
206 multiclass VOP1_64_32 <bits<8> op, string opName, list<dag> pattern>
207 : VOP1_Helper <op, VReg_64, VSrc_32, opName, pattern>;
209 multiclass VOP2_Helper <bits<6> op, RegisterClass vrc, RegisterClass arc,
210 string opName, list<dag> pattern, string revOp> {
212 op, (outs vrc:$dst), (ins arc:$src0, vrc:$src1),
213 opName#"_e32 $dst, $src0, $src1", pattern
214 >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
217 {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
219 (ins arc:$src0, arc:$src1,
220 i32imm:$abs, i32imm:$clamp,
221 i32imm:$omod, i32imm:$neg),
222 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
223 >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
224 let src2 = SIOperand.ZERO;
228 multiclass VOP2_32 <bits<6> op, string opName, list<dag> pattern,
229 string revOp = opName>
230 : VOP2_Helper <op, VReg_32, VSrc_32, opName, pattern, revOp>;
232 multiclass VOP2_64 <bits<6> op, string opName, list<dag> pattern,
233 string revOp = opName>
234 : VOP2_Helper <op, VReg_64, VSrc_64, opName, pattern, revOp>;
236 multiclass VOP2b_32 <bits<6> op, string opName, list<dag> pattern,
237 string revOp = opName> {
240 op, (outs VReg_32:$dst), (ins VSrc_32:$src0, VReg_32:$src1),
241 opName#"_e32 $dst, $src0, $src1", pattern
242 >, VOP <opName>, VOP2_REV<revOp#"_e32", !eq(revOp, opName)>;
245 {1, 0, 0, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
247 (ins VSrc_32:$src0, VSrc_32:$src1,
248 i32imm:$abs, i32imm:$clamp,
249 i32imm:$omod, i32imm:$neg),
250 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg", []
251 >, VOP <opName>, VOP2_REV<revOp#"_e64", !eq(revOp, opName)> {
252 let src2 = SIOperand.ZERO;
253 /* the VOP2 variant puts the carry out into VCC, the VOP3 variant
254 can write it into any SGPR. We currently don't use the carry out,
255 so for now hardcode it to VCC as well */
256 let sdst = SIOperand.VCC;
260 multiclass VOPC_Helper <bits<8> op, RegisterClass vrc, RegisterClass arc,
261 string opName, ValueType vt, PatLeaf cond> {
264 op, (ins arc:$src0, vrc:$src1),
265 opName#"_e32 $dst, $src0, $src1", []
269 {0, op{7}, op{6}, op{5}, op{4}, op{3}, op{2}, op{1}, op{0}},
271 (ins arc:$src0, arc:$src1,
272 InstFlag:$abs, InstFlag:$clamp,
273 InstFlag:$omod, InstFlag:$neg),
274 opName#"_e64 $dst, $src0, $src1, $abs, $clamp, $omod, $neg",
275 !if(!eq(!cast<string>(cond), "COND_NULL"), []<dag>,
276 [(set SReg_64:$dst, (i1 (setcc (vt arc:$src0), arc:$src1, cond)))]
279 let src2 = SIOperand.ZERO;
283 multiclass VOPC_32 <bits<8> op, string opName,
284 ValueType vt = untyped, PatLeaf cond = COND_NULL>
285 : VOPC_Helper <op, VReg_32, VSrc_32, opName, vt, cond>;
287 multiclass VOPC_64 <bits<8> op, string opName,
288 ValueType vt = untyped, PatLeaf cond = COND_NULL>
289 : VOPC_Helper <op, VReg_64, VSrc_64, opName, vt, cond>;
291 class VOP3_32 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
292 op, (outs VReg_32:$dst),
293 (ins VSrc_32:$src0, VSrc_32:$src1, VSrc_32:$src2,
294 InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
295 opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
298 class VOP3_64_Shift <bits <9> op, string opName, list<dag> pattern> : VOP3 <
299 op, (outs VReg_64:$dst),
300 (ins VSrc_64:$src0, VSrc_32:$src1),
301 opName#" $dst, $src0, $src1", pattern
304 let src2 = SIOperand.ZERO;
311 class VOP3_64 <bits<9> op, string opName, list<dag> pattern> : VOP3 <
312 op, (outs VReg_64:$dst),
313 (ins VSrc_64:$src0, VSrc_64:$src1, VSrc_64:$src2,
314 InstFlag:$abs, InstFlag:$clamp, InstFlag:$omod, InstFlag:$neg),
315 opName#" $dst, $src0, $src1, $src2, $abs, $clamp, $omod, $neg", pattern
318 //===----------------------------------------------------------------------===//
319 // Vector I/O classes
320 //===----------------------------------------------------------------------===//
322 class DS_Load_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
324 (outs regClass:$vdst),
325 (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
326 i8imm:$offset0, i8imm:$offset1),
327 asm#" $vdst, $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
333 class DS_Store_Helper <bits<8> op, string asm, RegisterClass regClass> : DS <
336 (ins i1imm:$gds, VReg_32:$addr, VReg_32:$data0, VReg_32:$data1,
337 i8imm:$offset0, i8imm:$offset1),
338 asm#" $gds, $addr, $data0, $data1, $offset0, $offset1, [M0]",
345 class MTBUF_Store_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
348 (ins regClass:$vdata, i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc,
349 i1imm:$addr64, i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr,
350 SReg_128:$srsrc, i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
351 asm#" $vdata, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
352 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
358 multiclass MUBUF_Load_Helper <bits<7> op, string asm, RegisterClass regClass> {
360 let glc = 0, lds = 0, slc = 0, tfe = 0, soffset = 128 /* ZERO */,
363 let offen = 1, idxen = 0, addr64 = 0, offset = 0 in {
364 def _OFFEN : MUBUF <op, (outs regClass:$vdata),
365 (ins SReg_128:$srsrc, VReg_32:$vaddr),
366 asm#" $vdata, $srsrc + $vaddr", []>;
369 let offen = 0, idxen = 1, addr64 = 0 in {
370 def _IDXEN : MUBUF <op, (outs regClass:$vdata),
371 (ins SReg_128:$srsrc, VReg_32:$vaddr, i16imm:$offset),
372 asm#" $vdata, $srsrc[$vaddr] + $offset", []>;
375 let offen = 0, idxen = 0, addr64 = 1 in {
376 def _ADDR64 : MUBUF <op, (outs regClass:$vdata),
377 (ins SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
378 asm#" $vdata, $srsrc + $vaddr + $offset", []>;
383 class MUBUF_Store_Helper <bits<7> op, string name, RegisterClass vdataClass,
385 MUBUF <op, (outs), (ins vdataClass:$vdata, SReg_128:$srsrc, VReg_64:$vaddr, i16imm:$offset),
386 name#" $vdata, $srsrc + $vaddr + $offset",
400 let soffset = 128; // ZERO
403 class MTBUF_Load_Helper <bits<3> op, string asm, RegisterClass regClass> : MTBUF <
405 (outs regClass:$dst),
406 (ins i16imm:$offset, i1imm:$offen, i1imm:$idxen, i1imm:$glc, i1imm:$addr64,
407 i8imm:$dfmt, i8imm:$nfmt, VReg_32:$vaddr, SReg_128:$srsrc,
408 i1imm:$slc, i1imm:$tfe, SSrc_32:$soffset),
409 asm#" $dst, $offset, $offen, $idxen, $glc, $addr64, $dfmt,"
410 #" $nfmt, $vaddr, $srsrc, $slc, $tfe, $soffset",
416 class MIMG_NoSampler_Helper <bits<7> op, string asm,
417 RegisterClass src_rc> : MIMG <
419 (outs VReg_128:$vdata),
420 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
421 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
423 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
424 #" $tfe, $lwe, $slc, $vaddr, $srsrc",
429 let hasPostISelHook = 1;
432 multiclass MIMG_NoSampler <bits<7> op, string asm> {
433 def _V1 : MIMG_NoSampler_Helper <op, asm, VReg_32>;
434 def _V2 : MIMG_NoSampler_Helper <op, asm, VReg_64>;
435 def _V4 : MIMG_NoSampler_Helper <op, asm, VReg_128>;
438 class MIMG_Sampler_Helper <bits<7> op, string asm,
439 RegisterClass src_rc> : MIMG <
441 (outs VReg_128:$vdata),
442 (ins i32imm:$dmask, i1imm:$unorm, i1imm:$glc, i1imm:$da, i1imm:$r128,
443 i1imm:$tfe, i1imm:$lwe, i1imm:$slc, src_rc:$vaddr,
444 SReg_256:$srsrc, SReg_128:$ssamp),
445 asm#" $vdata, $dmask, $unorm, $glc, $da, $r128,"
446 #" $tfe, $lwe, $slc, $vaddr, $srsrc, $ssamp",
450 let hasPostISelHook = 1;
453 multiclass MIMG_Sampler <bits<7> op, string asm> {
454 def _V1 : MIMG_Sampler_Helper <op, asm, VReg_32>;
455 def _V2 : MIMG_Sampler_Helper <op, asm, VReg_64>;
456 def _V4 : MIMG_Sampler_Helper <op, asm, VReg_128>;
457 def _V8 : MIMG_Sampler_Helper <op, asm, VReg_256>;
458 def _V16 : MIMG_Sampler_Helper <op, asm, VReg_512>;
461 //===----------------------------------------------------------------------===//
462 // Vector instruction mappings
463 //===----------------------------------------------------------------------===//
465 // Maps an opcode in e32 form to its e64 equivalent
466 def getVOPe64 : InstrMapping {
467 let FilterClass = "VOP";
468 let RowFields = ["OpName"];
469 let ColFields = ["Size"];
471 let ValueCols = [["8"]];
474 // Maps an original opcode to its commuted version
475 def getCommuteRev : InstrMapping {
476 let FilterClass = "VOP2_REV";
477 let RowFields = ["RevOp"];
478 let ColFields = ["IsOrig"];
480 let ValueCols = [["0"]];
483 // Maps an commuted opcode to its original version
484 def getCommuteOrig : InstrMapping {
485 let FilterClass = "VOP2_REV";
486 let RowFields = ["RevOp"];
487 let ColFields = ["IsOrig"];
489 let ValueCols = [["1"]];
492 include "SIInstructions.td"