1//===-- VOP3Instructions.td - Vector Instruction Defintions ---------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10//===----------------------------------------------------------------------===//
11// VOP3 Classes
12//===----------------------------------------------------------------------===//
13
14class getVOP3ModPat<VOPProfile P, SDPatternOperator node> {
15  dag src0 = !if(P.HasOMod,
16    (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod),
17    (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp));
18
19  list<dag> ret3 = [(set P.DstVT:$vdst,
20    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0),
21          (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
22          (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers))))];
23
24  list<dag> ret2 = [(set P.DstVT:$vdst,
25    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0),
26          (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers))))];
27
28  list<dag> ret1 = [(set P.DstVT:$vdst,
29    (DivergentFragOrOp<node, P>.ret (P.Src0VT src0)))];
30
31  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
32                  !if(!eq(P.NumSrcArgs, 2), ret2,
33                  ret1));
34}
35
36class getVOP3PModPat<VOPProfile P, SDPatternOperator node> {
37  list<dag> ret3 = [(set P.DstVT:$vdst,
38    (DivergentFragOrOp<node, P>.ret (P.Src0VT !if(P.HasClamp, (VOP3PMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp),
39                                    (VOP3PMods P.Src0VT:$src0, i32:$src0_modifiers))),
40          (P.Src1VT (VOP3PMods P.Src1VT:$src1, i32:$src1_modifiers)),
41          (P.Src2VT (VOP3PMods P.Src2VT:$src2, i32:$src2_modifiers))))];
42
43  list<dag> ret2 = [(set P.DstVT:$vdst,
44    (DivergentFragOrOp<node, P>.ret !if(P.HasClamp, (P.Src0VT (VOP3PMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)),
45                          (P.Src0VT (VOP3PMods P.Src0VT:$src0, i32:$src0_modifiers))),
46          (P.Src1VT (VOP3PMods P.Src1VT:$src1, i32:$src1_modifiers))))];
47
48  list<dag> ret1 = [(set P.DstVT:$vdst,
49    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3PMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp))))];
50
51  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
52                  !if(!eq(P.NumSrcArgs, 2), ret2,
53                  ret1));
54}
55
56class getVOP3OpSelPat<VOPProfile P, SDPatternOperator node> {
57  list<dag> ret3 = [(set P.DstVT:$vdst,
58    (DivergentFragOrOp<node, P>.ret (P.Src0VT !if(P.HasClamp, (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp),
59                                    (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))),
60          (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers)),
61          (P.Src2VT (VOP3OpSel P.Src2VT:$src2, i32:$src2_modifiers))))];
62
63  list<dag> ret2 = [(set P.DstVT:$vdst,
64    (DivergentFragOrOp<node, P>.ret !if(P.HasClamp, (P.Src0VT (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)),
65                          (P.Src0VT (VOP3OpSel P.Src0VT:$src0, i32:$src0_modifiers))),
66          (P.Src1VT (VOP3OpSel P.Src1VT:$src1, i32:$src1_modifiers))))];
67
68  list<dag> ret1 = [(set P.DstVT:$vdst,
69    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSel0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp))))];
70
71  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
72                  !if(!eq(P.NumSrcArgs, 2), ret2,
73                  ret1));
74}
75
76class getVOP3OpSelModPat<VOPProfile P, SDPatternOperator node> {
77  list<dag> ret3 = [(set P.DstVT:$vdst,
78    (DivergentFragOrOp<node, P>.ret (P.Src0VT !if(P.HasClamp, (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp),
79                                    (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
80          (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers)),
81          (P.Src2VT (VOP3OpSelMods P.Src2VT:$src2, i32:$src2_modifiers))))];
82
83  list<dag> ret2 = [(set P.DstVT:$vdst,
84    (DivergentFragOrOp<node, P>.ret !if(P.HasClamp, (P.Src0VT (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp)),
85                          (P.Src0VT (VOP3OpSelMods P.Src0VT:$src0, i32:$src0_modifiers))),
86          (P.Src1VT (VOP3OpSelMods P.Src1VT:$src1, i32:$src1_modifiers))))];
87
88  list<dag> ret1 = [(set P.DstVT:$vdst,
89    (DivergentFragOrOp<node, P>.ret (P.Src0VT (VOP3OpSelMods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp))))];
90
91  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
92                  !if(!eq(P.NumSrcArgs, 2), ret2,
93                  ret1));
94}
95
96class getVOP3Pat<VOPProfile P, SDPatternOperator node> {
97  list<dag> ret3 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2))];
98  list<dag> ret2 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0, P.Src1VT:$src1))];
99  list<dag> ret1 = [(set P.DstVT:$vdst, (DivergentFragOrOp<node, P>.ret P.Src0VT:$src0))];
100  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
101                  !if(!eq(P.NumSrcArgs, 2), ret2,
102                  ret1));
103}
104
105class getVOP3ClampPat<VOPProfile P, SDPatternOperator node> {
106  list<dag> ret3 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, i1:$clamp))];
107  list<dag> ret2 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, P.Src1VT:$src1, i1:$clamp))];
108  list<dag> ret1 = [(set P.DstVT:$vdst, (node P.Src0VT:$src0, i1:$clamp))];
109  list<dag> ret = !if(!eq(P.NumSrcArgs, 3), ret3,
110                  !if(!eq(P.NumSrcArgs, 2), ret2,
111                  ret1));
112}
113
114class VOP3Inst<string OpName, VOPProfile P, SDPatternOperator node = null_frag, bit VOP3Only = 0> :
115  VOP3_Pseudo<OpName, P,
116    !if(P.HasOpSel,
117        !if(P.HasModifiers,
118            getVOP3OpSelModPat<P, node>.ret,
119            getVOP3OpSelPat<P, node>.ret),
120        !if(P.HasModifiers,
121            getVOP3ModPat<P, node>.ret,
122            !if(P.HasIntClamp,
123                getVOP3ClampPat<P, node>.ret,
124                getVOP3Pat<P, node>.ret))),
125    VOP3Only, 0, P.HasOpSel> {
126
127  let IntClamp = P.HasIntClamp;
128  let AsmMatchConverter =
129    !if(P.HasOpSel,
130        "cvtVOP3OpSel",
131        !if(!or(P.HasModifiers, !or(P.HasOMod, P.HasIntClamp)),
132            "cvtVOP3",
133            ""));
134}
135
136// Special case for v_div_fmas_{f32|f64}, since it seems to be the
137// only VOP instruction that implicitly reads VCC.
138let Asm64 = " $vdst, $src0_modifiers, $src1_modifiers, $src2_modifiers$clamp$omod" in {
139def VOP_F32_F32_F32_F32_VCC : VOPProfile<[f32, f32, f32, f32]> {
140  let Outs64 = (outs DstRC.RegClass:$vdst);
141}
142def VOP_F64_F64_F64_F64_VCC : VOPProfile<[f64, f64, f64, f64]> {
143  let Outs64 = (outs DstRC.RegClass:$vdst);
144}
145}
146
147class getVOP3VCC<VOPProfile P, SDPatternOperator node> {
148  list<dag> ret =
149    [(set P.DstVT:$vdst,
150      (node (P.Src0VT (VOP3Mods0 P.Src0VT:$src0, i32:$src0_modifiers, i1:$clamp, i32:$omod)),
151            (P.Src1VT (VOP3Mods P.Src1VT:$src1, i32:$src1_modifiers)),
152            (P.Src2VT (VOP3Mods P.Src2VT:$src2, i32:$src2_modifiers)),
153            (i1 VCC)))];
154}
155
156class VOP3Features<bit Clamp, bit OpSel, bit Packed> {
157  bit HasClamp = Clamp;
158  bit HasOpSel = OpSel;
159  bit IsPacked = Packed;
160}
161
162def VOP3_REGULAR : VOP3Features<0, 0, 0>;
163def VOP3_CLAMP   : VOP3Features<1, 0, 0>;
164def VOP3_OPSEL   : VOP3Features<1, 1, 0>;
165def VOP3_PACKED  : VOP3Features<1, 1, 1>;
166
167class VOP3_Profile<VOPProfile P, VOP3Features Features = VOP3_REGULAR> : VOPProfile<P.ArgVT> {
168
169  let HasClamp = !if(Features.HasClamp, 1, P.HasClamp);
170  let HasOpSel = !if(Features.HasOpSel, 1, P.HasOpSel);
171  let IsPacked = !if(Features.IsPacked, 1, P.IsPacked);
172
173  let HasModifiers = !if(Features.IsPacked, 1, P.HasModifiers);
174
175  // FIXME: Hack to stop printing _e64
176  let Outs64 = (outs DstRC.RegClass:$vdst);
177  let Asm64 =
178    " " # !if(Features.HasOpSel,
179              getAsmVOP3OpSel<NumSrcArgs,
180                              HasIntClamp,
181                              HasSrc0FloatMods,
182                              HasSrc1FloatMods,
183                              HasSrc2FloatMods>.ret,
184              !if(Features.HasClamp,
185                  getAsm64<HasDst, NumSrcArgs, HasIntClamp,
186                           HasModifiers, HasOMod, DstVT>.ret,
187                  P.Asm64));
188  let NeedPatGen = P.NeedPatGen;
189}
190
191class VOP3b_Profile<ValueType vt> : VOPProfile<[vt, vt, vt, vt]> {
192  // v_div_scale_{f32|f64} do not support input modifiers.
193  let HasModifiers = 0;
194  let HasOMod = 0;
195  let Outs64 = (outs DstRC:$vdst, SReg_64:$sdst);
196  let Asm64 = " $vdst, $sdst, $src0, $src1, $src2";
197}
198
199def VOP3b_F32_I1_F32_F32_F32 : VOP3b_Profile<f32> {
200  // FIXME: Hack to stop printing _e64
201  let DstRC = RegisterOperand<VGPR_32>;
202}
203
204def VOP3b_F64_I1_F64_F64_F64 : VOP3b_Profile<f64> {
205  // FIXME: Hack to stop printing _e64
206  let DstRC = RegisterOperand<VReg_64>;
207}
208
209def VOP3b_I64_I1_I32_I32_I64 : VOPProfile<[i64, i32, i32, i64]> {
210  let HasClamp = 1;
211
212  // FIXME: Hack to stop printing _e64
213  let DstRC = RegisterOperand<VReg_64>;
214
215  let Outs64 = (outs DstRC:$vdst, SReg_64:$sdst);
216  let Asm64 = " $vdst, $sdst, $src0, $src1, $src2$clamp";
217}
218
219//===----------------------------------------------------------------------===//
220// VOP3 INTERP
221//===----------------------------------------------------------------------===//
222
223class VOP3Interp<string OpName, VOPProfile P, list<dag> pattern = []> :
224                 VOP3_Pseudo<OpName, P, pattern> {
225  let AsmMatchConverter = "cvtVOP3Interp";
226}
227
228def VOP3_INTERP : VOPProfile<[f32, f32, i32, untyped]> {
229  let Ins64 = (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
230                   Attr:$attr, AttrChan:$attrchan,
231                   clampmod:$clamp, omod:$omod);
232
233  let Asm64 = "$vdst, $src0_modifiers, $attr$attrchan$clamp$omod";
234}
235
236def VOP3_INTERP_MOV : VOPProfile<[f32, i32, i32, untyped]> {
237  let Ins64 = (ins InterpSlot:$src0,
238                   Attr:$attr, AttrChan:$attrchan,
239                   clampmod:$clamp, omod:$omod);
240
241  let Asm64 = "$vdst, $src0, $attr$attrchan$clamp$omod";
242
243  let HasClamp = 1;
244}
245
246class getInterp16Asm <bit HasSrc2, bit HasOMod> {
247  string src2 = !if(HasSrc2, ", $src2_modifiers", "");
248  string omod = !if(HasOMod, "$omod", "");
249  string ret =
250    " $vdst, $src0_modifiers, $attr$attrchan"#src2#"$high$clamp"#omod;
251}
252
253class getInterp16Ins <bit HasSrc2, bit HasOMod,
254                      Operand Src0Mod, Operand Src2Mod> {
255  dag ret = !if(HasSrc2,
256                !if(HasOMod,
257                    (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
258                         Attr:$attr, AttrChan:$attrchan,
259                         Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
260                         highmod:$high, clampmod:$clamp, omod:$omod),
261                    (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
262                         Attr:$attr, AttrChan:$attrchan,
263                         Src2Mod:$src2_modifiers, VRegSrc_32:$src2,
264                         highmod:$high, clampmod:$clamp)
265                ),
266                (ins Src0Mod:$src0_modifiers, VRegSrc_32:$src0,
267                     Attr:$attr, AttrChan:$attrchan,
268                     highmod:$high, clampmod:$clamp, omod:$omod)
269            );
270}
271
272class VOP3_INTERP16 <list<ValueType> ArgVT> : VOPProfile<ArgVT> {
273
274  let HasOMod = !if(!eq(DstVT.Value, f16.Value), 0, 1);
275  let HasHigh = 1;
276
277  let Outs64 = (outs VGPR_32:$vdst);
278  let Ins64 = getInterp16Ins<HasSrc2, HasOMod, Src0Mod, Src2Mod>.ret;
279  let Asm64 = getInterp16Asm<HasSrc2, HasOMod>.ret;
280}
281
282//===----------------------------------------------------------------------===//
283// VOP3 Instructions
284//===----------------------------------------------------------------------===//
285
286let isCommutable = 1 in {
287
288def V_MAD_LEGACY_F32 : VOP3Inst <"v_mad_legacy_f32", VOP3_Profile<VOP_F32_F32_F32_F32>>;
289def V_MAD_F32 : VOP3Inst <"v_mad_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, fmad>;
290def V_MAD_I32_I24 : VOP3Inst <"v_mad_i32_i24", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
291def V_MAD_U32_U24 : VOP3Inst <"v_mad_u32_u24", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
292def V_FMA_F32 : VOP3Inst <"v_fma_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, fma>;
293def V_LERP_U8 : VOP3Inst <"v_lerp_u8", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_lerp>;
294
295let SchedRW = [WriteDoubleAdd] in {
296let FPDPRounding = 1 in {
297def V_FMA_F64 : VOP3Inst <"v_fma_f64", VOP3_Profile<VOP_F64_F64_F64_F64>, fma>;
298def V_ADD_F64 : VOP3Inst <"v_add_f64", VOP3_Profile<VOP_F64_F64_F64>, fadd, 1>;
299def V_MUL_F64 : VOP3Inst <"v_mul_f64", VOP3_Profile<VOP_F64_F64_F64>, fmul, 1>;
300} // End FPDPRounding = 1
301def V_MIN_F64 : VOP3Inst <"v_min_f64", VOP3_Profile<VOP_F64_F64_F64>, fminnum_like, 1>;
302def V_MAX_F64 : VOP3Inst <"v_max_f64", VOP3_Profile<VOP_F64_F64_F64>, fmaxnum_like, 1>;
303} // End SchedRW = [WriteDoubleAdd]
304
305let SchedRW = [WriteQuarterRate32] in {
306def V_MUL_LO_U32 : VOP3Inst <"v_mul_lo_u32", VOP3_Profile<VOP_I32_I32_I32>>;
307def V_MUL_HI_U32 : VOP3Inst <"v_mul_hi_u32", VOP3_Profile<VOP_I32_I32_I32>, mulhu>;
308def V_MUL_LO_I32 : VOP3Inst <"v_mul_lo_i32", VOP3_Profile<VOP_I32_I32_I32>>;
309def V_MUL_HI_I32 : VOP3Inst <"v_mul_hi_i32", VOP3_Profile<VOP_I32_I32_I32>, mulhs>;
310} // End SchedRW = [WriteQuarterRate32]
311
312let Uses = [VCC, EXEC] in {
313// v_div_fmas_f32:
314//   result = src0 * src1 + src2
315//   if (vcc)
316//     result *= 2^32
317//
318def V_DIV_FMAS_F32 : VOP3_Pseudo <"v_div_fmas_f32", VOP_F32_F32_F32_F32_VCC,
319  getVOP3VCC<VOP_F32_F32_F32_F32_VCC, AMDGPUdiv_fmas>.ret> {
320  let SchedRW = [WriteFloatFMA];
321}
322// v_div_fmas_f64:
323//   result = src0 * src1 + src2
324//   if (vcc)
325//     result *= 2^64
326//
327def V_DIV_FMAS_F64 : VOP3_Pseudo <"v_div_fmas_f64", VOP_F64_F64_F64_F64_VCC,
328  getVOP3VCC<VOP_F64_F64_F64_F64_VCC, AMDGPUdiv_fmas>.ret> {
329  let SchedRW = [WriteDouble];
330  let FPDPRounding = 1;
331}
332} // End Uses = [VCC, EXEC]
333
334} // End isCommutable = 1
335
336def V_CUBEID_F32 : VOP3Inst <"v_cubeid_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, int_amdgcn_cubeid>;
337def V_CUBESC_F32 : VOP3Inst <"v_cubesc_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, int_amdgcn_cubesc>;
338def V_CUBETC_F32 : VOP3Inst <"v_cubetc_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, int_amdgcn_cubetc>;
339def V_CUBEMA_F32 : VOP3Inst <"v_cubema_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, int_amdgcn_cubema>;
340def V_BFE_U32 : VOP3Inst <"v_bfe_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUbfe_u32>;
341def V_BFE_I32 : VOP3Inst <"v_bfe_i32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUbfe_i32>;
342def V_BFI_B32 : VOP3Inst <"v_bfi_b32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUbfi>;
343def V_ALIGNBIT_B32 : VOP3Inst <"v_alignbit_b32", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_alignbit>;
344def V_ALIGNBYTE_B32 : VOP3Inst <"v_alignbyte_b32", VOP3_Profile<VOP_I32_I32_I32_I32>, int_amdgcn_alignbyte>;
345def V_MIN3_F32 : VOP3Inst <"v_min3_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUfmin3>;
346def V_MIN3_I32 : VOP3Inst <"v_min3_i32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUsmin3>;
347def V_MIN3_U32 : VOP3Inst <"v_min3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUumin3>;
348def V_MAX3_F32 : VOP3Inst <"v_max3_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUfmax3>;
349def V_MAX3_I32 : VOP3Inst <"v_max3_i32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUsmax3>;
350def V_MAX3_U32 : VOP3Inst <"v_max3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUumax3>;
351def V_MED3_F32 : VOP3Inst <"v_med3_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUfmed3>;
352def V_MED3_I32 : VOP3Inst <"v_med3_i32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUsmed3>;
353def V_MED3_U32 : VOP3Inst <"v_med3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUumed3>;
354def V_SAD_U8 : VOP3Inst <"v_sad_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
355def V_SAD_HI_U8 : VOP3Inst <"v_sad_hi_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
356def V_SAD_U16 : VOP3Inst <"v_sad_u16", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
357def V_SAD_U32 : VOP3Inst <"v_sad_u32", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
358def V_CVT_PK_U8_F32 : VOP3Inst<"v_cvt_pk_u8_f32", VOP3_Profile<VOP_I32_F32_I32_I32>, int_amdgcn_cvt_pk_u8_f32>;
359def V_DIV_FIXUP_F32 : VOP3Inst <"v_div_fixup_f32", VOP3_Profile<VOP_F32_F32_F32_F32>, AMDGPUdiv_fixup>;
360
361let SchedRW = [WriteDoubleAdd], FPDPRounding = 1 in {
362def V_DIV_FIXUP_F64 : VOP3Inst <"v_div_fixup_f64", VOP3_Profile<VOP_F64_F64_F64_F64>, AMDGPUdiv_fixup>;
363def V_LDEXP_F64 : VOP3Inst <"v_ldexp_f64", VOP3_Profile<VOP_F64_F64_I32>, AMDGPUldexp, 1>;
364} // End SchedRW = [WriteDoubleAdd], FPDPRounding = 1
365
366def V_DIV_SCALE_F32 : VOP3_Pseudo <"v_div_scale_f32", VOP3b_F32_I1_F32_F32_F32, [], 1> {
367  let SchedRW = [WriteFloatFMA, WriteSALU];
368  let AsmMatchConverter = "";
369}
370
371// Double precision division pre-scale.
372def V_DIV_SCALE_F64 : VOP3_Pseudo <"v_div_scale_f64", VOP3b_F64_I1_F64_F64_F64, [], 1> {
373  let SchedRW = [WriteDouble, WriteSALU];
374  let AsmMatchConverter = "";
375  let FPDPRounding = 1;
376}
377
378def V_MSAD_U8 : VOP3Inst <"v_msad_u8", VOP3_Profile<VOP_I32_I32_I32_I32, VOP3_CLAMP>>;
379
380let Constraints = "@earlyclobber $vdst" in {
381def V_MQSAD_PK_U16_U8 : VOP3Inst <"v_mqsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64, VOP3_CLAMP>>;
382} // End Constraints = "@earlyclobber $vdst"
383
384def V_TRIG_PREOP_F64 : VOP3Inst <"v_trig_preop_f64", VOP3_Profile<VOP_F64_F64_I32>, AMDGPUtrig_preop> {
385  let SchedRW = [WriteDouble];
386}
387
388let SchedRW = [Write64Bit] in {
389// These instructions only exist on SI and CI
390let SubtargetPredicate = isSICI, Predicates = [isSICI] in {
391def V_LSHL_B64 : VOP3Inst <"v_lshl_b64", VOP3_Profile<VOP_PAT_GEN<VOP_I64_I64_I32>>, shl>;
392def V_LSHR_B64 : VOP3Inst <"v_lshr_b64", VOP3_Profile<VOP_PAT_GEN<VOP_I64_I64_I32>>, srl>;
393def V_ASHR_I64 : VOP3Inst <"v_ashr_i64", VOP3_Profile<VOP_PAT_GEN<VOP_I64_I64_I32>>, sra>;
394def V_MULLIT_F32 : VOP3Inst <"v_mullit_f32", VOP3_Profile<VOP_F32_F32_F32_F32>>;
395} // End SubtargetPredicate = isSICI, Predicates = [isSICI]
396
397let SubtargetPredicate = isVI in {
398def V_LSHLREV_B64 : VOP3Inst <"v_lshlrev_b64", VOP3_Profile<VOP_I64_I32_I64>>;
399def V_LSHRREV_B64 : VOP3Inst <"v_lshrrev_b64", VOP3_Profile<VOP_I64_I32_I64>>;
400def V_ASHRREV_I64 : VOP3Inst <"v_ashrrev_i64", VOP3_Profile<VOP_I64_I32_I64>>;
401} // End SubtargetPredicate = isVI
402} // End SchedRW = [Write64Bit]
403
404let Predicates = [isVI] in {
405def : GCNPat <
406 (getDivergentFrag<shl>.ret i64:$x, i32:$y),
407 (V_LSHLREV_B64 $y, $x)
408>;
409def : AMDGPUPat <
410 (getDivergentFrag<srl>.ret i64:$x, i32:$y),
411 (V_LSHRREV_B64 $y, $x)
412>;
413def : AMDGPUPat <
414 (getDivergentFrag<sra>.ret i64:$x, i32:$y),
415 (V_ASHRREV_I64 $y, $x)
416>;
417}
418
419
420let SubtargetPredicate = isCIVI in {
421
422let Constraints = "@earlyclobber $vdst", SchedRW = [WriteQuarterRate32] in {
423def V_QSAD_PK_U16_U8 : VOP3Inst <"v_qsad_pk_u16_u8", VOP3_Profile<VOP_I64_I64_I32_I64, VOP3_CLAMP>>;
424def V_MQSAD_U32_U8 : VOP3Inst <"v_mqsad_u32_u8", VOP3_Profile<VOP_V4I32_I64_I32_V4I32, VOP3_CLAMP>>;
425} // End Constraints = "@earlyclobber $vdst", SchedRW = [WriteQuarterRate32]
426
427let isCommutable = 1 in {
428let SchedRW = [WriteQuarterRate32, WriteSALU] in {
429def V_MAD_U64_U32 : VOP3Inst <"v_mad_u64_u32", VOP3b_I64_I1_I32_I32_I64>;
430def V_MAD_I64_I32 : VOP3Inst <"v_mad_i64_i32", VOP3b_I64_I1_I32_I32_I64>;
431} // End SchedRW = [WriteDouble, WriteSALU]
432} // End isCommutable = 1
433
434} // End SubtargetPredicate = isCIVI
435
436
437def V_DIV_FIXUP_F16 : VOP3Inst <"v_div_fixup_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, AMDGPUdiv_fixup> {
438  let Predicates = [Has16BitInsts, isVIOnly];
439  let FPDPRounding = 1;
440}
441def V_DIV_FIXUP_F16_gfx9 : VOP3Inst <"v_div_fixup_f16_gfx9",
442                                      VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUdiv_fixup> {
443  let renamedInGFX9 = 1;
444  let Predicates = [Has16BitInsts, isGFX9];
445  let FPDPRounding = 1;
446}
447
448def V_FMA_F16 : VOP3Inst <"v_fma_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fma> {
449  let Predicates = [Has16BitInsts, isVIOnly];
450  let FPDPRounding = 1;
451}
452def V_FMA_F16_gfx9 : VOP3Inst <"v_fma_f16_gfx9", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, fma> {
453  let renamedInGFX9 = 1;
454  let Predicates = [Has16BitInsts, isGFX9];
455  let FPDPRounding = 1;
456}
457
458let SubtargetPredicate = Has16BitInsts, isCommutable = 1 in {
459
460let renamedInGFX9 = 1 in {
461def V_MAD_U16 : VOP3Inst <"v_mad_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_CLAMP>>;
462def V_MAD_I16 : VOP3Inst <"v_mad_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_CLAMP>>;
463let FPDPRounding = 1 in {
464def V_MAD_F16 : VOP3Inst <"v_mad_f16", VOP3_Profile<VOP_F16_F16_F16_F16>, fmad>;
465let Uses = [M0, EXEC] in {
466def V_INTERP_P2_F16 : VOP3Interp <"v_interp_p2_f16", VOP3_INTERP16<[f16, f32, i32, f32]>>;
467} // End Uses = [M0, EXEC]
468} // End FPDPRounding = 1
469} // End renamedInGFX9 = 1
470
471let SubtargetPredicate = isGFX9 in {
472def V_MAD_F16_gfx9   : VOP3Inst <"v_mad_f16_gfx9", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>> {
473  let FPDPRounding = 1;
474}
475def V_MAD_U16_gfx9   : VOP3Inst <"v_mad_u16_gfx9", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>>;
476def V_MAD_I16_gfx9   : VOP3Inst <"v_mad_i16_gfx9", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>>;
477def V_INTERP_P2_F16_gfx9 : VOP3Interp <"v_interp_p2_f16_gfx9", VOP3_INTERP16<[f16, f32, i32, f32]>>;
478} // End SubtargetPredicate = isGFX9
479
480let Uses = [M0, EXEC], FPDPRounding = 1 in {
481def V_INTERP_P1LL_F16 : VOP3Interp <"v_interp_p1ll_f16", VOP3_INTERP16<[f32, f32, i32, untyped]>>;
482def V_INTERP_P1LV_F16 : VOP3Interp <"v_interp_p1lv_f16", VOP3_INTERP16<[f32, f32, i32, f16]>>;
483} // End Uses = [M0, EXEC], FPDPRounding = 1
484
485} // End SubtargetPredicate = Has16BitInsts, isCommutable = 1
486
487let SubtargetPredicate = isVI in {
488def V_INTERP_P1_F32_e64  : VOP3Interp <"v_interp_p1_f32", VOP3_INTERP>;
489def V_INTERP_P2_F32_e64  : VOP3Interp <"v_interp_p2_f32", VOP3_INTERP>;
490def V_INTERP_MOV_F32_e64 : VOP3Interp <"v_interp_mov_f32", VOP3_INTERP_MOV>;
491
492def V_PERM_B32 : VOP3Inst <"v_perm_b32", VOP3_Profile<VOP_I32_I32_I32_I32>, AMDGPUperm>;
493} // End SubtargetPredicate = isVI
494
495let Predicates = [Has16BitInsts] in {
496
497multiclass Ternary_i16_Pats <SDPatternOperator op1, SDPatternOperator op2,
498                             Instruction inst, SDPatternOperator op3> {
499def : GCNPat <
500  (op2 (op1 i16:$src0, i16:$src1), i16:$src2),
501  (inst i16:$src0, i16:$src1, i16:$src2, (i1 0))
502>;
503
504}
505
506defm: Ternary_i16_Pats<mul, add, V_MAD_U16, zext>;
507defm: Ternary_i16_Pats<mul, add, V_MAD_I16, sext>;
508
509} // End Predicates = [Has16BitInsts]
510
511class ThreeOpFrag<SDPatternOperator op1, SDPatternOperator op2> : PatFrag<
512  (ops node:$x, node:$y, node:$z),
513  // When the inner operation is used multiple times, selecting 3-op
514  // instructions may still be beneficial -- if the other users can be
515  // combined similarly. Let's be conservative for now.
516  (op2 (HasOneUseBinOp<op1> node:$x, node:$y), node:$z),
517  [{
518    // Only use VALU ops when the result is divergent.
519    if (!N->isDivergent())
520      return false;
521
522    // Check constant bus limitations.
523    //
524    // Note: Use !isDivergent as a conservative proxy for whether the value
525    //       is in an SGPR (uniform values can end up in VGPRs as well).
526    unsigned ConstantBusUses = 0;
527    for (unsigned i = 0; i < 3; ++i) {
528      if (!Operands[i]->isDivergent() &&
529          !isInlineImmediate(Operands[i].getNode())) {
530        ConstantBusUses++;
531        if (ConstantBusUses >= 2)
532          return false;
533      }
534    }
535
536    return true;
537  }]
538> {
539  let PredicateCodeUsesOperands = 1;
540}
541
542let SubtargetPredicate = isGFX9 in {
543def V_PACK_B32_F16 : VOP3Inst <"v_pack_b32_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
544def V_LSHL_ADD_U32 : VOP3Inst <"v_lshl_add_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
545def V_ADD_LSHL_U32 : VOP3Inst <"v_add_lshl_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
546def V_ADD3_U32 : VOP3Inst <"v_add3_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
547def V_LSHL_OR_B32 : VOP3Inst <"v_lshl_or_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
548def V_AND_OR_B32 : VOP3Inst <"v_and_or_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
549def V_OR3_B32 : VOP3Inst <"v_or3_b32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
550
551def V_XAD_U32 : VOP3Inst <"v_xad_u32", VOP3_Profile<VOP_I32_I32_I32_I32>>;
552
553def V_MED3_F16 : VOP3Inst <"v_med3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmed3>;
554def V_MED3_I16 : VOP3Inst <"v_med3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmed3>;
555def V_MED3_U16 : VOP3Inst <"v_med3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumed3>;
556
557def V_MIN3_F16 : VOP3Inst <"v_min3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmin3>;
558def V_MIN3_I16 : VOP3Inst <"v_min3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmin3>;
559def V_MIN3_U16 : VOP3Inst <"v_min3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumin3>;
560
561def V_MAX3_F16 : VOP3Inst <"v_max3_f16", VOP3_Profile<VOP_F16_F16_F16_F16, VOP3_OPSEL>, AMDGPUfmax3>;
562def V_MAX3_I16 : VOP3Inst <"v_max3_i16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUsmax3>;
563def V_MAX3_U16 : VOP3Inst <"v_max3_u16", VOP3_Profile<VOP_I16_I16_I16_I16, VOP3_OPSEL>, AMDGPUumax3>;
564
565def V_ADD_I16 : VOP3Inst <"v_add_i16", VOP3_Profile<VOP_I16_I16_I16, VOP3_OPSEL>>;
566def V_SUB_I16 : VOP3Inst <"v_sub_i16", VOP3_Profile<VOP_I16_I16_I16, VOP3_OPSEL>>;
567
568def V_MAD_U32_U16 : VOP3Inst <"v_mad_u32_u16", VOP3_Profile<VOP_I32_I16_I16_I32, VOP3_OPSEL>>;
569def V_MAD_I32_I16 : VOP3Inst <"v_mad_i32_i16", VOP3_Profile<VOP_I32_I16_I16_I32, VOP3_OPSEL>>;
570
571def V_CVT_PKNORM_I16_F16 : VOP3Inst <"v_cvt_pknorm_i16_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
572def V_CVT_PKNORM_U16_F16 : VOP3Inst <"v_cvt_pknorm_u16_f16", VOP3_Profile<VOP_B32_F16_F16, VOP3_OPSEL>>;
573
574def V_ADD_I32_gfx9 : VOP3Inst <"v_add_i32_gfx9", VOP3_Profile<VOP_I32_I32_I32>>;
575def V_SUB_I32_gfx9 : VOP3Inst <"v_sub_i32_gfx9", VOP3_Profile<VOP_I32_I32_I32>>;
576
577
578class ThreeOp_i32_Pats <SDPatternOperator op1, SDPatternOperator op2, Instruction inst> : GCNPat <
579  // This matches (op2 (op1 i32:$src0, i32:$src1), i32:$src2) with conditions.
580  (ThreeOpFrag<op1, op2> i32:$src0, i32:$src1, i32:$src2),
581  (inst i32:$src0, i32:$src1, i32:$src2)
582>;
583
584def : ThreeOp_i32_Pats<shl, add, V_LSHL_ADD_U32>;
585def : ThreeOp_i32_Pats<add, shl, V_ADD_LSHL_U32>;
586def : ThreeOp_i32_Pats<add, add, V_ADD3_U32>;
587def : ThreeOp_i32_Pats<shl, or, V_LSHL_OR_B32>;
588def : ThreeOp_i32_Pats<and, or, V_AND_OR_B32>;
589def : ThreeOp_i32_Pats<or, or, V_OR3_B32>;
590def : ThreeOp_i32_Pats<xor, add, V_XAD_U32>;
591
592} // End SubtargetPredicate = isGFX9
593
594//===----------------------------------------------------------------------===//
595// Integer Clamp Patterns
596//===----------------------------------------------------------------------===//
597
598class getClampPat<VOPProfile P, SDPatternOperator node> {
599  dag ret3 = (P.DstVT (node P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2));
600  dag ret2 = (P.DstVT (node P.Src0VT:$src0, P.Src1VT:$src1));
601  dag ret1 = (P.DstVT (node P.Src0VT:$src0));
602  dag ret = !if(!eq(P.NumSrcArgs, 3), ret3,
603            !if(!eq(P.NumSrcArgs, 2), ret2,
604            ret1));
605}
606
607class getClampRes<VOPProfile P, Instruction inst> {
608  dag ret3 = (inst P.Src0VT:$src0, P.Src1VT:$src1, P.Src2VT:$src2, (i1 0));
609  dag ret2 = (inst P.Src0VT:$src0, P.Src1VT:$src1, (i1 0));
610  dag ret1 = (inst P.Src0VT:$src0, (i1 0));
611  dag ret = !if(!eq(P.NumSrcArgs, 3), ret3,
612            !if(!eq(P.NumSrcArgs, 2), ret2,
613            ret1));
614}
615
616class IntClampPat<VOP3Inst inst, SDPatternOperator node> : GCNPat<
617  getClampPat<inst.Pfl, node>.ret,
618  getClampRes<inst.Pfl, inst>.ret
619>;
620
621def : IntClampPat<V_MAD_I32_I24, AMDGPUmad_i24>;
622def : IntClampPat<V_MAD_U32_U24, AMDGPUmad_u24>;
623
624def : IntClampPat<V_SAD_U8, int_amdgcn_sad_u8>;
625def : IntClampPat<V_SAD_HI_U8, int_amdgcn_sad_hi_u8>;
626def : IntClampPat<V_SAD_U16, int_amdgcn_sad_u16>;
627
628def : IntClampPat<V_MSAD_U8, int_amdgcn_msad_u8>;
629def : IntClampPat<V_MQSAD_PK_U16_U8, int_amdgcn_mqsad_pk_u16_u8>;
630
631def : IntClampPat<V_QSAD_PK_U16_U8, int_amdgcn_qsad_pk_u16_u8>;
632def : IntClampPat<V_MQSAD_U32_U8, int_amdgcn_mqsad_u32_u8>;
633
634//===----------------------------------------------------------------------===//
635// Target
636//===----------------------------------------------------------------------===//
637
638//===----------------------------------------------------------------------===//
639// SI
640//===----------------------------------------------------------------------===//
641
642let AssemblerPredicates = [isSICI], DecoderNamespace = "SICI" in {
643
644multiclass VOP3_Real_si<bits<9> op> {
645  def _si : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.SI>,
646            VOP3e_si <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
647}
648
649multiclass VOP3be_Real_si<bits<9> op> {
650  def _si : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.SI>,
651            VOP3be_si <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
652}
653
654} // End AssemblerPredicates = [isSICI], DecoderNamespace = "SICI"
655
656defm V_MAD_LEGACY_F32   : VOP3_Real_si <0x140>;
657defm V_MAD_F32          : VOP3_Real_si <0x141>;
658defm V_MAD_I32_I24      : VOP3_Real_si <0x142>;
659defm V_MAD_U32_U24      : VOP3_Real_si <0x143>;
660defm V_CUBEID_F32       : VOP3_Real_si <0x144>;
661defm V_CUBESC_F32       : VOP3_Real_si <0x145>;
662defm V_CUBETC_F32       : VOP3_Real_si <0x146>;
663defm V_CUBEMA_F32       : VOP3_Real_si <0x147>;
664defm V_BFE_U32          : VOP3_Real_si <0x148>;
665defm V_BFE_I32          : VOP3_Real_si <0x149>;
666defm V_BFI_B32          : VOP3_Real_si <0x14a>;
667defm V_FMA_F32          : VOP3_Real_si <0x14b>;
668defm V_FMA_F64          : VOP3_Real_si <0x14c>;
669defm V_LERP_U8          : VOP3_Real_si <0x14d>;
670defm V_ALIGNBIT_B32     : VOP3_Real_si <0x14e>;
671defm V_ALIGNBYTE_B32    : VOP3_Real_si <0x14f>;
672defm V_MULLIT_F32       : VOP3_Real_si <0x150>;
673defm V_MIN3_F32         : VOP3_Real_si <0x151>;
674defm V_MIN3_I32         : VOP3_Real_si <0x152>;
675defm V_MIN3_U32         : VOP3_Real_si <0x153>;
676defm V_MAX3_F32         : VOP3_Real_si <0x154>;
677defm V_MAX3_I32         : VOP3_Real_si <0x155>;
678defm V_MAX3_U32         : VOP3_Real_si <0x156>;
679defm V_MED3_F32         : VOP3_Real_si <0x157>;
680defm V_MED3_I32         : VOP3_Real_si <0x158>;
681defm V_MED3_U32         : VOP3_Real_si <0x159>;
682defm V_SAD_U8           : VOP3_Real_si <0x15a>;
683defm V_SAD_HI_U8        : VOP3_Real_si <0x15b>;
684defm V_SAD_U16          : VOP3_Real_si <0x15c>;
685defm V_SAD_U32          : VOP3_Real_si <0x15d>;
686defm V_CVT_PK_U8_F32    : VOP3_Real_si <0x15e>;
687defm V_DIV_FIXUP_F32    : VOP3_Real_si <0x15f>;
688defm V_DIV_FIXUP_F64    : VOP3_Real_si <0x160>;
689defm V_LSHL_B64         : VOP3_Real_si <0x161>;
690defm V_LSHR_B64         : VOP3_Real_si <0x162>;
691defm V_ASHR_I64         : VOP3_Real_si <0x163>;
692defm V_ADD_F64          : VOP3_Real_si <0x164>;
693defm V_MUL_F64          : VOP3_Real_si <0x165>;
694defm V_MIN_F64          : VOP3_Real_si <0x166>;
695defm V_MAX_F64          : VOP3_Real_si <0x167>;
696defm V_LDEXP_F64        : VOP3_Real_si <0x168>;
697defm V_MUL_LO_U32       : VOP3_Real_si <0x169>;
698defm V_MUL_HI_U32       : VOP3_Real_si <0x16a>;
699defm V_MUL_LO_I32       : VOP3_Real_si <0x16b>;
700defm V_MUL_HI_I32       : VOP3_Real_si <0x16c>;
701defm V_DIV_SCALE_F32    : VOP3be_Real_si <0x16d>;
702defm V_DIV_SCALE_F64    : VOP3be_Real_si <0x16e>;
703defm V_DIV_FMAS_F32     : VOP3_Real_si <0x16f>;
704defm V_DIV_FMAS_F64     : VOP3_Real_si <0x170>;
705defm V_MSAD_U8          : VOP3_Real_si <0x171>;
706defm V_MQSAD_PK_U16_U8  : VOP3_Real_si <0x173>;
707defm V_TRIG_PREOP_F64   : VOP3_Real_si <0x174>;
708
709//===----------------------------------------------------------------------===//
710// CI
711//===----------------------------------------------------------------------===//
712
713multiclass VOP3_Real_ci<bits<9> op> {
714  def _ci : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.SI>,
715            VOP3e_si <op, !cast<VOP3_Pseudo>(NAME).Pfl> {
716    let AssemblerPredicates = [isCIOnly];
717    let DecoderNamespace = "CI";
718  }
719}
720
721multiclass VOP3be_Real_ci<bits<9> op> {
722  def _ci : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.SI>,
723            VOP3be_si <op, !cast<VOP3_Pseudo>(NAME).Pfl> {
724    let AssemblerPredicates = [isCIOnly];
725    let DecoderNamespace = "CI";
726  }
727}
728
729defm V_QSAD_PK_U16_U8   : VOP3_Real_ci <0x172>;
730defm V_MQSAD_U32_U8     : VOP3_Real_ci <0x175>;
731defm V_MAD_U64_U32      : VOP3be_Real_ci <0x176>;
732defm V_MAD_I64_I32      : VOP3be_Real_ci <0x177>;
733
734//===----------------------------------------------------------------------===//
735// VI
736//===----------------------------------------------------------------------===//
737
738let AssemblerPredicates = [isVI], DecoderNamespace = "VI" in {
739
740multiclass VOP3_Real_vi<bits<10> op> {
741  def _vi : VOP3_Real<!cast<VOP_Pseudo>(NAME), SIEncodingFamily.VI>,
742            VOP3e_vi <op, !cast<VOP_Pseudo>(NAME).Pfl>;
743}
744
745multiclass VOP3be_Real_vi<bits<10> op> {
746  def _vi : VOP3_Real<!cast<VOP_Pseudo>(NAME), SIEncodingFamily.VI>,
747            VOP3be_vi <op, !cast<VOP_Pseudo>(NAME).Pfl>;
748}
749
750multiclass VOP3OpSel_Real_gfx9<bits<10> op> {
751  def _vi : VOP3_Real<!cast<VOP_Pseudo>(NAME), SIEncodingFamily.VI>,
752            VOP3OpSel_gfx9 <op, !cast<VOP_Pseudo>(NAME).Pfl>;
753}
754
755multiclass VOP3Interp_Real_vi<bits<10> op> {
756  def _vi : VOP3_Real<!cast<VOP_Pseudo>(NAME), SIEncodingFamily.VI>,
757            VOP3Interp_vi <op, !cast<VOP_Pseudo>(NAME).Pfl>;
758}
759
760} // End AssemblerPredicates = [isVI], DecoderNamespace = "VI"
761
762let AssemblerPredicates = [isVIOnly], DecoderNamespace = "VI" in {
763
764multiclass VOP3_F16_Real_vi<bits<10> op> {
765  def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
766            VOP3e_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
767}
768
769multiclass VOP3Interp_F16_Real_vi<bits<10> op> {
770  def _vi : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.VI>,
771            VOP3Interp_vi <op, !cast<VOP3_Pseudo>(NAME).Pfl>;
772}
773
774} // End AssemblerPredicates = [isVIOnly], DecoderNamespace = "VI"
775
776let AssemblerPredicates = [isGFX9], DecoderNamespace = "GFX9" in {
777
778multiclass VOP3_F16_Real_gfx9<bits<10> op, string OpName, string AsmName> {
779  def _gfx9 : VOP3_Real<!cast<VOP3_Pseudo>(OpName), SIEncodingFamily.GFX9>,
780            VOP3e_vi <op, !cast<VOP3_Pseudo>(OpName).Pfl> {
781              VOP3_Pseudo ps = !cast<VOP3_Pseudo>(OpName);
782              let AsmString = AsmName # ps.AsmOperands;
783            }
784}
785
786multiclass VOP3OpSel_F16_Real_gfx9<bits<10> op, string AsmName> {
787  def _gfx9 : VOP3_Real<!cast<VOP3_Pseudo>(NAME), SIEncodingFamily.GFX9>,
788            VOP3OpSel_gfx9 <op, !cast<VOP3_Pseudo>(NAME).Pfl> {
789              VOP3_Pseudo ps = !cast<VOP3_Pseudo>(NAME);
790              let AsmString = AsmName # ps.AsmOperands;
791            }
792}
793
794multiclass VOP3Interp_F16_Real_gfx9<bits<10> op, string OpName, string AsmName> {
795  def _gfx9 : VOP3_Real<!cast<VOP3_Pseudo>(OpName), SIEncodingFamily.GFX9>,
796            VOP3Interp_vi <op, !cast<VOP3_Pseudo>(OpName).Pfl> {
797              VOP3_Pseudo ps = !cast<VOP3_Pseudo>(OpName);
798              let AsmString = AsmName # ps.AsmOperands;
799            }
800}
801
802multiclass VOP3_Real_gfx9<bits<10> op, string AsmName> {
803  def _gfx9 : VOP3_Real<!cast<VOP_Pseudo>(NAME), SIEncodingFamily.GFX9>,
804              VOP3e_vi <op, !cast<VOP_Pseudo>(NAME).Pfl> {
805              VOP_Pseudo ps = !cast<VOP_Pseudo>(NAME);
806              let AsmString = AsmName # ps.AsmOperands;
807            }
808}
809
810} // End AssemblerPredicates = [isGFX9], DecoderNamespace = "GFX9"
811
812defm V_MAD_U64_U32      : VOP3be_Real_vi <0x1E8>;
813defm V_MAD_I64_I32      : VOP3be_Real_vi <0x1E9>;
814
815defm V_MAD_LEGACY_F32   : VOP3_Real_vi <0x1c0>;
816defm V_MAD_F32          : VOP3_Real_vi <0x1c1>;
817defm V_MAD_I32_I24      : VOP3_Real_vi <0x1c2>;
818defm V_MAD_U32_U24      : VOP3_Real_vi <0x1c3>;
819defm V_CUBEID_F32       : VOP3_Real_vi <0x1c4>;
820defm V_CUBESC_F32       : VOP3_Real_vi <0x1c5>;
821defm V_CUBETC_F32       : VOP3_Real_vi <0x1c6>;
822defm V_CUBEMA_F32       : VOP3_Real_vi <0x1c7>;
823defm V_BFE_U32          : VOP3_Real_vi <0x1c8>;
824defm V_BFE_I32          : VOP3_Real_vi <0x1c9>;
825defm V_BFI_B32          : VOP3_Real_vi <0x1ca>;
826defm V_FMA_F32          : VOP3_Real_vi <0x1cb>;
827defm V_FMA_F64          : VOP3_Real_vi <0x1cc>;
828defm V_LERP_U8          : VOP3_Real_vi <0x1cd>;
829defm V_ALIGNBIT_B32     : VOP3_Real_vi <0x1ce>;
830defm V_ALIGNBYTE_B32    : VOP3_Real_vi <0x1cf>;
831defm V_MIN3_F32         : VOP3_Real_vi <0x1d0>;
832defm V_MIN3_I32         : VOP3_Real_vi <0x1d1>;
833defm V_MIN3_U32         : VOP3_Real_vi <0x1d2>;
834defm V_MAX3_F32         : VOP3_Real_vi <0x1d3>;
835defm V_MAX3_I32         : VOP3_Real_vi <0x1d4>;
836defm V_MAX3_U32         : VOP3_Real_vi <0x1d5>;
837defm V_MED3_F32         : VOP3_Real_vi <0x1d6>;
838defm V_MED3_I32         : VOP3_Real_vi <0x1d7>;
839defm V_MED3_U32         : VOP3_Real_vi <0x1d8>;
840defm V_SAD_U8           : VOP3_Real_vi <0x1d9>;
841defm V_SAD_HI_U8        : VOP3_Real_vi <0x1da>;
842defm V_SAD_U16          : VOP3_Real_vi <0x1db>;
843defm V_SAD_U32          : VOP3_Real_vi <0x1dc>;
844defm V_CVT_PK_U8_F32    : VOP3_Real_vi <0x1dd>;
845defm V_DIV_FIXUP_F32    : VOP3_Real_vi <0x1de>;
846defm V_DIV_FIXUP_F64    : VOP3_Real_vi <0x1df>;
847defm V_DIV_SCALE_F32    : VOP3be_Real_vi <0x1e0>;
848defm V_DIV_SCALE_F64    : VOP3be_Real_vi <0x1e1>;
849defm V_DIV_FMAS_F32     : VOP3_Real_vi <0x1e2>;
850defm V_DIV_FMAS_F64     : VOP3_Real_vi <0x1e3>;
851defm V_MSAD_U8          : VOP3_Real_vi <0x1e4>;
852defm V_QSAD_PK_U16_U8   : VOP3_Real_vi <0x1e5>;
853defm V_MQSAD_PK_U16_U8  : VOP3_Real_vi <0x1e6>;
854defm V_MQSAD_U32_U8     : VOP3_Real_vi <0x1e7>;
855
856defm V_PERM_B32         : VOP3_Real_vi <0x1ed>;
857
858defm V_MAD_F16          : VOP3_F16_Real_vi <0x1ea>;
859defm V_MAD_U16          : VOP3_F16_Real_vi <0x1eb>;
860defm V_MAD_I16          : VOP3_F16_Real_vi <0x1ec>;
861defm V_FMA_F16          : VOP3_F16_Real_vi <0x1ee>;
862defm V_DIV_FIXUP_F16    : VOP3_F16_Real_vi <0x1ef>;
863defm V_INTERP_P2_F16    : VOP3Interp_F16_Real_vi <0x276>;
864
865let FPDPRounding = 1 in {
866defm V_MAD_LEGACY_F16       : VOP3_F16_Real_gfx9 <0x1ea, "V_MAD_F16",       "v_mad_legacy_f16">;
867defm V_FMA_LEGACY_F16       : VOP3_F16_Real_gfx9 <0x1ee, "V_FMA_F16",       "v_fma_legacy_f16">;
868defm V_DIV_FIXUP_LEGACY_F16 : VOP3_F16_Real_gfx9 <0x1ef, "V_DIV_FIXUP_F16", "v_div_fixup_legacy_f16">;
869defm V_INTERP_P2_LEGACY_F16 : VOP3Interp_F16_Real_gfx9 <0x276, "V_INTERP_P2_F16", "v_interp_p2_legacy_f16">;
870} // End FPDPRounding = 1
871
872defm V_MAD_LEGACY_U16       : VOP3_F16_Real_gfx9 <0x1eb, "V_MAD_U16",       "v_mad_legacy_u16">;
873defm V_MAD_LEGACY_I16       : VOP3_F16_Real_gfx9 <0x1ec, "V_MAD_I16",       "v_mad_legacy_i16">;
874
875defm V_MAD_F16_gfx9         : VOP3OpSel_F16_Real_gfx9 <0x203, "v_mad_f16">;
876defm V_MAD_U16_gfx9         : VOP3OpSel_F16_Real_gfx9 <0x204, "v_mad_u16">;
877defm V_MAD_I16_gfx9         : VOP3OpSel_F16_Real_gfx9 <0x205, "v_mad_i16">;
878defm V_FMA_F16_gfx9         : VOP3OpSel_F16_Real_gfx9 <0x206, "v_fma_f16">;
879defm V_DIV_FIXUP_F16_gfx9   : VOP3OpSel_F16_Real_gfx9 <0x207, "v_div_fixup_f16">;
880defm V_INTERP_P2_F16_gfx9   : VOP3Interp_F16_Real_gfx9 <0x277, "V_INTERP_P2_F16_gfx9", "v_interp_p2_f16">;
881
882defm V_ADD_I32_gfx9         : VOP3_Real_gfx9 <0x29c, "v_add_i32">;
883defm V_SUB_I32_gfx9         : VOP3_Real_gfx9 <0x29d, "v_sub_i32">;
884
885defm V_INTERP_P1_F32_e64  : VOP3Interp_Real_vi <0x270>;
886defm V_INTERP_P2_F32_e64  : VOP3Interp_Real_vi <0x271>;
887defm V_INTERP_MOV_F32_e64 : VOP3Interp_Real_vi <0x272>;
888
889defm V_INTERP_P1LL_F16  : VOP3Interp_Real_vi <0x274>;
890defm V_INTERP_P1LV_F16  : VOP3Interp_Real_vi <0x275>;
891defm V_ADD_F64          : VOP3_Real_vi <0x280>;
892defm V_MUL_F64          : VOP3_Real_vi <0x281>;
893defm V_MIN_F64          : VOP3_Real_vi <0x282>;
894defm V_MAX_F64          : VOP3_Real_vi <0x283>;
895defm V_LDEXP_F64        : VOP3_Real_vi <0x284>;
896defm V_MUL_LO_U32       : VOP3_Real_vi <0x285>;
897
898// removed from VI as identical to V_MUL_LO_U32
899let isAsmParserOnly = 1 in {
900defm V_MUL_LO_I32       : VOP3_Real_vi <0x285>;
901}
902
903defm V_MUL_HI_U32       : VOP3_Real_vi <0x286>;
904defm V_MUL_HI_I32       : VOP3_Real_vi <0x287>;
905
906defm V_READLANE_B32     : VOP3_Real_vi <0x289>;
907defm V_WRITELANE_B32    : VOP3_Real_vi <0x28a>;
908
909defm V_LSHLREV_B64      : VOP3_Real_vi <0x28f>;
910defm V_LSHRREV_B64      : VOP3_Real_vi <0x290>;
911defm V_ASHRREV_I64      : VOP3_Real_vi <0x291>;
912defm V_TRIG_PREOP_F64   : VOP3_Real_vi <0x292>;
913
914defm V_LSHL_ADD_U32 : VOP3_Real_vi <0x1fd>;
915defm V_ADD_LSHL_U32 : VOP3_Real_vi <0x1fe>;
916defm V_ADD3_U32 : VOP3_Real_vi <0x1ff>;
917defm V_LSHL_OR_B32 : VOP3_Real_vi <0x200>;
918defm V_AND_OR_B32 : VOP3_Real_vi <0x201>;
919defm V_OR3_B32 : VOP3_Real_vi <0x202>;
920defm V_PACK_B32_F16 : VOP3OpSel_Real_gfx9 <0x2a0>;
921
922defm V_XAD_U32 : VOP3_Real_vi <0x1f3>;
923
924defm V_MIN3_F16 : VOP3OpSel_Real_gfx9 <0x1f4>;
925defm V_MIN3_I16 : VOP3OpSel_Real_gfx9 <0x1f5>;
926defm V_MIN3_U16 : VOP3OpSel_Real_gfx9 <0x1f6>;
927
928defm V_MAX3_F16 : VOP3OpSel_Real_gfx9 <0x1f7>;
929defm V_MAX3_I16 : VOP3OpSel_Real_gfx9 <0x1f8>;
930defm V_MAX3_U16 : VOP3OpSel_Real_gfx9 <0x1f9>;
931
932defm V_MED3_F16 : VOP3OpSel_Real_gfx9 <0x1fa>;
933defm V_MED3_I16 : VOP3OpSel_Real_gfx9 <0x1fb>;
934defm V_MED3_U16 : VOP3OpSel_Real_gfx9 <0x1fc>;
935
936defm V_ADD_I16  : VOP3OpSel_Real_gfx9 <0x29e>;
937defm V_SUB_I16  : VOP3OpSel_Real_gfx9 <0x29f>;
938
939defm V_MAD_U32_U16 : VOP3OpSel_Real_gfx9 <0x1f1>;
940defm V_MAD_I32_I16 : VOP3OpSel_Real_gfx9 <0x1f2>;
941
942defm V_CVT_PKNORM_I16_F16 : VOP3OpSel_Real_gfx9 <0x299>;
943defm V_CVT_PKNORM_U16_F16 : VOP3OpSel_Real_gfx9 <0x29a>;
944