1//===-- SIInstructions.td - SI Instruction Defintions ---------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9// This file was originally auto-generated from a GPU register header file and
10// all the instruction definitions were originally commented out.  Instructions
11// that are not yet supported remain commented out.
12//===----------------------------------------------------------------------===//
13
14def has16BankLDS : Predicate<"Subtarget->getLDSBankCount() == 16">;
15def has32BankLDS : Predicate<"Subtarget->getLDSBankCount() == 32">;
16def HasVGPRIndexMode : Predicate<"Subtarget->hasVGPRIndexMode()">,
17                      AssemblerPredicate<"FeatureVGPRIndexMode">;
18def HasMovrel : Predicate<"Subtarget->hasMovrel()">,
19                AssemblerPredicate<"FeatureMovrel">;
20
21class GCNPat<dag pattern, dag result> : AMDGPUPat<pattern, result> {
22  let SubtargetPredicate = isGCN;
23}
24
25
26include "VOPInstructions.td"
27include "SOPInstructions.td"
28include "SMInstructions.td"
29include "FLATInstructions.td"
30include "BUFInstructions.td"
31
32//===----------------------------------------------------------------------===//
33// EXP Instructions
34//===----------------------------------------------------------------------===//
35
36defm EXP : EXP_m<0, AMDGPUexport>;
37defm EXP_DONE : EXP_m<1, AMDGPUexport_done>;
38
39//===----------------------------------------------------------------------===//
40// VINTRP Instructions
41//===----------------------------------------------------------------------===//
42
43let Uses = [M0, EXEC] in {
44
45// FIXME: Specify SchedRW for VINTRP insturctions.
46
47multiclass V_INTERP_P1_F32_m : VINTRP_m <
48  0x00000000,
49  (outs VGPR_32:$vdst),
50  (ins VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan),
51  "v_interp_p1_f32 $vdst, $vsrc, $attr$attrchan",
52  [(set f32:$vdst, (AMDGPUinterp_p1 f32:$vsrc, (i32 imm:$attrchan),
53                                               (i32 imm:$attr)))]
54>;
55
56let OtherPredicates = [has32BankLDS] in {
57
58defm V_INTERP_P1_F32 : V_INTERP_P1_F32_m;
59
60} // End OtherPredicates = [has32BankLDS]
61
62let OtherPredicates = [has16BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1 in {
63
64defm V_INTERP_P1_F32_16bank : V_INTERP_P1_F32_m;
65
66} // End OtherPredicates = [has32BankLDS], Constraints = "@earlyclobber $vdst", isAsmParserOnly=1
67
68let DisableEncoding = "$src0", Constraints = "$src0 = $vdst" in {
69
70defm V_INTERP_P2_F32 : VINTRP_m <
71  0x00000001,
72  (outs VGPR_32:$vdst),
73  (ins VGPR_32:$src0, VGPR_32:$vsrc, Attr:$attr, AttrChan:$attrchan),
74  "v_interp_p2_f32 $vdst, $vsrc, $attr$attrchan",
75  [(set f32:$vdst, (AMDGPUinterp_p2 f32:$src0, f32:$vsrc, (i32 imm:$attrchan),
76                                                          (i32 imm:$attr)))]>;
77
78} // End DisableEncoding = "$src0", Constraints = "$src0 = $vdst"
79
80defm V_INTERP_MOV_F32 : VINTRP_m <
81  0x00000002,
82  (outs VGPR_32:$vdst),
83  (ins InterpSlot:$vsrc, Attr:$attr, AttrChan:$attrchan),
84  "v_interp_mov_f32 $vdst, $vsrc, $attr$attrchan",
85  [(set f32:$vdst, (AMDGPUinterp_mov (i32 imm:$vsrc), (i32 imm:$attrchan),
86                                     (i32 imm:$attr)))]>;
87
88} // End Uses = [M0, EXEC]
89
90//===----------------------------------------------------------------------===//
91// Pseudo Instructions
92//===----------------------------------------------------------------------===//
93def ATOMIC_FENCE : SPseudoInstSI<
94  (outs), (ins i32imm:$ordering, i32imm:$scope),
95  [(atomic_fence (i32 imm:$ordering), (i32 imm:$scope))],
96  "ATOMIC_FENCE $ordering, $scope"> {
97  let hasSideEffects = 1;
98  let maybeAtomic = 1;
99}
100
101let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC] in {
102
103// For use in patterns
104def V_CNDMASK_B64_PSEUDO : VOP3Common <(outs VReg_64:$vdst),
105  (ins VSrc_b64:$src0, VSrc_b64:$src1, SSrc_b64:$src2), "", []> {
106  let isPseudo = 1;
107  let isCodeGenOnly = 1;
108  let usesCustomInserter = 1;
109}
110
111// 64-bit vector move instruction.  This is mainly used by the SIFoldOperands
112// pass to enable folding of inline immediates.
113def V_MOV_B64_PSEUDO : VPseudoInstSI <(outs VReg_64:$vdst),
114                                      (ins VSrc_b64:$src0)>;
115
116// Pseudoinstruction for @llvm.amdgcn.wqm. It is turned into a copy after the
117// WQM pass processes it.
118def WQM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
119
120// Pseudoinstruction for @llvm.amdgcn.wwm. It is turned into a copy post-RA, so
121// that the @earlyclobber is respected. The @earlyclobber is to make sure that
122// the instruction that defines $src0 (which is run in WWM) doesn't
123// accidentally clobber inactive channels of $vdst.
124let Constraints = "@earlyclobber $vdst" in {
125def WWM : PseudoInstSI <(outs unknown:$vdst), (ins unknown:$src0)>;
126}
127
128} // End let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Uses = [EXEC]
129
130def EXIT_WWM : SPseudoInstSI <(outs SReg_64:$sdst), (ins SReg_64:$src0)> {
131  let hasSideEffects = 0;
132  let mayLoad = 0;
133  let mayStore = 0;
134}
135
136// Invert the exec mask and overwrite the inactive lanes of dst with inactive,
137// restoring it after we're done.
138def V_SET_INACTIVE_B32 : VPseudoInstSI <(outs VGPR_32:$vdst),
139  (ins VGPR_32: $src, VSrc_b32:$inactive),
140  [(set i32:$vdst, (int_amdgcn_set_inactive i32:$src, i32:$inactive))]> {
141  let Constraints = "$src = $vdst";
142}
143
144def V_SET_INACTIVE_B64 : VPseudoInstSI <(outs VReg_64:$vdst),
145  (ins VReg_64: $src, VSrc_b64:$inactive),
146  [(set i64:$vdst, (int_amdgcn_set_inactive i64:$src, i64:$inactive))]> {
147  let Constraints = "$src = $vdst";
148}
149
150let usesCustomInserter = 1, SALU = 1 in {
151def GET_GROUPSTATICSIZE : PseudoInstSI <(outs SReg_32:$sdst), (ins),
152  [(set SReg_32:$sdst, (int_amdgcn_groupstaticsize))]>;
153} // End let usesCustomInserter = 1, SALU = 1
154
155def S_MOV_B64_term : PseudoInstSI<(outs SReg_64:$dst),
156   (ins SSrc_b64:$src0)> {
157  let SALU = 1;
158  let isAsCheapAsAMove = 1;
159  let isTerminator = 1;
160}
161
162def S_XOR_B64_term : PseudoInstSI<(outs SReg_64:$dst),
163   (ins SSrc_b64:$src0, SSrc_b64:$src1)> {
164  let SALU = 1;
165  let isAsCheapAsAMove = 1;
166  let isTerminator = 1;
167}
168
169def S_ANDN2_B64_term : PseudoInstSI<(outs SReg_64:$dst),
170   (ins SSrc_b64:$src0, SSrc_b64:$src1)> {
171  let SALU = 1;
172  let isAsCheapAsAMove = 1;
173  let isTerminator = 1;
174}
175
176def WAVE_BARRIER : SPseudoInstSI<(outs), (ins),
177  [(int_amdgcn_wave_barrier)]> {
178  let SchedRW = [];
179  let hasNoSchedulingInfo = 1;
180  let hasSideEffects = 1;
181  let mayLoad = 1;
182  let mayStore = 1;
183  let isBarrier = 1;
184  let isConvergent = 1;
185  let FixedSize = 1;
186  let Size = 0;
187}
188
189// SI pseudo instructions. These are used by the CFG structurizer pass
190// and should be lowered to ISA instructions prior to codegen.
191
192// Dummy terminator instruction to use after control flow instructions
193// replaced with exec mask operations.
194def SI_MASK_BRANCH : VPseudoInstSI <
195  (outs), (ins brtarget:$target)> {
196  let isBranch = 0;
197  let isTerminator = 1;
198  let isBarrier = 0;
199  let SchedRW = [];
200  let hasNoSchedulingInfo = 1;
201  let FixedSize = 1;
202  let Size = 0;
203}
204
205let isTerminator = 1 in {
206
207let OtherPredicates = [EnableLateCFGStructurize] in {
208 def SI_NON_UNIFORM_BRCOND_PSEUDO : CFPseudoInstSI <
209  (outs),
210  (ins SReg_64:$vcc, brtarget:$target),
211  [(brcond i1:$vcc, bb:$target)]> {
212    let Size = 12;
213}
214}
215
216def SI_IF: CFPseudoInstSI <
217  (outs SReg_64:$dst), (ins SReg_64:$vcc, brtarget:$target),
218  [(set i64:$dst, (AMDGPUif i1:$vcc, bb:$target))], 1, 1> {
219  let Constraints = "";
220  let Size = 12;
221  let hasSideEffects = 1;
222}
223
224def SI_ELSE : CFPseudoInstSI <
225  (outs SReg_64:$dst),
226  (ins SReg_64:$src, brtarget:$target, i1imm:$execfix), [], 1, 1> {
227  let Constraints = "$src = $dst";
228  let Size = 12;
229  let hasSideEffects = 1;
230}
231
232def SI_LOOP : CFPseudoInstSI <
233  (outs), (ins SReg_64:$saved, brtarget:$target),
234  [(AMDGPUloop i64:$saved, bb:$target)], 1, 1> {
235  let Size = 8;
236  let isBranch = 0;
237  let hasSideEffects = 1;
238}
239
240} // End isTerminator = 1
241
242def SI_END_CF : CFPseudoInstSI <
243  (outs), (ins SReg_64:$saved),
244  [(int_amdgcn_end_cf i64:$saved)], 1, 1> {
245  let Size = 4;
246  let isAsCheapAsAMove = 1;
247  let isReMaterializable = 1;
248  let hasSideEffects = 1;
249  let mayLoad = 1; // FIXME: Should not need memory flags
250  let mayStore = 1;
251}
252
253def SI_BREAK : CFPseudoInstSI <
254  (outs SReg_64:$dst), (ins SReg_64:$src),
255  [(set i64:$dst, (int_amdgcn_break i64:$src))], 1> {
256  let Size = 4;
257  let isAsCheapAsAMove = 1;
258  let isReMaterializable = 1;
259}
260
261def SI_IF_BREAK : CFPseudoInstSI <
262  (outs SReg_64:$dst), (ins SReg_64:$vcc, SReg_64:$src),
263  [(set i64:$dst, (int_amdgcn_if_break i1:$vcc, i64:$src))]> {
264  let Size = 4;
265  let isAsCheapAsAMove = 1;
266  let isReMaterializable = 1;
267}
268
269def SI_ELSE_BREAK : CFPseudoInstSI <
270  (outs SReg_64:$dst), (ins SReg_64:$src0, SReg_64:$src1),
271  [(set i64:$dst, (int_amdgcn_else_break i64:$src0, i64:$src1))]> {
272  let Size = 4;
273  let isAsCheapAsAMove = 1;
274  let isReMaterializable = 1;
275}
276
277let Uses = [EXEC], Defs = [EXEC,VCC] in {
278def SI_KILL : PseudoInstSI <
279  (outs), (ins VSrc_b32:$src),
280  [(AMDGPUkill i32:$src)]> {
281  let isConvergent = 1;
282  let usesCustomInserter = 1;
283}
284
285def SI_KILL_TERMINATOR : SPseudoInstSI <
286  (outs), (ins VSrc_b32:$src)> {
287  let isTerminator = 1;
288}
289
290def SI_ILLEGAL_COPY : SPseudoInstSI <
291  (outs unknown:$dst), (ins unknown:$src),
292  [], " ; illegal copy $src to $dst">;
293
294} // End Uses = [EXEC], Defs = [EXEC,VCC]
295
296// Branch on undef scc. Used to avoid intermediate copy from
297// IMPLICIT_DEF to SCC.
298def SI_BR_UNDEF : SPseudoInstSI <(outs), (ins sopp_brtarget:$simm16)> {
299  let isTerminator = 1;
300  let usesCustomInserter = 1;
301}
302
303def SI_PS_LIVE : PseudoInstSI <
304  (outs SReg_64:$dst), (ins),
305  [(set i1:$dst, (int_amdgcn_ps_live))]> {
306  let SALU = 1;
307}
308
309def SI_MASKED_UNREACHABLE : SPseudoInstSI <(outs), (ins),
310  [(int_amdgcn_unreachable)],
311  "; divergent unreachable"> {
312  let Size = 0;
313  let hasNoSchedulingInfo = 1;
314  let FixedSize = 1;
315}
316
317// Used as an isel pseudo to directly emit initialization with an
318// s_mov_b32 rather than a copy of another initialized
319// register. MachineCSE skips copies, and we don't want to have to
320// fold operands before it runs.
321def SI_INIT_M0 : SPseudoInstSI <(outs), (ins SSrc_b32:$src)> {
322  let Defs = [M0];
323  let usesCustomInserter = 1;
324  let isAsCheapAsAMove = 1;
325  let isReMaterializable = 1;
326}
327
328def SI_INIT_EXEC : SPseudoInstSI <
329  (outs), (ins i64imm:$src), []> {
330  let Defs = [EXEC];
331  let usesCustomInserter = 1;
332  let isAsCheapAsAMove = 1;
333}
334
335def SI_INIT_EXEC_FROM_INPUT : SPseudoInstSI <
336  (outs), (ins SSrc_b32:$input, i32imm:$shift), []> {
337  let Defs = [EXEC];
338  let usesCustomInserter = 1;
339}
340
341// Return for returning shaders to a shader variant epilog.
342def SI_RETURN_TO_EPILOG : SPseudoInstSI <
343  (outs), (ins variable_ops), [(AMDGPUreturn_to_epilog)]> {
344  let isTerminator = 1;
345  let isBarrier = 1;
346  let isReturn = 1;
347  let hasNoSchedulingInfo = 1;
348  let DisableWQM = 1;
349}
350
351// Return for returning function calls.
352def SI_RETURN : SPseudoInstSI <
353  (outs), (ins), [],
354  "; return"> {
355  let isTerminator = 1;
356  let isBarrier = 1;
357  let isReturn = 1;
358  let SchedRW = [WriteBranch];
359}
360
361// Return for returning function calls without output register.
362//
363// This version is only needed so we can fill in the output regiter in
364// the custom inserter.
365def SI_CALL_ISEL : SPseudoInstSI <
366  (outs), (ins SSrc_b64:$src0), [(AMDGPUcall i64:$src0)]> {
367  let Size = 4;
368  let isCall = 1;
369  let SchedRW = [WriteBranch];
370  let usesCustomInserter = 1;
371}
372
373// Wrapper around s_swappc_b64 with extra $callee parameter to track
374// the called function after regalloc.
375def SI_CALL : SPseudoInstSI <
376  (outs SReg_64:$dst), (ins SSrc_b64:$src0, unknown:$callee)> {
377  let Size = 4;
378  let isCall = 1;
379  let UseNamedOperandTable = 1;
380  let SchedRW = [WriteBranch];
381}
382
383// Tail call handling pseudo
384def SI_TCRETURN_ISEL : SPseudoInstSI<(outs),
385  (ins SSrc_b64:$src0, i32imm:$fpdiff),
386  [(AMDGPUtc_return i64:$src0, i32:$fpdiff)]> {
387  let isCall = 1;
388  let isTerminator = 1;
389  let isReturn = 1;
390  let isBarrier = 1;
391  let SchedRW = [WriteBranch];
392  let usesCustomInserter = 1;
393}
394
395def SI_TCRETURN : SPseudoInstSI <
396  (outs),
397  (ins SSrc_b64:$src0, unknown:$callee, i32imm:$fpdiff)> {
398  let Size = 4;
399  let isCall = 1;
400  let isTerminator = 1;
401  let isReturn = 1;
402  let isBarrier = 1;
403  let UseNamedOperandTable = 1;
404  let SchedRW = [WriteBranch];
405}
406
407
408def ADJCALLSTACKUP : SPseudoInstSI<
409  (outs), (ins i32imm:$amt0, i32imm:$amt1),
410  [(callseq_start timm:$amt0, timm:$amt1)],
411  "; adjcallstackup $amt0 $amt1"> {
412  let Size = 8; // Worst case. (s_add_u32 + constant)
413  let FixedSize = 1;
414  let hasSideEffects = 1;
415  let usesCustomInserter = 1;
416}
417
418def ADJCALLSTACKDOWN : SPseudoInstSI<
419  (outs), (ins i32imm:$amt1, i32imm:$amt2),
420  [(callseq_end timm:$amt1, timm:$amt2)],
421  "; adjcallstackdown $amt1"> {
422  let Size = 8; // Worst case. (s_add_u32 + constant)
423  let hasSideEffects = 1;
424  let usesCustomInserter = 1;
425}
426
427let Defs = [M0, EXEC],
428  UseNamedOperandTable = 1 in {
429
430class SI_INDIRECT_SRC<RegisterClass rc> : VPseudoInstSI <
431  (outs VGPR_32:$vdst),
432  (ins rc:$src, VS_32:$idx, i32imm:$offset)> {
433  let usesCustomInserter = 1;
434}
435
436class SI_INDIRECT_DST<RegisterClass rc> : VPseudoInstSI <
437  (outs rc:$vdst),
438  (ins rc:$src, VS_32:$idx, i32imm:$offset, VGPR_32:$val)> {
439  let Constraints = "$src = $vdst";
440  let usesCustomInserter = 1;
441}
442
443// TODO: We can support indirect SGPR access.
444def SI_INDIRECT_SRC_V1 : SI_INDIRECT_SRC<VGPR_32>;
445def SI_INDIRECT_SRC_V2 : SI_INDIRECT_SRC<VReg_64>;
446def SI_INDIRECT_SRC_V4 : SI_INDIRECT_SRC<VReg_128>;
447def SI_INDIRECT_SRC_V8 : SI_INDIRECT_SRC<VReg_256>;
448def SI_INDIRECT_SRC_V16 : SI_INDIRECT_SRC<VReg_512>;
449
450def SI_INDIRECT_DST_V1 : SI_INDIRECT_DST<VGPR_32>;
451def SI_INDIRECT_DST_V2 : SI_INDIRECT_DST<VReg_64>;
452def SI_INDIRECT_DST_V4 : SI_INDIRECT_DST<VReg_128>;
453def SI_INDIRECT_DST_V8 : SI_INDIRECT_DST<VReg_256>;
454def SI_INDIRECT_DST_V16 : SI_INDIRECT_DST<VReg_512>;
455
456} // End Uses = [EXEC], Defs = [M0, EXEC]
457
458multiclass SI_SPILL_SGPR <RegisterClass sgpr_class> {
459  let UseNamedOperandTable = 1, SGPRSpill = 1, Uses = [EXEC] in {
460    def _SAVE : PseudoInstSI <
461      (outs),
462      (ins sgpr_class:$data, i32imm:$addr)> {
463      let mayStore = 1;
464      let mayLoad = 0;
465    }
466
467    def _RESTORE : PseudoInstSI <
468      (outs sgpr_class:$data),
469      (ins i32imm:$addr)> {
470      let mayStore = 0;
471      let mayLoad = 1;
472    }
473  } // End UseNamedOperandTable = 1
474}
475
476// You cannot use M0 as the output of v_readlane_b32 instructions or
477// use it in the sdata operand of SMEM instructions. We still need to
478// be able to spill the physical register m0, so allow it for
479// SI_SPILL_32_* instructions.
480defm SI_SPILL_S32  : SI_SPILL_SGPR <SReg_32>;
481defm SI_SPILL_S64  : SI_SPILL_SGPR <SReg_64>;
482defm SI_SPILL_S128 : SI_SPILL_SGPR <SReg_128>;
483defm SI_SPILL_S256 : SI_SPILL_SGPR <SReg_256>;
484defm SI_SPILL_S512 : SI_SPILL_SGPR <SReg_512>;
485
486multiclass SI_SPILL_VGPR <RegisterClass vgpr_class> {
487  let UseNamedOperandTable = 1, VGPRSpill = 1,
488       SchedRW = [WriteVMEM] in {
489    def _SAVE : VPseudoInstSI <
490      (outs),
491      (ins vgpr_class:$vdata, i32imm:$vaddr, SReg_128:$srsrc,
492           SReg_32:$soffset, i32imm:$offset)> {
493      let mayStore = 1;
494      let mayLoad = 0;
495      // (2 * 4) + (8 * num_subregs) bytes maximum
496      let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8);
497    }
498
499    def _RESTORE : VPseudoInstSI <
500      (outs vgpr_class:$vdata),
501      (ins i32imm:$vaddr, SReg_128:$srsrc, SReg_32:$soffset,
502           i32imm:$offset)> {
503      let mayStore = 0;
504      let mayLoad = 1;
505
506      // (2 * 4) + (8 * num_subregs) bytes maximum
507      let Size = !add(!shl(!srl(vgpr_class.Size, 5), 3), 8);
508    }
509  } // End UseNamedOperandTable = 1, VGPRSpill = 1, SchedRW = [WriteVMEM]
510}
511
512defm SI_SPILL_V32  : SI_SPILL_VGPR <VGPR_32>;
513defm SI_SPILL_V64  : SI_SPILL_VGPR <VReg_64>;
514defm SI_SPILL_V96  : SI_SPILL_VGPR <VReg_96>;
515defm SI_SPILL_V128 : SI_SPILL_VGPR <VReg_128>;
516defm SI_SPILL_V256 : SI_SPILL_VGPR <VReg_256>;
517defm SI_SPILL_V512 : SI_SPILL_VGPR <VReg_512>;
518
519def SI_PC_ADD_REL_OFFSET : SPseudoInstSI <
520  (outs SReg_64:$dst),
521  (ins si_ga:$ptr_lo, si_ga:$ptr_hi),
522  [(set SReg_64:$dst,
523   (i64 (SIpc_add_rel_offset (tglobaladdr:$ptr_lo), (tglobaladdr:$ptr_hi))))]> {
524  let Defs = [SCC];
525}
526
527def : GCNPat <
528  (AMDGPUinit_exec i64:$src),
529  (SI_INIT_EXEC (as_i64imm $src))
530>;
531
532def : GCNPat <
533  (AMDGPUinit_exec_from_input i32:$input, i32:$shift),
534  (SI_INIT_EXEC_FROM_INPUT (i32 $input), (as_i32imm $shift))
535>;
536
537def : GCNPat<
538  (AMDGPUtrap timm:$trapid),
539  (S_TRAP $trapid)
540>;
541
542def : GCNPat<
543  (AMDGPUelse i64:$src, bb:$target),
544  (SI_ELSE $src, $target, 0)
545>;
546
547def : GCNPat <
548  (int_AMDGPU_kilp),
549  (SI_KILL (i32 0xbf800000))
550>;
551
552//===----------------------------------------------------------------------===//
553// VOP1 Patterns
554//===----------------------------------------------------------------------===//
555
556let SubtargetPredicate = isGCN, OtherPredicates = [UnsafeFPMath] in {
557
558//def : RcpPat<V_RCP_F64_e32, f64>;
559//defm : RsqPat<V_RSQ_F64_e32, f64>;
560//defm : RsqPat<V_RSQ_F32_e32, f32>;
561
562def : RsqPat<V_RSQ_F32_e32, f32>;
563def : RsqPat<V_RSQ_F64_e32, f64>;
564
565// Convert (x - floor(x)) to fract(x)
566def : GCNPat <
567  (f32 (fsub (f32 (VOP3Mods f32:$x, i32:$mods)),
568             (f32 (ffloor (f32 (VOP3Mods f32:$x, i32:$mods)))))),
569  (V_FRACT_F32_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE)
570>;
571
572// Convert (x + (-floor(x))) to fract(x)
573def : GCNPat <
574  (f64 (fadd (f64 (VOP3Mods f64:$x, i32:$mods)),
575             (f64 (fneg (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))))))),
576  (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE)
577>;
578
579} // End SubtargetPredicate = isGCN, OtherPredicates = [UnsafeFPMath]
580
581
582// f16_to_fp patterns
583def : GCNPat <
584  (f32 (f16_to_fp i32:$src0)),
585  (V_CVT_F32_F16_e64 SRCMODS.NONE, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)
586>;
587
588def : GCNPat <
589  (f32 (f16_to_fp (and_oneuse i32:$src0, 0x7fff))),
590  (V_CVT_F32_F16_e64 SRCMODS.ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)
591>;
592
593def : GCNPat <
594  (f32 (f16_to_fp (or_oneuse i32:$src0, 0x8000))),
595  (V_CVT_F32_F16_e64 SRCMODS.NEG_ABS, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)
596>;
597
598def : GCNPat <
599  (f32 (f16_to_fp (xor_oneuse i32:$src0, 0x8000))),
600  (V_CVT_F32_F16_e64 SRCMODS.NEG, $src0, DSTCLAMP.NONE, DSTOMOD.NONE)
601>;
602
603def : GCNPat <
604  (f64 (fpextend f16:$src)),
605  (V_CVT_F64_F32_e32 (V_CVT_F32_F16_e32 $src))
606>;
607
608// fp_to_fp16 patterns
609def : GCNPat <
610  (i32 (AMDGPUfp_to_f16 (f32 (VOP3Mods f32:$src0, i32:$src0_modifiers)))),
611  (V_CVT_F16_F32_e64 $src0_modifiers, f32:$src0, DSTCLAMP.NONE, DSTOMOD.NONE)
612>;
613
614def : GCNPat <
615  (i32 (fp_to_sint f16:$src)),
616  (V_CVT_I32_F32_e32 (V_CVT_F32_F16_e32 $src))
617>;
618
619def : GCNPat <
620  (i32 (fp_to_uint f16:$src)),
621  (V_CVT_U32_F32_e32 (V_CVT_F32_F16_e32 $src))
622>;
623
624def : GCNPat <
625  (f16 (sint_to_fp i32:$src)),
626  (V_CVT_F16_F32_e32 (V_CVT_F32_I32_e32 $src))
627>;
628
629def : GCNPat <
630  (f16 (uint_to_fp i32:$src)),
631  (V_CVT_F16_F32_e32 (V_CVT_F32_U32_e32 $src))
632>;
633
634//===----------------------------------------------------------------------===//
635// VOP2 Patterns
636//===----------------------------------------------------------------------===//
637
638multiclass FMADPat <ValueType vt, Instruction inst> {
639  def : GCNPat <
640    (vt (fmad (VOP3NoMods vt:$src0),
641              (VOP3NoMods vt:$src1),
642              (VOP3NoMods vt:$src2))),
643    (inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1,
644          SRCMODS.NONE, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
645  >;
646}
647
648defm : FMADPat <f16, V_MAC_F16_e64>;
649defm : FMADPat <f32, V_MAC_F32_e64>;
650
651class FMADModsPat<Instruction inst, SDPatternOperator mad_opr> : GCNPat<
652  (f32 (mad_opr (VOP3Mods f32:$src0, i32:$src0_mod),
653  (VOP3Mods f32:$src1, i32:$src1_mod),
654  (VOP3Mods f32:$src2, i32:$src2_mod))),
655  (inst $src0_mod, $src0, $src1_mod, $src1,
656  $src2_mod, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
657>;
658
659def : FMADModsPat<V_MAD_F32, AMDGPUfmad_ftz>;
660
661multiclass SelectPat <ValueType vt, Instruction inst> {
662  def : GCNPat <
663    (vt (select i1:$src0, vt:$src1, vt:$src2)),
664    (inst $src2, $src1, $src0)
665  >;
666}
667
668defm : SelectPat <i16, V_CNDMASK_B32_e64>;
669defm : SelectPat <i32, V_CNDMASK_B32_e64>;
670defm : SelectPat <f16, V_CNDMASK_B32_e64>;
671defm : SelectPat <f32, V_CNDMASK_B32_e64>;
672
673def : GCNPat <
674  (i32 (add (i32 (ctpop i32:$popcnt)), i32:$val)),
675  (V_BCNT_U32_B32_e64 $popcnt, $val)
676>;
677
678/********** ============================================ **********/
679/********** Extraction, Insertion, Building and Casting  **********/
680/********** ============================================ **********/
681
682foreach Index = 0-2 in {
683  def Extract_Element_v2i32_#Index : Extract_Element <
684    i32, v2i32, Index, !cast<SubRegIndex>(sub#Index)
685  >;
686  def Insert_Element_v2i32_#Index : Insert_Element <
687    i32, v2i32, Index, !cast<SubRegIndex>(sub#Index)
688  >;
689
690  def Extract_Element_v2f32_#Index : Extract_Element <
691    f32, v2f32, Index, !cast<SubRegIndex>(sub#Index)
692  >;
693  def Insert_Element_v2f32_#Index : Insert_Element <
694    f32, v2f32, Index, !cast<SubRegIndex>(sub#Index)
695  >;
696}
697
698foreach Index = 0-3 in {
699  def Extract_Element_v4i32_#Index : Extract_Element <
700    i32, v4i32, Index, !cast<SubRegIndex>(sub#Index)
701  >;
702  def Insert_Element_v4i32_#Index : Insert_Element <
703    i32, v4i32, Index, !cast<SubRegIndex>(sub#Index)
704  >;
705
706  def Extract_Element_v4f32_#Index : Extract_Element <
707    f32, v4f32, Index, !cast<SubRegIndex>(sub#Index)
708  >;
709  def Insert_Element_v4f32_#Index : Insert_Element <
710    f32, v4f32, Index, !cast<SubRegIndex>(sub#Index)
711  >;
712}
713
714foreach Index = 0-7 in {
715  def Extract_Element_v8i32_#Index : Extract_Element <
716    i32, v8i32, Index, !cast<SubRegIndex>(sub#Index)
717  >;
718  def Insert_Element_v8i32_#Index : Insert_Element <
719    i32, v8i32, Index, !cast<SubRegIndex>(sub#Index)
720  >;
721
722  def Extract_Element_v8f32_#Index : Extract_Element <
723    f32, v8f32, Index, !cast<SubRegIndex>(sub#Index)
724  >;
725  def Insert_Element_v8f32_#Index : Insert_Element <
726    f32, v8f32, Index, !cast<SubRegIndex>(sub#Index)
727  >;
728}
729
730foreach Index = 0-15 in {
731  def Extract_Element_v16i32_#Index : Extract_Element <
732    i32, v16i32, Index, !cast<SubRegIndex>(sub#Index)
733  >;
734  def Insert_Element_v16i32_#Index : Insert_Element <
735    i32, v16i32, Index, !cast<SubRegIndex>(sub#Index)
736  >;
737
738  def Extract_Element_v16f32_#Index : Extract_Element <
739    f32, v16f32, Index, !cast<SubRegIndex>(sub#Index)
740  >;
741  def Insert_Element_v16f32_#Index : Insert_Element <
742    f32, v16f32, Index, !cast<SubRegIndex>(sub#Index)
743  >;
744}
745
746let SubtargetPredicate = isGCN in {
747
748// FIXME: Why do only some of these type combinations for SReg and
749// VReg?
750// 16-bit bitcast
751def : BitConvert <i16, f16, VGPR_32>;
752def : BitConvert <f16, i16, VGPR_32>;
753def : BitConvert <i16, f16, SReg_32>;
754def : BitConvert <f16, i16, SReg_32>;
755
756// 32-bit bitcast
757def : BitConvert <i32, f32, VGPR_32>;
758def : BitConvert <f32, i32, VGPR_32>;
759def : BitConvert <i32, f32, SReg_32>;
760def : BitConvert <f32, i32, SReg_32>;
761def : BitConvert <v2i16, i32, SReg_32>;
762def : BitConvert <i32, v2i16, SReg_32>;
763def : BitConvert <v2f16, i32, SReg_32>;
764def : BitConvert <i32, v2f16, SReg_32>;
765def : BitConvert <v2i16, v2f16, SReg_32>;
766def : BitConvert <v2f16, v2i16, SReg_32>;
767def : BitConvert <v2f16, f32, SReg_32>;
768def : BitConvert <f32, v2f16, SReg_32>;
769def : BitConvert <v2i16, f32, SReg_32>;
770def : BitConvert <f32, v2i16, SReg_32>;
771
772// 64-bit bitcast
773def : BitConvert <i64, f64, VReg_64>;
774def : BitConvert <f64, i64, VReg_64>;
775def : BitConvert <v2i32, v2f32, VReg_64>;
776def : BitConvert <v2f32, v2i32, VReg_64>;
777def : BitConvert <i64, v2i32, VReg_64>;
778def : BitConvert <v2i32, i64, VReg_64>;
779def : BitConvert <i64, v2f32, VReg_64>;
780def : BitConvert <v2f32, i64, VReg_64>;
781def : BitConvert <f64, v2f32, VReg_64>;
782def : BitConvert <v2f32, f64, VReg_64>;
783def : BitConvert <f64, v2i32, VReg_64>;
784def : BitConvert <v2i32, f64, VReg_64>;
785def : BitConvert <v4i32, v4f32, VReg_128>;
786def : BitConvert <v4f32, v4i32, VReg_128>;
787
788// 128-bit bitcast
789def : BitConvert <v2i64, v4i32, SReg_128>;
790def : BitConvert <v4i32, v2i64, SReg_128>;
791def : BitConvert <v2f64, v4f32, VReg_128>;
792def : BitConvert <v2f64, v4i32, VReg_128>;
793def : BitConvert <v4f32, v2f64, VReg_128>;
794def : BitConvert <v4i32, v2f64, VReg_128>;
795def : BitConvert <v2i64, v2f64, VReg_128>;
796def : BitConvert <v2f64, v2i64, VReg_128>;
797
798// 256-bit bitcast
799def : BitConvert <v8i32, v8f32, SReg_256>;
800def : BitConvert <v8f32, v8i32, SReg_256>;
801def : BitConvert <v8i32, v8f32, VReg_256>;
802def : BitConvert <v8f32, v8i32, VReg_256>;
803
804// 512-bit bitcast
805def : BitConvert <v16i32, v16f32, VReg_512>;
806def : BitConvert <v16f32, v16i32, VReg_512>;
807
808} // End SubtargetPredicate = isGCN
809
810/********** =================== **********/
811/********** Src & Dst modifiers **********/
812/********** =================== **********/
813
814
815// If denormals are not enabled, it only impacts the compare of the
816// inputs. The output result is not flushed.
817class ClampPat<Instruction inst, ValueType vt> : GCNPat <
818  (vt (AMDGPUclamp (VOP3Mods vt:$src0, i32:$src0_modifiers))),
819  (inst i32:$src0_modifiers, vt:$src0,
820        i32:$src0_modifiers, vt:$src0, DSTCLAMP.ENABLE, DSTOMOD.NONE)
821>;
822
823def : ClampPat<V_MAX_F32_e64, f32>;
824def : ClampPat<V_MAX_F64, f64>;
825def : ClampPat<V_MAX_F16_e64, f16>;
826
827def : GCNPat <
828  (v2f16 (AMDGPUclamp (VOP3PMods v2f16:$src0, i32:$src0_modifiers))),
829  (V_PK_MAX_F16 $src0_modifiers, $src0,
830                $src0_modifiers, $src0, DSTCLAMP.ENABLE)
831>;
832
833/********** ================================ **********/
834/********** Floating point absolute/negative **********/
835/********** ================================ **********/
836
837// Prevent expanding both fneg and fabs.
838
839def : GCNPat <
840  (fneg (fabs f32:$src)),
841  (S_OR_B32 $src, (S_MOV_B32(i32 0x80000000))) // Set sign bit
842>;
843
844// FIXME: Should use S_OR_B32
845def : GCNPat <
846  (fneg (fabs f64:$src)),
847  (REG_SEQUENCE VReg_64,
848    (i32 (EXTRACT_SUBREG f64:$src, sub0)),
849    sub0,
850    (V_OR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)),
851                  (V_MOV_B32_e32 (i32 0x80000000))), // Set sign bit.
852    sub1)
853>;
854
855def : GCNPat <
856  (fabs f32:$src),
857  (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x7fffffff)))
858>;
859
860def : GCNPat <
861  (fneg f32:$src),
862  (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x80000000)))
863>;
864
865def : GCNPat <
866  (fabs f64:$src),
867  (REG_SEQUENCE VReg_64,
868    (i32 (EXTRACT_SUBREG f64:$src, sub0)),
869    sub0,
870    (V_AND_B32_e64 (i32 (EXTRACT_SUBREG f64:$src, sub1)),
871                   (V_MOV_B32_e32 (i32 0x7fffffff))), // Set sign bit.
872     sub1)
873>;
874
875def : GCNPat <
876  (fneg f64:$src),
877  (REG_SEQUENCE VReg_64,
878    (i32 (EXTRACT_SUBREG f64:$src, sub0)),
879    sub0,
880    (V_XOR_B32_e32 (i32 (EXTRACT_SUBREG f64:$src, sub1)),
881                   (i32 (V_MOV_B32_e32 (i32 0x80000000)))),
882    sub1)
883>;
884
885def : GCNPat <
886  (fcopysign f16:$src0, f16:$src1),
887  (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0, $src1)
888>;
889
890def : GCNPat <
891  (fcopysign f32:$src0, f16:$src1),
892  (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), $src0,
893             (V_LSHLREV_B32_e64 (i32 16), $src1))
894>;
895
896def : GCNPat <
897  (fcopysign f64:$src0, f16:$src1),
898  (REG_SEQUENCE SReg_64,
899    (i32 (EXTRACT_SUBREG $src0, sub0)), sub0,
900    (V_BFI_B32 (S_MOV_B32 (i32 0x7fffffff)), (i32 (EXTRACT_SUBREG $src0, sub1)),
901               (V_LSHLREV_B32_e64 (i32 16), $src1)), sub1)
902>;
903
904def : GCNPat <
905  (fcopysign f16:$src0, f32:$src1),
906  (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0,
907             (V_LSHRREV_B32_e64 (i32 16), $src1))
908>;
909
910def : GCNPat <
911  (fcopysign f16:$src0, f64:$src1),
912  (V_BFI_B32 (S_MOV_B32 (i32 0x00007fff)), $src0,
913             (V_LSHRREV_B32_e64 (i32 16), (EXTRACT_SUBREG $src1, sub1)))
914>;
915
916def : GCNPat <
917  (fneg f16:$src),
918  (V_XOR_B32_e32 $src, (V_MOV_B32_e32 (i32 0x00008000)))
919>;
920
921def : GCNPat <
922  (fabs f16:$src),
923  (V_AND_B32_e64 $src, (V_MOV_B32_e32 (i32 0x00007fff)))
924>;
925
926def : GCNPat <
927  (fneg (fabs f16:$src)),
928  (S_OR_B32 $src, (S_MOV_B32 (i32 0x00008000))) // Set sign bit
929>;
930
931def : GCNPat <
932  (fneg v2f16:$src),
933  (V_XOR_B32_e64 (S_MOV_B32 (i32 0x80008000)), $src)
934>;
935
936def : GCNPat <
937  (fabs v2f16:$src),
938  (V_AND_B32_e64 (S_MOV_B32 (i32 0x7fff7fff)), $src)
939>;
940
941// This is really (fneg (fabs v2f16:$src))
942//
943// fabs is not reported as free because there is modifier for it in
944// VOP3P instructions, so it is turned into the bit op.
945def : GCNPat <
946  (fneg (v2f16 (bitconvert (and_oneuse i32:$src, 0x7fff7fff)))),
947  (S_OR_B32 (S_MOV_B32 (i32 0x80008000)), $src) // Set sign bit
948>;
949
950/********** ================== **********/
951/********** Immediate Patterns **********/
952/********** ================== **********/
953
954def : GCNPat <
955  (VGPRImm<(i32 imm)>:$imm),
956  (V_MOV_B32_e32 imm:$imm)
957>;
958
959def : GCNPat <
960  (VGPRImm<(f32 fpimm)>:$imm),
961  (V_MOV_B32_e32 (f32 (bitcast_fpimm_to_i32 $imm)))
962>;
963
964def : GCNPat <
965  (i32 imm:$imm),
966  (S_MOV_B32 imm:$imm)
967>;
968
969// FIXME: Workaround for ordering issue with peephole optimizer where
970// a register class copy interferes with immediate folding.  Should
971// use s_mov_b32, which can be shrunk to s_movk_i32
972def : GCNPat <
973  (VGPRImm<(f16 fpimm)>:$imm),
974  (V_MOV_B32_e32 (f16 (bitcast_fpimm_to_i32 $imm)))
975>;
976
977def : GCNPat <
978  (f32 fpimm:$imm),
979  (S_MOV_B32 (f32 (bitcast_fpimm_to_i32 $imm)))
980>;
981
982def : GCNPat <
983  (f16 fpimm:$imm),
984  (S_MOV_B32 (i32 (bitcast_fpimm_to_i32 $imm)))
985>;
986
987def : GCNPat <
988 (i32 frameindex:$fi),
989 (V_MOV_B32_e32 (i32 (frameindex_to_targetframeindex $fi)))
990>;
991
992def : GCNPat <
993  (i64 InlineImm<i64>:$imm),
994  (S_MOV_B64 InlineImm<i64>:$imm)
995>;
996
997// XXX - Should this use a s_cmp to set SCC?
998
999// Set to sign-extended 64-bit value (true = -1, false = 0)
1000def : GCNPat <
1001  (i1 imm:$imm),
1002  (S_MOV_B64 (i64 (as_i64imm $imm)))
1003>;
1004
1005def : GCNPat <
1006  (f64 InlineFPImm<f64>:$imm),
1007  (S_MOV_B64 (f64 (bitcast_fpimm_to_i64 InlineFPImm<f64>:$imm)))
1008>;
1009
1010/********** ================== **********/
1011/********** Intrinsic Patterns **********/
1012/********** ================== **********/
1013
1014let SubtargetPredicate = isGCN in {
1015def : POW_Common <V_LOG_F32_e32, V_EXP_F32_e32, V_MUL_LEGACY_F32_e32>;
1016}
1017
1018def : GCNPat <
1019  (i32 (sext i1:$src0)),
1020  (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src0)
1021>;
1022
1023class Ext32Pat <SDNode ext> : GCNPat <
1024  (i32 (ext i1:$src0)),
1025  (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src0)
1026>;
1027
1028def : Ext32Pat <zext>;
1029def : Ext32Pat <anyext>;
1030
1031// The multiplication scales from [0,1] to the unsigned integer range
1032def : GCNPat <
1033  (AMDGPUurecip i32:$src0),
1034  (V_CVT_U32_F32_e32
1035    (V_MUL_F32_e32 (i32 CONST.FP_UINT_MAX_PLUS_1),
1036                   (V_RCP_IFLAG_F32_e32 (V_CVT_F32_U32_e32 $src0))))
1037>;
1038
1039//===----------------------------------------------------------------------===//
1040// VOP3 Patterns
1041//===----------------------------------------------------------------------===//
1042
1043let SubtargetPredicate = isGCN in {
1044
1045def : IMad24Pat<V_MAD_I32_I24, 1>;
1046def : UMad24Pat<V_MAD_U32_U24, 1>;
1047
1048defm : BFIPatterns <V_BFI_B32, S_MOV_B32, SReg_64>;
1049def : ROTRPattern <V_ALIGNBIT_B32>;
1050
1051}
1052
1053def : GCNPat<(i32 (trunc (srl i64:$src0, (and i32:$src1, (i32 31))))),
1054          (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)),
1055                          (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>;
1056
1057def : GCNPat<(i32 (trunc (srl i64:$src0, (i32 ShiftAmt32Imm:$src1)))),
1058          (V_ALIGNBIT_B32 (i32 (EXTRACT_SUBREG (i64 $src0), sub1)),
1059                          (i32 (EXTRACT_SUBREG (i64 $src0), sub0)), $src1)>;
1060
1061/********** ====================== **********/
1062/**********   Indirect addressing  **********/
1063/********** ====================== **********/
1064
1065multiclass SI_INDIRECT_Pattern <ValueType vt, ValueType eltvt, string VecSize> {
1066  // Extract with offset
1067  def : GCNPat<
1068    (eltvt (extractelt vt:$src, (MOVRELOffset i32:$idx, (i32 imm:$offset)))),
1069    (!cast<Instruction>("SI_INDIRECT_SRC_"#VecSize) $src, $idx, imm:$offset)
1070  >;
1071
1072  // Insert with offset
1073  def : GCNPat<
1074    (insertelt vt:$src, eltvt:$val, (MOVRELOffset i32:$idx, (i32 imm:$offset))),
1075    (!cast<Instruction>("SI_INDIRECT_DST_"#VecSize) $src, $idx, imm:$offset, $val)
1076  >;
1077}
1078
1079defm : SI_INDIRECT_Pattern <v2f32, f32, "V2">;
1080defm : SI_INDIRECT_Pattern <v4f32, f32, "V4">;
1081defm : SI_INDIRECT_Pattern <v8f32, f32, "V8">;
1082defm : SI_INDIRECT_Pattern <v16f32, f32, "V16">;
1083
1084defm : SI_INDIRECT_Pattern <v2i32, i32, "V2">;
1085defm : SI_INDIRECT_Pattern <v4i32, i32, "V4">;
1086defm : SI_INDIRECT_Pattern <v8i32, i32, "V8">;
1087defm : SI_INDIRECT_Pattern <v16i32, i32, "V16">;
1088
1089//===----------------------------------------------------------------------===//
1090// SAD Patterns
1091//===----------------------------------------------------------------------===//
1092
1093def : GCNPat <
1094  (add (sub_oneuse (umax i32:$src0, i32:$src1),
1095                   (umin i32:$src0, i32:$src1)),
1096       i32:$src2),
1097  (V_SAD_U32 $src0, $src1, $src2, (i1 0))
1098>;
1099
1100def : GCNPat <
1101  (add (select_oneuse (i1 (setugt i32:$src0, i32:$src1)),
1102                      (sub i32:$src0, i32:$src1),
1103                      (sub i32:$src1, i32:$src0)),
1104       i32:$src2),
1105  (V_SAD_U32 $src0, $src1, $src2, (i1 0))
1106>;
1107
1108//===----------------------------------------------------------------------===//
1109// Conversion Patterns
1110//===----------------------------------------------------------------------===//
1111
1112def : GCNPat<(i32 (sext_inreg i32:$src, i1)),
1113  (S_BFE_I32 i32:$src, (i32 65536))>; // 0 | 1 << 16
1114
1115// Handle sext_inreg in i64
1116def : GCNPat <
1117  (i64 (sext_inreg i64:$src, i1)),
1118  (S_BFE_I64 i64:$src, (i32 0x10000)) // 0 | 1 << 16
1119>;
1120
1121def : GCNPat <
1122  (i16 (sext_inreg i16:$src, i1)),
1123  (S_BFE_I32 $src, (i32 0x00010000)) // 0 | 1 << 16
1124>;
1125
1126def : GCNPat <
1127  (i16 (sext_inreg i16:$src, i8)),
1128  (S_BFE_I32 $src, (i32 0x80000)) // 0 | 8 << 16
1129>;
1130
1131def : GCNPat <
1132  (i64 (sext_inreg i64:$src, i8)),
1133  (S_BFE_I64 i64:$src, (i32 0x80000)) // 0 | 8 << 16
1134>;
1135
1136def : GCNPat <
1137  (i64 (sext_inreg i64:$src, i16)),
1138  (S_BFE_I64 i64:$src, (i32 0x100000)) // 0 | 16 << 16
1139>;
1140
1141def : GCNPat <
1142  (i64 (sext_inreg i64:$src, i32)),
1143  (S_BFE_I64 i64:$src, (i32 0x200000)) // 0 | 32 << 16
1144>;
1145
1146def : GCNPat <
1147  (i64 (zext i32:$src)),
1148  (REG_SEQUENCE SReg_64, $src, sub0, (S_MOV_B32 (i32 0)), sub1)
1149>;
1150
1151def : GCNPat <
1152  (i64 (anyext i32:$src)),
1153  (REG_SEQUENCE SReg_64, $src, sub0, (i32 (IMPLICIT_DEF)), sub1)
1154>;
1155
1156class ZExt_i64_i1_Pat <SDNode ext> : GCNPat <
1157  (i64 (ext i1:$src)),
1158    (REG_SEQUENCE VReg_64,
1159      (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src), sub0,
1160      (S_MOV_B32 (i32 0)), sub1)
1161>;
1162
1163
1164def : ZExt_i64_i1_Pat<zext>;
1165def : ZExt_i64_i1_Pat<anyext>;
1166
1167// FIXME: We need to use COPY_TO_REGCLASS to work-around the fact that
1168// REG_SEQUENCE patterns don't support instructions with multiple outputs.
1169def : GCNPat <
1170  (i64 (sext i32:$src)),
1171    (REG_SEQUENCE SReg_64, $src, sub0,
1172    (i32 (COPY_TO_REGCLASS (S_ASHR_I32 $src, (i32 31)), SReg_32_XM0)), sub1)
1173>;
1174
1175def : GCNPat <
1176  (i64 (sext i1:$src)),
1177  (REG_SEQUENCE VReg_64,
1178    (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub0,
1179    (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src), sub1)
1180>;
1181
1182class FPToI1Pat<Instruction Inst, int KOne, ValueType kone_type, ValueType vt, SDPatternOperator fp_to_int> : GCNPat <
1183  (i1 (fp_to_int (vt (VOP3Mods vt:$src0, i32:$src0_modifiers)))),
1184  (i1 (Inst 0, (kone_type KOne), $src0_modifiers, $src0, DSTCLAMP.NONE))
1185>;
1186
1187def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_ONE, i32, f32, fp_to_uint>;
1188def : FPToI1Pat<V_CMP_EQ_F32_e64, CONST.FP32_NEG_ONE, i32, f32, fp_to_sint>;
1189def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_ONE, i64, f64, fp_to_uint>;
1190def : FPToI1Pat<V_CMP_EQ_F64_e64, CONST.FP64_NEG_ONE, i64, f64, fp_to_sint>;
1191
1192// If we need to perform a logical operation on i1 values, we need to
1193// use vector comparisons since there is only one SCC register. Vector
1194// comparisons still write to a pair of SGPRs, so treat these as
1195// 64-bit comparisons. When legalizing SGPR copies, instructions
1196// resulting in the copies from SCC to these instructions will be
1197// moved to the VALU.
1198def : GCNPat <
1199  (i1 (and i1:$src0, i1:$src1)),
1200  (S_AND_B64 $src0, $src1)
1201>;
1202
1203def : GCNPat <
1204  (i1 (or i1:$src0, i1:$src1)),
1205  (S_OR_B64 $src0, $src1)
1206>;
1207
1208def : GCNPat <
1209  (i1 (xor i1:$src0, i1:$src1)),
1210  (S_XOR_B64 $src0, $src1)
1211>;
1212
1213def : GCNPat <
1214  (f32 (sint_to_fp i1:$src)),
1215  (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_NEG_ONE), $src)
1216>;
1217
1218def : GCNPat <
1219  (f32 (uint_to_fp i1:$src)),
1220  (V_CNDMASK_B32_e64 (i32 0), (i32 CONST.FP32_ONE), $src)
1221>;
1222
1223def : GCNPat <
1224  (f64 (sint_to_fp i1:$src)),
1225  (V_CVT_F64_I32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 -1), $src))
1226>;
1227
1228def : GCNPat <
1229  (f64 (uint_to_fp i1:$src)),
1230  (V_CVT_F64_U32_e32 (V_CNDMASK_B32_e64 (i32 0), (i32 1), $src))
1231>;
1232
1233//===----------------------------------------------------------------------===//
1234// Miscellaneous Patterns
1235//===----------------------------------------------------------------------===//
1236def : GCNPat <
1237  (i32 (AMDGPUfp16_zext f16:$src)),
1238  (COPY $src)
1239>;
1240
1241
1242def : GCNPat <
1243  (i32 (trunc i64:$a)),
1244  (EXTRACT_SUBREG $a, sub0)
1245>;
1246
1247def : GCNPat <
1248  (i1 (trunc i32:$a)),
1249  (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1))
1250>;
1251
1252def : GCNPat <
1253  (i1 (trunc i16:$a)),
1254  (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1), $a), (i32 1))
1255>;
1256
1257def : GCNPat <
1258  (i1 (trunc i64:$a)),
1259  (V_CMP_EQ_U32_e64 (S_AND_B32 (i32 1),
1260                    (i32 (EXTRACT_SUBREG $a, sub0))), (i32 1))
1261>;
1262
1263def : GCNPat <
1264  (i32 (bswap i32:$a)),
1265  (V_BFI_B32 (S_MOV_B32 (i32 0x00ff00ff)),
1266             (V_ALIGNBIT_B32 $a, $a, (i32 24)),
1267             (V_ALIGNBIT_B32 $a, $a, (i32 8)))
1268>;
1269
1270let OtherPredicates = [NoFP16Denormals] in {
1271def : GCNPat<
1272  (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))),
1273  (V_MUL_F16_e64 0, (i32 CONST.FP16_ONE), $src_mods, $src, 0, 0)
1274>;
1275
1276def : GCNPat<
1277  (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))),
1278  (V_PK_MUL_F16 0, (i32 CONST.V2FP16_ONE), $src_mods, $src, DSTCLAMP.NONE)
1279>;
1280}
1281
1282let OtherPredicates = [FP16Denormals] in {
1283def : GCNPat<
1284  (fcanonicalize (f16 (VOP3Mods f16:$src, i32:$src_mods))),
1285  (V_MAX_F16_e64 $src_mods, $src, $src_mods, $src, 0, 0)
1286>;
1287
1288def : GCNPat<
1289  (fcanonicalize (v2f16 (VOP3PMods v2f16:$src, i32:$src_mods))),
1290  (V_PK_MAX_F16 $src_mods, $src, $src_mods, $src, DSTCLAMP.NONE)
1291>;
1292}
1293
1294let OtherPredicates = [NoFP32Denormals] in {
1295def : GCNPat<
1296  (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))),
1297  (V_MUL_F32_e64 0, (i32 CONST.FP32_ONE), $src_mods, $src, 0, 0)
1298>;
1299}
1300
1301let OtherPredicates = [FP32Denormals] in {
1302def : GCNPat<
1303  (fcanonicalize (f32 (VOP3Mods f32:$src, i32:$src_mods))),
1304  (V_MAX_F32_e64 $src_mods, $src, $src_mods, $src, 0, 0)
1305>;
1306}
1307
1308let OtherPredicates = [NoFP64Denormals] in {
1309def : GCNPat<
1310  (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))),
1311  (V_MUL_F64 0, CONST.FP64_ONE, $src_mods, $src, 0, 0)
1312>;
1313}
1314
1315let OtherPredicates = [FP64Denormals] in {
1316def : GCNPat<
1317  (fcanonicalize (f64 (VOP3Mods f64:$src, i32:$src_mods))),
1318  (V_MAX_F64 $src_mods, $src, $src_mods, $src, 0, 0)
1319>;
1320}
1321
1322
1323// Allow integer inputs
1324class ExpPattern<SDPatternOperator node, ValueType vt, Instruction Inst> : GCNPat<
1325  (node (i8 timm:$tgt), (i8 timm:$en), vt:$src0, vt:$src1, vt:$src2, vt:$src3, (i1 timm:$compr), (i1 timm:$vm)),
1326  (Inst i8:$tgt, vt:$src0, vt:$src1, vt:$src2, vt:$src3, i1:$vm, i1:$compr, i8:$en)
1327>;
1328
1329def : ExpPattern<AMDGPUexport, i32, EXP>;
1330def : ExpPattern<AMDGPUexport_done, i32, EXP_DONE>;
1331
1332def : GCNPat <
1333  (v2i16 (build_vector i16:$src0, i16:$src1)),
1334  (v2i16 (S_PACK_LL_B32_B16 $src0, $src1))
1335>;
1336
1337// COPY_TO_REGCLASS is workaround tablegen bug from multiple outputs
1338// from S_LSHL_B32's multiple outputs from implicit scc def.
1339def : GCNPat <
1340  (v2i16 (build_vector (i16 0), i16:$src1)),
1341  (v2i16 (COPY_TO_REGCLASS (S_LSHL_B32 i16:$src1, (i16 16)), SReg_32_XM0))
1342>;
1343
1344// With multiple uses of the shift, this will duplicate the shift and
1345// increase register pressure.
1346def : GCNPat <
1347  (v2i16 (build_vector i16:$src0, (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))),
1348  (v2i16 (S_PACK_LH_B32_B16 i16:$src0, i32:$src1))
1349>;
1350
1351def : GCNPat <
1352  (v2i16 (build_vector (i16 (trunc (srl_oneuse i32:$src0, (i32 16)))),
1353                       (i16 (trunc (srl_oneuse i32:$src1, (i32 16)))))),
1354  (v2i16 (S_PACK_HH_B32_B16 $src0, $src1))
1355>;
1356
1357// TODO: Should source modifiers be matched to v_pack_b32_f16?
1358def : GCNPat <
1359  (v2f16 (build_vector f16:$src0, f16:$src1)),
1360  (v2f16 (S_PACK_LL_B32_B16 $src0, $src1))
1361>;
1362
1363// def : GCNPat <
1364//   (v2f16 (scalar_to_vector f16:$src0)),
1365//   (COPY $src0)
1366// >;
1367
1368// def : GCNPat <
1369//   (v2i16 (scalar_to_vector i16:$src0)),
1370//   (COPY $src0)
1371// >;
1372
1373//===----------------------------------------------------------------------===//
1374// Fract Patterns
1375//===----------------------------------------------------------------------===//
1376
1377let SubtargetPredicate = isSI in {
1378
1379// V_FRACT is buggy on SI, so the F32 version is never used and (x-floor(x)) is
1380// used instead. However, SI doesn't have V_FLOOR_F64, so the most efficient
1381// way to implement it is using V_FRACT_F64.
1382// The workaround for the V_FRACT bug is:
1383//    fract(x) = isnan(x) ? x : min(V_FRACT(x), 0.99999999999999999)
1384
1385// Convert floor(x) to (x - fract(x))
1386def : GCNPat <
1387  (f64 (ffloor (f64 (VOP3Mods f64:$x, i32:$mods)))),
1388  (V_ADD_F64
1389      $mods,
1390      $x,
1391      SRCMODS.NEG,
1392      (V_CNDMASK_B64_PSEUDO
1393         (V_MIN_F64
1394             SRCMODS.NONE,
1395             (V_FRACT_F64_e64 $mods, $x, DSTCLAMP.NONE, DSTOMOD.NONE),
1396             SRCMODS.NONE,
1397             (V_MOV_B64_PSEUDO 0x3fefffffffffffff),
1398             DSTCLAMP.NONE, DSTOMOD.NONE),
1399         $x,
1400         (V_CMP_CLASS_F64_e64 SRCMODS.NONE, $x, (i32 3 /*NaN*/))),
1401      DSTCLAMP.NONE, DSTOMOD.NONE)
1402>;
1403
1404} // End SubtargetPredicates = isSI
1405
1406//============================================================================//
1407// Miscellaneous Optimization Patterns
1408//============================================================================//
1409
1410// Undo sub x, c -> add x, -c canonicalization since c is more likely
1411// an inline immediate than -c.
1412// TODO: Also do for 64-bit.
1413def : GCNPat<
1414  (add i32:$src0, (i32 NegSubInlineConst32:$src1)),
1415  (S_SUB_I32 $src0, NegSubInlineConst32:$src1)
1416>;
1417
1418
1419multiclass BFMPatterns <ValueType vt, InstSI BFM, InstSI MOV> {
1420  def : GCNPat <
1421    (vt (shl (vt (add (vt (shl 1, vt:$a)), -1)), vt:$b)),
1422    (BFM $a, $b)
1423  >;
1424
1425  def : GCNPat <
1426    (vt (add (vt (shl 1, vt:$a)), -1)),
1427    (BFM $a, (MOV (i32 0)))
1428  >;
1429}
1430
1431let SubtargetPredicate = isGCN in {
1432
1433defm : BFMPatterns <i32, S_BFM_B32, S_MOV_B32>;
1434// FIXME: defm : BFMPatterns <i64, S_BFM_B64, S_MOV_B64>;
1435
1436defm : BFEPattern <V_BFE_U32, V_BFE_I32, S_MOV_B32>;
1437def : SHA256MaPattern <V_BFI_B32, V_XOR_B32_e64>;
1438
1439def : IntMed3Pat<V_MED3_I32, smax, smax_oneuse, smin_oneuse>;
1440def : IntMed3Pat<V_MED3_U32, umax, umax_oneuse, umin_oneuse>;
1441
1442}
1443
1444// This matches 16 permutations of
1445// max(min(x, y), min(max(x, y), z))
1446class FPMed3Pat<ValueType vt,
1447                Instruction med3Inst> : GCNPat<
1448  (fmaxnum (fminnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
1449                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
1450           (fminnum_oneuse (fmaxnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
1451                                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
1452                           (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))),
1453  (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE, DSTOMOD.NONE)
1454>;
1455
1456class FP16Med3Pat<ValueType vt,
1457                Instruction med3Inst> : GCNPat<
1458  (fmaxnum (fminnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
1459                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
1460           (fminnum_oneuse (fmaxnum_oneuse (VOP3Mods_nnan vt:$src0, i32:$src0_mods),
1461                                           (VOP3Mods_nnan vt:$src1, i32:$src1_mods)),
1462                           (vt (VOP3Mods_nnan vt:$src2, i32:$src2_mods)))),
1463  (med3Inst $src0_mods, $src0, $src1_mods, $src1, $src2_mods, $src2, DSTCLAMP.NONE)
1464>;
1465
1466class Int16Med3Pat<Instruction med3Inst,
1467                   SDPatternOperator max,
1468                   SDPatternOperator max_oneuse,
1469                   SDPatternOperator min_oneuse,
1470                   ValueType vt = i32> : GCNPat<
1471  (max (min_oneuse vt:$src0, vt:$src1),
1472       (min_oneuse (max_oneuse vt:$src0, vt:$src1), vt:$src2)),
1473  (med3Inst SRCMODS.NONE, $src0, SRCMODS.NONE, $src1, SRCMODS.NONE, $src2, DSTCLAMP.NONE)
1474>;
1475
1476def : FPMed3Pat<f32, V_MED3_F32>;
1477
1478let OtherPredicates = [isGFX9] in {
1479def : FP16Med3Pat<f16, V_MED3_F16>;
1480def : Int16Med3Pat<V_MED3_I16, smax, smax_oneuse, smin_oneuse, i16>;
1481def : Int16Med3Pat<V_MED3_U16, umax, umax_oneuse, umin_oneuse, i16>;
1482} // End Predicates = [isGFX9]
1483
1484//============================================================================//
1485// Assembler aliases
1486//============================================================================//
1487
1488multiclass NoCarryAlias<string Inst,
1489  Instruction Inst32NC, Instruction Inst64NC,
1490  Instruction Inst32CO, Instruction Inst64CO> {
1491  def : InstAlias<Inst#" $vdst, $src0, $src1",
1492    (Inst32NC VGPR_32:$vdst, VSrc_b32:$src0, VGPR_32:$src1), 1000>,
1493    Requires<[HasAddNoCarryInsts]>;
1494
1495  def : InstAlias<Inst#" $vdst, $src0, $src1",
1496    (Inst64NC VGPR_32:$vdst, VCSrc_b32:$src0, VCSrc_b32:$src1), -10>,
1497    Requires<[HasAddNoCarryInsts]>;
1498
1499  def : InstAlias<Inst#" $vdst, vcc, $src0, $src1",
1500    (Inst32CO VGPR_32:$vdst, VSrc_b32:$src0, VGPR_32:$src1), 1000>,
1501    Requires<[HasAddNoCarryInsts]>;
1502
1503  def : InstAlias<Inst#" $vdst, $sdst, $src0, $src1",
1504    (Inst64CO VGPR_32:$vdst, SReg_64:$sdst, VSrc_b32:$src0, VGPR_32:$src1), -10>,
1505    Requires<[HasAddNoCarryInsts]>;
1506}
1507
1508// gfx9 made a mess of add instruction names. The existing add
1509// instructions add _co added to the names, and their old names were
1510// repurposed to a version without carry out.
1511// TODO: Do we need SubtargetPredicates for MnemonicAliases?
1512let Predicates = [HasAddNoCarryInsts] in {
1513defm : NoCarryAlias<"v_add_u32", V_ADD_U32_e32_vi, V_ADD_U32_e64_vi,
1514                                 V_ADD_I32_e32_vi, V_ADD_I32_e64_vi>;
1515defm : NoCarryAlias<"v_sub_u32", V_SUB_U32_e32_vi, V_SUB_U32_e64_vi,
1516                                 V_SUB_I32_e32_vi, V_SUB_I32_e64_vi>;
1517defm : NoCarryAlias<"v_subrev_u32",
1518  V_SUBREV_U32_e32_vi, V_SUBREV_U32_e64_vi,
1519  V_SUBREV_I32_e32_vi, V_SUBREV_I32_e64_vi>;
1520}
1521
1522let Predicates = [NotHasAddNoCarryInsts] in {
1523def : MnemonicAlias<"v_add_u32", "v_add_i32">;
1524def : MnemonicAlias<"v_sub_u32", "v_sub_i32">;
1525def : MnemonicAlias<"v_subrev_u32", "v_subrev_i32">;
1526}
1527