diff options
Diffstat (limited to 'llvm/lib/Target/AMDGPU/MIMGInstructions.td')
-rw-r--r-- | llvm/lib/Target/AMDGPU/MIMGInstructions.td | 169 |
1 files changed, 101 insertions, 68 deletions
diff --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td index c295b7f79442..d924f733624a 100644 --- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td +++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td @@ -48,6 +48,7 @@ class MIMGBaseOpcode : PredicateControl { bit IsAtomicRet = 0; bit MSAA = 0; bit BVH = 0; + bit A16 = 0; } def MIMGBaseOpcode : GenericEnum { @@ -59,7 +60,7 @@ def MIMGBaseOpcodesTable : GenericTable { let CppTypeName = "MIMGBaseOpcodeInfo"; let Fields = ["BaseOpcode", "Store", "Atomic", "AtomicX2", "Sampler", "Gather4", "NumExtraArgs", "Gradients", "G16", "Coordinates", - "LodOrClampOrMip", "HasD16", "MSAA", "BVH"]; + "LodOrClampOrMip", "HasD16", "MSAA", "BVH", "A16"]; string TypeOf_BaseOpcode = "MIMGBaseOpcode"; let PrimaryKey = ["BaseOpcode"]; @@ -206,7 +207,6 @@ class MIMG <dag outs, string dns = ""> : MIMG_Base <outs, dns> { let hasPostISelHook = 1; - let AsmMatchConverter = "cvtMIMG"; Instruction Opcode = !cast<Instruction>(NAME); MIMGBaseOpcode BaseOpcode; @@ -235,22 +235,41 @@ def getMIMGInfo : SearchIndex { let Key = ["Opcode"]; } -// This class used to use !foldl to memoize the AddrAsmNames list. -// It turned out that that was much slower than using !filter. +class NSAHelper { + dag AddrIns; + string AddrAsm; + int NSA; +} + class MIMGNSAHelper<int num_addrs, - list<RegisterClass> addr_types=!listsplat(VGPR_32, num_addrs)> { - list<string> AddrAsmNames = - !foreach(i, !filter(i, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], - !lt(i, num_addrs)), "vaddr" # i); - dag AddrIns = !dag(ins, addr_types, AddrAsmNames); - string AddrAsm = "[$" # !interleave(AddrAsmNames, ", $") # "]"; - - int NSA = !if(!le(num_addrs, 1), ?, + list<RegisterClass> addr_types=!listsplat(VGPR_32, num_addrs)> + : NSAHelper<> { + list<string> AddrAsmNames = !foreach(i, !range(num_addrs), "vaddr" # i); + let AddrIns = !dag(ins, addr_types, AddrAsmNames); + let AddrAsm = "[$" # !interleave(AddrAsmNames, ", $") # "]"; + + let NSA = !if(!le(num_addrs, 1), ?, !if(!le(num_addrs, 5), 1, !if(!le(num_addrs, 9), 2, !if(!le(num_addrs, 13), 3, ?)))); } +class PartialNSAHelper<int num_addrs, int max_addr, RegisterClass LastAddrRC> + : NSAHelper<> { + + list<RegisterClass> addr_types = + !if(!ge(num_addrs, max_addr), + !listconcat(!listsplat(VGPR_32, !sub(max_addr, 1)), [LastAddrRC]), + !listsplat(VGPR_32, num_addrs)); + + int VAddrCount = !if(!gt(num_addrs, max_addr), max_addr, num_addrs); + list<string> AddrAsmNames = !foreach(i, !range(VAddrCount), "vaddr" # i); + + let AddrIns = !dag(ins, addr_types, AddrAsmNames); + let AddrAsm = "[$" # !interleave(AddrAsmNames, ", $") # "]"; + let NSA = 1; +} + // Base class of all pre-gfx10 MIMG instructions. class MIMG_gfx6789<bits<8> op, dag outs, string dns = ""> : MIMG<outs, dns>, MIMGe_gfx6789<op> { @@ -321,7 +340,8 @@ class MIMG_gfx11<int op, dag outs, string dns = ""> // Base class for all NSA MIMG instructions. // Note that 1-dword addresses always use non-NSA variants. class MIMG_nsa_gfx11<int op, dag outs, int num_addrs, string dns="", - list<RegisterClass> addr_types=[]> + list<RegisterClass> addr_types=[], + RegisterClass LastAddrRC = VGPR_32> : MIMG<outs, dns>, MIMGe_gfx11<op> { let SubtargetPredicate = isGFX11Plus; let AssemblerPredicate = isGFX11Plus; @@ -329,9 +349,9 @@ class MIMG_nsa_gfx11<int op, dag outs, int num_addrs, string dns="", let MIMGEncoding = MIMGEncGfx11NSA; let VAddrOperands = num_addrs; - MIMGNSAHelper nsah = !if(!empty(addr_types), - MIMGNSAHelper<num_addrs>, - MIMGNSAHelper<num_addrs, addr_types>); + NSAHelper nsah = !if(!empty(addr_types), + PartialNSAHelper<num_addrs, 5, LastAddrRC>, + MIMGNSAHelper<num_addrs, addr_types>); dag AddrIns = nsah.AddrIns; string AddrAsm = nsah.AddrAsm; @@ -672,7 +692,6 @@ class MIMG_Atomic_gfx6789_base <bits<8> op, string asm, RegisterClass data_rc, RegisterClass addr_rc, string dns=""> : MIMG_gfx6789 <op, (outs data_rc:$vdst), dns> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = (ins data_rc:$vdata, addr_rc:$vaddr, SReg_256:$srsrc, DMask:$dmask, UNorm:$unorm, CPol:$cpol, @@ -684,7 +703,6 @@ class MIMG_Atomic_gfx90a_base <bits<8> op, string asm, RegisterClass data_rc, RegisterClass addr_rc, string dns=""> : MIMG_gfx90a <op, (outs getLdStRegisterOperand<data_rc>.ret:$vdst), dns> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = (ins getLdStRegisterOperand<data_rc>.ret:$vdata, addr_rc:$vaddr, SReg_256:$srsrc, @@ -720,7 +738,6 @@ class MIMG_Atomic_gfx10<mimgopc op, string opcode, : MIMG_gfx10<!cast<int>(op.GFX10M), (outs DataRC:$vdst), !if(enableDisasm, "AMDGPU", "")> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = (ins DataRC:$vdata, AddrRC:$vaddr0, SReg_256:$srsrc, DMask:$dmask, Dim:$dim, UNorm:$unorm, CPol:$cpol, @@ -734,7 +751,6 @@ class MIMG_Atomic_nsa_gfx10<mimgopc op, string opcode, : MIMG_nsa_gfx10<!cast<int>(op.GFX10M), (outs DataRC:$vdst), num_addrs, !if(enableDisasm, "AMDGPU", "")> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = !con((ins DataRC:$vdata), AddrIns, @@ -750,7 +766,6 @@ class MIMG_Atomic_gfx11<mimgopc op, string opcode, : MIMG_gfx11<!cast<int>(op.GFX11), (outs DataRC:$vdst), !if(enableDisasm, "AMDGPU", "")> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = (ins DataRC:$vdata, AddrRC:$vaddr0, SReg_256:$srsrc, DMask:$dmask, Dim:$dim, UNorm:$unorm, CPol:$cpol, @@ -764,7 +779,6 @@ class MIMG_Atomic_nsa_gfx11<mimgopc op, string opcode, : MIMG_nsa_gfx11<!cast<int>(op.GFX11), (outs DataRC:$vdst), num_addrs, !if(enableDisasm, "AMDGPU", "")> { let Constraints = "$vdst = $vdata"; - let AsmMatchConverter = "cvtMIMGAtomic"; let InOperandList = !con((ins DataRC:$vdata), AddrIns, @@ -934,8 +948,9 @@ class MIMG_Sampler_gfx11<mimgopc op, string opcode, class MIMG_Sampler_nsa_gfx11<mimgopc op, string opcode, RegisterClass DataRC, int num_addrs, - string dns=""> - : MIMG_nsa_gfx11<op.GFX11, (outs DataRC:$vdata), num_addrs, dns> { + RegisterClass LastVAddrSize, string dns=""> + : MIMG_nsa_gfx11<op.GFX11, (outs DataRC:$vdata), num_addrs, dns, [], + LastVAddrSize> { let InOperandList = !con(AddrIns, (ins SReg_256:$srsrc, SReg_128:$ssamp, DMask:$dmask, Dim:$dim, UNorm:$unorm, CPol:$cpol, @@ -946,29 +961,34 @@ class MIMG_Sampler_nsa_gfx11<mimgopc op, string opcode, #!if(BaseOpcode.HasD16, "$d16", ""); } -class MIMGAddrSize<int dw, bit enable_disasm> { +class MIMGAddrSize<int dw, bit enable_disasm, int AddrDW = dw> { int NumWords = dw; - RegisterClass RegClass = !if(!le(NumWords, 0), ?, - !if(!eq(NumWords, 1), VGPR_32, - !if(!eq(NumWords, 2), VReg_64, - !if(!eq(NumWords, 3), VReg_96, - !if(!eq(NumWords, 4), VReg_128, - !if(!eq(NumWords, 5), VReg_160, - !if(!eq(NumWords, 6), VReg_192, - !if(!eq(NumWords, 7), VReg_224, - !if(!le(NumWords, 8), VReg_256, - !if(!le(NumWords, 9), VReg_288, - !if(!le(NumWords, 10), VReg_320, - !if(!le(NumWords, 11), VReg_352, - !if(!le(NumWords, 12), VReg_384, - !if(!le(NumWords, 16), VReg_512, ?)))))))))))))); + RegisterClass RegClass = !if(!le(AddrDW, 0), ?, + !if(!eq(AddrDW, 1), VGPR_32, + !if(!eq(AddrDW, 2), VReg_64, + !if(!eq(AddrDW, 3), VReg_96, + !if(!eq(AddrDW, 4), VReg_128, + !if(!eq(AddrDW, 5), VReg_160, + !if(!eq(AddrDW, 6), VReg_192, + !if(!eq(AddrDW, 7), VReg_224, + !if(!eq(AddrDW, 8), VReg_256, + !if(!eq(AddrDW, 9), VReg_288, + !if(!eq(AddrDW, 10), VReg_320, + !if(!eq(AddrDW, 11), VReg_352, + !if(!eq(AddrDW, 12), VReg_384, + !if(!le(AddrDW, 16), VReg_512, ?)))))))))))))); // Whether the instruction variant with this vaddr size should be enabled for // the auto-generated disassembler. bit Disassemble = enable_disasm; } +// Returns the MIMGAddrSize with the size of last VAddr for partial NSA +class LastVAddrSize <int dw, int max_idx, bit enable_disasm> + : MIMGAddrSize<dw, enable_disasm, + !if(!gt(dw, max_idx), !sub(dw, max_idx), 0)>; + // Return whether x is in lst. class isIntInList<int x, list<int> lst> { bit ret = !foldl(0, lst, lhs, y, !or(lhs, !eq(x, y))); @@ -985,7 +1005,8 @@ class MIMGAddrSizes_dw_range<list<int> range> { int Max = !if(!empty(!tail(range)), Min, !head(!tail(range))); } -class MIMG_Sampler_AddrSizes<AMDGPUSampleVariant sample, bit isG16> { +class MIMG_Sampler_AddrSizes<AMDGPUSampleVariant sample, bit isG16, + int nsa_max_addr = 5> { // List of all possible numbers of address words, taking all combinations of // A16 and image dimension into account (note: no MSAA, since this is for // sample/gather ops). @@ -1031,6 +1052,21 @@ class MIMG_Sampler_AddrSizes<AMDGPUSampleVariant sample, bit isG16> { !if(isIntInList<dw, AllNumAddrWords>.ret, !listconcat(lhs, [MIMGAddrSize<dw, !empty(lhs)>]), lhs)))); + + // In NSA format if there is a requirement for more VGPRs than the format + // supports, then the rest are sequential after the last one. Generate + // machine instructions for all possible number of words. The disassembler + // defaults to the largest number of arguments but no larger than max nsa + // size. List is generated with the register class needed for last vaddr since + // it is the only one that could have a register other than VGPR32. + int EnableDisasmNum = !foldl(!head(AllNumAddrWords), !tail(AllNumAddrWords), + acc, var, !if(!le(var, nsa_max_addr), var, acc)); + list<LastVAddrSize> PartialNSAInstrs = + !foldl([]<LastVAddrSize>, [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2], lhs, dw, + !if(isIntInList<dw, AllNumAddrWords>.ret, + !listconcat(lhs, [LastVAddrSize<dw, !sub(nsa_max_addr, 1), + !eq(dw, EnableDisasmNum)>]), + lhs)); } multiclass MIMG_Sampler_Src_Helper <mimgopc op, string asm, @@ -1066,9 +1102,14 @@ multiclass MIMG_Sampler_Src_Helper <mimgopc op, string asm, : MIMG_Sampler_nsa_gfx10<op, asm, dst_rc, addr.NumWords, !if(!and(enableDisasm, addr.Disassemble), "AMDGPU", "")>; } - if !and(op.HAS_GFX11, !le(addr.NumWords, 5)) then { + } + } + + foreach addr = MIMG_Sampler_AddrSizes<sample, isG16, 5/*MaxNSASize*/>.PartialNSAInstrs in { + let VAddrDwords = addr.NumWords in { + if op.HAS_GFX11 then { def _V # addr.NumWords # _nsa_gfx11 - : MIMG_Sampler_nsa_gfx11<op, asm, dst_rc, addr.NumWords, + : MIMG_Sampler_nsa_gfx11<op, asm, dst_rc, addr.NumWords, addr.RegClass, !if(!and(enableDisasm, addr.Disassemble), "AMDGPU", "")>; } } @@ -1144,51 +1185,43 @@ class MIMG_IntersectRay_Helper<bit Is64, bit IsA16> { [node_ptr_type, VGPR_32, VReg_96, VReg_96, VReg_96]); } -class MIMG_IntersectRay_gfx10<mimgopc op, string opcode, RegisterClass AddrRC, bit IsA16> +class MIMG_IntersectRay_gfx10<mimgopc op, string opcode, RegisterClass AddrRC> : MIMG_gfx10<op.GFX10M, (outs VReg_128:$vdata), "AMDGPU"> { - - let InOperandList = !con((ins AddrRC:$vaddr0, SReg_128:$srsrc), - !if(IsA16, (ins A16:$a16), (ins))); - let AsmString = opcode#" $vdata, $vaddr0, $srsrc"#!if(IsA16, "$a16", ""); + let InOperandList = (ins AddrRC:$vaddr0, SReg_128:$srsrc, A16:$a16); + let AsmString = opcode#" $vdata, $vaddr0, $srsrc$a16"; let nsa = 0; } -class MIMG_IntersectRay_nsa_gfx10<mimgopc op, string opcode, int num_addrs, bit IsA16> +class MIMG_IntersectRay_nsa_gfx10<mimgopc op, string opcode, int num_addrs> : MIMG_nsa_gfx10<op.GFX10M, (outs VReg_128:$vdata), num_addrs, "AMDGPU"> { - let InOperandList = !con(nsah.AddrIns, - (ins SReg_128:$srsrc), - !if(IsA16, (ins A16:$a16), (ins))); - let AsmString = opcode#" $vdata, "#nsah.AddrAsm#", $srsrc"#!if(IsA16, "$a16", ""); + let InOperandList = !con(nsah.AddrIns, (ins SReg_128:$srsrc, A16:$a16)); + let AsmString = opcode#" $vdata, "#nsah.AddrAsm#", $srsrc$a16"; } -class MIMG_IntersectRay_gfx11<mimgopc op, string opcode, RegisterClass AddrRC, bit IsA16> +class MIMG_IntersectRay_gfx11<mimgopc op, string opcode, RegisterClass AddrRC> : MIMG_gfx11<op.GFX11, (outs VReg_128:$vdata), "AMDGPU"> { - - let InOperandList = !con((ins AddrRC:$vaddr0, SReg_128:$srsrc), - !if(IsA16, (ins A16:$a16), (ins))); - let AsmString = opcode#" $vdata, $vaddr0, $srsrc"#!if(IsA16, "$a16", ""); + let InOperandList = (ins AddrRC:$vaddr0, SReg_128:$srsrc, A16:$a16); + let AsmString = opcode#" $vdata, $vaddr0, $srsrc$a16"; let nsa = 0; } class MIMG_IntersectRay_nsa_gfx11<mimgopc op, string opcode, int num_addrs, - bit IsA16, list<RegisterClass> addr_types> + list<RegisterClass> addr_types> : MIMG_nsa_gfx11<op.GFX11, (outs VReg_128:$vdata), num_addrs, "AMDGPU", addr_types> { - let InOperandList = !con(nsah.AddrIns, - (ins SReg_128:$srsrc), - !if(IsA16, (ins A16:$a16), (ins))); - let AsmString = opcode#" $vdata, "#nsah.AddrAsm#", $srsrc"#!if(IsA16, "$a16", ""); + let InOperandList = !con(nsah.AddrIns, (ins SReg_128:$srsrc, A16:$a16)); + let AsmString = opcode#" $vdata, "#nsah.AddrAsm#", $srsrc$a16"; } multiclass MIMG_IntersectRay<mimgopc op, string opcode, bit Is64, bit IsA16> { defvar info = MIMG_IntersectRay_Helper<Is64, IsA16>; def "" : MIMGBaseOpcode { let BVH = 1; + let A16 = IsA16; } - let AsmMatchConverter = !if(IsA16, "cvtIntersectRay", ""), - dmask = 0xf, + let dmask = 0xf, unorm = 1, d16 = 0, cpol = 0, @@ -1201,17 +1234,17 @@ multiclass MIMG_IntersectRay<mimgopc op, string opcode, bit Is64, bit IsA16> { d16 = 0, BaseOpcode = !cast<MIMGBaseOpcode>(NAME), VDataDwords = 4 in { - def _sa_gfx10 : MIMG_IntersectRay_gfx10<op, opcode, info.RegClass, IsA16> { + def _sa_gfx10 : MIMG_IntersectRay_gfx10<op, opcode, info.RegClass> { let VAddrDwords = info.VAddrDwords; } - def _sa_gfx11 : MIMG_IntersectRay_gfx11<op, opcode, info.RegClass, IsA16> { + def _sa_gfx11 : MIMG_IntersectRay_gfx11<op, opcode, info.RegClass> { let VAddrDwords = info.VAddrDwords; } - def _nsa_gfx10 : MIMG_IntersectRay_nsa_gfx10<op, opcode, info.num_addrs, IsA16> { + def _nsa_gfx10 : MIMG_IntersectRay_nsa_gfx10<op, opcode, info.num_addrs> { let VAddrDwords = info.num_addrs; } def _nsa_gfx11 : MIMG_IntersectRay_nsa_gfx11<op, opcode, - info.gfx11_nsa_addrs, IsA16, + info.gfx11_nsa_addrs, info.gfx11_addr_types> { let VAddrDwords = info.num_addrs; } |