xref: /llvm-project/llvm/lib/Target/AMDGPU/VINTERPInstructions.td (revision 85142f5b3581f0d8466cca8a09bba80dafc63b8c)
1//===-- VINTERPInstructions.td - VINTERP Instruction Definitions ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10// VINTERP encoding
11//===----------------------------------------------------------------------===//
12
13class VINTERPe <VOPProfile P> : Enc64 {
14  bits<11> vdst;
15  bits<4> src0_modifiers;
16  bits<11> src0;
17  bits<3> src1_modifiers;
18  bits<11> src1;
19  bits<3> src2_modifiers;
20  bits<11> src2;
21  bits<1> clamp;
22  bits<3> waitexp;
23
24  let Inst{31-26} = 0x33; // VOP3P encoding
25  let Inst{25-24} = 0x1; // VINTERP sub-encoding
26
27  let Inst{7-0}   = vdst{7-0};
28  let Inst{10-8}  = waitexp;
29  // Fields for hi/lo 16-bits of register selection
30  let Inst{11} = !if(P.HasSrc0, src0_modifiers{2}, 0);
31  let Inst{12} = !if(P.HasSrc1, src1_modifiers{2}, 0);
32  let Inst{13} = !if(P.HasSrc2, src2_modifiers{2}, 0);
33  let Inst{14} = !if(P.HasDst, src0_modifiers{3}, 0);
34  let Inst{15}    = clamp;
35  let Inst{40-32} = src0{8-0};
36  let Inst{49-41} = src1{8-0};
37  let Inst{58-50} = src2{8-0};
38  let Inst{61}    = src0_modifiers{0}; // neg(0)
39  let Inst{62}    = src1_modifiers{0}; // neg(1)
40  let Inst{63}    = src2_modifiers{0}; // neg(2)
41}
42
43class VINTERPe_gfx11 <bits<7> op, VOPProfile P> : VINTERPe<P> {
44  let Inst{22-16} = op;
45}
46
47class VINTERPe_gfx12 <bits<7> op, VOPProfile P> : VINTERPe<P> {
48  let Inst{20-16} = op{4-0};
49}
50
51//===----------------------------------------------------------------------===//
52// VOP3 VINTERP
53//===----------------------------------------------------------------------===//
54
55class VINTERP_Pseudo <string OpName, VOPProfile P, list<dag> pattern = []> :
56  VOP3_Pseudo<OpName, P, pattern, 0, 0> {
57  let AsmMatchConverter = "cvtVINTERP";
58  let mayRaiseFPException = 0;
59
60  let VOP3_OPSEL = 1;
61  let VINTERP = 1;
62}
63
64class VINTERP_Real <VOP_Pseudo ps, int EncodingFamily, string asmName> :
65  VOP3_Real <ps, EncodingFamily, asmName> {
66  let VINTERP = 1;
67  let IsSingle = 1;
68}
69
70def VOP3_VINTERP_F32 : VOPProfile<[f32, f32, f32, f32]> {
71  let HasOpSel = 0;
72  let HasModifiers = 1;
73
74  let Src0Mod = FPVRegInputMods;
75  let Src1Mod = FPVRegInputMods;
76  let Src2Mod = FPVRegInputMods;
77
78  let Outs64 = (outs VGPR_32:$vdst);
79  let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
80                   Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
81                   Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
82                   Clamp:$clamp,
83                   WaitEXP:$waitexp);
84
85  let Asm64 = " $vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$waitexp";
86}
87
88class VOP3_VINTERP_F16_t16 <list<ValueType> ArgVT> : VOPProfile_True16<VOPProfile<ArgVT>> {
89  let Src0Mod = FPT16VRegInputMods</*Fake16*/0>;
90  let Src1Mod = FPVRegInputMods;
91  let Src2Mod = !if(!eq(ArgVT[3].Size, 16), FPT16VRegInputMods</*Fake16*/0>,
92                                            FPVRegInputMods);
93  let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_16:$src0,
94                   Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
95                   Src2Mod:$src2_modifiers,
96                   !if(!eq(ArgVT[3].Size, 16), VRegSrc_16, VRegSrc_32):$src2,
97                   Clamp:$clamp, op_sel0:$op_sel,
98                   WaitEXP:$waitexp);
99
100  let Asm64 = "$vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$op_sel$waitexp";
101}
102
103class VOP3_VINTERP_F16_fake16 <list<ValueType> ArgVT> : VOPProfile_Fake16<VOPProfile<ArgVT>> {
104  let Src0Mod = FPT16VRegInputMods</*Fake16*/1>;
105  let Src1Mod = FPVRegInputMods;
106  let Src2Mod = !if(!eq(ArgVT[3].Size, 16), FPT16VRegInputMods</*Fake16*/1>,
107                                            FPVRegInputMods);
108
109  let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_fake16:$src0,
110                   Src1Mod:$src1_modifiers, VRegSrc_32:$src1,
111                   Src2Mod:$src2_modifiers,
112                   !if(!eq(ArgVT[3].Size, 16), VRegSrc_fake16, VRegSrc_32):$src2,
113                   Clamp:$clamp, op_sel0:$op_sel,
114                   WaitEXP:$waitexp);
115
116  let Asm64 = "$vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$op_sel$waitexp";
117}
118
119//===----------------------------------------------------------------------===//
120// VINTERP Pseudo Instructions
121//===----------------------------------------------------------------------===//
122
123let SubtargetPredicate = HasVINTERPEncoding in {
124
125multiclass VINTERP_t16<string OpName, list<ValueType> ArgVT> {
126  let True16Predicate = UseRealTrue16Insts in {
127    def _t16 : VINTERP_Pseudo<OpName#"_t16", VOP3_VINTERP_F16_t16<ArgVT>> ;
128  }
129  let True16Predicate = UseFakeTrue16Insts in {
130    def _fake16 : VINTERP_Pseudo<OpName#"_fake16", VOP3_VINTERP_F16_fake16<ArgVT>> ;
131  }
132}
133
134let Uses = [M0, EXEC, MODE] in {
135def V_INTERP_P10_F32_inreg : VINTERP_Pseudo <"v_interp_p10_f32", VOP3_VINTERP_F32>;
136def V_INTERP_P2_F32_inreg : VINTERP_Pseudo <"v_interp_p2_f32", VOP3_VINTERP_F32>;
137
138defm V_INTERP_P10_F16_F32_inreg : VINTERP_t16<"v_interp_p10_f16_f32", [f32, f16, f32, f16]>;
139defm V_INTERP_P2_F16_F32_inreg : VINTERP_t16<"v_interp_p2_f16_f32", [f16, f16, f32, f32]>;
140} // Uses = [M0, EXEC, MODE]
141
142let Uses = [M0, EXEC] in {
143defm V_INTERP_P10_RTZ_F16_F32_inreg : VINTERP_t16<"v_interp_p10_rtz_f16_f32", [f32, f16, f32, f16]>;
144defm V_INTERP_P2_RTZ_F16_F32_inreg : VINTERP_t16 <"v_interp_p2_rtz_f16_f32", [f16, f16, f32, f32]>;
145} // Uses = [M0, EXEC]
146
147} // SubtargetPredicate = HasVINTERPEncoding.
148
149class VInterpF32Pat <SDPatternOperator op, Instruction inst> : GCNPat <
150   (f32 (op
151      (VINTERPMods f32:$src0, i32:$src0_modifiers),
152      (VINTERPMods f32:$src1, i32:$src1_modifiers),
153      (VINTERPMods f32:$src2, i32:$src2_modifiers))),
154    (inst $src0_modifiers, $src0,
155          $src1_modifiers, $src1,
156          $src2_modifiers, $src2,
157          0, /* clamp */
158          7) /* wait_exp */
159>;
160
161class VInterpF16Pat <SDPatternOperator op, Instruction inst,
162                     ValueType dst_type, bit high,
163                     list<ComplexPattern> pat> : GCNPat <
164   (dst_type (op
165      (pat[0] f32:$src0, i32:$src0_modifiers),
166      (pat[1] f32:$src1, i32:$src1_modifiers),
167      (pat[2] f32:$src2, i32:$src2_modifiers),
168      !if(high, (i1 -1), (i1 0)))),
169    (inst $src0_modifiers, $src0,
170          $src1_modifiers, $src1,
171          $src2_modifiers, $src2,
172          0, /* clamp */
173          /* op_sel = 0 */
174          7) /* wait_exp */
175>;
176
177multiclass VInterpF16Pat <SDPatternOperator op, Instruction inst,
178                          ValueType dst_type, list<ComplexPattern> high_pat> {
179  def : VInterpF16Pat<op, inst, dst_type, 0,
180                      [VINTERPMods, VINTERPMods, VINTERPMods]>;
181  def : VInterpF16Pat<op, inst, dst_type, 1, high_pat>;
182}
183
184class VInterpF16Pat_t16 <SDPatternOperator op, Instruction inst,
185                     ValueType dstVT, bit high, bit isP2> : GCNPat <
186   (dstVT (op
187      (VINTERPMods f32:$src0, i32:$src0_modifiers),
188      (VINTERPMods f32:$src1, i32:$src1_modifiers),
189      (VINTERPMods f32:$src2, i32:$src2_modifiers),
190      !if(high, (i1 -1), (i1 0)))),
191    (inst $src0_modifiers,
192          (f16 (EXTRACT_SUBREG VGPR_32:$src0, !if(high, hi16, lo16))),
193          $src1_modifiers, VGPR_32:$src1,
194          $src2_modifiers,
195          !if(isP2, (f32 VGPR_32:$src2),
196                    (f16 (EXTRACT_SUBREG VGPR_32:$src2, !if(high, hi16, lo16)))),
197          0, /* clamp */
198          7) /* wait_exp */
199>;
200
201multiclass VInterpF16Pat_t16 <SDPatternOperator op, Instruction inst,
202                          ValueType dstVT, bit isP2> {
203  def : VInterpF16Pat_t16<op, inst, dstVT, 0, isP2>;
204  def : VInterpF16Pat_t16<op, inst, dstVT, 1, isP2>;
205}
206
207def : VInterpF32Pat<int_amdgcn_interp_inreg_p10, V_INTERP_P10_F32_inreg>;
208def : VInterpF32Pat<int_amdgcn_interp_inreg_p2, V_INTERP_P2_F32_inreg>;
209
210let True16Predicate = UseRealTrue16Insts in {
211defm : VInterpF16Pat_t16<int_amdgcn_interp_inreg_p10_f16,
212                     V_INTERP_P10_F16_F32_inreg_t16, f32, 0>;
213defm : VInterpF16Pat_t16<int_amdgcn_interp_inreg_p2_f16,
214                     V_INTERP_P2_F16_F32_inreg_t16, f16, 1>;
215defm : VInterpF16Pat_t16<int_amdgcn_interp_p10_rtz_f16,
216                     V_INTERP_P10_RTZ_F16_F32_inreg_t16, f32, 0>;
217defm : VInterpF16Pat_t16<int_amdgcn_interp_p2_rtz_f16,
218                     V_INTERP_P2_RTZ_F16_F32_inreg_t16, f16, 1>;
219}
220
221let True16Predicate = UseFakeTrue16Insts in {
222defm : VInterpF16Pat<int_amdgcn_interp_inreg_p10_f16,
223                     V_INTERP_P10_F16_F32_inreg_fake16, f32,
224                     [VINTERPModsHi, VINTERPMods, VINTERPModsHi]>;
225defm : VInterpF16Pat<int_amdgcn_interp_inreg_p2_f16,
226                     V_INTERP_P2_F16_F32_inreg_fake16, f16,
227                     [VINTERPModsHi, VINTERPMods, VINTERPMods]>;
228defm : VInterpF16Pat<int_amdgcn_interp_p10_rtz_f16,
229                     V_INTERP_P10_RTZ_F16_F32_inreg_fake16, f32,
230                     [VINTERPModsHi, VINTERPMods, VINTERPModsHi]>;
231defm : VInterpF16Pat<int_amdgcn_interp_p2_rtz_f16,
232                     V_INTERP_P2_RTZ_F16_F32_inreg_fake16, f16,
233                     [VINTERPModsHi, VINTERPMods, VINTERPMods]>;
234}
235
236//===----------------------------------------------------------------------===//
237// VINTERP Real Instructions
238//===----------------------------------------------------------------------===//
239
240multiclass VINTERP_Real_gfx11 <bits<7> op, string asmName> {
241  defvar ps = !cast<VOP3_Pseudo>(NAME);
242  let AssemblerPredicate = isGFX11Only, DecoderNamespace = "GFX11" #
243                           !if(ps.Pfl.IsRealTrue16, "", "_FAKE16") in {
244    def _gfx11 :
245      VINTERP_Real<ps, SIEncodingFamily.GFX11, asmName>,
246      VINTERPe_gfx11<op, ps.Pfl>;
247  }
248}
249
250multiclass VINTERP_Real_gfx12 <bits<7> op, string asmName> {
251  defvar ps = !cast<VOP3_Pseudo>(NAME);
252  let AssemblerPredicate = isGFX12Only, DecoderNamespace = "GFX12" #
253                           !if(ps.Pfl.IsRealTrue16, "", "_FAKE16") in {
254    def _gfx12 :
255      VINTERP_Real<ps, SIEncodingFamily.GFX12, asmName>,
256      VINTERPe_gfx12<op, ps.Pfl>;
257  }
258}
259
260multiclass VINTERP_Real_gfx11_gfx12 <bits<7> op, string asmName = !cast<VOP3_Pseudo>(NAME).Mnemonic> :
261  VINTERP_Real_gfx11<op, asmName>, VINTERP_Real_gfx12<op, asmName>;
262
263multiclass VINTERP_Real_t16_and_fake16_gfx11_gfx12 <bits<7> op, string asmName = !cast<VOP3_Pseudo>(NAME).Mnemonic> {
264  defm _t16:    VINTERP_Real_gfx11_gfx12<op, asmName>;
265  defm _fake16: VINTERP_Real_gfx11_gfx12<op, asmName>;
266}
267
268
269defm V_INTERP_P10_F32_inreg : VINTERP_Real_gfx11_gfx12<0x000>;
270defm V_INTERP_P2_F32_inreg : VINTERP_Real_gfx11_gfx12<0x001>;
271defm V_INTERP_P10_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x002, "v_interp_p10_f16_f32">;
272defm V_INTERP_P2_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x003, "v_interp_p2_f16_f32">;
273defm V_INTERP_P10_RTZ_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x004, "v_interp_p10_rtz_f16_f32">;
274defm V_INTERP_P2_RTZ_F16_F32_inreg : VINTERP_Real_t16_and_fake16_gfx11_gfx12<0x005, "v_interp_p2_rtz_f16_f32">;
275
276let AssemblerPredicate = isGFX11Plus in
277def : AMDGPUMnemonicAlias<"v_interp_p2_new_f32", "v_interp_p2_f32">;
278