1//===-- SIInstructions.td - SI 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// This file was originally auto-generated from a GPU register header file and
9// all the instruction definitions were originally commented out.  Instructions
10// that are not yet supported remain commented out.
11//===----------------------------------------------------------------------===//
12
13class GCNPat<dag pattern, dag result> : Pat<pattern, result>, GCNPredicateControl {
14
15}
16
17class UniformSextInreg<ValueType VT> : PatFrag<
18  (ops node:$src),
19  (sext_inreg $src, VT),
20  [{ return !N->isDivergent(); }]>;
21
22class DivergentSextInreg<ValueType VT> : PatFrag<
23  (ops node:$src),
24  (sext_inreg $src, VT),
25  [{ return N->isDivergent(); }]>;
26
27include "SOPInstructions.td"
28include "VOPInstructions.td"
29include "SMInstructions.td"
30include "FLATInstructions.td"
31include "BUFInstructions.td"
32include "EXPInstructions.td"
33include "LDSDIRInstructions.td"
34include "VINTERPInstructions.td"
35
36//===----------------------------------------------------------------------===//
37// VINTRP Instructions
38//===----------------------------------------------------------------------===//
39
40// Used to inject printing of "_e32" suffix for VI (there are "_e64" variants for VI)
41def VINTRPDst : VINTRPDstOperand <VGPR_32>;
42
43let Uses = [MODE, M0, EXEC] in {
44
45// FIXME: Specify SchedRW for VINTRP instructions.
46
47multiclass V_INTERP_P1_F32_m : VINTRP_m <
48  0x00000000,
49  (outs VINTRPDst:$vdst),
50  (ins VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan),
51  "v_interp_p1_f32$vdst, $vsrc, $attr$attrchan",
52  [(set f32:$vdst, (int_amdgcn_interp_p1 f32:$vsrc,
53                   (i32 timm:$attrchan), (i32 timm:$attr), M0))]
54>;
55
56let OtherPredicates = [has32BankLDS, isNotGFX90APlus] in {
57
58defm V_INTERP_P1_F32 : V_INTERP_P1_F32_m;
59
60} // End OtherPredicates = [has32BankLDS, isNotGFX90APlus]
61
62let OtherPredicates = [has16BankLDS, isNotGFX90APlus],
63    Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 in {
64
65defm V_INTERP_P1_F32_16bank : V_INTERP_P1_F32_m;
66
67} // End OtherPredicates = [has32BankLDS, isNotGFX90APlus],
68  //     Constraints = "@earlyclobber $vdst", isAsmParserOnly=1
69
70let OtherPredicates = [isNotGFX90APlus] in {
71let DisableEncoding = "$src0", Constraints = "$src0 = $vdst" in {
72
73defm V_INTERP_P2_F32 : VINTRP_m <
74  0x00000001,
75  (outs VINTRPDst:$vdst),
76  (ins VGPR_32:$src0, VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan),
77  "v_interp_p2_f32$vdst, $vsrc, $attr$attrchan",
78  [(set f32:$vdst, (int_amdgcn_interp_p2 f32:$src0, f32:$vsrc,
79                   (i32 timm:$attrchan), (i32 timm:$attr), M0))]>;
80
81} // End DisableEncoding = "$src0", Constraints = "$src0 = $vdst"
82
83defm V_INTERP_MOV_F32 : VINTRP_m <
84  0x00000002,
85  (outs VINTRPDst:$vdst),
86  (ins InterpSlot:$vsrc, Attr:$attr, AttrChan:$attrchan),
87  "v_interp_mov_f32$vdst, $vsrc, $attr$attrchan",
88  [(set f32:$vdst, (int_amdgcn_interp_mov (i32 timm:$vsrc),
89                   (i32 timm:$attrchan), (i32 timm:$attr), M0))]>;
90
91} // End OtherPredicates = [isNotGFX90APlus]
92
93} // End Uses = [MODE, M0, EXEC]
94
95//===----------------------------------------------------------------------===//
96// Pseudo Instructions
97//===----------------------------------------------------------------------===//
98def ATOMIC_FENCE : SPseudoInstSI<
99  (outs), (ins i32imm:$ordering, i32imm:$scope),
100  [(atomic_fence (i32 timm:$ordering), (i32 timm:$scope))],
101  "ATOMIC_FENCE $ordering, $scope"> {
102  let hasSideEffects = 1;
103  let maybeAtomic = 1;
104}
105
106let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] in {
107
108// For use in patterns
109def V_CNDMASK_B64_PSEUDO : VOP3Common <(outs VReg_64:$vdst),
110  (ins VSrc_b64:$src0, VSrc_b64:$src1, SSrc_b64:$src2), "", []> {
111  let isPseudo = 1;
112  let isCodeGenOnly = 1;
113  let usesCustomInserter = 1;
114}
115
116// 64-bit vector move instruction. This is mainly used by the
117// SIFoldOperands pass to enable folding of inline immediates.
118def V_MOV_B64_PSEUDO : VPseudoInstSI <(outs VReg_64:$vdst),
119                                      (ins VSrc_b64:$src0)> {
120  let isReMaterializable = 1;
121  let isAsCheapAsAMove = 1;
122  let isMoveImm = 1;
123  let SchedRW = [Write64Bit];
124  let Size = 16; // Needs maximum 2 v_mov_b32 instructions 8 byte long each.
125}
126
127// 64-bit vector move with dpp. Expanded post-RA.
128def V_MOV_B64_DPP_PSEUDO : VOP_DPP_Pseudo <"v_mov_b64_dpp", VOP_I64_I64> {
129  let Size = 16; // Requires two 8-byte v_mov_b32_dpp to complete.
130}
131
132// 64-bit scalar move immediate instruction. This is used to avoid subregs
133// initialization and allow rematerialization.
134def S_MOV_B64_IMM_PSEUDO : SPseudoInstSI <(outs SReg_64:$sdst),
135                                          (ins i64imm:$src0)> {
136  let isReMaterializable = 1;
137  let isAsCheapAsAMove = 1;
138  let isMoveImm = 1;
139  let SchedRW = [WriteSALU, Write64Bit];
140  let Size = 16; // Needs maximum 2 s_mov_b32 instructions 8 byte long each.
141  let Uses = [];
142}
143
144// Pseudoinstruction for @llvm.amdgcn.wqm. It is turned into a copy after the
145// WQM pass processes it.
146def WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
147
148// Pseudoinstruction for @llvm.amdgcn.softwqm. Like @llvm.amdgcn.wqm it is
149// turned into a copy by WQM pass, but does not seed WQM requirements.
150def SOFT_WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
151
152// Pseudoinstruction for @llvm.amdgcn.strict.wwm. It is turned into a copy post-RA, so
153// that the @earlyclobber is respected. The @earlyclobber is to make sure that
154// the instruction that defines $src0 (which is run in Whole Wave Mode) doesn't
155// accidentally clobber inactive channels of $vdst.
156let Constraints = "@earlyclobber $vdst" in {
157def STRICT_WWM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
158def STRICT_WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
159}
160
161} // End let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC]
162
163def ENTER_STRICT_WWM : SPseudoInstSI <(outs SReg_1:$sdst), (ins i64imm:$src0)> {
164  let Uses = [EXEC];
165  let Defs = [EXEC, SCC];
166  let hasSideEffects = 0;
167  let mayLoad = 0;
168  let mayStore = 0;
169}
170
171def EXIT_STRICT_WWM : SPseudoInstSI <(outs SReg_1:$sdst), (ins SReg_1:$src0)> {
172  let hasSideEffects = 0;
173  let mayLoad = 0;
174  let mayStore = 0;
175}
176
177def ENTER_STRICT_WQM : SPseudoInstSI <(outs SReg_1:$sdst), (ins i64imm:$src0)> {
178  let Uses = [EXEC];
179  let Defs = [EXEC, SCC];
180  let hasSideEffects = 0;
181  let mayLoad = 0;
182  let mayStore = 0;
183}
184
185def EXIT_STRICT_WQM : SPseudoInstSI <(outs SReg_1:$sdst), (ins SReg_1:$src0)> {
186  let hasSideEffects = 0;
187  let mayLoad = 0;
188  let mayStore = 0;
189}
190
191// Pseudo instructions used for @llvm.fptrunc.round upward
192// and @llvm.fptrunc.round downward.
193// These intrinsics will be legalized to G_FPTRUNC_ROUND_UPWARD
194// and G_FPTRUNC_ROUND_DOWNWARD before being lowered to
195// FPTRUNC_UPWARD_PSEUDO and FPTRUNC_DOWNWARD_PSEUDO.
196// The final codegen is done in the ModeRegister pass.
197let Uses = [MODE, EXEC] in {
198def FPTRUNC_UPWARD_PSEUDO : VPseudoInstSI <(outs VGPR_32:$vdst),
199  (ins VGPR_32:$src0),
200  [(set f16:$vdst, (SIfptrunc_round_upward f32:$src0))]>;
201
202def FPTRUNC_DOWNWARD_PSEUDO : VPseudoInstSI <(outs VGPR_32:$vdst),
203  (ins VGPR_32:$src0),
204  [(set f16:$vdst, (SIfptrunc_round_downward f32:$src0))]>;
205} // End Uses = [MODE, EXEC]
206
207// Invert the exec mask and overwrite the inactive lanes of dst with inactive,
208// restoring it after we're done.
209let Defs = [SCC] in {
210def V_SET_INACTIVE_B32 : VPseudoInstSI <(outs VGPR_32:$vdst),
211  (ins VSrc_b32: $src, VSrc_b32:$inactive),
212  [(set i32:$vdst, (int_amdgcn_set_inactive i32:$src, i32:$inactive))]> {
213}
214
215def V_SET_INACTIVE_B64 : VPseudoInstSI <(outs VReg_64:$vdst),
216  (ins VSrc_b64: $src, VSrc_b64:$inactive),
217  [(set i64:$vdst, (int_amdgcn_set_inactive i64:$src, i64:$inactive))]> {
218}
219} // End Defs = [SCC]
220
221let usesCustomInserter = 1, Defs = [VCC, EXEC] in {
222def V_ADD_U64_PSEUDO : VPseudoInstSI <
223  (outs VReg_64:$vdst), (ins VSrc_b64:$src0, VSrc_b64:$src1),
224  [(set VReg_64:$vdst, (getDivergentFrag<add>.ret i64:$src0, i64:$src1))]
225>;
226
227def V_SUB_U64_PSEUDO : VPseudoInstSI <
228  (outs VReg_64:$vdst), (ins VSrc_b64:$src0, VSrc_b64:$src1),
229  [(set VReg_64:$vdst, (getDivergentFrag<sub>.ret i64:$src0, i64:$src1))]
230>;
231} // End usesCustomInserter = 1, Defs = [VCC, EXEC]
232
233let usesCustomInserter = 1, Defs = [SCC] in {
234def S_ADD_U64_PSEUDO : SPseudoInstSI <
235  (outs SReg_64:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1),
236  [(set SReg_64:$sdst, (UniformBinFrag<add> i64:$src0, i64:$src1))]
237>;
238
239def S_SUB_U64_PSEUDO : SPseudoInstSI <
240  (outs SReg_64:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1),
241  [(set SReg_64:$sdst, (UniformBinFrag<sub> i64:$src0, i64:$src1))]
242>;
243
244def S_ADD_U64_CO_PSEUDO : SPseudoInstSI <
245  (outs SReg_64:$vdst, VOPDstS64orS32:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1)
246>;
247
248def S_SUB_U64_CO_PSEUDO : SPseudoInstSI <
249  (outs SReg_64:$vdst, VOPDstS64orS32:$sdst), (ins SSrc_b64:$src0, SSrc_b64:$src1)
250>;
251
252def S_ADD_CO_PSEUDO : SPseudoInstSI <
253  (outs SReg_32:$sdst, SSrc_i1:$scc_out), (ins SSrc_b32:$src0, SSrc_b32:$src1, SSrc_i1:$scc_in)
254>;
255
256def S_SUB_CO_PSEUDO : SPseudoInstSI <
257  (outs SReg_32:$sdst, SSrc_i1:$scc_out), (ins SSrc_b32:$src0, SSrc_b32:$src1, SSrc_i1:$scc_in)
258>;
259
260def S_UADDO_PSEUDO : SPseudoInstSI <
261  (outs SReg_32:$sdst, SSrc_i1:$scc_out), (ins SSrc_b32:$src0, SSrc_b32:$src1)
262>;
263
264def S_USUBO_PSEUDO : SPseudoInstSI <
265  (outs SReg_32:$sdst, SSrc_i1:$scc_out), (ins SSrc_b32:$src0, SSrc_b32:$src1)
266>;
267
268} // End usesCustomInserter = 1, Defs = [SCC]
269
270let usesCustomInserter = 1 in {
271def GET_GROUPSTATICSIZE : SPseudoInstSI <(outs SReg_32:$sdst), (ins),
272  [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>;
273} // End let usesCustomInserter = 1, SALU = 1
274
275// Wrap an instruction by duplicating it, except for setting isTerminator.
276class WrapTerminatorInst<SOP_Pseudo base_inst> : SPseudoInstSI<
277      base_inst.OutOperandList,
278      base_inst.InOperandList> {
279  let Uses = base_inst.Uses;
280  let Defs = base_inst.Defs;
281  let isTerminator = 1;
282  let isAsCheapAsAMove = base_inst.isAsCheapAsAMove;
283  let hasSideEffects = base_inst.hasSideEffects;
284  let UseNamedOperandTable = base_inst.UseNamedOperandTable;
285  let CodeSize = base_inst.CodeSize;
286  let SchedRW = base_inst.SchedRW;
287}
288
289let WaveSizePredicate = isWave64 in {
290def S_MOV_B64_term : WrapTerminatorInst<S_MOV_B64>;
291def S_XOR_B64_term : WrapTerminatorInst<S_XOR_B64>;
292def S_OR_B64_term : WrapTerminatorInst<S_OR_B64>;
293def S_ANDN2_B64_term : WrapTerminatorInst<S_ANDN2_B64>;
294def S_AND_B64_term : WrapTerminatorInst<S_AND_B64>;
295}
296
297let WaveSizePredicate = isWave32 in {
298def S_MOV_B32_term : WrapTerminatorInst<S_MOV_B32>;
299def S_XOR_B32_term : WrapTerminatorInst<S_XOR_B32>;
300def S_OR_B32_term : WrapTerminatorInst<S_OR_B32>;
301def S_ANDN2_B32_term : WrapTerminatorInst<S_ANDN2_B32>;
302def S_AND_B32_term : WrapTerminatorInst<S_AND_B32>;
303}
304
305
306def WAVE_BARRIER : SPseudoInstSI<(outs), (ins),
307  [(int_amdgcn_wave_barrier)]> {
308  let SchedRW = [];
309  let hasNoSchedulingInfo = 1;
310  let hasSideEffects = 1;
311  let mayLoad = 0;
312  let mayStore = 0;
313  let isConvergent = 1;
314  let FixedSize = 1;
315  let Size = 0;
316}
317
318def SCHED_BARRIER : SPseudoInstSI<(outs), (ins i32imm:$mask),
319  [(int_amdgcn_sched_barrier (i32 timm:$mask))]> {
320  let SchedRW = [];
321  let hasNoSchedulingInfo = 1;
322  let hasSideEffects = 1;
323  let mayLoad = 0;
324  let mayStore = 0;
325  let isConvergent = 1;
326  let FixedSize = 1;
327  let Size = 0;
328}
329
330// SI pseudo instructions. These are used by the CFG structurizer pass
331// and should be lowered to ISA instructions prior to codegen.
332
333let isTerminator = 1 in {
334
335let OtherPredicates = [EnableLateCFGStructurize] in {
336 def SI_NON_UNIFORM_BRCOND_PSEUDO : CFPseudoInstSI <
337  (outs),
338  (ins SReg_1:$vcc, brtarget:$target),
339  [(brcond i1:$vcc, bb:$target)]> {
340    let Size = 12;
341}
342}
343
344def SI_IF: CFPseudoInstSI <
345  (outs SReg_1:$dst), (ins SReg_1:$vcc, brtarget:$target),
346  [(set i1:$dst, (AMDGPUif i1:$vcc, bb:$target))], 1, 1> {
347  let Constraints = "";
348  let Size = 12;
349  let hasSideEffects = 1;
350}
351
352def SI_ELSE : CFPseudoInstSI <
353  (outs SReg_1:$dst),
354  (ins SReg_1:$src, brtarget:$target), [], 1, 1> {
355  let Size = 12;
356  let hasSideEffects = 1;
357}
358
359def SI_WATERFALL_LOOP : CFPseudoInstSI <
360  (outs),
361  (ins brtarget:$target), [], 1> {
362  let Size = 8;
363  let isBranch = 1;
364  let Defs = [];
365}
366
367def SI_LOOP : CFPseudoInstSI <
368  (outs), (ins SReg_1:$saved, brtarget:$target),
369  [(AMDGPUloop i1:$saved, bb:$target)], 1, 1> {
370  let Size = 8;
371  let isBranch = 1;
372  let hasSideEffects = 1;
373}
374
375} // End isTerminator = 1
376
377def SI_END_CF : CFPseudoInstSI <
378  (outs), (ins SReg_1:$saved), [], 1, 1> {
379  let Size = 4;
380  let isAsCheapAsAMove = 1;
381  let isReMaterializable = 1;
382  let hasSideEffects = 1;
383  let mayLoad = 1; // FIXME: Should not need memory flags
384  let mayStore = 1;
385}
386
387def SI_IF_BREAK : CFPseudoInstSI <
388  (outs SReg_1:$dst), (ins SReg_1:$vcc, SReg_1:$src), []> {
389  let Size = 4;
390  let isAsCheapAsAMove = 1;
391  let isReMaterializable = 1;
392}
393
394// Branch to the early termination block of the shader if SCC is 0.
395// This uses SCC from a previous SALU operation, i.e. the update of
396// a mask of live lanes after a kill/demote operation.
397// Only valid in pixel shaders.
398def SI_EARLY_TERMINATE_SCC0 : SPseudoInstSI <(outs), (ins)> {
399  let Uses = [EXEC,SCC];
400}
401
402let Uses = [EXEC] in {
403
404multiclass PseudoInstKill <dag ins> {
405  // Even though this pseudo can usually be expanded without an SCC def, we
406  // conservatively assume that it has an SCC def, both because it is sometimes
407  // required in degenerate cases (when V_CMPX cannot be used due to constant
408  // bus limitations) and because it allows us to avoid having to track SCC
409  // liveness across basic blocks.
410  let Defs = [EXEC,SCC] in
411  def _PSEUDO : PseudoInstSI <(outs), ins> {
412    let isConvergent = 1;
413    let usesCustomInserter = 1;
414  }
415
416  let Defs = [EXEC,SCC] in
417  def _TERMINATOR : SPseudoInstSI <(outs), ins> {
418    let isTerminator = 1;
419  }
420}
421
422defm SI_KILL_I1 : PseudoInstKill <(ins SCSrc_i1:$src, i1imm:$killvalue)>;
423let Defs = [VCC] in
424defm SI_KILL_F32_COND_IMM : PseudoInstKill <(ins VSrc_b32:$src0, i32imm:$src1, i32imm:$cond)>;
425
426let Defs = [EXEC,VCC] in
427def SI_ILLEGAL_COPY : SPseudoInstSI <
428  (outs unknown:$dst), (ins unknown:$src),
429  [], " ; illegal copy $src to $dst">;
430
431} // End Uses = [EXEC], Defs = [EXEC,VCC]
432
433// Branch on undef scc. Used to avoid intermediate copy from
434// IMPLICIT_DEF to SCC.
435def SI_BR_UNDEF : SPseudoInstSI <(outs), (ins sopp_brtarget:$simm16)> {
436  let isTerminator = 1;
437  let usesCustomInserter = 1;
438  let isBranch = 1;
439}
440
441def SI_PS_LIVE : PseudoInstSI <
442  (outs SReg_1:$dst), (ins),
443  [(set i1:$dst, (int_amdgcn_ps_live))]> {
444  let SALU = 1;
445}
446
447let Uses = [EXEC] in {
448def SI_LIVE_MASK : PseudoInstSI <
449  (outs SReg_1:$dst), (ins),
450  [(set i1:$dst, (int_amdgcn_live_mask))]> {
451  let SALU = 1;
452}
453let Defs = [EXEC,SCC] in {
454// Demote: Turn a pixel shader thread into a helper lane.
455def SI_DEMOTE_I1 : SPseudoInstSI <(outs), (ins SCSrc_i1:$src, i1imm:$killvalue)>;
456} // End Defs = [EXEC,SCC]
457} // End Uses = [EXEC]
458
459def SI_MASKED_UNREACHABLE : SPseudoInstSI <(outs), (ins),
460  [(int_amdgcn_unreachable)],
461  "; divergent unreachable"> {
462  let Size = 0;
463  let hasNoSchedulingInfo = 1;
464  let FixedSize = 1;
465}
466
467// Used as an isel pseudo to directly emit initialization with an
468// s_mov_b32 rather than a copy of another initialized
469// register. MachineCSE skips copies, and we don't want to have to
470// fold operands before it runs.
471def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> {
472  let Defs = [M0];
473  let usesCustomInserter = 1;
474  let isAsCheapAsAMove = 1;
475  let isReMaterializable = 1;
476}
477
478def SI_INIT_EXEC : SPseudoInstSI <
479  (outs), (ins i64imm:$src),
480  [(int_amdgcn_init_exec (i64 timm:$src))]> {
481  let Defs = [EXEC];
482  let isAsCheapAsAMove = 1;
483}
484
485def SI_INIT_EXEC_FROM_INPUT : SPseudoInstSI <
486  (outs), (ins SSrc_b32:$input, i32imm:$shift),
487  [(int_amdgcn_init_exec_from_input i32:$input, (i32 timm:$shift))]> {
488  let Defs = [EXEC];
489}
490
491// Return for returning shaders to a shader variant epilog.
492def SI_RETURN_TO_EPILOG : SPseudoInstSI <
493  (outs), (ins variable_ops), [(AMDGPUreturn_to_epilog)]> {
494  let isTerminator = 1;
495  let isBarrier = 1;
496  let isReturn = 1;
497  let hasNoSchedulingInfo = 1;
498  let DisableWQM = 1;
499  let FixedSize = 1;
500}
501
502// Return for returning function calls.
503def SI_RETURN : SPseudoInstSI <
504  (outs), (ins), [(AMDGPUret_flag)],
505  "; return"> {
506  let isTerminator = 1;
507  let isBarrier = 1;
508  let isReturn = 1;
509  let SchedRW = [WriteBranch];
510}
511
512// Return for returning function calls without output register.
513//
514// This version is only needed so we can fill in the output register
515// in the custom inserter.
516def SI_CALL_ISEL : SPseudoInstSI <
517  (outs), (ins SSrc_b64:$src0, unknown:$callee),
518  [(AMDGPUcall i64:$src0, tglobaladdr:$callee)]> {
519  let Size = 4;
520  let isCall = 1;
521  let SchedRW = [WriteBranch];
522  let usesCustomInserter = 1;
523  // TODO: Should really base this on the call target
524  let isConvergent = 1;
525}
526
527def : GCNPat<
528  (AMDGPUcall i64:$src0, (i64 0)),
529  (SI_CALL_ISEL $src0, (i64 0))
530>;
531
532// Wrapper around s_swappc_b64 with extra $callee parameter to track
533// the called function after regalloc.
534def SI_CALL : SPseudoInstSI <
535  (outs SReg_64:$dst), (ins SSrc_b64:$src0, unknown:$callee)> {
536  let Size = 4;
537  let FixedSize = 1;
538  let isCall = 1;
539  let UseNamedOperandTable = 1;
540  let SchedRW = [WriteBranch];
541  // TODO: Should really base this on the call target
542  let isConvergent = 1;
543}
544
545// Tail call handling pseudo
546def SI_TCRETURN : SPseudoInstSI <(outs),
547  (ins SReg_64:$src0, unknown:$callee, i32imm:$fpdiff),
548  [(AMDGPUtc_return i64:$src0, tglobaladdr:$callee, i32:$fpdiff)]> {
549  let Size = 4;
550  let FixedSize = 1;
551  let isCall = 1;
552  let isTerminator = 1;
553  let isReturn = 1;
554  let isBarrier = 1;
555  let UseNamedOperandTable = 1;
556  let SchedRW = [WriteBranch];
557  // TODO: Should really base this on the call target
558  let isConvergent = 1;
559}
560
561// Handle selecting indirect tail calls
562def : GCNPat<
563  (AMDGPUtc_return i64:$src0, (i64 0), (i32 timm:$fpdiff)),
564  (SI_TCRETURN SReg_64:$src0, (i64 0), i32imm:$fpdiff)
565>;
566
567def ADJCALLSTACKUP : SPseudoInstSI<
568  (outs), (ins i32imm:$amt0, i32imm:$amt1),
569  [(callseq_start timm:$amt0, timm:$amt1)],
570  "; adjcallstackup $amt0 $amt1"> {
571  let Size = 8; // Worst case. (s_add_u32 + constant)
572  let FixedSize = 1;
573  let hasSideEffects = 1;
574  let usesCustomInserter = 1;
575  let SchedRW = [WriteSALU];
576  let Defs = [SCC];
577}
578
579def ADJCALLSTACKDOWN : SPseudoInstSI<
580  (outs), (ins i32imm:$amt1, i32imm:$amt2),
581  [(callseq_end timm:$amt1, timm:$amt2)],
582  "; adjcallstackdown $amt1"> {
583  let Size = 8; // Worst case. (s_add_u32 + constant)
584  let hasSideEffects = 1;
585  let usesCustomInserter = 1;
586  let SchedRW = [WriteSALU];
587  let Defs = [SCC];
588}
589
590let Defs = [M0, EXEC, SCC],
591  UseNamedOperandTable = 1 in {
592
593// SI_INDIRECT_SRC/DST are only used by legacy SelectionDAG indirect
594// addressing implementation.
595class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI <
596  (outs VGPR_32:$vdst),
597  (ins rc:$src, VS_32:$idx, i32imm:$offset)> {
598  let usesCustomInserter = 1;
599}
600
601class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI <
602  (outs rc:$vdst),
603  (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> {
604  let Constraints = "$src = $vdst";
605  let usesCustomInserter = 1;
606}
607
608def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>;
609def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>;
610def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>;
611def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>;
612def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>;
613def SI_INDIRECT_SRC_V32 : SI_INDIRECT_SRC<VReg_1024>;
614
615def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>;
616def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>;
617def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>;
618def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>;
619def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>;
620def SI_INDIRECT_DST_V32 : SI_INDIRECT_DST<VReg_1024>;
621
622} // End Uses = [EXEC], Defs = [M0, EXEC]
623
624// This is a pseudo variant of the v_movreld_b32 instruction in which the
625// vector operand appears only twice, once as def and once as use. Using this
626// pseudo avoids problems with the Two Address instructions pass.
627class INDIRECT_REG_WRITE_MOVREL_pseudo<RegisterClass rc,
628                                RegisterOperand val_ty> : PseudoInstSI <
629  (outs rc:$vdst), (ins rc:$vsrc, val_ty:$val, i32imm:$subreg)> {
630  let Constraints = "$vsrc = $vdst";
631  let Uses = [M0];
632}
633
634class V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<RegisterClass rc> :
635  INDIRECT_REG_WRITE_MOVREL_pseudo<rc, VSrc_b32> {
636  let VALU = 1;
637  let VOP1 = 1;
638  let Uses = [M0, EXEC];
639}
640
641class S_INDIRECT_REG_WRITE_MOVREL_pseudo<RegisterClass rc,
642                                  RegisterOperand val_ty> :
643  INDIRECT_REG_WRITE_MOVREL_pseudo<rc, val_ty> {
644  let SALU = 1;
645  let SOP1 = 1;
646  let Uses = [M0];
647}
648
649class S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<RegisterClass rc> :
650  S_INDIRECT_REG_WRITE_MOVREL_pseudo<rc, SSrc_b32>;
651class S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<RegisterClass rc> :
652  S_INDIRECT_REG_WRITE_MOVREL_pseudo<rc, SSrc_b64>;
653
654def V_INDIRECT_REG_WRITE_MOVREL_B32_V1 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VGPR_32>;
655def V_INDIRECT_REG_WRITE_MOVREL_B32_V2 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_64>;
656def V_INDIRECT_REG_WRITE_MOVREL_B32_V3 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_96>;
657def V_INDIRECT_REG_WRITE_MOVREL_B32_V4 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_128>;
658def V_INDIRECT_REG_WRITE_MOVREL_B32_V5 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_160>;
659def V_INDIRECT_REG_WRITE_MOVREL_B32_V8 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_256>;
660def V_INDIRECT_REG_WRITE_MOVREL_B32_V16 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_512>;
661def V_INDIRECT_REG_WRITE_MOVREL_B32_V32 : V_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<VReg_1024>;
662
663def S_INDIRECT_REG_WRITE_MOVREL_B32_V1 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_32>;
664def S_INDIRECT_REG_WRITE_MOVREL_B32_V2 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_64>;
665def S_INDIRECT_REG_WRITE_MOVREL_B32_V3 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_96>;
666def S_INDIRECT_REG_WRITE_MOVREL_B32_V4 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_128>;
667def S_INDIRECT_REG_WRITE_MOVREL_B32_V5 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_160>;
668def S_INDIRECT_REG_WRITE_MOVREL_B32_V8 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_256>;
669def S_INDIRECT_REG_WRITE_MOVREL_B32_V16 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_512>;
670def S_INDIRECT_REG_WRITE_MOVREL_B32_V32 : S_INDIRECT_REG_WRITE_MOVREL_B32_pseudo<SReg_1024>;
671
672def S_INDIRECT_REG_WRITE_MOVREL_B64_V1 : S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<SReg_64>;
673def S_INDIRECT_REG_WRITE_MOVREL_B64_V2 : S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<SReg_128>;
674def S_INDIRECT_REG_WRITE_MOVREL_B64_V4 : S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<SReg_256>;
675def S_INDIRECT_REG_WRITE_MOVREL_B64_V8 : S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<SReg_512>;
676def S_INDIRECT_REG_WRITE_MOVREL_B64_V16 : S_INDIRECT_REG_WRITE_MOVREL_B64_pseudo<SReg_1024>;
677
678// These variants of V_INDIRECT_REG_READ/WRITE use VGPR indexing. By using these
679// pseudos we avoid spills or copies being inserted within indirect sequences
680// that switch the VGPR indexing mode. Spills to accvgprs could be effected by
681// this mode switching.
682
683class V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<RegisterClass rc> : PseudoInstSI <
684  (outs rc:$vdst), (ins rc:$vsrc, VSrc_b32:$val, SSrc_b32:$idx, i32imm:$subreg)> {
685  let Constraints = "$vsrc = $vdst";
686  let VALU = 1;
687  let Uses = [M0, EXEC];
688  let Defs = [M0];
689}
690
691def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VGPR_32>;
692def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_64>;
693def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_96>;
694def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_128>;
695def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_160>;
696def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_256>;
697def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_512>;
698def V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32 : V_INDIRECT_REG_WRITE_GPR_IDX_pseudo<VReg_1024>;
699
700class V_INDIRECT_REG_READ_GPR_IDX_pseudo<RegisterClass rc> : PseudoInstSI <
701  (outs VGPR_32:$vdst), (ins rc:$vsrc, SSrc_b32:$idx, i32imm:$subreg)> {
702  let VALU = 1;
703  let Uses = [M0, EXEC];
704  let Defs = [M0];
705}
706
707def V_INDIRECT_REG_READ_GPR_IDX_B32_V1 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VGPR_32>;
708def V_INDIRECT_REG_READ_GPR_IDX_B32_V2 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_64>;
709def V_INDIRECT_REG_READ_GPR_IDX_B32_V3 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_96>;
710def V_INDIRECT_REG_READ_GPR_IDX_B32_V4 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_128>;
711def V_INDIRECT_REG_READ_GPR_IDX_B32_V5 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_160>;
712def V_INDIRECT_REG_READ_GPR_IDX_B32_V8 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_256>;
713def V_INDIRECT_REG_READ_GPR_IDX_B32_V16 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_512>;
714def V_INDIRECT_REG_READ_GPR_IDX_B32_V32 : V_INDIRECT_REG_READ_GPR_IDX_pseudo<VReg_1024>;
715
716multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> {
717  let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in {
718    def _SAVE : PseudoInstSI <
719      (outs),
720      (ins sgpr_class:$data, i32imm:$addr)> {
721      let mayStore = 1;
722      let mayLoad = 0;
723    }
724
725    def _RESTORE : PseudoInstSI <
726      (outs sgpr_class:$data),
727      (ins i32imm:$addr)> {
728      let mayStore = 0;
729      let mayLoad = 1;
730    }
731  } // End UseNamedOperandTable = 1
732}
733
734// You cannot use M0 as the output of v_readlane_b32 instructions or
735// use it in the sdata operand of SMEM instructions. We still need to
736// be able to spill the physical register m0, so allow it for
737// SI_SPILL_32_* instructions.
738defm SI_SPILL_S32  : SI_SPILL_SGPR <SReg_32>;
739defm SI_SPILL_S64  : SI_SPILL_SGPR <SReg_64>;
740defm SI_SPILL_S96  : SI_SPILL_SGPR <SReg_96>;
741defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>;
742defm SI_SPILL_S160 : SI_SPILL_SGPR <SReg_160>;
743defm SI_SPILL_S192 : SI_SPILL_SGPR <SReg_192>;
744defm SI_SPILL_S224 : SI_SPILL_SGPR <SReg_224>;
745defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>;
746defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>;
747defm SI_SPILL_S1024 : SI_SPILL_SGPR <SReg_1024>;
748
749// VGPR or AGPR spill instructions. In case of AGPR spilling a temp register
750// needs to be used and an extra instruction to move between VGPR and AGPR.
751// UsesTmp adds to the total size of an expanded spill in this case.
752multiclass SI_SPILL_VGPR <RegisterClass vgpr_class, bit UsesTmp = 0> {
753  let UseNamedOperandTable = 1, VGPRSpill = 1,
754       SchedRW = [WriteVMEM] in {
755    def _SAVE : VPseudoInstSI <
756      (outs),
757      (ins vgpr_class:$vdata, i32imm:$vaddr,
758           SReg_32:$soffset, i32imm:$offset)> {
759      let mayStore = 1;
760      let mayLoad = 0;
761      // (2 * 4) + (8 * num_subregs) bytes maximum
762      int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), !add(UsesTmp, 3)), 8);
763      // Size field is unsigned char and cannot fit more.
764      let Size = !if(!le(MaxSize, 256), MaxSize, 252);
765    }
766
767    def _RESTORE : VPseudoInstSI <
768      (outs vgpr_class:$vdata),
769      (ins i32imm:$vaddr,
770           SReg_32:$soffset, i32imm:$offset)> {
771      let mayStore = 0;
772      let mayLoad = 1;
773
774      // (2 * 4) + (8 * num_subregs) bytes maximum
775      int MaxSize = !add(!shl(!srl(vgpr_class.Size, 5), !add(UsesTmp, 3)), 8);
776      // Size field is unsigned char and cannot fit more.
777      let Size = !if(!le(MaxSize, 256), MaxSize, 252);
778    }
779  } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM]
780}
781
782defm SI_SPILL_V32  : SI_SPILL_VGPR <VGPR_32>;
783defm SI_SPILL_V64  : SI_SPILL_VGPR <VReg_64>;
784defm SI_SPILL_V96  : SI_SPILL_VGPR <VReg_96>;
785defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>;
786defm SI_SPILL_V160 : SI_SPILL_VGPR <VReg_160>;
787defm SI_SPILL_V192 : SI_SPILL_VGPR <VReg_192>;
788defm SI_SPILL_V224 : SI_SPILL_VGPR <VReg_224>;
789defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>;
790defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>;
791defm SI_SPILL_V1024 : SI_SPILL_VGPR <VReg_1024>;
792
793defm SI_SPILL_A32  : SI_SPILL_VGPR <AGPR_32, 1>;
794defm SI_SPILL_A64  : SI_SPILL_VGPR <AReg_64, 1>;
795defm SI_SPILL_A96  : SI_SPILL_VGPR <AReg_96, 1>;
796defm SI_SPILL_A128 : SI_SPILL_VGPR <AReg_128, 1>;
797defm SI_SPILL_A160 : SI_SPILL_VGPR <AReg_160, 1>;
798defm SI_SPILL_A192 : SI_SPILL_VGPR <AReg_192, 1>;
799defm SI_SPILL_A224 : SI_SPILL_VGPR <AReg_224, 1>;
800defm SI_SPILL_A256 : SI_SPILL_VGPR <AReg_256, 1>;
801defm SI_SPILL_A512 : SI_SPILL_VGPR <AReg_512, 1>;
802defm SI_SPILL_A1024 : SI_SPILL_VGPR <AReg_1024, 1>;
803
804defm SI_SPILL_AV32  : SI_SPILL_VGPR <AV_32, 1>;
805defm SI_SPILL_AV64  : SI_SPILL_VGPR <AV_64, 1>;
806defm SI_SPILL_AV96  : SI_SPILL_VGPR <AV_96, 1>;
807defm SI_SPILL_AV128 : SI_SPILL_VGPR <AV_128, 1>;
808defm SI_SPILL_AV160 : SI_SPILL_VGPR <AV_160, 1>;
809defm SI_SPILL_AV192 : SI_SPILL_VGPR <AV_192, 1>;
810defm SI_SPILL_AV224 : SI_SPILL_VGPR <AV_224, 1>;
811defm SI_SPILL_AV256 : SI_SPILL_VGPR <AV_256, 1>;
812defm SI_SPILL_AV512 : SI_SPILL_VGPR <AV_512, 1>;
813defm SI_SPILL_AV1024 : SI_SPILL_VGPR <AV_1024, 1>;
814
815def SI_PC_ADD_REL_OFFSET : SPseudoInstSI <
816  (outs SReg_64:$dst),
817  (ins si_ga:$ptr_lo, si_ga:$ptr_hi),
818  [(set SReg_64:$dst,
819      (i64 (SIpc_add_rel_offset tglobaladdr:$ptr_lo, tglobaladdr:$ptr_hi)))]> {
820  let Defs = [SCC];
821}
822
823def : GCNPat <
824  (SIpc_add_rel_offset tglobaladdr:$ptr_lo, 0),
825  (SI_PC_ADD_REL_OFFSET $ptr_lo, (i32 0))
826>;
827
828def : GCNPat<
829  (AMDGPUtrap timm:$trapid),
830  (S_TRAP $trapid)
831>;
832
833def : GCNPat<
834  (AMDGPUelse i1:$src, bb:$target),
835  (SI_ELSE $src, $target)
836>;
837
838def : Pat <
839  (int_amdgcn_kill i1:$src),
840  (SI_KILL_I1_PSEUDO SCSrc_i1:$src, 0)
841>;
842
843def : Pat <
844  (int_amdgcn_kill (i1 (not i1:$src))),
845  (SI_KILL_I1_PSEUDO SCSrc_i1:$src, -1)
846>;
847
848def : Pat <
849  (int_amdgcn_kill (i1 (setcc f32:$src, InlineImmFP32:$imm, cond:$cond))),
850  (SI_KILL_F32_COND_IMM_PSEUDO VSrc_b32:$src, (bitcast_fpimm_to_i32 $imm), (cond_as_i32imm $cond))
851>;
852
853def : Pat <
854  (int_amdgcn_wqm_demote i1:$src),
855  (SI_DEMOTE_I1 SCSrc_i1:$src, 0)
856>;
857
858def : Pat <
859  (int_amdgcn_wqm_demote (i1 (not i1:$src))),
860  (SI_DEMOTE_I1 SCSrc_i1:$src, -1)
861>;
862
863  // TODO: we could add more variants for other types of conditionals
864
865def : Pat <
866  (i64 (int_amdgcn_icmp i1:$src, (i1 0), (i32 33))),
867  (COPY $src) // Return the SGPRs representing i1 src
868>;
869
870def : Pat <
871  (i32 (int_amdgcn_icmp i1:$src, (i1 0), (i32 33))),
872  (COPY $src) // Return the SGPRs representing i1 src
873>;
874
875//===----------------------------------------------------------------------===//
876// VOP1 Patterns
877//===----------------------------------------------------------------------===//
878
879let OtherPredicates = [UnsafeFPMath] in {
880
881// Convert (x - floor(x)) to fract(x)
882def : GCNPat <
883  (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)),
884             (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))),
885  (V_FRACT_F32_e64 $mods, $x)
886>;
887
888// Convert (x + (-floor(x))) to fract(x)
889def : GCNPat <
890  (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)),
891             (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))),
892  (V_FRACT_F64_e64 $mods, $x)
893>;
894
895} // End OtherPredicates = [UnsafeFPMath]
896
897
898// f16_to_fp patterns
899def : GCNPat <
900  (f32 (f16_to_fp i32:$src0)),
901  (V_CVT_F32_F16_e64 SRCMODS.NONE, $src0)
902>;
903
904def : GCNPat <
905  (f32 (f16_to_fp (and_oneuse i32:$src0, 0x7fff))),
906  (V_CVT_F32_F16_e64 SRCMODS.ABS, $src0)
907>;
908
909def : GCNPat <
910  (f32 (f16_to_fp (i32 (srl_oneuse (and_oneuse i32:$src0, 0x7fff0000), (i32 16))))),
911  (V_CVT_F32_F16_e64 SRCMODS.ABS, (i32 (V_LSHRREV_B32_e64 (i32 16), i32:$src0)))
912>;
913
914def : GCNPat <
915  (f32 (f16_to_fp (or_oneuse i32:$src0, 0x8000))),
916  (V_CVT_F32_F16_e64 SRCMODS.NEG_ABS, $src0)
917>;
918
919def : GCNPat <
920  (f32 (f16_to_fp (xor_oneuse i32:$src0, 0x8000))),
921  (V_CVT_F32_F16_e64 SRCMODS.NEG, $src0)
922>;
923
924def : GCNPat <
925  (f64 (fpextend f16:$src)),
926  (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src))
927>;
928
929// fp_to_fp16 patterns
930def : GCNPat <
931  (i32 (AMDGPUfp_to_f16 (f32 (VOP3Mods f32:$src0, i32:$src0_modifiers)))),
932  (V_CVT_F16_F32_e64 $src0_modifiers, f32:$src0)
933>;
934
935def : GCNPat <
936  (i32 (fp_to_sint f16:$src)),
937  (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 VSrc_b32:$src))
938>;
939
940def : GCNPat <
941  (i32 (fp_to_uint f16:$src)),
942  (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 VSrc_b32:$src))
943>;
944
945def : GCNPat <
946  (f16 (sint_to_fp i32:$src)),
947  (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 VSrc_b32:$src))
948>;
949
950def : GCNPat <
951  (f16 (uint_to_fp i32:$src)),
952  (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 VSrc_b32:$src))
953>;
954
955//===----------------------------------------------------------------------===//
956// VOP2 Patterns
957//===----------------------------------------------------------------------===//
958
959// NoMods pattern used for mac. If there are any source modifiers then it's
960// better to select mad instead of mac.
961class FMADPat <ValueType vt, Instruction inst, SDPatternOperator node>
962  : GCNPat <(vt (node (vt (VOP3NoMods vt:$src0)),
963                      (vt (VOP3NoMods vt:$src1)),
964                      (vt (VOP3NoMods vt:$src2)))),
965    (inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
966          SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
967>;
968
969// Prefer mac form when there are no modifiers.
970let AddedComplexity = 9 in {
971let OtherPredicates = [HasMadMacF32Insts] in {
972def : FMADPat <f32, V_MAC_F32_e64, fmad>;
973def : FMADPat <f32, V_MAC_F32_e64, AMDGPUfmad_ftz>;
974} // OtherPredicates = [HasMadMacF32Insts]
975
976// Don't allow source modifiers. If there are any source modifiers then it's
977// better to select mad instead of mac.
978let SubtargetPredicate = isGFX6GFX7GFX10,
979    OtherPredicates = [HasMadMacF32Insts, NoFP32Denormals] in
980def : GCNPat <
981      (f32 (fadd (AMDGPUfmul_legacy (VOP3NoMods f32:$src0),
982                                    (VOP3NoMods f32:$src1)),
983                 (VOP3NoMods f32:$src2))),
984      (V_MAC_LEGACY_F32_e64 SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
985                            SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
986>;
987
988// Don't allow source modifiers. If there are any source modifiers then it's
989// better to select fma instead of fmac.
990let SubtargetPredicate = HasFmaLegacy32 in
991def : GCNPat <
992      (f32 (int_amdgcn_fma_legacy (VOP3NoMods f32:$src0),
993                                  (VOP3NoMods f32:$src1),
994                                  (VOP3NoMods f32:$src2))),
995      (V_FMAC_LEGACY_F32_e64 SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
996                             SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
997>;
998
999let SubtargetPredicate = Has16BitInsts in {
1000def : FMADPat <f16, V_MAC_F16_e64, fmad>;
1001def : FMADPat <f16, V_MAC_F16_e64, AMDGPUfmad_ftz>;
1002} // SubtargetPredicate = Has16BitInsts
1003} // AddedComplexity = 9
1004
1005class FMADModsPat<ValueType Ty, Instruction inst, SDPatternOperator mad_opr>
1006  : GCNPat<
1007  (Ty (mad_opr (Ty (VOP3Mods Ty:$src0, i32:$src0_mod)),
1008               (Ty (VOP3Mods Ty:$src1, i32:$src1_mod)),
1009               (Ty (VOP3Mods Ty:$src2, i32:$src2_mod)))),
1010  (inst $src0_mod, $src0, $src1_mod, $src1,
1011  $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
1012>;
1013
1014let OtherPredicates = [HasMadMacF32Insts] in
1015def : FMADModsPat<f32, V_MAD_F32_e64, AMDGPUfmad_ftz>;
1016
1017let OtherPredicates = [HasMadMacF32Insts, NoFP32Denormals] in
1018def : GCNPat <
1019      (f32 (fadd (AMDGPUfmul_legacy (VOP3Mods f32:$src0, i32:$src0_mod),
1020                                    (VOP3Mods f32:$src1, i32:$src1_mod)),
1021                 (VOP3Mods f32:$src2, i32:$src2_mod))),
1022      (V_MAD_LEGACY_F32_e64 $src0_mod, $src0, $src1_mod, $src1,
1023                        $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
1024>;
1025
1026let SubtargetPredicate = Has16BitInsts in
1027def : FMADModsPat<f16, V_MAD_F16_e64, AMDGPUfmad_ftz>;
1028
1029class VOPSelectModsPat <ValueType vt> : GCNPat <
1030  (vt (select i1:$src0, (VOP3Mods vt:$src1, i32:$src1_mods),
1031                        (VOP3Mods vt:$src2, i32:$src2_mods))),
1032  (V_CNDMASK_B32_e64 FP32InputMods:$src2_mods, VSrc_b32:$src2,
1033                     FP32InputMods:$src1_mods, VSrc_b32:$src1, SSrc_i1:$src0)
1034>;
1035
1036class VOPSelectPat <ValueType vt> : GCNPat <
1037  (vt (select i1:$src0, vt:$src1, vt:$src2)),
1038  (V_CNDMASK_B32_e64 0, VSrc_b32:$src2, 0, VSrc_b32:$src1, SSrc_i1:$src0)
1039>;
1040
1041def : VOPSelectModsPat <i32>;
1042def : VOPSelectModsPat <f32>;
1043def : VOPSelectPat <f16>;
1044def : VOPSelectPat <i16>;
1045
1046let AddedComplexity = 1 in {
1047def : GCNPat <
1048  (i32 (add (i32 (getDivergentFrag<ctpop>.ret i32:$popcnt)), i32:$val)),
1049  (V_BCNT_U32_B32_e64 $popcnt, $val)
1050>;
1051}
1052
1053def : GCNPat <
1054  (i32 (DivergentUnaryFrag<ctpop> i32:$popcnt)),
1055  (V_BCNT_U32_B32_e64 VSrc_b32:$popcnt, (i32 0))
1056>;
1057
1058def : GCNPat <
1059  (i16 (add (i16 (trunc (i32 (getDivergentFrag<ctpop>.ret i32:$popcnt)))), i16:$val)),
1060  (V_BCNT_U32_B32_e64 $popcnt, $val)
1061>;
1062
1063def : GCNPat <
1064  (i64 (DivergentUnaryFrag<ctpop> i64:$src)),
1065  (REG_SEQUENCE VReg_64,
1066    (V_BCNT_U32_B32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub1)),
1067      (i32 (V_BCNT_U32_B32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0)))), sub0,
1068      (i32 (V_MOV_B32_e32 (i32 0))), sub1)
1069>;
1070
1071/********** ============================================ **********/
1072/********** Extraction, Insertion, Building and Casting  **********/
1073/********** ============================================ **********/
1074
1075// Special case for 2 element vectors. REQ_SEQUENCE produces better code
1076// than an INSERT_SUBREG.
1077multiclass Insert_Element_V2<RegisterClass RC, ValueType elem_type, ValueType vec_type> {
1078  def : GCNPat <
1079    (insertelt vec_type:$vec, elem_type:$elem, 0),
1080    (REG_SEQUENCE RC, $elem, sub0, (elem_type (EXTRACT_SUBREG $vec, sub1)), sub1)
1081  >;
1082
1083  def : GCNPat <
1084    (insertelt vec_type:$vec, elem_type:$elem, 1),
1085    (REG_SEQUENCE RC, (elem_type (EXTRACT_SUBREG $vec, sub0)), sub0, $elem, sub1)
1086  >;
1087}
1088
1089foreach Index = 0-1 in {
1090  def Extract_Element_v2i32_#Index : Extract_Element <
1091    i32, v2i32, Index, !cast<SubRegIndex>(sub#Index)
1092  >;
1093
1094  def Extract_Element_v2f32_#Index : Extract_Element <
1095    f32, v2f32, Index, !cast<SubRegIndex>(sub#Index)
1096  >;
1097}
1098
1099defm : Insert_Element_V2 <SReg_64, i32, v2i32>;
1100defm : Insert_Element_V2 <SReg_64, f32, v2f32>;
1101
1102foreach Index = 0-2 in {
1103  def Extract_Element_v3i32_#Index : Extract_Element <
1104    i32, v3i32, Index, !cast<SubRegIndex>(sub#Index)
1105  >;
1106  def Insert_Element_v3i32_#Index : Insert_Element <
1107    i32, v3i32, Index, !cast<SubRegIndex>(sub#Index)
1108  >;
1109
1110  def Extract_Element_v3f32_#Index : Extract_Element <
1111    f32, v3f32, Index, !cast<SubRegIndex>(sub#Index)
1112  >;
1113  def Insert_Element_v3f32_#Index : Insert_Element <
1114    f32, v3f32, Index, !cast<SubRegIndex>(sub#Index)
1115  >;
1116}
1117
1118foreach Index = 0-3 in {
1119  def Extract_Element_v4i32_#Index : Extract_Element <
1120    i32, v4i32, Index, !cast<SubRegIndex>(sub#Index)
1121  >;
1122  def Insert_Element_v4i32_#Index : Insert_Element <
1123    i32, v4i32, Index, !cast<SubRegIndex>(sub#Index)
1124  >;
1125
1126  def Extract_Element_v4f32_#Index : Extract_Element <
1127    f32, v4f32, Index, !cast<SubRegIndex>(sub#Index)
1128  >;
1129  def Insert_Element_v4f32_#Index : Insert_Element <
1130    f32, v4f32, Index, !cast<SubRegIndex>(sub#Index)
1131  >;
1132}
1133
1134foreach Index = 0-4 in {
1135  def Extract_Element_v5i32_#Index : Extract_Element <
1136    i32, v5i32, Index, !cast<SubRegIndex>(sub#Index)
1137  >;
1138  def Insert_Element_v5i32_#Index : Insert_Element <
1139    i32, v5i32, Index, !cast<SubRegIndex>(sub#Index)
1140  >;
1141
1142  def Extract_Element_v5f32_#Index : Extract_Element <
1143    f32, v5f32, Index, !cast<SubRegIndex>(sub#Index)
1144  >;
1145  def Insert_Element_v5f32_#Index : Insert_Element <
1146    f32, v5f32, Index, !cast<SubRegIndex>(sub#Index)
1147  >;
1148}
1149
1150foreach Index = 0-5 in {
1151  def Extract_Element_v6i32_#Index : Extract_Element <
1152    i32, v6i32, Index, !cast<SubRegIndex>(sub#Index)
1153  >;
1154  def Insert_Element_v6i32_#Index : Insert_Element <
1155    i32, v6i32, Index, !cast<SubRegIndex>(sub#Index)
1156  >;
1157
1158  def Extract_Element_v6f32_#Index : Extract_Element <
1159    f32, v6f32, Index, !cast<SubRegIndex>(sub#Index)
1160  >;
1161  def Insert_Element_v6f32_#Index : Insert_Element <
1162    f32, v6f32, Index, !cast<SubRegIndex>(sub#Index)
1163  >;
1164}
1165
1166foreach Index = 0-6 in {
1167  def Extract_Element_v7i32_#Index : Extract_Element <
1168    i32, v7i32, Index, !cast<SubRegIndex>(sub#Index)
1169  >;
1170  def Insert_Element_v7i32_#Index : Insert_Element <
1171    i32, v7i32, Index, !cast<SubRegIndex>(sub#Index)
1172  >;
1173
1174  def Extract_Element_v7f32_#Index : Extract_Element <
1175    f32, v7f32, Index, !cast<SubRegIndex>(sub#Index)
1176  >;
1177  def Insert_Element_v7f32_#Index : Insert_Element <
1178    f32, v7f32, Index, !cast<SubRegIndex>(sub#Index)
1179  >;
1180}
1181
1182foreach Index = 0-7 in {
1183  def Extract_Element_v8i32_#Index : Extract_Element <
1184    i32, v8i32, Index, !cast<SubRegIndex>(sub#Index)
1185  >;
1186  def Insert_Element_v8i32_#Index : Insert_Element <
1187    i32, v8i32, Index, !cast<SubRegIndex>(sub#Index)
1188  >;
1189
1190  def Extract_Element_v8f32_#Index : Extract_Element <
1191    f32, v8f32, Index, !cast<SubRegIndex>(sub#Index)
1192  >;
1193  def Insert_Element_v8f32_#Index : Insert_Element <
1194    f32, v8f32, Index, !cast<SubRegIndex>(sub#Index)
1195  >;
1196}
1197
1198foreach Index = 0-15 in {
1199  def Extract_Element_v16i32_#Index : Extract_Element <
1200    i32, v16i32, Index, !cast<SubRegIndex>(sub#Index)
1201  >;
1202  def Insert_Element_v16i32_#Index : Insert_Element <
1203    i32, v16i32, Index, !cast<SubRegIndex>(sub#Index)
1204  >;
1205
1206  def Extract_Element_v16f32_#Index : Extract_Element <
1207    f32, v16f32, Index, !cast<SubRegIndex>(sub#Index)
1208  >;
1209  def Insert_Element_v16f32_#Index : Insert_Element <
1210    f32, v16f32, Index, !cast<SubRegIndex>(sub#Index)
1211  >;
1212}
1213
1214
1215def : Pat <
1216  (extract_subvector v4i16:$vec, (i32 0)),
1217  (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub0))
1218>;
1219
1220def : Pat <
1221  (extract_subvector v4i16:$vec, (i32 2)),
1222  (v2i16 (EXTRACT_SUBREG v4i16:$vec, sub1))
1223>;
1224
1225def : Pat <
1226  (extract_subvector v4f16:$vec, (i32 0)),
1227  (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub0))
1228>;
1229
1230def : Pat <
1231  (extract_subvector v4f16:$vec, (i32 2)),
1232  (v2f16 (EXTRACT_SUBREG v4f16:$vec, sub1))
1233>;
1234
1235def : Pat <
1236  (extract_subvector v8i16:$vec, (i32 0)),
1237  (v4i16 (EXTRACT_SUBREG v8i16:$vec, sub0_sub1))
1238>;
1239
1240def : Pat <
1241  (extract_subvector v8i16:$vec, (i32 4)),
1242  (v4i16 (EXTRACT_SUBREG v8i16:$vec, sub2_sub3))
1243>;
1244
1245def : Pat <
1246  (extract_subvector v8f16:$vec, (i32 0)),
1247  (v4f16 (EXTRACT_SUBREG v8f16:$vec, sub0_sub1))
1248>;
1249
1250def : Pat <
1251  (extract_subvector v8f16:$vec, (i32 4)),
1252  (v4f16 (EXTRACT_SUBREG v8f16:$vec, sub2_sub3))
1253>;
1254
1255foreach Index = 0-31 in {
1256  def Extract_Element_v32i32_#Index : Extract_Element <
1257    i32, v32i32, Index, !cast<SubRegIndex>(sub#Index)
1258  >;
1259
1260  def Insert_Element_v32i32_#Index : Insert_Element <
1261    i32, v32i32, Index, !cast<SubRegIndex>(sub#Index)
1262  >;
1263
1264  def Extract_Element_v32f32_#Index : Extract_Element <
1265    f32, v32f32, Index, !cast<SubRegIndex>(sub#Index)
1266  >;
1267
1268  def Insert_Element_v32f32_#Index : Insert_Element <
1269    f32, v32f32, Index, !cast<SubRegIndex>(sub#Index)
1270  >;
1271}
1272
1273// FIXME: Why do only some of these type combinations for SReg and
1274// VReg?
1275// 16-bit bitcast
1276def : BitConvert <i16, f16, VGPR_32>;
1277def : BitConvert <f16, i16, VGPR_32>;
1278def : BitConvert <i16, f16, SReg_32>;
1279def : BitConvert <f16, i16, SReg_32>;
1280
1281// 32-bit bitcast
1282def : BitConvert <i32, f32, VGPR_32>;
1283def : BitConvert <f32, i32, VGPR_32>;
1284def : BitConvert <i32, f32, SReg_32>;
1285def : BitConvert <f32, i32, SReg_32>;
1286def : BitConvert <v2i16, i32, SReg_32>;
1287def : BitConvert <i32, v2i16, SReg_32>;
1288def : BitConvert <v2f16, i32, SReg_32>;
1289def : BitConvert <i32, v2f16, SReg_32>;
1290def : BitConvert <v2i16, v2f16, SReg_32>;
1291def : BitConvert <v2f16, v2i16, SReg_32>;
1292def : BitConvert <v2f16, f32, SReg_32>;
1293def : BitConvert <f32, v2f16, SReg_32>;
1294def : BitConvert <v2i16, f32, SReg_32>;
1295def : BitConvert <f32, v2i16, SReg_32>;
1296
1297// 64-bit bitcast
1298def : BitConvert <i64, f64, VReg_64>;
1299def : BitConvert <f64, i64, VReg_64>;
1300def : BitConvert <v2i32, v2f32, VReg_64>;
1301def : BitConvert <v2f32, v2i32, VReg_64>;
1302def : BitConvert <i64, v2i32, VReg_64>;
1303def : BitConvert <v2i32, i64, VReg_64>;
1304def : BitConvert <i64, v2f32, VReg_64>;
1305def : BitConvert <v2f32, i64, VReg_64>;
1306def : BitConvert <f64, v2f32, VReg_64>;
1307def : BitConvert <v2f32, f64, VReg_64>;
1308def : BitConvert <f64, v2i32, VReg_64>;
1309def : BitConvert <v2i32, f64, VReg_64>;
1310def : BitConvert <v4i16, v4f16, VReg_64>;
1311def : BitConvert <v4f16, v4i16, VReg_64>;
1312
1313// FIXME: Make SGPR
1314def : BitConvert <v2i32, v4f16, VReg_64>;
1315def : BitConvert <v4f16, v2i32, VReg_64>;
1316def : BitConvert <v2i32, v4f16, VReg_64>;
1317def : BitConvert <v2i32, v4i16, VReg_64>;
1318def : BitConvert <v4i16, v2i32, VReg_64>;
1319def : BitConvert <v2f32, v4f16, VReg_64>;
1320def : BitConvert <v4f16, v2f32, VReg_64>;
1321def : BitConvert <v2f32, v4i16, VReg_64>;
1322def : BitConvert <v4i16, v2f32, VReg_64>;
1323def : BitConvert <v4i16, f64, VReg_64>;
1324def : BitConvert <v4f16, f64, VReg_64>;
1325def : BitConvert <f64, v4i16, VReg_64>;
1326def : BitConvert <f64, v4f16, VReg_64>;
1327def : BitConvert <v4i16, i64, VReg_64>;
1328def : BitConvert <v4f16, i64, VReg_64>;
1329def : BitConvert <i64, v4i16, VReg_64>;
1330def : BitConvert <i64, v4f16, VReg_64>;
1331
1332def : BitConvert <v4i32, v4f32, VReg_128>;
1333def : BitConvert <v4f32, v4i32, VReg_128>;
1334
1335// 96-bit bitcast
1336def : BitConvert <v3i32, v3f32, SGPR_96>;
1337def : BitConvert <v3f32, v3i32, SGPR_96>;
1338
1339// 128-bit bitcast
1340def : BitConvert <v2i64, v4i32, SReg_128>;
1341def : BitConvert <v4i32, v2i64, SReg_128>;
1342def : BitConvert <v2f64, v4f32, VReg_128>;
1343def : BitConvert <v2f64, v4i32, VReg_128>;
1344def : BitConvert <v4f32, v2f64, VReg_128>;
1345def : BitConvert <v4i32, v2f64, VReg_128>;
1346def : BitConvert <v2i64, v2f64, VReg_128>;
1347def : BitConvert <v2f64, v2i64, VReg_128>;
1348def : BitConvert <v4f32, v2i64, VReg_128>;
1349def : BitConvert <v2i64, v4f32, VReg_128>;
1350def : BitConvert <v8i16, v4i32, SReg_128>;
1351def : BitConvert <v4i32, v8i16, SReg_128>;
1352def : BitConvert <v8f16, v4f32, VReg_128>;
1353def : BitConvert <v8f16, v4i32, VReg_128>;
1354def : BitConvert <v4f32, v8f16, VReg_128>;
1355def : BitConvert <v4i32, v8f16, VReg_128>;
1356def : BitConvert <v8i16, v8f16, VReg_128>;
1357def : BitConvert <v8f16, v8i16, VReg_128>;
1358def : BitConvert <v4f32, v8i16, VReg_128>;
1359def : BitConvert <v8i16, v4f32, VReg_128>;
1360def : BitConvert <v8i16, v8f16, SReg_128>;
1361def : BitConvert <v8i16, v2i64, SReg_128>;
1362def : BitConvert <v8i16, v2f64, SReg_128>;
1363def : BitConvert <v8f16, v2i64, SReg_128>;
1364def : BitConvert <v8f16, v2f64, SReg_128>;
1365def : BitConvert <v8f16, v8i16, SReg_128>;
1366def : BitConvert <v2i64, v8i16, SReg_128>;
1367def : BitConvert <v2f64, v8i16, SReg_128>;
1368def : BitConvert <v2i64, v8f16, SReg_128>;
1369def : BitConvert <v2f64, v8f16, SReg_128>;
1370
1371// 160-bit bitcast
1372def : BitConvert <v5i32, v5f32, SReg_160>;
1373def : BitConvert <v5f32, v5i32, SReg_160>;
1374def : BitConvert <v5i32, v5f32, VReg_160>;
1375def : BitConvert <v5f32, v5i32, VReg_160>;
1376
1377// 192-bit bitcast
1378def : BitConvert <v6i32, v6f32, SReg_192>;
1379def : BitConvert <v6f32, v6i32, SReg_192>;
1380def : BitConvert <v6i32, v6f32, VReg_192>;
1381def : BitConvert <v6f32, v6i32, VReg_192>;
1382def : BitConvert <v3i64, v3f64, VReg_192>;
1383def : BitConvert <v3f64, v3i64, VReg_192>;
1384def : BitConvert <v3i64, v6i32, VReg_192>;
1385def : BitConvert <v3i64, v6f32, VReg_192>;
1386def : BitConvert <v3f64, v6i32, VReg_192>;
1387def : BitConvert <v3f64, v6f32, VReg_192>;
1388def : BitConvert <v6i32, v3i64, VReg_192>;
1389def : BitConvert <v6f32, v3i64, VReg_192>;
1390def : BitConvert <v6i32, v3f64, VReg_192>;
1391def : BitConvert <v6f32, v3f64, VReg_192>;
1392
1393// 224-bit bitcast
1394def : BitConvert <v7i32, v7f32, SReg_224>;
1395def : BitConvert <v7f32, v7i32, SReg_224>;
1396def : BitConvert <v7i32, v7f32, VReg_224>;
1397def : BitConvert <v7f32, v7i32, VReg_224>;
1398
1399// 256-bit bitcast
1400def : BitConvert <v8i32, v8f32, SReg_256>;
1401def : BitConvert <v8f32, v8i32, SReg_256>;
1402def : BitConvert <v8i32, v8f32, VReg_256>;
1403def : BitConvert <v8f32, v8i32, VReg_256>;
1404def : BitConvert <v4i64, v4f64, VReg_256>;
1405def : BitConvert <v4f64, v4i64, VReg_256>;
1406def : BitConvert <v4i64, v8i32, VReg_256>;
1407def : BitConvert <v4i64, v8f32, VReg_256>;
1408def : BitConvert <v4f64, v8i32, VReg_256>;
1409def : BitConvert <v4f64, v8f32, VReg_256>;
1410def : BitConvert <v8i32, v4i64, VReg_256>;
1411def : BitConvert <v8f32, v4i64, VReg_256>;
1412def : BitConvert <v8i32, v4f64, VReg_256>;
1413def : BitConvert <v8f32, v4f64, VReg_256>;
1414
1415
1416// 512-bit bitcast
1417def : BitConvert <v16i32, v16f32, VReg_512>;
1418def : BitConvert <v16f32, v16i32, VReg_512>;
1419def : BitConvert <v8i64,  v8f64,  VReg_512>;
1420def : BitConvert <v8f64,  v8i64,  VReg_512>;
1421def : BitConvert <v8i64,  v16i32, VReg_512>;
1422def : BitConvert <v8f64,  v16i32, VReg_512>;
1423def : BitConvert <v16i32, v8i64,  VReg_512>;
1424def : BitConvert <v16i32, v8f64,  VReg_512>;
1425def : BitConvert <v8i64,  v16f32, VReg_512>;
1426def : BitConvert <v8f64,  v16f32, VReg_512>;
1427def : BitConvert <v16f32, v8i64,  VReg_512>;
1428def : BitConvert <v16f32, v8f64,  VReg_512>;
1429
1430// 1024-bit bitcast
1431def : BitConvert <v32i32, v32f32, VReg_1024>;
1432def : BitConvert <v32f32, v32i32, VReg_1024>;
1433def : BitConvert <v16i64, v16f64, VReg_1024>;
1434def : BitConvert <v16f64, v16i64, VReg_1024>;
1435def : BitConvert <v16i64, v32i32, VReg_1024>;
1436def : BitConvert <v32i32, v16i64, VReg_1024>;
1437def : BitConvert <v16f64, v32f32, VReg_1024>;
1438def : BitConvert <v32f32, v16f64, VReg_1024>;
1439def : BitConvert <v16i64, v32f32, VReg_1024>;
1440def : BitConvert <v32i32, v16f64, VReg_1024>;
1441def : BitConvert <v16f64, v32i32, VReg_1024>;
1442def : BitConvert <v32f32, v16i64, VReg_1024>;
1443
1444
1445/********** =================== **********/
1446/********** Src & Dst modifiers **********/
1447/********** =================== **********/
1448
1449
1450// If denormals are not enabled, it only impacts the compare of the
1451// inputs. The output result is not flushed.
1452class ClampPat<Instruction inst, ValueType vt> : GCNPat <
1453  (vt (AMDGPUclamp (VOP3Mods vt:$src0, i32:$src0_modifiers))),
1454  (inst i32:$src0_modifiers, vt:$src0,
1455        i32:$src0_modifiers, vt:$src0, DSTCLAMP.ENABLE, DSTOMOD.NONE)
1456>;
1457
1458def : ClampPat<V_MAX_F32_e64, f32>;
1459def : ClampPat<V_MAX_F64_e64, f64>;
1460def : ClampPat<V_MAX_F16_e64, f16>;
1461
1462let SubtargetPredicate = HasVOP3PInsts in {
1463def : GCNPat <
1464  (v2f16 (AMDGPUclamp (VOP3PMods v2f16:$src0, i32:$src0_modifiers))),
1465  (V_PK_MAX_F16 $src0_modifiers, $src0,
1466                $src0_modifiers, $src0, DSTCLAMP.ENABLE)
1467>;
1468}
1469
1470
1471/********** ================================ **********/
1472/********** Floating point absolute/negative **********/
1473/********** ================================ **********/
1474
1475def : GCNPat <
1476  (UniformUnaryFrag<fneg> (fabs (f32 SReg_32:$src))),
1477  (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80000000))) // Set sign bit
1478>;
1479
1480def : GCNPat <
1481  (UniformUnaryFrag<fabs> (f32 SReg_32:$src)),
1482  (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x7fffffff)))
1483>;
1484
1485def : GCNPat <
1486  (UniformUnaryFrag<fneg> (f32 SReg_32:$src)),
1487  (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80000000)))
1488>;
1489
1490def : GCNPat <
1491  (UniformUnaryFrag<fneg> (f16 SReg_32:$src)),
1492  (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00008000)))
1493>;
1494
1495def : GCNPat <
1496  (UniformUnaryFrag<fabs> (f16 SReg_32:$src)),
1497  (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00007fff)))
1498>;
1499
1500def : GCNPat <
1501  (UniformUnaryFrag<fneg> (fabs (f16 SReg_32:$src))),
1502  (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit
1503>;
1504
1505def : GCNPat <
1506  (UniformUnaryFrag<fneg> (v2f16 SReg_32:$src)),
1507  (S_XOR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000)))
1508>;
1509
1510def : GCNPat <
1511  (UniformUnaryFrag<fabs> (v2f16 SReg_32:$src)),
1512  (S_AND_B32 SReg_32:$src, (S_MOV_B32 (i32 0x7fff7fff)))
1513>;
1514
1515// This is really (fneg (fabs v2f16:$src))
1516//
1517// fabs is not reported as free because there is modifier for it in
1518// VOP3P instructions, so it is turned into the bit op.
1519def : GCNPat <
1520  (UniformUnaryFrag<fneg> (v2f16 (bitconvert (and_oneuse (i32 SReg_32:$src), 0x7fff7fff)))),
1521  (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit
1522>;
1523
1524def : GCNPat <
1525  (UniformUnaryFrag<fneg> (v2f16 (fabs SReg_32:$src))),
1526  (S_OR_B32 SReg_32:$src, (S_MOV_B32 (i32 0x80008000))) // Set sign bit
1527>;
1528
1529
1530// COPY_TO_REGCLASS is needed to avoid using SCC from S_XOR_B32 instead
1531// of the real value.
1532def : GCNPat <
1533  (UniformUnaryFrag<fneg> (v2f32 SReg_64:$src)),
1534  (v2f32 (REG_SEQUENCE SReg_64,
1535         (f32 (COPY_TO_REGCLASS (S_XOR_B32 (i32 (EXTRACT_SUBREG $src, sub0)),
1536                                           (i32 (S_MOV_B32 (i32 0x80000000)))),
1537                                 SReg_32)), sub0,
1538         (f32 (COPY_TO_REGCLASS (S_XOR_B32 (i32 (EXTRACT_SUBREG $src, sub1)),
1539                                           (i32 (S_MOV_B32 (i32 0x80000000)))),
1540                                 SReg_32)), sub1))
1541>;
1542
1543def : GCNPat <
1544  (UniformUnaryFrag<fabs> (v2f32 SReg_64:$src)),
1545  (v2f32 (REG_SEQUENCE SReg_64,
1546         (f32 (COPY_TO_REGCLASS (S_AND_B32 (i32 (EXTRACT_SUBREG $src, sub0)),
1547                                           (i32 (S_MOV_B32 (i32 0x7fffffff)))),
1548                                 SReg_32)), sub0,
1549         (f32 (COPY_TO_REGCLASS (S_AND_B32 (i32 (EXTRACT_SUBREG $src, sub1)),
1550                                           (i32 (S_MOV_B32 (i32 0x7fffffff)))),
1551                                 SReg_32)), sub1))
1552>;
1553
1554def : GCNPat <
1555  (UniformUnaryFrag<fneg> (fabs (v2f32 SReg_64:$src))),
1556  (v2f32 (REG_SEQUENCE SReg_64,
1557         (f32 (COPY_TO_REGCLASS (S_OR_B32 (i32 (EXTRACT_SUBREG $src, sub0)),
1558                                           (i32 (S_MOV_B32 (i32 0x80000000)))),
1559                                 SReg_32)), sub0,
1560         (f32 (COPY_TO_REGCLASS (S_OR_B32 (i32 (EXTRACT_SUBREG $src, sub1)),
1561                                           (i32 (S_MOV_B32 (i32 0x80000000)))),
1562                                 SReg_32)), sub1))
1563>;
1564
1565// FIXME: Use S_BITSET0_B32/B64?
1566def : GCNPat <
1567  (UniformUnaryFrag<fabs> (f64 SReg_64:$src)),
1568  (REG_SEQUENCE SReg_64,
1569    (i32 (EXTRACT_SUBREG SReg_64:$src, sub0)),
1570    sub0,
1571    (i32 (COPY_TO_REGCLASS (S_AND_B32 (i32 (EXTRACT_SUBREG SReg_64:$src, sub1)),
1572                   (S_MOV_B32 (i32 0x7fffffff))), SReg_32)), // Set sign bit.
1573     sub1)
1574>;
1575
1576def : GCNPat <
1577  (UniformUnaryFrag<fneg> (f64 SReg_64:$src)),
1578  (REG_SEQUENCE SReg_64,
1579    (i32 (EXTRACT_SUBREG SReg_64:$src, sub0)),
1580    sub0,
1581    (i32 (COPY_TO_REGCLASS (S_XOR_B32 (i32 (EXTRACT_SUBREG SReg_64:$src, sub1)),
1582                   (i32 (S_MOV_B32 (i32 0x80000000)))), SReg_32)),
1583    sub1)
1584>;
1585
1586def : GCNPat <
1587  (UniformUnaryFrag<fneg> (fabs (f64 SReg_64:$src))),
1588  (REG_SEQUENCE SReg_64,
1589    (i32 (EXTRACT_SUBREG SReg_64:$src, sub0)),
1590    sub0,
1591    (i32 (COPY_TO_REGCLASS (S_OR_B32 (i32 (EXTRACT_SUBREG SReg_64:$src, sub1)),
1592                  (S_MOV_B32 (i32 0x80000000))), SReg_32)),// Set sign bit.
1593    sub1)
1594>;
1595
1596
1597def : GCNPat <
1598  (fneg (fabs (f32 VGPR_32:$src))),
1599  (V_OR_B32_e64 (S_MOV_B32 (i32 0x80000000)), VGPR_32:$src) // Set sign bit
1600>;
1601
1602def : GCNPat <
1603  (fabs (f32 VGPR_32:$src)),
1604  (V_AND_B32_e64 (S_MOV_B32 (i32 0x7fffffff)), VGPR_32:$src)
1605>;
1606
1607def : GCNPat <
1608  (fneg (f32 VGPR_32:$src)),
1609  (V_XOR_B32_e64 (S_MOV_B32 (i32 0x80000000)), VGPR_32:$src)
1610>;
1611
1612def : GCNPat <
1613  (fabs (f16 VGPR_32:$src)),
1614  (V_AND_B32_e64 (S_MOV_B32 (i32 0x00007fff)), VGPR_32:$src)
1615>;
1616
1617def : GCNPat <
1618  (fneg (f16 VGPR_32:$src)),
1619  (V_XOR_B32_e64 (S_MOV_B32 (i32 0x00008000)), VGPR_32:$src)
1620>;
1621
1622def : GCNPat <
1623  (fneg (fabs (f16 VGPR_32:$src))),
1624  (V_OR_B32_e64 (S_MOV_B32 (i32 0x00008000)), VGPR_32:$src) // Set sign bit
1625>;
1626
1627def : GCNPat <
1628  (fneg (v2f16 VGPR_32:$src)),
1629  (V_XOR_B32_e64 (S_MOV_B32 (i32 0x80008000)), VGPR_32:$src)
1630>;
1631
1632def : GCNPat <
1633  (fabs (v2f16 VGPR_32:$src)),
1634  (V_AND_B32_e64 (S_MOV_B32 (i32 0x7fff7fff)), VGPR_32:$src)
1635>;
1636
1637def : GCNPat <
1638  (fneg (v2f16 (fabs VGPR_32:$src))),
1639  (V_OR_B32_e64 (S_MOV_B32 (i32 0x80008000)), VGPR_32:$src)
1640>;
1641
1642def : GCNPat <
1643  (fabs (f64 VReg_64:$src)),
1644  (REG_SEQUENCE VReg_64,
1645    (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)),
1646    sub0,
1647    (V_AND_B32_e64 (i32 (S_MOV_B32 (i32 0x7fffffff))),
1648        (i32 (EXTRACT_SUBREG VReg_64:$src, sub1))),
1649     sub1)
1650>;
1651
1652def : GCNPat <
1653  (fneg (f64 VReg_64:$src)),
1654  (REG_SEQUENCE VReg_64,
1655    (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)),
1656    sub0,
1657    (V_XOR_B32_e64 (i32 (S_MOV_B32 (i32 0x80000000))),
1658        (i32 (EXTRACT_SUBREG VReg_64:$src, sub1))),
1659    sub1)
1660>;
1661
1662def : GCNPat <
1663  (fneg (fabs (f64 VReg_64:$src))),
1664  (REG_SEQUENCE VReg_64,
1665    (i32 (EXTRACT_SUBREG VReg_64:$src, sub0)),
1666    sub0,
1667    (V_OR_B32_e64 (i32 (S_MOV_B32 (i32 0x80000000))),
1668        (i32 (EXTRACT_SUBREG VReg_64:$src, sub1))),
1669    sub1)
1670>;
1671
1672def : GCNPat <
1673  (getDivergentFrag<fneg>.ret (v2f32 VReg_64:$src)),
1674  (V_PK_ADD_F32 11 /* OP_SEL_1 | NEG_LO | HEG_HI */, VReg_64:$src,
1675                11 /* OP_SEL_1 | NEG_LO | HEG_HI */, 0,
1676                0, 0, 0, 0, 0)
1677> {
1678  let SubtargetPredicate = HasPackedFP32Ops;
1679}
1680
1681def : GCNPat <
1682  (fcopysign f16:$src0, f16:$src1),
1683  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00007fff)), $src0, $src1)
1684>;
1685
1686def : GCNPat <
1687  (fcopysign f32:$src0, f16:$src1),
1688  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)), $src0,
1689             (V_LSHLREV_B32_e64 (i32 16), $src1))
1690>;
1691
1692def : GCNPat <
1693  (fcopysign f64:$src0, f16:$src1),
1694  (REG_SEQUENCE SReg_64,
1695    (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
1696    (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)), (i32 (EXTRACT_SUBREG $src0, sub1)),
1697               (V_LSHLREV_B32_e64 (i32 16), $src1)), sub1)
1698>;
1699
1700def : GCNPat <
1701  (fcopysign f16:$src0, f32:$src1),
1702  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00007fff)), $src0,
1703             (V_LSHRREV_B32_e64 (i32 16), $src1))
1704>;
1705
1706def : GCNPat <
1707  (fcopysign f16:$src0, f64:$src1),
1708  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00007fff)), $src0,
1709             (V_LSHRREV_B32_e64 (i32 16), (EXTRACT_SUBREG $src1, sub1)))
1710>;
1711
1712/********** ================== **********/
1713/********** Immediate Patterns **********/
1714/********** ================== **********/
1715
1716def : GCNPat <
1717  (VGPRImm<(i32 imm)>:$imm),
1718  (V_MOV_B32_e32 imm:$imm)
1719>;
1720
1721def : GCNPat <
1722  (VGPRImm<(f32 fpimm)>:$imm),
1723  (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm)))
1724>;
1725
1726def : GCNPat <
1727  (i32 imm:$imm),
1728  (S_MOV_B32 imm:$imm)
1729>;
1730
1731def : GCNPat <
1732  (VGPRImm<(SIlds tglobaladdr:$ga)>),
1733  (V_MOV_B32_e32 $ga)
1734>;
1735
1736def : GCNPat <
1737  (SIlds tglobaladdr:$ga),
1738  (S_MOV_B32 $ga)
1739>;
1740
1741// FIXME: Workaround for ordering issue with peephole optimizer where
1742// a register class copy interferes with immediate folding.  Should
1743// use s_mov_b32, which can be shrunk to s_movk_i32
1744def : GCNPat <
1745  (VGPRImm<(f16 fpimm)>:$imm),
1746  (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm)))
1747>;
1748
1749def : GCNPat <
1750  (f32 fpimm:$imm),
1751  (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm)))
1752>;
1753
1754def : GCNPat <
1755  (f16 fpimm:$imm),
1756  (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm)))
1757>;
1758
1759def : GCNPat <
1760  (p5 frameindex:$fi),
1761  (V_MOV_B32_e32 (p5 (frameindex_to_targetframeindex $fi)))
1762>;
1763
1764def : GCNPat <
1765  (p5 frameindex:$fi),
1766  (S_MOV_B32 (p5 (frameindex_to_targetframeindex $fi)))
1767>;
1768
1769def : GCNPat <
1770  (i64 InlineImm64:$imm),
1771  (S_MOV_B64 InlineImm64:$imm)
1772>;
1773
1774// XXX - Should this use a s_cmp to set SCC?
1775
1776// Set to sign-extended 64-bit value (true = -1, false = 0)
1777def : GCNPat <
1778  (i1 imm:$imm),
1779  (S_MOV_B64 (i64 (as_i64imm $imm)))
1780> {
1781  let WaveSizePredicate = isWave64;
1782}
1783
1784def : GCNPat <
1785  (i1 imm:$imm),
1786  (S_MOV_B32 (i32 (as_i32imm $imm)))
1787> {
1788  let WaveSizePredicate = isWave32;
1789}
1790
1791def : GCNPat <
1792  (f64 InlineImmFP64:$imm),
1793  (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineImmFP64:$imm)))
1794>;
1795
1796/********** ================== **********/
1797/********** Intrinsic Patterns **********/
1798/********** ================== **********/
1799
1800def : GCNPat <
1801  (f32 (fpow (VOP3Mods f32:$src0, i32:$src0_mods), (VOP3Mods f32:$src1, i32:$src1_mods))),
1802  (V_EXP_F32_e64 SRCMODS.NONE, (V_MUL_LEGACY_F32_e64 $src1_mods, $src1, SRCMODS.NONE, (V_LOG_F32_e64 $src0_mods, $src0), 0, 0))
1803>;
1804
1805def : GCNPat <
1806  (i32 (sext i1:$src0)),
1807  (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
1808                     /*src1mod*/(i32 0), /*src1*/(i32 -1), $src0)
1809>;
1810
1811class Ext32Pat <SDNode ext> : GCNPat <
1812  (i32 (ext i1:$src0)),
1813  (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
1814                     /*src1mod*/(i32 0), /*src1*/(i32 1), $src0)
1815>;
1816
1817def : Ext32Pat <zext>;
1818def : Ext32Pat <anyext>;
1819
1820// The multiplication scales from [0,1) to the unsigned integer range,
1821// rounding down a bit to avoid unwanted overflow.
1822def : GCNPat <
1823  (AMDGPUurecip i32:$src0),
1824  (V_CVT_U32_F32_e32
1825    (V_MUL_F32_e32 (i32 CONST.FP_4294966784),
1826                   (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0))))
1827>;
1828
1829//===----------------------------------------------------------------------===//
1830// VOP3 Patterns
1831//===----------------------------------------------------------------------===//
1832
1833def : IMad24Pat<V_MAD_I32_I24_e64, 1>;
1834def : UMad24Pat<V_MAD_U32_U24_e64, 1>;
1835
1836// BFI patterns
1837
1838def BFIImm32 : PatFrag<
1839  (ops node:$x, node:$y, node:$z),
1840  (i32 (DivergentBinFrag<or> (and node:$y, node:$x), (and node:$z, imm))),
1841  [{
1842    auto *X = dyn_cast<ConstantSDNode>(N->getOperand(0)->getOperand(1));
1843    auto *NotX = dyn_cast<ConstantSDNode>(N->getOperand(1)->getOperand(1));
1844    return X && NotX &&
1845      ~(unsigned)X->getZExtValue() == (unsigned)NotX->getZExtValue();
1846  }]
1847>;
1848
1849// Definition from ISA doc:
1850// (y & x) | (z & ~x)
1851def : AMDGPUPat <
1852  (DivergentBinFrag<or> (and i32:$y, i32:$x), (and i32:$z, (not i32:$x))),
1853  (V_BFI_B32_e64 VSrc_b32:$x, VSrc_b32:$y, VSrc_b32:$z)
1854>;
1855
1856// (y & C) | (z & ~C)
1857def : AMDGPUPat <
1858  (BFIImm32 i32:$x, i32:$y, i32:$z),
1859  (V_BFI_B32_e64 VSrc_b32:$x, VSrc_b32:$y, VSrc_b32:$z)
1860>;
1861
1862// 64-bit version
1863def : AMDGPUPat <
1864  (DivergentBinFrag<or> (and i64:$y, i64:$x), (and i64:$z, (not i64:$x))),
1865  (REG_SEQUENCE VReg_64,
1866    (V_BFI_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub0)),
1867               (i32 (EXTRACT_SUBREG VReg_64:$y, sub0)),
1868               (i32 (EXTRACT_SUBREG VReg_64:$z, sub0))), sub0,
1869    (V_BFI_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub1)),
1870               (i32 (EXTRACT_SUBREG VReg_64:$y, sub1)),
1871               (i32 (EXTRACT_SUBREG VReg_64:$z, sub1))), sub1)
1872>;
1873
1874// SHA-256 Ch function
1875// z ^ (x & (y ^ z))
1876def : AMDGPUPat <
1877  (DivergentBinFrag<xor> i32:$z, (and i32:$x, (xor i32:$y, i32:$z))),
1878  (V_BFI_B32_e64 VSrc_b32:$x, VSrc_b32:$y, VSrc_b32:$z)
1879>;
1880
1881// 64-bit version
1882def : AMDGPUPat <
1883  (DivergentBinFrag<xor> i64:$z, (and i64:$x, (xor i64:$y, i64:$z))),
1884  (REG_SEQUENCE VReg_64,
1885    (V_BFI_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub0)),
1886               (i32 (EXTRACT_SUBREG VReg_64:$y, sub0)),
1887               (i32 (EXTRACT_SUBREG VReg_64:$z, sub0))), sub0,
1888    (V_BFI_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub1)),
1889               (i32 (EXTRACT_SUBREG VReg_64:$y, sub1)),
1890               (i32 (EXTRACT_SUBREG VReg_64:$z, sub1))), sub1)
1891>;
1892
1893def : AMDGPUPat <
1894  (fcopysign f32:$src0, f32:$src1),
1895  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)), $src0, $src1)
1896>;
1897
1898def : AMDGPUPat <
1899  (fcopysign f32:$src0, f64:$src1),
1900  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)), $src0,
1901             (i32 (EXTRACT_SUBREG SReg_64:$src1, sub1)))
1902>;
1903
1904def : AMDGPUPat <
1905  (fcopysign f64:$src0, f64:$src1),
1906  (REG_SEQUENCE SReg_64,
1907    (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
1908    (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)),
1909               (i32 (EXTRACT_SUBREG SReg_64:$src0, sub1)),
1910               (i32 (EXTRACT_SUBREG SReg_64:$src1, sub1))), sub1)
1911>;
1912
1913def : AMDGPUPat <
1914  (fcopysign f64:$src0, f32:$src1),
1915  (REG_SEQUENCE SReg_64,
1916    (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
1917    (V_BFI_B32_e64 (S_MOV_B32 (i32 0x7fffffff)),
1918               (i32 (EXTRACT_SUBREG SReg_64:$src0, sub1)),
1919               $src1), sub1)
1920>;
1921
1922def : ROTRPattern <V_ALIGNBIT_B32_e64>;
1923
1924def : GCNPat<(i32 (trunc (srl i64:$src0, (and i32:$src1, (i32 31))))),
1925          (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)),
1926                          (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>;
1927
1928def : GCNPat<(i32 (trunc (srl i64:$src0, (i32 ShiftAmt32Imm:$src1)))),
1929          (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)),
1930                          (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>;
1931
1932/********** ====================== **********/
1933/**********   Indirect addressing  **********/
1934/********** ====================== **********/
1935
1936multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> {
1937  // Extract with offset
1938  def : GCNPat<
1939    (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))),
1940    (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset)
1941  >;
1942
1943  // Insert with offset
1944  def : GCNPat<
1945    (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))),
1946    (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val)
1947  >;
1948}
1949
1950defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">;
1951defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">;
1952defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">;
1953defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">;
1954defm : SI_INDIRECT_Pattern <v32f32, f32, "V32">;
1955
1956defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">;
1957defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">;
1958defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">;
1959defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">;
1960defm : SI_INDIRECT_Pattern <v32i32, i32, "V32">;
1961
1962//===----------------------------------------------------------------------===//
1963// SAD Patterns
1964//===----------------------------------------------------------------------===//
1965
1966def : GCNPat <
1967  (add (sub_oneuse (umax i32:$src0, i32:$src1),
1968                   (umin i32:$src0, i32:$src1)),
1969       i32:$src2),
1970  (V_SAD_U32_e64 $src0, $src1, $src2, (i1 0))
1971>;
1972
1973def : GCNPat <
1974  (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)),
1975                      (sub i32:$src0, i32:$src1),
1976                      (sub i32:$src1, i32:$src0)),
1977       i32:$src2),
1978  (V_SAD_U32_e64 $src0, $src1, $src2, (i1 0))
1979>;
1980
1981//===----------------------------------------------------------------------===//
1982// Conversion Patterns
1983//===----------------------------------------------------------------------===//
1984def : GCNPat<(i32 (UniformSextInreg<i1> i32:$src)),
1985  (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16
1986
1987// Handle sext_inreg in i64
1988def : GCNPat <
1989  (i64 (UniformSextInreg<i1> i64:$src)),
1990  (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16
1991>;
1992
1993def : GCNPat <
1994  (i16 (UniformSextInreg<i1> i16:$src)),
1995  (S_BFE_I32 $src, (i32 0x00010000)) // 0 | 1 << 16
1996>;
1997
1998def : GCNPat <
1999  (i16 (UniformSextInreg<i8> i16:$src)),
2000  (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16
2001>;
2002
2003def : GCNPat <
2004  (i64 (UniformSextInreg<i8> i64:$src)),
2005  (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16
2006>;
2007
2008def : GCNPat <
2009  (i64 (UniformSextInreg<i16> i64:$src)),
2010  (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16
2011>;
2012
2013def : GCNPat <
2014  (i64 (UniformSextInreg<i32> i64:$src)),
2015  (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16
2016>;
2017
2018def : GCNPat<
2019  (i32 (DivergentSextInreg<i1> i32:$src)),
2020  (V_BFE_I32_e64 i32:$src, (i32 0), (i32 1))>;
2021
2022def : GCNPat <
2023  (i16 (DivergentSextInreg<i1> i16:$src)),
2024  (V_BFE_I32_e64 $src, (i32 0), (i32 1))
2025>;
2026
2027def : GCNPat <
2028  (i16 (DivergentSextInreg<i8> i16:$src)),
2029  (V_BFE_I32_e64 $src, (i32 0), (i32 8))
2030>;
2031
2032def : GCNPat<
2033  (i32 (DivergentSextInreg<i8> i32:$src)),
2034  (V_BFE_I32_e64 i32:$src, (i32 0), (i32 8))
2035>;
2036
2037def : GCNPat <
2038  (i32 (DivergentSextInreg<i16> i32:$src)),
2039  (V_BFE_I32_e64 $src, (i32 0), (i32 16))
2040>;
2041
2042def : GCNPat <
2043  (i64 (DivergentSextInreg<i1> i64:$src)),
2044  (REG_SEQUENCE VReg_64,
2045    (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 1)), sub0,
2046    (V_ASHRREV_I32_e32  (i32 31), (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 1))), sub1)
2047>;
2048
2049def : GCNPat <
2050  (i64 (DivergentSextInreg<i8> i64:$src)),
2051  (REG_SEQUENCE VReg_64,
2052    (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 8)), sub0,
2053    (V_ASHRREV_I32_e32 (i32 31), (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 8))), sub1)
2054>;
2055
2056def : GCNPat <
2057  (i64 (DivergentSextInreg<i16> i64:$src)),
2058  (REG_SEQUENCE VReg_64,
2059    (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 16)), sub0,
2060    (V_ASHRREV_I32_e32 (i32 31), (V_BFE_I32_e64 (i32 (EXTRACT_SUBREG i64:$src, sub0)), (i32 0), (i32 16))), sub1)
2061>;
2062
2063def : GCNPat <
2064  (i64 (DivergentSextInreg<i32> i64:$src)),
2065  (REG_SEQUENCE VReg_64,
2066    (i32 (EXTRACT_SUBREG i64:$src, sub0)), sub0,
2067    (V_ASHRREV_I32_e32 (i32 31), (i32 (EXTRACT_SUBREG i64:$src, sub0))), sub1)
2068>;
2069
2070def : GCNPat <
2071  (i64 (zext i32:$src)),
2072  (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1)
2073>;
2074
2075def : GCNPat <
2076  (i64 (anyext i32:$src)),
2077  (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1)
2078>;
2079
2080class ZExt_i64_i1_Pat <SDNode ext> : GCNPat <
2081  (i64 (ext i1:$src)),
2082    (REG_SEQUENCE VReg_64,
2083      (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2084                         /*src1mod*/(i32 0), /*src1*/(i32 1), $src),
2085      sub0, (S_MOV_B32 (i32 0)), sub1)
2086>;
2087
2088
2089def : ZExt_i64_i1_Pat<zext>;
2090def : ZExt_i64_i1_Pat<anyext>;
2091
2092// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that
2093// REG_SEQUENCE patterns don't support instructions with multiple outputs.
2094def : GCNPat <
2095  (i64 (UniformUnaryFrag<sext> i32:$src)),
2096    (REG_SEQUENCE SReg_64, $src, sub0,
2097    (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1)
2098>;
2099
2100def : GCNPat <
2101  (i64 (DivergentUnaryFrag<sext> i32:$src)),
2102    (REG_SEQUENCE VReg_64, $src, sub0,
2103    (i32 (COPY_TO_REGCLASS (V_ASHRREV_I32_e64 (i32 31), $src), VGPR_32)), sub1)
2104>;
2105
2106def : GCNPat <
2107  (i64 (sext i1:$src)),
2108  (REG_SEQUENCE VReg_64,
2109    (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2110                       /*src1mod*/(i32 0), /*src1*/(i32 -1), $src), sub0,
2111    (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2112                       /*src1mod*/(i32 0), /*src1*/(i32 -1), $src), sub1)
2113>;
2114
2115class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : GCNPat <
2116  (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))),
2117  (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE))
2118>;
2119
2120def : FPToI1Pat<V_CMP_EQ_F16_e64, CONST.FP16_ONE, i16, f16, fp_to_uint>;
2121def : FPToI1Pat<V_CMP_EQ_F16_e64, CONST.FP16_NEG_ONE, i16, f16, fp_to_sint>;
2122def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>;
2123def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>;
2124def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>;
2125def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>;
2126
2127// If we need to perform a logical operation on i1 values, we need to
2128// use vector comparisons since there is only one SCC register. Vector
2129// comparisons may write to a pair of SGPRs or a single SGPR, so treat
2130// these as 32 or 64-bit comparisons. When legalizing SGPR copies,
2131// instructions resulting in the copies from SCC to these instructions
2132// will be moved to the VALU.
2133
2134let WaveSizePredicate = isWave64 in {
2135def : GCNPat <
2136  (i1 (and i1:$src0, i1:$src1)),
2137  (S_AND_B64 $src0, $src1)
2138>;
2139
2140def : GCNPat <
2141  (i1 (or i1:$src0, i1:$src1)),
2142  (S_OR_B64 $src0, $src1)
2143>;
2144
2145def : GCNPat <
2146  (i1 (xor i1:$src0, i1:$src1)),
2147  (S_XOR_B64 $src0, $src1)
2148>;
2149
2150def : GCNPat <
2151  (i1 (add i1:$src0, i1:$src1)),
2152  (S_XOR_B64 $src0, $src1)
2153>;
2154
2155def : GCNPat <
2156  (i1 (sub i1:$src0, i1:$src1)),
2157  (S_XOR_B64 $src0, $src1)
2158>;
2159
2160let AddedComplexity = 1 in {
2161def : GCNPat <
2162  (i1 (add i1:$src0, (i1 -1))),
2163  (S_NOT_B64 $src0)
2164>;
2165
2166def : GCNPat <
2167  (i1 (sub i1:$src0, (i1 -1))),
2168  (S_NOT_B64 $src0)
2169>;
2170}
2171} // end isWave64
2172
2173let WaveSizePredicate = isWave32 in {
2174def : GCNPat <
2175  (i1 (and i1:$src0, i1:$src1)),
2176  (S_AND_B32 $src0, $src1)
2177>;
2178
2179def : GCNPat <
2180  (i1 (or i1:$src0, i1:$src1)),
2181  (S_OR_B32 $src0, $src1)
2182>;
2183
2184def : GCNPat <
2185  (i1 (xor i1:$src0, i1:$src1)),
2186  (S_XOR_B32 $src0, $src1)
2187>;
2188
2189def : GCNPat <
2190  (i1 (add i1:$src0, i1:$src1)),
2191  (S_XOR_B32 $src0, $src1)
2192>;
2193
2194def : GCNPat <
2195  (i1 (sub i1:$src0, i1:$src1)),
2196  (S_XOR_B32 $src0, $src1)
2197>;
2198
2199let AddedComplexity = 1 in {
2200def : GCNPat <
2201  (i1 (add i1:$src0, (i1 -1))),
2202  (S_NOT_B32 $src0)
2203>;
2204
2205def : GCNPat <
2206  (i1 (sub i1:$src0, (i1 -1))),
2207  (S_NOT_B32 $src0)
2208>;
2209}
2210} // end isWave32
2211
2212def : GCNPat <
2213  (i32 (DivergentBinFrag<xor> i32:$src0, (i32 -1))),
2214  (V_NOT_B32_e32 $src0)
2215>;
2216
2217def : GCNPat <
2218  (i64 (DivergentBinFrag<xor> i64:$src0, (i64 -1))),
2219    (REG_SEQUENCE VReg_64,
2220      (V_NOT_B32_e32 (i32 (EXTRACT_SUBREG i64:$src0, sub0))), sub0,
2221      (V_NOT_B32_e32 (i32 (EXTRACT_SUBREG i64:$src0, sub1))), sub1
2222    )
2223>;
2224
2225def : GCNPat <
2226  (f16 (sint_to_fp i1:$src)),
2227  (V_CVT_F16_F32_e32 (
2228      V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2229                        /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_NEG_ONE),
2230                        SSrc_i1:$src))
2231>;
2232
2233def : GCNPat <
2234  (f16 (uint_to_fp i1:$src)),
2235  (V_CVT_F16_F32_e32 (
2236      V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2237                        /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_ONE),
2238                        SSrc_i1:$src))
2239>;
2240
2241def : GCNPat <
2242  (f32 (sint_to_fp i1:$src)),
2243  (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2244                        /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_NEG_ONE),
2245                        SSrc_i1:$src)
2246>;
2247
2248def : GCNPat <
2249  (f32 (uint_to_fp i1:$src)),
2250  (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2251                        /*src1mod*/(i32 0), /*src1*/(i32 CONST.FP32_ONE),
2252                        SSrc_i1:$src)
2253>;
2254
2255def : GCNPat <
2256  (f64 (sint_to_fp i1:$src)),
2257  (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2258                                        /*src1mod*/(i32 0), /*src1*/(i32 -1),
2259                                        SSrc_i1:$src))
2260>;
2261
2262def : GCNPat <
2263  (f64 (uint_to_fp i1:$src)),
2264  (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 /*src0mod*/(i32 0), /*src0*/(i32 0),
2265                                        /*src1mod*/(i32 0), /*src1*/(i32 1),
2266                                        SSrc_i1:$src))
2267>;
2268
2269//===----------------------------------------------------------------------===//
2270// Miscellaneous Patterns
2271//===----------------------------------------------------------------------===//
2272
2273// Eliminate a zero extension from an fp16 operation if it already
2274// zeros the high bits of the 32-bit register.
2275//
2276// This is complicated on gfx9+. Some instructions maintain the legacy
2277// zeroing behavior, but others preserve the high bits. Some have a
2278// control bit to change the behavior. We can't simply say with
2279// certainty what the source behavior is without more context on how
2280// the src is lowered. e.g. fptrunc + fma may be lowered to a
2281// v_fma_mix* instruction which does not zero, or may not.
2282def : GCNPat<
2283  (i32 (DivergentUnaryFrag<abs> i32:$src)),
2284  (V_MAX_I32_e64 (V_SUB_CO_U32_e32 (i32 0), $src), $src)>;
2285
2286let AddedComplexity = 1 in {
2287def : GCNPat<
2288  (i32 (DivergentUnaryFrag<abs> i32:$src)),
2289  (V_MAX_I32_e64 (V_SUB_U32_e32 (i32 0), $src), $src)>{
2290  let SubtargetPredicate = HasAddNoCarryInsts;
2291}
2292}  // AddedComplexity = 1
2293
2294def : GCNPat<
2295  (i32 (DivergentUnaryFrag<zext> i16:$src)),
2296  (V_AND_B32_e64 (S_MOV_B32 (i32 0xffff)), $src)
2297>;
2298
2299def : GCNPat<
2300  (i64 (DivergentUnaryFrag<zext> i16:$src)),
2301  (REG_SEQUENCE VReg_64,
2302    (V_AND_B32_e64 (S_MOV_B32 (i32 0xffff)), $src), sub0,
2303    (S_MOV_B32 (i32 0)), sub1)
2304>;
2305
2306def : GCNPat<
2307  (i32 (zext (i16 (bitconvert fp16_zeros_high_16bits:$src)))),
2308  (COPY VSrc_b16:$src)>;
2309
2310def : GCNPat <
2311  (i32 (trunc i64:$a)),
2312  (EXTRACT_SUBREG $a, sub0)
2313>;
2314
2315def : GCNPat <
2316  (i1 (UniformUnaryFrag<trunc> i32:$a)),
2317  (S_CMP_EQ_U32 (S_AND_B32 (i32 1), $a), (i32 1))
2318>;
2319
2320def : GCNPat <
2321  (i1 (UniformUnaryFrag<trunc> i16:$a)),
2322  (S_CMP_EQ_U32 (S_AND_B32 (i32 1), $a), (i32 1))
2323>;
2324
2325def : GCNPat <
2326  (i1 (UniformUnaryFrag<trunc> i64:$a)),
2327  (S_CMP_EQ_U32 (S_AND_B32 (i32 1),
2328                    (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1))
2329>;
2330
2331def : GCNPat <
2332  (i1 (DivergentUnaryFrag<trunc> i32:$a)),
2333  (V_CMP_EQ_U32_e64 (V_AND_B32_e64 (i32 1), $a), (i32 1))
2334>;
2335
2336def : GCNPat <
2337  (i1 (DivergentUnaryFrag<trunc> i16:$a)),
2338  (V_CMP_EQ_U32_e64 (V_AND_B32_e64 (i32 1), $a), (i32 1))
2339>;
2340
2341def IMMBitSelConst : SDNodeXForm<imm, [{
2342  return CurDAG->getTargetConstant(1ULL << N->getZExtValue(), SDLoc(N),
2343                                   MVT::i32);
2344}]>;
2345
2346// Matching separate SRL and TRUNC instructions
2347// with dependent operands (SRL dest is source of TRUNC)
2348// generates three instructions. However, by using bit shifts,
2349// the V_LSHRREV_B32_e64 result can be directly used in the
2350// operand of the V_AND_B32_e64 instruction:
2351// (trunc i32 (srl i32 $a, i32 $b)) ->
2352// v_and_b32_e64 $a, (1 << $b), $a
2353// v_cmp_ne_u32_e64 $a, 0, $a
2354
2355// Handle the VALU case.
2356def : GCNPat <
2357  (i1 (DivergentUnaryFrag<trunc> (i32 (srl i32:$a, (i32 imm:$b))))),
2358  (V_CMP_NE_U32_e64 (V_AND_B32_e64 (i32 (IMMBitSelConst $b)), $a),
2359    (i32 0))
2360>;
2361
2362// Handle the scalar case.
2363def : GCNPat <
2364  (i1 (UniformUnaryFrag<trunc> (i32 (srl i32:$a, (i32 imm:$b))))),
2365  (S_CMP_LG_U32 (S_AND_B32 (i32 (IMMBitSelConst $b)), $a),
2366    (i32 0))
2367>;
2368
2369def : GCNPat <
2370  (i1 (DivergentUnaryFrag<trunc> i64:$a)),
2371  (V_CMP_EQ_U32_e64 (V_AND_B32_e64 (i32 1),
2372                    (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1))
2373>;
2374
2375def : GCNPat <
2376  (i32 (bswap i32:$a)),
2377  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00ff00ff)),
2378             (V_ALIGNBIT_B32_e64 VSrc_b32:$a, VSrc_b32:$a, (i32 24)),
2379             (V_ALIGNBIT_B32_e64 VSrc_b32:$a, VSrc_b32:$a, (i32 8)))
2380>;
2381
2382// FIXME: This should have been narrowed to i32 during legalization.
2383// This pattern should also be skipped for GlobalISel
2384def : GCNPat <
2385  (i64 (bswap i64:$a)),
2386  (REG_SEQUENCE VReg_64,
2387  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00ff00ff)),
2388             (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub1)),
2389                             (i32 (EXTRACT_SUBREG VReg_64:$a, sub1)),
2390                             (i32 24)),
2391             (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub1)),
2392                             (i32 (EXTRACT_SUBREG VReg_64:$a, sub1)),
2393                             (i32 8))),
2394  sub0,
2395  (V_BFI_B32_e64 (S_MOV_B32 (i32 0x00ff00ff)),
2396             (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub0)),
2397                             (i32 (EXTRACT_SUBREG VReg_64:$a, sub0)),
2398                             (i32 24)),
2399             (V_ALIGNBIT_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub0)),
2400                             (i32 (EXTRACT_SUBREG VReg_64:$a, sub0)),
2401                             (i32 8))),
2402  sub1)
2403>;
2404
2405// FIXME: The AddedComplexity should not be needed, but in GlobalISel
2406// the BFI pattern ends up taking precedence without it.
2407let SubtargetPredicate = isGFX8Plus, AddedComplexity = 1 in {
2408// Magic number: 3 | (2 << 8) | (1 << 16) | (0 << 24)
2409//
2410// My reading of the manual suggests we should be using src0 for the
2411// register value, but this is what seems to work.
2412def : GCNPat <
2413  (i32 (bswap i32:$a)),
2414  (V_PERM_B32_e64 (i32 0), VSrc_b32:$a, (S_MOV_B32 (i32 0x00010203)))
2415>;
2416
2417// FIXME: This should have been narrowed to i32 during legalization.
2418// This pattern should also be skipped for GlobalISel
2419def : GCNPat <
2420  (i64 (bswap i64:$a)),
2421  (REG_SEQUENCE VReg_64,
2422  (V_PERM_B32_e64  (i32 0), (EXTRACT_SUBREG VReg_64:$a, sub1),
2423              (S_MOV_B32 (i32 0x00010203))),
2424  sub0,
2425  (V_PERM_B32_e64  (i32 0), (EXTRACT_SUBREG VReg_64:$a, sub0),
2426              (S_MOV_B32 (i32 0x00010203))),
2427  sub1)
2428>;
2429
2430// Magic number: 1 | (0 << 8) | (12 << 16) | (12 << 24)
2431// The 12s emit 0s.
2432def : GCNPat <
2433  (i16 (bswap i16:$a)),
2434  (V_PERM_B32_e64  (i32 0), VSrc_b32:$a, (S_MOV_B32 (i32 0x0c0c0001)))
2435>;
2436
2437def : GCNPat <
2438  (i32 (zext (bswap i16:$a))),
2439  (V_PERM_B32_e64  (i32 0), VSrc_b32:$a, (S_MOV_B32 (i32 0x0c0c0001)))
2440>;
2441
2442// Magic number: 1 | (0 << 8) | (3 << 16) | (2 << 24)
2443def : GCNPat <
2444  (v2i16 (bswap v2i16:$a)),
2445  (V_PERM_B32_e64  (i32 0), VSrc_b32:$a, (S_MOV_B32 (i32 0x02030001)))
2446>;
2447
2448}
2449
2450def : GCNPat<
2451  (i64 (DivergentUnaryFrag<bitreverse> i64:$a)),
2452  (REG_SEQUENCE VReg_64,
2453   (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub1))), sub0,
2454   (V_BFREV_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$a, sub0))), sub1)>;
2455
2456// Prefer selecting to max when legal, but using mul is always valid.
2457let AddedComplexity = -5 in {
2458def : GCNPat<
2459  (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))),
2460  (V_MUL_F16_e64 0, (i32 CONST.FP16_ONE), $src_mods, $src)
2461>;
2462
2463def : GCNPat<
2464  (fcanonicalize (f16 (fneg (VOP3Mods f16:$src, i32:$src_mods)))),
2465  (V_MUL_F16_e64 0, (i32 CONST.FP16_NEG_ONE), $src_mods, $src)
2466>;
2467
2468def : GCNPat<
2469  (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))),
2470  (V_PK_MUL_F16 0, (i32 CONST.FP16_ONE), $src_mods, $src, DSTCLAMP.NONE)
2471>;
2472
2473def : GCNPat<
2474  (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))),
2475  (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), $src_mods, $src)
2476>;
2477
2478def : GCNPat<
2479  (fcanonicalize (f32 (fneg (VOP3Mods f32:$src, i32:$src_mods)))),
2480  (V_MUL_F32_e64 0, (i32 CONST.FP32_NEG_ONE), $src_mods, $src)
2481>;
2482
2483// TODO: Handle fneg like other types.
2484def : GCNPat<
2485  (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))),
2486  (V_MUL_F64_e64  0, CONST.FP64_ONE, $src_mods, $src)
2487>;
2488} // End AddedComplexity = -5
2489
2490multiclass SelectCanonicalizeAsMax<
2491  list<Predicate> f32_preds = [],
2492  list<Predicate> f64_preds = [],
2493  list<Predicate> f16_preds = []> {
2494  def : GCNPat<
2495    (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))),
2496    (V_MAX_F32_e64 $src_mods, $src, $src_mods, $src)> {
2497    let OtherPredicates = f32_preds;
2498  }
2499
2500  def : GCNPat<
2501    (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))),
2502    (V_MAX_F64_e64  $src_mods, $src, $src_mods, $src)> {
2503    let OtherPredicates = f64_preds;
2504  }
2505
2506  def : GCNPat<
2507    (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))),
2508    (V_MAX_F16_e64 $src_mods, $src, $src_mods, $src, 0, 0)> {
2509    // FIXME: Should have 16-bit inst subtarget predicate
2510    let OtherPredicates = f16_preds;
2511  }
2512
2513  def : GCNPat<
2514    (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))),
2515    (V_PK_MAX_F16 $src_mods, $src, $src_mods, $src, DSTCLAMP.NONE)> {
2516    // FIXME: Should have VOP3P subtarget predicate
2517    let OtherPredicates = f16_preds;
2518  }
2519}
2520
2521// On pre-gfx9 targets, v_max_*/v_min_* did not respect the denormal
2522// mode, and would never flush. For f64, it's faster to do implement
2523// this with a max. For f16/f32 it's a wash, but prefer max when
2524// valid.
2525//
2526// FIXME: Lowering f32/f16 with max is worse since we can use a
2527// smaller encoding if the input is fneg'd. It also adds an extra
2528// register use.
2529let SubtargetPredicate = HasMinMaxDenormModes in {
2530  defm : SelectCanonicalizeAsMax<[], [], []>;
2531} // End SubtargetPredicate = HasMinMaxDenormModes
2532
2533let SubtargetPredicate = NotHasMinMaxDenormModes in {
2534  // Use the max lowering if we don't need to flush.
2535
2536  // FIXME: We don't do use this for f32 as a workaround for the
2537  // library being compiled with the default ieee mode, but
2538  // potentially being called from flushing kernels. Really we should
2539  // not be mixing code expecting different default FP modes, but mul
2540  // works in any FP environment.
2541  defm : SelectCanonicalizeAsMax<[FalsePredicate], [FP64Denormals], [FP16Denormals]>;
2542} // End SubtargetPredicate = NotHasMinMaxDenormModes
2543
2544
2545let OtherPredicates = [HasDLInsts] in {
2546// Don't allow source modifiers. If there are any source modifiers then it's
2547// better to select fma instead of fmac.
2548def : GCNPat <
2549  (fma (f32 (VOP3NoMods f32:$src0)),
2550       (f32 (VOP3NoMods f32:$src1)),
2551       (f32 (VOP3NoMods f32:$src2))),
2552  (V_FMAC_F32_e64 SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
2553                  SRCMODS.NONE, $src2)
2554>;
2555} // End OtherPredicates = [HasDLInsts]
2556
2557let SubtargetPredicate = isGFX10Plus in
2558// Don't allow source modifiers. If there are any source modifiers then it's
2559// better to select fma instead of fmac.
2560def : GCNPat <
2561  (fma (f16 (VOP3NoMods f32:$src0)),
2562       (f16 (VOP3NoMods f32:$src1)),
2563       (f16 (VOP3NoMods f32:$src2))),
2564  (V_FMAC_F16_e64 SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
2565                  SRCMODS.NONE, $src2)
2566>;
2567
2568let SubtargetPredicate = isGFX90APlus in
2569// Don't allow source modifiers. If there are any source modifiers then it's
2570// better to select fma instead of fmac.
2571def : GCNPat <
2572  (fma (f64 (VOP3NoMods f64:$src0)),
2573       (f64 (VOP3NoMods f64:$src1)),
2574       (f64 (VOP3NoMods f64:$src2))),
2575  (V_FMAC_F64_e64 SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
2576                  SRCMODS.NONE, $src2)
2577>;
2578
2579// COPY is workaround tablegen bug from multiple outputs
2580// from S_LSHL_B32's multiple outputs from implicit scc def.
2581def : GCNPat <
2582  (v2i16 (UniformBinFrag<build_vector> (i16 0), (i16 SReg_32:$src1))),
2583  (S_LSHL_B32 SReg_32:$src1, (i16 16))
2584>;
2585
2586def : GCNPat <
2587  (v2i16 (DivergentBinFrag<build_vector> (i16 0), (i16 SReg_32:$src1))),
2588  (v2i16 (V_LSHLREV_B32_e64 (i16 16), SReg_32:$src1))
2589>;
2590
2591
2592def : GCNPat <
2593  (v2i16 (UniformBinFrag<build_vector> (i16 SReg_32:$src1), (i16 0))),
2594  (S_AND_B32 (S_MOV_B32 (i32 0xffff)), SReg_32:$src1)
2595>;
2596
2597def : GCNPat <
2598  (v2i16 (DivergentBinFrag<build_vector> (i16 SReg_32:$src1), (i16 0))),
2599  (v2i16 (V_AND_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), SReg_32:$src1))
2600>;
2601
2602def : GCNPat <
2603  (v2f16 (UniformBinFrag<build_vector> (f16 SReg_32:$src1), (f16 FP_ZERO))),
2604  (S_AND_B32 (S_MOV_B32 (i32 0xffff)), SReg_32:$src1)
2605>;
2606
2607def : GCNPat <
2608  (v2f16 (DivergentBinFrag<build_vector> (f16 SReg_32:$src1), (f16 FP_ZERO))),
2609  (v2f16 (V_AND_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), SReg_32:$src1))
2610>;
2611
2612def : GCNPat <
2613  (v2i16 (UniformBinFrag<build_vector> (i16 SReg_32:$src0), (i16 undef))),
2614  (COPY_TO_REGCLASS SReg_32:$src0, SReg_32)
2615>;
2616
2617def : GCNPat <
2618  (v2i16 (DivergentBinFrag<build_vector> (i16 VGPR_32:$src0), (i16 undef))),
2619  (COPY_TO_REGCLASS VGPR_32:$src0, VGPR_32)
2620>;
2621
2622def : GCNPat <
2623  (v2f16 (build_vector f16:$src0, (f16 undef))),
2624  (COPY $src0)
2625>;
2626
2627def : GCNPat <
2628  (v2i16 (UniformBinFrag<build_vector> (i16 undef), (i16 SReg_32:$src1))),
2629  (S_LSHL_B32 SReg_32:$src1, (i32 16))
2630>;
2631
2632def : GCNPat <
2633  (v2i16 (DivergentBinFrag<build_vector> (i16 undef), (i16 SReg_32:$src1))),
2634  (v2i16 (V_LSHLREV_B32_e64 (i32 16), SReg_32:$src1))
2635>;
2636
2637
2638def : GCNPat <
2639  (v2f16 (UniformBinFrag<build_vector> (f16 undef), (f16 SReg_32:$src1))),
2640  (S_LSHL_B32 SReg_32:$src1, (i32 16))
2641>;
2642
2643def : GCNPat <
2644  (v2f16 (DivergentBinFrag<build_vector> (f16 undef), (f16 SReg_32:$src1))),
2645  (v2f16 (V_LSHLREV_B32_e64 (i32 16), SReg_32:$src1))
2646>;
2647
2648let SubtargetPredicate = HasVOP3PInsts in {
2649def : GCNPat <
2650  (v2i16 (UniformBinFrag<build_vector> (i16 SReg_32:$src0), (i16 SReg_32:$src1))),
2651  (S_PACK_LL_B32_B16 SReg_32:$src0, SReg_32:$src1)
2652>;
2653
2654def : GCNPat <
2655  (v2i16 (DivergentBinFrag<build_vector> (i16 SReg_32:$src0), (i16 SReg_32:$src1))),
2656  (v2i16 (V_LSHL_OR_B32_e64 $src1, (i32 16), (i32 (V_AND_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), $src0))))
2657>;
2658
2659// With multiple uses of the shift, this will duplicate the shift and
2660// increase register pressure.
2661def : GCNPat <
2662  (v2i16 (UniformBinFrag<build_vector> (i16 SReg_32:$src0), (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))),
2663  (v2i16 (S_PACK_LH_B32_B16 SReg_32:$src0, SReg_32:$src1))
2664>;
2665
2666def : GCNPat <
2667  (v2i16 (DivergentBinFrag<build_vector> (i16 SReg_32:$src0), (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))),
2668  (v2i16 (V_BFI_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), SReg_32:$src0, SReg_32:$src1))
2669>;
2670
2671
2672def : GCNPat <
2673  (v2i16 (UniformBinFrag<build_vector> (i16 (trunc (srl_oneuse SReg_32:$src0, (i32 16)))),
2674                       (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))),
2675  (S_PACK_HH_B32_B16 SReg_32:$src0, SReg_32:$src1)
2676>;
2677
2678def : GCNPat <
2679  (v2i16 (DivergentBinFrag<build_vector> (i16 (trunc (srl_oneuse SReg_32:$src0, (i32 16)))),
2680                       (i16 (trunc (srl_oneuse SReg_32:$src1, (i32 16)))))),
2681  (v2i16 (V_AND_OR_B32_e64 SReg_32:$src1, (i32 (V_MOV_B32_e32 (i32 0xffff0000))), (i32 (V_LSHRREV_B32_e64 (i32 16), SReg_32:$src0))))
2682>;
2683
2684def : GCNPat <
2685  (v2f16 (UniformBinFrag<build_vector> (f16 SReg_32:$src0), (f16 SReg_32:$src1))),
2686  (S_PACK_LL_B32_B16 SReg_32:$src0, SReg_32:$src1)
2687>;
2688
2689def : GCNPat <
2690  (v2f16 (DivergentBinFrag<build_vector> (f16 SReg_32:$src0), (f16 SReg_32:$src1))),
2691  (v2f16 (V_LSHL_OR_B32_e64 SReg_32:$src1, (i32 16), (i32 (V_AND_B32_e64 (i32 (V_MOV_B32_e32 (i32 0xffff))), SReg_32:$src0))))
2692>;
2693
2694
2695def : GCNPat <
2696  (v2f16 (is_canonicalized<build_vector> (f16 (VOP3Mods (f16 VGPR_32:$src0), i32:$src0_mods)),
2697                                         (f16 (VOP3Mods (f16 VGPR_32:$src1), i32:$src1_mods)))),
2698  (V_PACK_B32_F16_e64 $src0_mods, VGPR_32:$src0, $src1_mods, VGPR_32:$src1)
2699>;
2700} // End SubtargetPredicate = HasVOP3PInsts
2701
2702def : GCNPat <
2703  (v2f16 (scalar_to_vector f16:$src0)),
2704  (COPY $src0)
2705>;
2706
2707def : GCNPat <
2708  (v2i16 (scalar_to_vector i16:$src0)),
2709  (COPY $src0)
2710>;
2711
2712def : GCNPat <
2713  (v4i16 (scalar_to_vector i16:$src0)),
2714  (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0)
2715>;
2716
2717def : GCNPat <
2718  (v4f16 (scalar_to_vector f16:$src0)),
2719  (INSERT_SUBREG (IMPLICIT_DEF), $src0, sub0)
2720>;
2721
2722def : GCNPat <
2723  (i64 (int_amdgcn_mov_dpp i64:$src, timm:$dpp_ctrl, timm:$row_mask,
2724                           timm:$bank_mask, timm:$bound_ctrl)),
2725  (V_MOV_B64_DPP_PSEUDO VReg_64_Align2:$src, VReg_64_Align2:$src,
2726                        (as_i32timm $dpp_ctrl), (as_i32timm $row_mask),
2727                        (as_i32timm $bank_mask),
2728                        (as_i1timm $bound_ctrl))
2729>;
2730
2731def : GCNPat <
2732  (i64 (int_amdgcn_update_dpp i64:$old, i64:$src, timm:$dpp_ctrl, timm:$row_mask,
2733                              timm:$bank_mask, timm:$bound_ctrl)),
2734  (V_MOV_B64_DPP_PSEUDO VReg_64_Align2:$old, VReg_64_Align2:$src, (as_i32timm $dpp_ctrl),
2735                        (as_i32timm $row_mask), (as_i32timm $bank_mask),
2736                        (as_i1timm $bound_ctrl))
2737>;
2738
2739//===----------------------------------------------------------------------===//
2740// Fract Patterns
2741//===----------------------------------------------------------------------===//
2742
2743let SubtargetPredicate = isGFX6 in {
2744
2745// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is
2746// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient
2747// way to implement it is using V_FRACT_F64.
2748// The workaround for the V_FRACT bug is:
2749//    fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999)
2750
2751// Convert floor(x) to (x - fract(x))
2752
2753// Don't bother handling this for GlobalISel, it's handled during
2754// lowering.
2755//
2756// FIXME: DAG should also custom lower this.
2757def : GCNPat <
2758  (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))),
2759  (V_ADD_F64_e64
2760      $mods,
2761      $x,
2762      SRCMODS.NEG,
2763      (V_CNDMASK_B64_PSEUDO
2764         (V_MIN_F64_e64
2765             SRCMODS.NONE,
2766             (V_FRACT_F64_e64 $mods, $x),
2767             SRCMODS.NONE,
2768             (V_MOV_B64_PSEUDO 0x3fefffffffffffff)),
2769         $x,
2770         (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))))
2771>;
2772
2773} // End SubtargetPredicates = isGFX6
2774
2775//============================================================================//
2776// Miscellaneous Optimization Patterns
2777//============================================================================//
2778
2779// Undo sub x, c -> add x, -c canonicalization since c is more likely
2780// an inline immediate than -c.
2781// TODO: Also do for 64-bit.
2782def : GCNPat<
2783  (UniformBinFrag<add> i32:$src0, (i32 NegSubInlineConst32:$src1)),
2784  (S_SUB_I32 SReg_32:$src0, NegSubInlineConst32:$src1)
2785>;
2786
2787def : GCNPat<
2788  (DivergentBinFrag<add> i32:$src0, (i32 NegSubInlineConst32:$src1)),
2789  (V_SUB_U32_e64 VS_32:$src0, NegSubInlineConst32:$src1)> {
2790  let SubtargetPredicate = HasAddNoCarryInsts;
2791}
2792
2793def : GCNPat<
2794  (DivergentBinFrag<add> i32:$src0, (i32 NegSubInlineConst32:$src1)),
2795  (V_SUB_CO_U32_e64 VS_32:$src0, NegSubInlineConst32:$src1)> {
2796  let SubtargetPredicate = NotHasAddNoCarryInsts;
2797}
2798
2799
2800// Avoid pointlessly materializing a constant in VGPR.
2801// FIXME: Should also do this for readlane, but tablegen crashes on
2802// the ignored src1.
2803def : GCNPat<
2804  (int_amdgcn_readfirstlane (i32 imm:$src)),
2805  (S_MOV_B32 SReg_32:$src)
2806>;
2807
2808multiclass BFMPatterns <ValueType vt, PatFrag SHL, PatFrag ADD, InstSI BFM> {
2809  def : GCNPat <
2810    (vt (SHL (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)),
2811    (BFM $a, $b)
2812  >;
2813
2814  def : GCNPat <
2815    (vt (ADD (vt (shl 1, vt:$a)), -1)),
2816    (BFM $a, (i32 0))
2817  >;
2818}
2819
2820defm : BFMPatterns <i32, UniformBinFrag<shl>, UniformBinFrag<add>, S_BFM_B32>;
2821// FIXME: defm : BFMPatterns <i64, UniformBinFrag<shl>, UniformBinFrag<add>, S_BFM_B64>;
2822defm : BFMPatterns <i32, DivergentBinFrag<shl>, DivergentBinFrag<add>, V_BFM_B32_e64>;
2823
2824// Bitfield extract patterns
2825
2826def IMMZeroBasedBitfieldMask : ImmLeaf <i32, [{
2827  return isMask_32(Imm);
2828}]>;
2829
2830def IMMPopCount : SDNodeXForm<imm, [{
2831  return CurDAG->getTargetConstant(countPopulation(N->getZExtValue()), SDLoc(N),
2832                                   MVT::i32);
2833}]>;
2834
2835def : AMDGPUPat <
2836  (DivergentBinFrag<and> (i32 (srl i32:$src, i32:$rshift)),
2837                         IMMZeroBasedBitfieldMask:$mask),
2838  (V_BFE_U32_e64 $src, $rshift, (i32 (IMMPopCount $mask)))
2839>;
2840
2841// x & ((1 << y) - 1)
2842def : AMDGPUPat <
2843  (DivergentBinFrag<and> i32:$src, (add_oneuse (shl_oneuse 1, i32:$width), -1)),
2844  (V_BFE_U32_e64 $src, (i32 0), $width)
2845>;
2846
2847// x & ~(-1 << y)
2848def : AMDGPUPat <
2849  (DivergentBinFrag<and> i32:$src,
2850                         (xor_oneuse (shl_oneuse -1, i32:$width), -1)),
2851  (V_BFE_U32_e64 $src, (i32 0), $width)
2852>;
2853
2854// x & (-1 >> (bitwidth - y))
2855def : AMDGPUPat <
2856  (DivergentBinFrag<and> i32:$src, (srl_oneuse -1, (sub 32, i32:$width))),
2857  (V_BFE_U32_e64 $src, (i32 0), $width)
2858>;
2859
2860// x << (bitwidth - y) >> (bitwidth - y)
2861def : AMDGPUPat <
2862  (DivergentBinFrag<srl> (shl_oneuse i32:$src, (sub 32, i32:$width)),
2863                         (sub 32, i32:$width)),
2864  (V_BFE_U32_e64 $src, (i32 0), $width)
2865>;
2866
2867def : AMDGPUPat <
2868  (DivergentBinFrag<sra> (shl_oneuse i32:$src, (sub 32, i32:$width)),
2869                         (sub 32, i32:$width)),
2870  (V_BFE_I32_e64 $src, (i32 0), $width)
2871>;
2872
2873// SHA-256 Ma patterns
2874
2875// ((x & z) | (y & (x | z))) -> BFI (XOR x, y), z, y
2876def : AMDGPUPat <
2877  (DivergentBinFrag<or> (and i32:$x, i32:$z),
2878                        (and i32:$y, (or i32:$x, i32:$z))),
2879  (V_BFI_B32_e64 (V_XOR_B32_e64 VSrc_b32:$x, VSrc_b32:$y), VSrc_b32:$z, VSrc_b32:$y)
2880>;
2881
2882def : AMDGPUPat <
2883  (DivergentBinFrag<or> (and i64:$x, i64:$z),
2884                        (and i64:$y, (or i64:$x, i64:$z))),
2885  (REG_SEQUENCE VReg_64,
2886    (V_BFI_B32_e64 (V_XOR_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub0)),
2887                    (i32 (EXTRACT_SUBREG VReg_64:$y, sub0))),
2888               (i32 (EXTRACT_SUBREG VReg_64:$z, sub0)),
2889               (i32 (EXTRACT_SUBREG VReg_64:$y, sub0))), sub0,
2890    (V_BFI_B32_e64 (V_XOR_B32_e64 (i32 (EXTRACT_SUBREG VReg_64:$x, sub1)),
2891                    (i32 (EXTRACT_SUBREG VReg_64:$y, sub1))),
2892               (i32 (EXTRACT_SUBREG VReg_64:$z, sub1)),
2893               (i32 (EXTRACT_SUBREG VReg_64:$y, sub1))), sub1)
2894>;
2895
2896multiclass IntMed3Pat<Instruction med3Inst,
2897                 SDPatternOperator min,
2898                 SDPatternOperator max,
2899                 SDPatternOperator min_oneuse,
2900                 SDPatternOperator max_oneuse> {
2901
2902  // This matches 16 permutations of
2903  // min(max(a, b), max(min(a, b), c))
2904  def : AMDGPUPat <
2905  (min (max_oneuse i32:$src0, i32:$src1),
2906       (max_oneuse (min_oneuse i32:$src0, i32:$src1), i32:$src2)),
2907  (med3Inst VSrc_b32:$src0, VSrc_b32:$src1, VSrc_b32:$src2)
2908>;
2909
2910  // This matches 16 permutations of
2911  // max(min(x, y), min(max(x, y), z))
2912  def : AMDGPUPat <
2913  (max (min_oneuse i32:$src0, i32:$src1),
2914       (min_oneuse (max_oneuse i32:$src0, i32:$src1), i32:$src2)),
2915  (med3Inst VSrc_b32:$src0, VSrc_b32:$src1, VSrc_b32:$src2)
2916>;
2917}
2918
2919defm : IntMed3Pat<V_MED3_I32_e64, smin, smax, smin_oneuse, smax_oneuse>;
2920defm : IntMed3Pat<V_MED3_U32_e64, umin, umax, umin_oneuse, umax_oneuse>;
2921
2922// This matches 16 permutations of
2923// max(min(x, y), min(max(x, y), z))
2924class FPMed3Pat<ValueType vt,
2925                //SDPatternOperator max, SDPatternOperator min,
2926                Instruction med3Inst> : GCNPat<
2927  (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
2928                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
2929           (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
2930                                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
2931                           (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))),
2932  (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
2933>;
2934
2935class FP16Med3Pat<ValueType vt,
2936                Instruction med3Inst> : GCNPat<
2937  (fmaxnum_like (fminnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
2938                                     (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
2939           (fminnum_like_oneuse (fmaxnum_like_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
2940                                                     (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
2941                           (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))),
2942  (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE)
2943>;
2944
2945multiclass Int16Med3Pat<Instruction med3Inst,
2946                   SDPatternOperator min,
2947                   SDPatternOperator max,
2948                   SDPatternOperator max_oneuse,
2949                   SDPatternOperator min_oneuse> {
2950  // This matches 16 permutations of
2951  // max(min(x, y), min(max(x, y), z))
2952  def : GCNPat <
2953  (max (min_oneuse i16:$src0, i16:$src1),
2954       (min_oneuse (max_oneuse i16:$src0, i16:$src1), i16:$src2)),
2955  (med3Inst SRCMODS.NONE, VSrc_b16:$src0, SRCMODS.NONE, VSrc_b16:$src1, SRCMODS.NONE, VSrc_b16:$src2, DSTCLAMP.NONE)
2956>;
2957
2958  // This matches 16 permutations of
2959  // min(max(a, b), max(min(a, b), c))
2960  def : GCNPat <
2961  (min (max_oneuse i16:$src0, i16:$src1),
2962      (max_oneuse (min_oneuse i16:$src0, i16:$src1), i16:$src2)),
2963  (med3Inst SRCMODS.NONE, VSrc_b16:$src0, SRCMODS.NONE, VSrc_b16:$src1, SRCMODS.NONE, VSrc_b16:$src2, DSTCLAMP.NONE)
2964>;
2965}
2966
2967def : FPMed3Pat<f32, V_MED3_F32_e64>;
2968
2969let OtherPredicates = [isGFX9Plus] in {
2970def : FP16Med3Pat<f16, V_MED3_F16_e64>;
2971defm : Int16Med3Pat<V_MED3_I16_e64, smin, smax, smax_oneuse, smin_oneuse>;
2972defm : Int16Med3Pat<V_MED3_U16_e64, umin, umax, umax_oneuse, umin_oneuse>;
2973} // End Predicates = [isGFX9Plus]
2974
2975class AMDGPUGenericInstruction : GenericInstruction {
2976  let Namespace = "AMDGPU";
2977}
2978
2979// Convert a wave address to a swizzled vector address (i.e. this is
2980// for copying the stack pointer to a vector address appropriate to
2981// use in the offset field of mubuf instructions).
2982def G_AMDGPU_WAVE_ADDRESS : AMDGPUGenericInstruction {
2983  let OutOperandList = (outs type0:$dst);
2984  let InOperandList = (ins type0:$src);
2985  let hasSideEffects = 0;
2986}
2987
2988// Returns -1 if the input is zero.
2989def G_AMDGPU_FFBH_U32 : AMDGPUGenericInstruction {
2990  let OutOperandList = (outs type0:$dst);
2991  let InOperandList = (ins type1:$src);
2992  let hasSideEffects = 0;
2993}
2994
2995// Returns -1 if the input is zero.
2996def G_AMDGPU_FFBL_B32 : AMDGPUGenericInstruction {
2997  let OutOperandList = (outs type0:$dst);
2998  let InOperandList = (ins type1:$src);
2999  let hasSideEffects = 0;
3000}
3001
3002def G_AMDGPU_RCP_IFLAG : AMDGPUGenericInstruction {
3003  let OutOperandList = (outs type0:$dst);
3004  let InOperandList = (ins type1:$src);
3005  let hasSideEffects = 0;
3006}
3007
3008class BufferLoadGenericInstruction : AMDGPUGenericInstruction {
3009  let OutOperandList = (outs type0:$dst);
3010  let InOperandList = (ins type1:$rsrc, type2:$vindex, type2:$voffset,
3011                           type2:$soffset, untyped_imm_0:$offset,
3012                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3013  let hasSideEffects = 0;
3014  let mayLoad = 1;
3015}
3016
3017class TBufferLoadGenericInstruction : AMDGPUGenericInstruction {
3018  let OutOperandList = (outs type0:$dst);
3019  let InOperandList = (ins type1:$rsrc, type2:$vindex, type2:$voffset,
3020                           type2:$soffset, untyped_imm_0:$offset, untyped_imm_0:$format,
3021                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3022  let hasSideEffects = 0;
3023  let mayLoad = 1;
3024}
3025
3026def G_AMDGPU_BUFFER_LOAD_UBYTE : BufferLoadGenericInstruction;
3027def G_AMDGPU_BUFFER_LOAD_SBYTE : BufferLoadGenericInstruction;
3028def G_AMDGPU_BUFFER_LOAD_USHORT : BufferLoadGenericInstruction;
3029def G_AMDGPU_BUFFER_LOAD_SSHORT : BufferLoadGenericInstruction;
3030def G_AMDGPU_BUFFER_LOAD : BufferLoadGenericInstruction;
3031def G_AMDGPU_BUFFER_LOAD_FORMAT : BufferLoadGenericInstruction;
3032def G_AMDGPU_BUFFER_LOAD_FORMAT_D16 : BufferLoadGenericInstruction;
3033def G_AMDGPU_TBUFFER_LOAD_FORMAT : TBufferLoadGenericInstruction;
3034def G_AMDGPU_TBUFFER_LOAD_FORMAT_D16 : TBufferLoadGenericInstruction;
3035
3036class BufferStoreGenericInstruction : AMDGPUGenericInstruction {
3037  let OutOperandList = (outs);
3038  let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset,
3039                           type2:$soffset, untyped_imm_0:$offset,
3040                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3041  let hasSideEffects = 0;
3042  let mayStore = 1;
3043}
3044
3045class TBufferStoreGenericInstruction : AMDGPUGenericInstruction {
3046  let OutOperandList = (outs);
3047  let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset,
3048                           type2:$soffset, untyped_imm_0:$offset,
3049                           untyped_imm_0:$format,
3050                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3051  let hasSideEffects = 0;
3052  let mayStore = 1;
3053}
3054
3055def G_AMDGPU_BUFFER_STORE : BufferStoreGenericInstruction;
3056def G_AMDGPU_BUFFER_STORE_BYTE : BufferStoreGenericInstruction;
3057def G_AMDGPU_BUFFER_STORE_SHORT : BufferStoreGenericInstruction;
3058def G_AMDGPU_BUFFER_STORE_FORMAT : BufferStoreGenericInstruction;
3059def G_AMDGPU_BUFFER_STORE_FORMAT_D16 : BufferStoreGenericInstruction;
3060def G_AMDGPU_TBUFFER_STORE_FORMAT : TBufferStoreGenericInstruction;
3061def G_AMDGPU_TBUFFER_STORE_FORMAT_D16 : TBufferStoreGenericInstruction;
3062
3063def G_AMDGPU_FMIN_LEGACY : AMDGPUGenericInstruction {
3064  let OutOperandList = (outs type0:$dst);
3065  let InOperandList = (ins type0:$src0, type0:$src1);
3066  let hasSideEffects = 0;
3067}
3068
3069def G_AMDGPU_FMAX_LEGACY : AMDGPUGenericInstruction {
3070  let OutOperandList = (outs type0:$dst);
3071  let InOperandList = (ins type0:$src0, type0:$src1);
3072  let hasSideEffects = 0;
3073}
3074
3075foreach N = 0-3 in {
3076def G_AMDGPU_CVT_F32_UBYTE#N : AMDGPUGenericInstruction {
3077  let OutOperandList = (outs type0:$dst);
3078  let InOperandList = (ins type0:$src0);
3079  let hasSideEffects = 0;
3080}
3081}
3082
3083def G_AMDGPU_CVT_PK_I16_I32 : AMDGPUGenericInstruction {
3084  let OutOperandList = (outs type0:$dst);
3085  let InOperandList = (ins type0:$src0, type0:$src1);
3086  let hasSideEffects = 0;
3087}
3088
3089def G_AMDGPU_SMED3 : AMDGPUGenericInstruction {
3090  let OutOperandList = (outs type0:$dst);
3091  let InOperandList = (ins type0:$src0, type0:$src1, type0:$src2);
3092  let hasSideEffects = 0;
3093}
3094
3095def G_AMDGPU_UMED3 : AMDGPUGenericInstruction {
3096  let OutOperandList = (outs type0:$dst);
3097  let InOperandList = (ins type0:$src0, type0:$src1, type0:$src2);
3098  let hasSideEffects = 0;
3099}
3100
3101def G_AMDGPU_FMED3 : AMDGPUGenericInstruction {
3102  let OutOperandList = (outs type0:$dst);
3103  let InOperandList = (ins type0:$src0, type0:$src1, type0:$src2);
3104  let hasSideEffects = 0;
3105}
3106
3107def G_AMDGPU_CLAMP : AMDGPUGenericInstruction {
3108  let OutOperandList = (outs type0:$dst);
3109  let InOperandList = (ins type0:$src);
3110  let hasSideEffects = 0;
3111}
3112
3113// Atomic cmpxchg. $cmpval ad $newval are packed in a single vector
3114// operand Expects a MachineMemOperand in addition to explicit
3115// operands.
3116def G_AMDGPU_ATOMIC_CMPXCHG : AMDGPUGenericInstruction {
3117  let OutOperandList = (outs type0:$oldval);
3118  let InOperandList = (ins ptype1:$addr, type0:$cmpval_newval);
3119  let hasSideEffects = 0;
3120  let mayLoad = 1;
3121  let mayStore = 1;
3122}
3123
3124let Namespace = "AMDGPU" in {
3125def G_AMDGPU_ATOMIC_INC : G_ATOMICRMW_OP;
3126def G_AMDGPU_ATOMIC_DEC : G_ATOMICRMW_OP;
3127def G_AMDGPU_ATOMIC_FMIN : G_ATOMICRMW_OP;
3128def G_AMDGPU_ATOMIC_FMAX : G_ATOMICRMW_OP;
3129}
3130
3131class BufferAtomicGenericInstruction<bit NoRtn = 0> : AMDGPUGenericInstruction {
3132  let OutOperandList = !if(NoRtn, (outs), (outs type0:$dst));
3133  let InOperandList = (ins type0:$vdata, type1:$rsrc, type2:$vindex, type2:$voffset,
3134                           type2:$soffset, untyped_imm_0:$offset,
3135                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3136  let hasSideEffects = 0;
3137  let mayLoad = 1;
3138  let mayStore = 1;
3139}
3140
3141def G_AMDGPU_BUFFER_ATOMIC_SWAP : BufferAtomicGenericInstruction;
3142def G_AMDGPU_BUFFER_ATOMIC_ADD : BufferAtomicGenericInstruction;
3143def G_AMDGPU_BUFFER_ATOMIC_SUB : BufferAtomicGenericInstruction;
3144def G_AMDGPU_BUFFER_ATOMIC_SMIN : BufferAtomicGenericInstruction;
3145def G_AMDGPU_BUFFER_ATOMIC_UMIN : BufferAtomicGenericInstruction;
3146def G_AMDGPU_BUFFER_ATOMIC_SMAX : BufferAtomicGenericInstruction;
3147def G_AMDGPU_BUFFER_ATOMIC_UMAX : BufferAtomicGenericInstruction;
3148def G_AMDGPU_BUFFER_ATOMIC_AND : BufferAtomicGenericInstruction;
3149def G_AMDGPU_BUFFER_ATOMIC_OR : BufferAtomicGenericInstruction;
3150def G_AMDGPU_BUFFER_ATOMIC_XOR : BufferAtomicGenericInstruction;
3151def G_AMDGPU_BUFFER_ATOMIC_INC : BufferAtomicGenericInstruction;
3152def G_AMDGPU_BUFFER_ATOMIC_DEC : BufferAtomicGenericInstruction;
3153def G_AMDGPU_BUFFER_ATOMIC_FADD : BufferAtomicGenericInstruction;
3154def G_AMDGPU_BUFFER_ATOMIC_FMIN : BufferAtomicGenericInstruction;
3155def G_AMDGPU_BUFFER_ATOMIC_FMAX : BufferAtomicGenericInstruction;
3156
3157def G_AMDGPU_BUFFER_ATOMIC_CMPSWAP : AMDGPUGenericInstruction {
3158  let OutOperandList = (outs type0:$dst);
3159  let InOperandList = (ins type0:$vdata, type0:$cmp, type1:$rsrc, type2:$vindex,
3160                           type2:$voffset, type2:$soffset, untyped_imm_0:$offset,
3161                           untyped_imm_0:$cachepolicy, untyped_imm_0:$idxen);
3162  let hasSideEffects = 0;
3163  let mayLoad = 1;
3164  let mayStore = 1;
3165}
3166
3167// Wrapper around llvm.amdgcn.s.buffer.load. This is mostly needed as
3168// a workaround for the intrinsic being defined as readnone, but
3169// really needs a memory operand.
3170def G_AMDGPU_S_BUFFER_LOAD : AMDGPUGenericInstruction {
3171  let OutOperandList = (outs type0:$dst);
3172  let InOperandList = (ins type1:$rsrc, type2:$offset, untyped_imm_0:$cachepolicy);
3173  let hasSideEffects = 0;
3174  let mayLoad = 1;
3175  let mayStore = 0;
3176}
3177
3178// This is equivalent to the G_INTRINSIC*, but the operands may have
3179// been legalized depending on the subtarget requirements.
3180def G_AMDGPU_INTRIN_IMAGE_LOAD : AMDGPUGenericInstruction {
3181  let OutOperandList = (outs type0:$dst);
3182  let InOperandList = (ins unknown:$intrin, variable_ops);
3183  let hasSideEffects = 0;
3184  let mayLoad = 1;
3185
3186  // FIXME: Use separate opcode for atomics.
3187  let mayStore = 1;
3188}
3189
3190def G_AMDGPU_INTRIN_IMAGE_LOAD_D16 : AMDGPUGenericInstruction {
3191  let OutOperandList = (outs type0:$dst);
3192  let InOperandList = (ins unknown:$intrin, variable_ops);
3193  let hasSideEffects = 0;
3194  let mayLoad = 1;
3195
3196  // FIXME: Use separate opcode for atomics.
3197  let mayStore = 1;
3198}
3199
3200// This is equivalent to the G_INTRINSIC*, but the operands may have
3201// been legalized depending on the subtarget requirements.
3202def G_AMDGPU_INTRIN_IMAGE_STORE : AMDGPUGenericInstruction {
3203  let OutOperandList = (outs);
3204  let InOperandList = (ins unknown:$intrin, variable_ops);
3205  let hasSideEffects = 0;
3206  let mayStore = 1;
3207}
3208
3209def G_AMDGPU_INTRIN_IMAGE_STORE_D16 : AMDGPUGenericInstruction {
3210  let OutOperandList = (outs);
3211  let InOperandList = (ins unknown:$intrin, variable_ops);
3212  let hasSideEffects = 0;
3213  let mayStore = 1;
3214}
3215
3216def G_AMDGPU_INTRIN_BVH_INTERSECT_RAY : AMDGPUGenericInstruction {
3217  let OutOperandList = (outs type0:$dst);
3218  let InOperandList = (ins unknown:$intrin, variable_ops);
3219  let hasSideEffects = 0;
3220  let mayLoad = 1;
3221  let mayStore = 0;
3222}
3223
3224// Generic instruction for SI_CALL, so we can select the register bank and insert a waterfall loop
3225// if necessary.
3226def G_SI_CALL : AMDGPUGenericInstruction {
3227  let OutOperandList = (outs SReg_64:$dst);
3228  let InOperandList = (ins type0:$src0, unknown:$callee);
3229  let Size = 4;
3230  let isCall = 1;
3231  let UseNamedOperandTable = 1;
3232  let SchedRW = [WriteBranch];
3233  // TODO: Should really base this on the call target
3234  let isConvergent = 1;
3235}
3236
3237def G_FPTRUNC_ROUND_UPWARD : AMDGPUGenericInstruction {
3238  let OutOperandList = (outs type0:$vdst);
3239  let InOperandList = (ins type1:$src0);
3240  let hasSideEffects = 0;
3241}
3242
3243def G_FPTRUNC_ROUND_DOWNWARD : AMDGPUGenericInstruction {
3244  let OutOperandList = (outs type0:$vdst);
3245  let InOperandList = (ins type1:$src0);
3246  let hasSideEffects = 0;
3247}
3248