]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AMDGPU/SIPeepholeSDWA.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304222, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AMDGPU / SIPeepholeSDWA.cpp
1 //===-- SIPeepholeSDWA.cpp - Peephole optimization for SDWA instructions --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file This pass tries to apply several peephole SDWA patterns.
11 ///
12 /// E.g. original:
13 ///   V_LSHRREV_B32_e32 %vreg0, 16, %vreg1
14 ///   V_ADD_I32_e32 %vreg2, %vreg0, %vreg3
15 ///   V_LSHLREV_B32_e32 %vreg4, 16, %vreg2
16 ///
17 /// Replace:
18 ///   V_ADD_I32_sdwa %vreg4, %vreg1, %vreg3
19 ///       dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:WORD_1 src1_sel:DWORD
20 ///
21 //===----------------------------------------------------------------------===//
22
23
24 #include "AMDGPU.h"
25 #include "AMDGPUSubtarget.h"
26 #include "SIDefines.h"
27 #include "SIInstrInfo.h"
28 #include "llvm/ADT/Statistic.h"
29 #include "llvm/ADT/STLExtras.h"
30 #include "llvm/CodeGen/MachineFunctionPass.h"
31 #include "llvm/CodeGen/MachineInstrBuilder.h"
32 #include <unordered_map>
33 #include <unordered_set>
34
35 using namespace llvm;
36
37 #define DEBUG_TYPE "si-peephole-sdwa"
38
39 STATISTIC(NumSDWAPatternsFound, "Number of SDWA patterns found.");
40 STATISTIC(NumSDWAInstructionsPeepholed,
41           "Number of instruction converted to SDWA.");
42
43 namespace {
44
45 class SDWAOperand;
46
47 class SIPeepholeSDWA : public MachineFunctionPass {
48 public:
49   typedef SmallVector<SDWAOperand *, 4> SDWAOperandsVector;
50
51 private:
52   MachineRegisterInfo *MRI;
53   const SIRegisterInfo *TRI;
54   const SIInstrInfo *TII;
55
56   std::unordered_map<MachineInstr *, std::unique_ptr<SDWAOperand>> SDWAOperands;
57   std::unordered_map<MachineInstr *, SDWAOperandsVector> PotentialMatches;
58   SmallVector<MachineInstr *, 8> ConvertedInstructions;
59
60   Optional<int64_t> foldToImm(const MachineOperand &Op) const;
61
62 public:
63   static char ID;
64
65   SIPeepholeSDWA() : MachineFunctionPass(ID) {
66     initializeSIPeepholeSDWAPass(*PassRegistry::getPassRegistry());
67   }
68
69   bool runOnMachineFunction(MachineFunction &MF) override;
70   void matchSDWAOperands(MachineFunction &MF);
71   bool isConvertibleToSDWA(const MachineInstr &MI) const;
72   bool convertToSDWA(MachineInstr &MI, const SDWAOperandsVector &SDWAOperands);
73   void legalizeScalarOperands(MachineInstr &MI) const;
74
75   StringRef getPassName() const override { return "SI Peephole SDWA"; }
76
77   void getAnalysisUsage(AnalysisUsage &AU) const override {
78     AU.setPreservesCFG();
79     MachineFunctionPass::getAnalysisUsage(AU);
80   }
81 };
82
83 class SDWAOperand {
84 private:
85   MachineOperand *Target; // Operand that would be used in converted instruction
86   MachineOperand *Replaced; // Operand that would be replace by Target
87
88 public:
89   SDWAOperand(MachineOperand *TargetOp, MachineOperand *ReplacedOp)
90       : Target(TargetOp), Replaced(ReplacedOp) {
91     assert(Target->isReg());
92     assert(Replaced->isReg());
93   }
94
95   virtual ~SDWAOperand() {}
96
97   virtual MachineInstr *potentialToConvert(const SIInstrInfo *TII) = 0;
98   virtual bool convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) = 0;
99
100   MachineOperand *getTargetOperand() const { return Target; }
101   MachineOperand *getReplacedOperand() const { return Replaced; }
102   MachineInstr *getParentInst() const { return Target->getParent(); }
103   MachineRegisterInfo *getMRI() const {
104     return &getParentInst()->getParent()->getParent()->getRegInfo();
105   }
106 };
107
108 using namespace AMDGPU::SDWA;
109
110 class SDWASrcOperand : public SDWAOperand {
111 private:
112   SdwaSel SrcSel;
113   bool Abs;
114   bool Neg;
115   bool Sext;
116
117 public:
118   SDWASrcOperand(MachineOperand *TargetOp, MachineOperand *ReplacedOp,
119                  SdwaSel SrcSel_ = DWORD, bool Abs_ = false, bool Neg_ = false,
120                  bool Sext_ = false)
121       : SDWAOperand(TargetOp, ReplacedOp), SrcSel(SrcSel_), Abs(Abs_),
122         Neg(Neg_), Sext(Sext_) {}
123
124   virtual MachineInstr *potentialToConvert(const SIInstrInfo *TII) override;
125   virtual bool convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) override;
126
127   SdwaSel getSrcSel() const { return SrcSel; }
128   bool getAbs() const { return Abs; }
129   bool getNeg() const { return Neg; }
130   bool getSext() const { return Sext; }
131
132   uint64_t getSrcMods() const;
133 };
134
135 class SDWADstOperand : public SDWAOperand {
136 private:
137   SdwaSel DstSel;
138   DstUnused DstUn;
139
140 public:
141   SDWADstOperand(MachineOperand *TargetOp, MachineOperand *ReplacedOp,
142                  SdwaSel DstSel_ = DWORD, DstUnused DstUn_ = UNUSED_PAD)
143       : SDWAOperand(TargetOp, ReplacedOp), DstSel(DstSel_), DstUn(DstUn_) {}
144
145   virtual MachineInstr *potentialToConvert(const SIInstrInfo *TII) override;
146   virtual bool convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) override;
147
148   SdwaSel getDstSel() const { return DstSel; }
149   DstUnused getDstUnused() const { return DstUn; }
150 };
151
152 } // End anonymous namespace.
153
154 INITIALIZE_PASS(SIPeepholeSDWA, DEBUG_TYPE, "SI Peephole SDWA", false, false)
155
156 char SIPeepholeSDWA::ID = 0;
157
158 char &llvm::SIPeepholeSDWAID = SIPeepholeSDWA::ID;
159
160 FunctionPass *llvm::createSIPeepholeSDWAPass() {
161   return new SIPeepholeSDWA();
162 }
163
164 #ifndef NDEBUG
165
166 static raw_ostream& operator<<(raw_ostream &OS, const SdwaSel &Sel) {
167   switch(Sel) {
168   case BYTE_0: OS << "BYTE_0"; break;
169   case BYTE_1: OS << "BYTE_1"; break;
170   case BYTE_2: OS << "BYTE_2"; break;
171   case BYTE_3: OS << "BYTE_3"; break;
172   case WORD_0: OS << "WORD_0"; break;
173   case WORD_1: OS << "WORD_1"; break;
174   case DWORD:  OS << "DWORD"; break;
175   }
176   return OS;
177 }
178
179 static raw_ostream& operator<<(raw_ostream &OS, const DstUnused &Un) {
180   switch(Un) {
181   case UNUSED_PAD: OS << "UNUSED_PAD"; break;
182   case UNUSED_SEXT: OS << "UNUSED_SEXT"; break;
183   case UNUSED_PRESERVE: OS << "UNUSED_PRESERVE"; break;
184   }
185   return OS;
186 }
187
188 static raw_ostream& operator<<(raw_ostream &OS, const SDWASrcOperand &Src) {
189   OS << "SDWA src: " << *Src.getTargetOperand()
190      << " src_sel:" << Src.getSrcSel()
191      << " abs:" << Src.getAbs() << " neg:" << Src.getNeg()
192      << " sext:" << Src.getSext() << '\n';
193   return OS;
194 }
195
196 static raw_ostream& operator<<(raw_ostream &OS, const SDWADstOperand &Dst) {
197   OS << "SDWA dst: " << *Dst.getTargetOperand()
198      << " dst_sel:" << Dst.getDstSel()
199      << " dst_unused:" << Dst.getDstUnused() << '\n';
200   return OS;
201 }
202
203 #endif
204
205 static void copyRegOperand(MachineOperand &To, const MachineOperand &From) {
206   assert(To.isReg() && From.isReg());
207   To.setReg(From.getReg());
208   To.setSubReg(From.getSubReg());
209   To.setIsUndef(From.isUndef());
210   if (To.isUse()) {
211     To.setIsKill(From.isKill());
212   } else {
213     To.setIsDead(From.isDead());
214   }
215 }
216
217 static bool isSameReg(const MachineOperand &LHS, const MachineOperand &RHS) {
218   return LHS.isReg() &&
219          RHS.isReg() &&
220          LHS.getReg() == RHS.getReg() &&
221          LHS.getSubReg() == RHS.getSubReg();
222 }
223
224 static bool isSubregOf(const MachineOperand &SubReg,
225                        const MachineOperand &SuperReg,
226                        const TargetRegisterInfo *TRI) {
227   
228   if (!SuperReg.isReg() || !SubReg.isReg())
229     return false;
230
231   if (isSameReg(SuperReg, SubReg))
232     return true;
233
234   if (SuperReg.getReg() != SubReg.getReg())
235     return false;
236
237   LaneBitmask SuperMask = TRI->getSubRegIndexLaneMask(SuperReg.getSubReg());
238   LaneBitmask SubMask = TRI->getSubRegIndexLaneMask(SubReg.getSubReg());
239   SuperMask |= ~SubMask;
240   return SuperMask.all();
241 }
242
243 uint64_t SDWASrcOperand::getSrcMods() const {
244   uint64_t Mods = 0;
245   if (Abs || Neg) {
246     assert(!Sext &&
247            "Float and integer src modifiers can't be set simulteniously");
248     Mods |= Abs ? SISrcMods::ABS : 0;
249     Mods |= Neg ? SISrcMods::NEG : 0;
250   } else if (Sext) {
251     Mods |= SISrcMods::SEXT;
252   }
253
254   return Mods;
255 }
256
257 MachineInstr *SDWASrcOperand::potentialToConvert(const SIInstrInfo *TII) {
258   // For SDWA src operand potential instruction is one that use register
259   // defined by parent instruction
260   MachineRegisterInfo *MRI = getMRI();
261   MachineOperand *Replaced = getReplacedOperand();
262   assert(Replaced->isReg());
263
264   MachineInstr *PotentialMI = nullptr;
265   for (MachineOperand &PotentialMO : MRI->use_operands(Replaced->getReg())) {
266     // If this is use of another subreg of dst reg then do nothing
267     if (!isSubregOf(*Replaced, PotentialMO, MRI->getTargetRegisterInfo()))
268       continue;
269
270     // If there exist use of superreg of dst then we should not combine this
271     // opernad
272     if (!isSameReg(PotentialMO, *Replaced))
273       return nullptr;
274
275     // Check that PotentialMI is only instruction that uses dst reg
276     if (PotentialMI == nullptr) {
277       PotentialMI = PotentialMO.getParent();
278     } else if (PotentialMI != PotentialMO.getParent()) {
279       return nullptr;
280     }
281   }
282
283   return PotentialMI;
284 }
285
286 bool SDWASrcOperand::convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) {
287   // Find operand in instruction that matches source operand and replace it with
288   // target operand. Set corresponding src_sel
289
290   MachineOperand *Src = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
291   MachineOperand *SrcSel = TII->getNamedOperand(MI, AMDGPU::OpName::src0_sel);
292   MachineOperand *SrcMods =
293       TII->getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
294   assert(Src && (Src->isReg() || Src->isImm()));
295   if (!isSameReg(*Src, *getReplacedOperand())) {
296     // If this is not src0 then it should be src1
297     Src = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
298     SrcSel = TII->getNamedOperand(MI, AMDGPU::OpName::src1_sel);
299     SrcMods = TII->getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
300
301     assert(Src && Src->isReg());
302
303     if ((MI.getOpcode() == AMDGPU::V_MAC_F16_sdwa ||
304          MI.getOpcode() == AMDGPU::V_MAC_F32_sdwa) &&
305         !isSameReg(*Src, *getReplacedOperand())) {
306       // In case of v_mac_f16/32_sdwa this pass can try to apply src operand to
307       // src2. This is not allowed.
308       return false;
309     }
310
311     assert(isSameReg(*Src, *getReplacedOperand()) && SrcSel && SrcMods);
312   }
313   copyRegOperand(*Src, *getTargetOperand());
314   SrcSel->setImm(getSrcSel());
315   SrcMods->setImm(getSrcMods());
316   getTargetOperand()->setIsKill(false);
317   return true;
318 }
319
320 MachineInstr *SDWADstOperand::potentialToConvert(const SIInstrInfo *TII) {
321   // For SDWA dst operand potential instruction is one that defines register
322   // that this operand uses
323   MachineRegisterInfo *MRI = getMRI();
324   MachineInstr *ParentMI = getParentInst();
325   MachineOperand *Replaced = getReplacedOperand();
326   assert(Replaced->isReg());
327
328   for (MachineOperand &PotentialMO : MRI->def_operands(Replaced->getReg())) {
329     if (!isSubregOf(*Replaced, PotentialMO, MRI->getTargetRegisterInfo()))
330       continue;
331
332     if (!isSameReg(*Replaced, PotentialMO))
333       return nullptr;
334
335     // Check that ParentMI is the only instruction that uses replaced register
336     for (MachineOperand &UseMO : MRI->use_operands(PotentialMO.getReg())) {
337       if (isSubregOf(UseMO, PotentialMO, MRI->getTargetRegisterInfo()) &&
338           UseMO.getParent() != ParentMI) {
339         return nullptr;
340       }
341     }
342
343     // Due to SSA this should be onle def of replaced register, so return it
344     return PotentialMO.getParent();
345   }
346
347   return nullptr;
348 }
349
350 bool SDWADstOperand::convertToSDWA(MachineInstr &MI, const SIInstrInfo *TII) {
351   // Replace vdst operand in MI with target operand. Set dst_sel and dst_unused
352
353   if ((MI.getOpcode() == AMDGPU::V_MAC_F16_sdwa ||
354        MI.getOpcode() == AMDGPU::V_MAC_F32_sdwa) &&
355       getDstSel() != AMDGPU::SDWA::DWORD) {
356     // v_mac_f16/32_sdwa allow dst_sel to be equal only to DWORD
357     return false;
358   }
359
360   MachineOperand *Operand = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
361   assert(Operand &&
362          Operand->isReg() &&
363          isSameReg(*Operand, *getReplacedOperand()));
364   copyRegOperand(*Operand, *getTargetOperand());
365   MachineOperand *DstSel= TII->getNamedOperand(MI, AMDGPU::OpName::dst_sel);
366   assert(DstSel);
367   DstSel->setImm(getDstSel());
368   MachineOperand *DstUnused= TII->getNamedOperand(MI, AMDGPU::OpName::dst_unused);
369   assert(DstUnused);
370   DstUnused->setImm(getDstUnused());
371
372   // Remove original instruction  because it would conflict with our new
373   // instruction by register definition
374   getParentInst()->eraseFromParent();
375   return true;
376 }
377
378 Optional<int64_t> SIPeepholeSDWA::foldToImm(const MachineOperand &Op) const {
379   if (Op.isImm()) {
380     return Op.getImm();
381   }
382
383   // If this is not immediate then it can be copy of immediate value, e.g.:
384   // %vreg1<def> = S_MOV_B32 255;
385   if (Op.isReg()) {
386     for (const MachineOperand &Def : MRI->def_operands(Op.getReg())) {
387       if (!isSameReg(Op, Def))
388         continue;
389
390       const MachineInstr *DefInst = Def.getParent();
391       if (!TII->isFoldableCopy(*DefInst))
392         return None;
393
394       const MachineOperand &Copied = DefInst->getOperand(1);
395       if (!Copied.isImm())
396         return None;
397
398       return Copied.getImm();
399     }
400   }
401
402   return None;
403 }
404
405 void SIPeepholeSDWA::matchSDWAOperands(MachineFunction &MF) {
406   for (MachineBasicBlock &MBB : MF) {
407     for (MachineInstr &MI : MBB) {
408       unsigned Opcode = MI.getOpcode();
409       switch (Opcode) {
410       case AMDGPU::V_LSHRREV_B32_e32:
411       case AMDGPU::V_ASHRREV_I32_e32:
412       case AMDGPU::V_LSHLREV_B32_e32: {
413         // from: v_lshrrev_b32_e32 v1, 16/24, v0
414         // to SDWA src:v0 src_sel:WORD_1/BYTE_3
415
416         // from: v_ashrrev_i32_e32 v1, 16/24, v0
417         // to SDWA src:v0 src_sel:WORD_1/BYTE_3 sext:1
418
419         // from: v_lshlrev_b32_e32 v1, 16/24, v0
420         // to SDWA dst:v1 dst_sel:WORD_1/BYTE_3 dst_unused:UNUSED_PAD
421         MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
422         auto Imm = foldToImm(*Src0);
423         if (!Imm)
424           break;
425
426         if (*Imm != 16 && *Imm != 24)
427           break;
428
429         MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
430         MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
431         if (TRI->isPhysicalRegister(Src1->getReg()) ||
432             TRI->isPhysicalRegister(Dst->getReg()))
433           break;
434
435         if (Opcode == AMDGPU::V_LSHLREV_B32_e32) {
436           auto SDWADst = make_unique<SDWADstOperand>(
437               Dst, Src1, *Imm == 16 ? WORD_1 : BYTE_3, UNUSED_PAD);
438           DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWADst << '\n');
439           SDWAOperands[&MI] = std::move(SDWADst);
440           ++NumSDWAPatternsFound;
441         } else {
442           auto SDWASrc = make_unique<SDWASrcOperand>(
443               Src1, Dst, *Imm == 16 ? WORD_1 : BYTE_3, false, false,
444               Opcode == AMDGPU::V_LSHRREV_B32_e32 ? false : true);
445           DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWASrc << '\n');
446           SDWAOperands[&MI] = std::move(SDWASrc);
447           ++NumSDWAPatternsFound;
448         }
449         break;
450       }
451
452       case AMDGPU::V_LSHRREV_B16_e32:
453       case AMDGPU::V_ASHRREV_I16_e32:
454       case AMDGPU::V_LSHLREV_B16_e32: {
455         // from: v_lshrrev_b16_e32 v1, 8, v0
456         // to SDWA src:v0 src_sel:BYTE_1
457
458         // from: v_ashrrev_i16_e32 v1, 8, v0
459         // to SDWA src:v0 src_sel:BYTE_1 sext:1
460
461         // from: v_lshlrev_b16_e32 v1, 8, v0
462         // to SDWA dst:v1 dst_sel:BYTE_1 dst_unused:UNUSED_PAD
463         MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
464         auto Imm = foldToImm(*Src0);
465         if (!Imm || *Imm != 8)
466           break;
467
468         MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
469         MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
470
471         if (TRI->isPhysicalRegister(Src1->getReg()) ||
472             TRI->isPhysicalRegister(Dst->getReg()))
473           break;
474
475         if (Opcode == AMDGPU::V_LSHLREV_B16_e32) {
476           auto SDWADst =
477             make_unique<SDWADstOperand>(Dst, Src1, BYTE_1, UNUSED_PAD);
478           DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWADst << '\n');
479           SDWAOperands[&MI] = std::move(SDWADst);
480           ++NumSDWAPatternsFound;
481         } else {
482           auto SDWASrc = make_unique<SDWASrcOperand>(
483               Src1, Dst, BYTE_1, false, false,
484               Opcode == AMDGPU::V_LSHRREV_B16_e32 ? false : true);
485           DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWASrc << '\n');
486           SDWAOperands[&MI] = std::move(SDWASrc);
487           ++NumSDWAPatternsFound;
488         }
489         break;
490       }
491
492       case AMDGPU::V_BFE_I32:
493       case AMDGPU::V_BFE_U32: {
494         // e.g.:
495         // from: v_bfe_u32 v1, v0, 8, 8
496         // to SDWA src:v0 src_sel:BYTE_1
497
498         // offset | width | src_sel
499         // ------------------------
500         // 0      | 8     | BYTE_0
501         // 0      | 16    | WORD_0
502         // 0      | 32    | DWORD ?
503         // 8      | 8     | BYTE_1
504         // 16     | 8     | BYTE_2
505         // 16     | 16    | WORD_1
506         // 24     | 8     | BYTE_3
507
508         MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
509         auto Offset = foldToImm(*Src1);
510         if (!Offset)
511           break;
512
513         MachineOperand *Src2 = TII->getNamedOperand(MI, AMDGPU::OpName::src2);
514         auto Width = foldToImm(*Src2);
515         if (!Width)
516           break;
517
518         SdwaSel SrcSel = DWORD;
519
520         if (*Offset == 0 && *Width == 8)
521           SrcSel = BYTE_0;
522         else if (*Offset == 0 && *Width == 16)
523           SrcSel = WORD_0;
524         else if (*Offset == 0 && *Width == 32)
525           SrcSel = DWORD;
526         else if (*Offset == 8 && *Width == 8)
527           SrcSel = BYTE_1;
528         else if (*Offset == 16 && *Width == 8)
529           SrcSel = BYTE_2;
530         else if (*Offset == 16 && *Width == 16)
531           SrcSel = WORD_1;
532         else if (*Offset == 24 && *Width == 8)
533           SrcSel = BYTE_3;
534         else
535           break;
536
537         MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
538         MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
539       
540         if (TRI->isPhysicalRegister(Src0->getReg()) ||
541             TRI->isPhysicalRegister(Dst->getReg()))
542           break;
543
544         auto SDWASrc = make_unique<SDWASrcOperand>(
545             Src0, Dst, SrcSel, false, false,
546             Opcode == AMDGPU::V_BFE_U32 ? false : true);
547         DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWASrc << '\n');
548         SDWAOperands[&MI] = std::move(SDWASrc);
549         ++NumSDWAPatternsFound;
550         break;
551       }
552       case AMDGPU::V_AND_B32_e32: {
553         // e.g.:
554         // from: v_and_b32_e32 v1, 0x0000ffff/0x000000ff, v0
555         // to SDWA src:v0 src_sel:WORD_0/BYTE_0
556
557         MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
558         auto Imm = foldToImm(*Src0);
559         if (!Imm)
560           break;
561
562         if (*Imm != 0x0000ffff && *Imm != 0x000000ff)
563           break;
564
565         MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
566         MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
567       
568         if (TRI->isPhysicalRegister(Src1->getReg()) ||
569             TRI->isPhysicalRegister(Dst->getReg()))
570           break;
571
572         auto SDWASrc = make_unique<SDWASrcOperand>(
573             Src1, Dst, *Imm == 0x0000ffff ? WORD_0 : BYTE_0);
574         DEBUG(dbgs() << "Match: " << MI << "To: " << *SDWASrc << '\n');
575         SDWAOperands[&MI] = std::move(SDWASrc);
576         ++NumSDWAPatternsFound;
577         break;
578       }
579       }
580     }
581   }
582 }
583
584 bool SIPeepholeSDWA::isConvertibleToSDWA(const MachineInstr &MI) const {
585   // Check if this instruction has opcode that supports SDWA
586   return AMDGPU::getSDWAOp(MI.getOpcode()) != -1;
587 }
588
589 bool SIPeepholeSDWA::convertToSDWA(MachineInstr &MI,
590                                    const SDWAOperandsVector &SDWAOperands) {
591   // Convert to sdwa
592   int SDWAOpcode = AMDGPU::getSDWAOp(MI.getOpcode());
593   assert(SDWAOpcode != -1);
594
595   const MCInstrDesc &SDWADesc = TII->get(SDWAOpcode);
596
597   // Create SDWA version of instruction MI and initialize its operands
598   MachineInstrBuilder SDWAInst =
599     BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), SDWADesc);
600
601   // Copy dst, if it is present in original then should also be present in SDWA
602   MachineOperand *Dst = TII->getNamedOperand(MI, AMDGPU::OpName::vdst);
603   if (Dst) {
604     assert(AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::vdst) != -1);
605     SDWAInst.add(*Dst);
606   } else {
607     assert(TII->isVOPC(MI));
608   }
609
610   // Copy src0, initialize src0_modifiers. All sdwa instructions has src0 and
611   // src0_modifiers (except for v_nop_sdwa, but it can't get here)
612   MachineOperand *Src0 = TII->getNamedOperand(MI, AMDGPU::OpName::src0);
613   assert(
614     Src0 &&
615     AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src0) != -1 &&
616     AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src0_modifiers) != -1);
617   SDWAInst.addImm(0);
618   SDWAInst.add(*Src0);
619
620   // Copy src1 if present, initialize src1_modifiers.
621   MachineOperand *Src1 = TII->getNamedOperand(MI, AMDGPU::OpName::src1);
622   if (Src1) {
623     assert(
624       AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src1) != -1 &&
625       AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src1_modifiers) != -1);
626     SDWAInst.addImm(0);
627     SDWAInst.add(*Src1);
628   } else {
629     assert(TII->isVOP1(MI));
630   }
631
632   if (SDWAOpcode == AMDGPU::V_MAC_F16_sdwa ||
633       SDWAOpcode == AMDGPU::V_MAC_F32_sdwa) {
634     // v_mac_f16/32 has additional src2 operand tied to vdst
635     MachineOperand *Src2 = TII->getNamedOperand(MI, AMDGPU::OpName::src2);
636     assert(Src2);
637     SDWAInst.add(*Src2);
638   }
639
640   // Initialize clamp.
641   assert(AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::clamp) != -1);
642   SDWAInst.addImm(0);
643
644   // Initialize dst_sel and dst_unused if present
645   if (Dst) {
646     assert(
647       AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::dst_sel) != -1 &&
648       AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::dst_unused) != -1);
649     SDWAInst.addImm(AMDGPU::SDWA::SdwaSel::DWORD);
650     SDWAInst.addImm(AMDGPU::SDWA::DstUnused::UNUSED_PAD);
651   }
652
653   // Initialize src0_sel
654   assert(AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src0_sel) != -1);
655   SDWAInst.addImm(AMDGPU::SDWA::SdwaSel::DWORD);
656
657
658   // Initialize src1_sel if present
659   if (Src1) {
660     assert(AMDGPU::getNamedOperandIdx(SDWAOpcode, AMDGPU::OpName::src1_sel) != -1);
661     SDWAInst.addImm(AMDGPU::SDWA::SdwaSel::DWORD);
662   }
663
664   // Apply all sdwa operand pattenrs
665   bool Converted = false;
666   for (auto &Operand : SDWAOperands) {
667     // There should be no intesection between SDWA operands and potential MIs
668     // e.g.:
669     // v_and_b32 v0, 0xff, v1 -> src:v1 sel:BYTE_0
670     // v_and_b32 v2, 0xff, v0 -> src:v0 sel:BYTE_0
671     // v_add_u32 v3, v4, v2
672     //
673     // In that example it is possible that we would fold 2nd instruction into 3rd
674     // (v_add_u32_sdwa) and then try to fold 1st instruction into 2nd (that was
675     // already destroyed). So if SDWAOperand is also a potential MI then do not
676     // apply it.
677     if (PotentialMatches.count(Operand->getParentInst()) == 0)
678       Converted |= Operand->convertToSDWA(*SDWAInst, TII);
679   }
680   if (Converted) {
681     ConvertedInstructions.push_back(SDWAInst);
682   } else {
683     SDWAInst->eraseFromParent();
684     return false;
685   }
686
687   DEBUG(dbgs() << "Convert instruction:" << MI
688                << "Into:" << *SDWAInst << '\n');
689   ++NumSDWAInstructionsPeepholed;
690
691   MI.eraseFromParent();
692   return true;
693 }
694
695 // If an instruction was converted to SDWA it should not have immediates or SGPR
696 // operands. Copy its scalar operands into VGPRs.
697 void SIPeepholeSDWA::legalizeScalarOperands(MachineInstr &MI) const {
698   const MCInstrDesc &Desc = TII->get(MI.getOpcode());
699   for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
700     MachineOperand &Op = MI.getOperand(I);
701     if (!Op.isImm() && !(Op.isReg() && !TRI->isVGPR(*MRI, Op.getReg())))
702       continue;
703     if (Desc.OpInfo[I].RegClass == -1 ||
704        !TRI->hasVGPRs(TRI->getRegClass(Desc.OpInfo[I].RegClass)))
705       continue;
706     unsigned VGPR = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
707     auto Copy = BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
708                         TII->get(AMDGPU::V_MOV_B32_e32), VGPR);
709     if (Op.isImm())
710       Copy.addImm(Op.getImm());
711     else if (Op.isReg())
712       Copy.addReg(Op.getReg(), Op.isKill() ? RegState::Kill : 0,
713                   Op.getSubReg());
714     Op.ChangeToRegister(VGPR, false);
715   }
716 }
717
718 bool SIPeepholeSDWA::runOnMachineFunction(MachineFunction &MF) {
719   const SISubtarget &ST = MF.getSubtarget<SISubtarget>();
720
721   if (!ST.hasSDWA() ||
722       !AMDGPU::isVI(ST)) { // TODO: Add support for SDWA on gfx9
723     return false;
724   }
725
726   MRI = &MF.getRegInfo();
727   TRI = ST.getRegisterInfo();
728   TII = ST.getInstrInfo();
729   
730   // Find all SDWA operands in MF.
731   matchSDWAOperands(MF);
732
733   for (const auto &OperandPair : SDWAOperands) {
734     const auto &Operand = OperandPair.second;
735     MachineInstr *PotentialMI = Operand->potentialToConvert(TII);
736     if (PotentialMI && isConvertibleToSDWA(*PotentialMI)) {
737       PotentialMatches[PotentialMI].push_back(Operand.get());
738     }
739   }
740
741   for (auto &PotentialPair : PotentialMatches) {
742     MachineInstr &PotentialMI = *PotentialPair.first;
743     convertToSDWA(PotentialMI, PotentialPair.second);
744   }
745
746   PotentialMatches.clear();
747   SDWAOperands.clear();
748
749   while (!ConvertedInstructions.empty())
750     legalizeScalarOperands(*ConvertedInstructions.pop_back_val());
751
752   return false;
753 }