xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86DomainReassignment.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===--- X86DomainReassignment.cpp - Selectively switch register classes---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass attempts to find instruction chains (closures) in one domain,
100b57cec5SDimitry Andric // and convert them to equivalent instructions in a different domain,
110b57cec5SDimitry Andric // if profitable.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "X86.h"
160b57cec5SDimitry Andric #include "X86InstrInfo.h"
170b57cec5SDimitry Andric #include "X86Subtarget.h"
180b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
190b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
200b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
220b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
270b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
280b57cec5SDimitry Andric #include "llvm/Support/Printable.h"
290b57cec5SDimitry Andric #include <bitset>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric #define DEBUG_TYPE "x86-domain-reassignment"
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric static cl::opt<bool> DisableX86DomainReassignment(
380b57cec5SDimitry Andric     "disable-x86-domain-reassignment", cl::Hidden,
390b57cec5SDimitry Andric     cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric namespace {
420b57cec5SDimitry Andric enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric static bool isGPR(const TargetRegisterClass *RC) {
450b57cec5SDimitry Andric   return X86::GR64RegClass.hasSubClassEq(RC) ||
460b57cec5SDimitry Andric          X86::GR32RegClass.hasSubClassEq(RC) ||
470b57cec5SDimitry Andric          X86::GR16RegClass.hasSubClassEq(RC) ||
480b57cec5SDimitry Andric          X86::GR8RegClass.hasSubClassEq(RC);
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric static bool isMask(const TargetRegisterClass *RC,
520b57cec5SDimitry Andric                    const TargetRegisterInfo *TRI) {
530b57cec5SDimitry Andric   return X86::VK16RegClass.hasSubClassEq(RC);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric static RegDomain getDomain(const TargetRegisterClass *RC,
570b57cec5SDimitry Andric                            const TargetRegisterInfo *TRI) {
580b57cec5SDimitry Andric   if (isGPR(RC))
590b57cec5SDimitry Andric     return GPRDomain;
600b57cec5SDimitry Andric   if (isMask(RC, TRI))
610b57cec5SDimitry Andric     return MaskDomain;
620b57cec5SDimitry Andric   return OtherDomain;
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric /// Return a register class equivalent to \p SrcRC, in \p Domain.
660b57cec5SDimitry Andric static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,
670b57cec5SDimitry Andric                                            RegDomain Domain) {
680b57cec5SDimitry Andric   assert(Domain == MaskDomain && "add domain");
690b57cec5SDimitry Andric   if (X86::GR8RegClass.hasSubClassEq(SrcRC))
700b57cec5SDimitry Andric     return &X86::VK8RegClass;
710b57cec5SDimitry Andric   if (X86::GR16RegClass.hasSubClassEq(SrcRC))
720b57cec5SDimitry Andric     return &X86::VK16RegClass;
730b57cec5SDimitry Andric   if (X86::GR32RegClass.hasSubClassEq(SrcRC))
740b57cec5SDimitry Andric     return &X86::VK32RegClass;
750b57cec5SDimitry Andric   if (X86::GR64RegClass.hasSubClassEq(SrcRC))
760b57cec5SDimitry Andric     return &X86::VK64RegClass;
770b57cec5SDimitry Andric   llvm_unreachable("add register class");
780b57cec5SDimitry Andric   return nullptr;
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric /// Abstract Instruction Converter class.
820b57cec5SDimitry Andric class InstrConverterBase {
830b57cec5SDimitry Andric protected:
840b57cec5SDimitry Andric   unsigned SrcOpcode;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric public:
870b57cec5SDimitry Andric   InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric   virtual ~InstrConverterBase() {}
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// \returns true if \p MI is legal to convert.
920b57cec5SDimitry Andric   virtual bool isLegal(const MachineInstr *MI,
930b57cec5SDimitry Andric                        const TargetInstrInfo *TII) const {
940b57cec5SDimitry Andric     assert(MI->getOpcode() == SrcOpcode &&
950b57cec5SDimitry Andric            "Wrong instruction passed to converter");
960b57cec5SDimitry Andric     return true;
970b57cec5SDimitry Andric   }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   /// Applies conversion to \p MI.
1000b57cec5SDimitry Andric   ///
1010b57cec5SDimitry Andric   /// \returns true if \p MI is no longer need, and can be deleted.
1020b57cec5SDimitry Andric   virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
1030b57cec5SDimitry Andric                             MachineRegisterInfo *MRI) const = 0;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   /// \returns the cost increment incurred by converting \p MI.
1060b57cec5SDimitry Andric   virtual double getExtraCost(const MachineInstr *MI,
1070b57cec5SDimitry Andric                               MachineRegisterInfo *MRI) const = 0;
1080b57cec5SDimitry Andric };
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric /// An Instruction Converter which ignores the given instruction.
1110b57cec5SDimitry Andric /// For example, PHI instructions can be safely ignored since only the registers
1120b57cec5SDimitry Andric /// need to change.
1130b57cec5SDimitry Andric class InstrIgnore : public InstrConverterBase {
1140b57cec5SDimitry Andric public:
1150b57cec5SDimitry Andric   InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
1180b57cec5SDimitry Andric                     MachineRegisterInfo *MRI) const override {
1190b57cec5SDimitry Andric     assert(isLegal(MI, TII) && "Cannot convert instruction");
1200b57cec5SDimitry Andric     return false;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   double getExtraCost(const MachineInstr *MI,
1240b57cec5SDimitry Andric                       MachineRegisterInfo *MRI) const override {
1250b57cec5SDimitry Andric     return 0;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric };
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric /// An Instruction Converter which replaces an instruction with another.
1300b57cec5SDimitry Andric class InstrReplacer : public InstrConverterBase {
1310b57cec5SDimitry Andric public:
1320b57cec5SDimitry Andric   /// Opcode of the destination instruction.
1330b57cec5SDimitry Andric   unsigned DstOpcode;
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)
1360b57cec5SDimitry Andric       : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   bool isLegal(const MachineInstr *MI,
1390b57cec5SDimitry Andric                const TargetInstrInfo *TII) const override {
1400b57cec5SDimitry Andric     if (!InstrConverterBase::isLegal(MI, TII))
1410b57cec5SDimitry Andric       return false;
1420b57cec5SDimitry Andric     // It's illegal to replace an instruction that implicitly defines a register
1430b57cec5SDimitry Andric     // with an instruction that doesn't, unless that register dead.
1440b57cec5SDimitry Andric     for (auto &MO : MI->implicit_operands())
1450b57cec5SDimitry Andric       if (MO.isReg() && MO.isDef() && !MO.isDead() &&
1460b57cec5SDimitry Andric           !TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
1470b57cec5SDimitry Andric         return false;
1480b57cec5SDimitry Andric     return true;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
1520b57cec5SDimitry Andric                     MachineRegisterInfo *MRI) const override {
1530b57cec5SDimitry Andric     assert(isLegal(MI, TII) && "Cannot convert instruction");
1540b57cec5SDimitry Andric     MachineInstrBuilder Bld =
1550b57cec5SDimitry Andric         BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));
1560b57cec5SDimitry Andric     // Transfer explicit operands from original instruction. Implicit operands
1570b57cec5SDimitry Andric     // are handled by BuildMI.
1580b57cec5SDimitry Andric     for (auto &Op : MI->explicit_operands())
1590b57cec5SDimitry Andric       Bld.add(Op);
1600b57cec5SDimitry Andric     return true;
1610b57cec5SDimitry Andric   }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   double getExtraCost(const MachineInstr *MI,
1640b57cec5SDimitry Andric                       MachineRegisterInfo *MRI) const override {
1650b57cec5SDimitry Andric     // Assuming instructions have the same cost.
1660b57cec5SDimitry Andric     return 0;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric };
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric /// An Instruction Converter which replaces an instruction with another, and
1710b57cec5SDimitry Andric /// adds a COPY from the new instruction's destination to the old one's.
1720b57cec5SDimitry Andric class InstrReplacerDstCOPY : public InstrConverterBase {
1730b57cec5SDimitry Andric public:
1740b57cec5SDimitry Andric   unsigned DstOpcode;
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)
1770b57cec5SDimitry Andric       : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
1800b57cec5SDimitry Andric                     MachineRegisterInfo *MRI) const override {
1810b57cec5SDimitry Andric     assert(isLegal(MI, TII) && "Cannot convert instruction");
1820b57cec5SDimitry Andric     MachineBasicBlock *MBB = MI->getParent();
1830b57cec5SDimitry Andric     auto &DL = MI->getDebugLoc();
1840b57cec5SDimitry Andric 
1858bcb0991SDimitry Andric     Register Reg = MRI->createVirtualRegister(
1860b57cec5SDimitry Andric         TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo(),
1870b57cec5SDimitry Andric                          *MBB->getParent()));
1880b57cec5SDimitry Andric     MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
1890b57cec5SDimitry Andric     for (unsigned Idx = 1, End = MI->getNumOperands(); Idx < End; ++Idx)
1900b57cec5SDimitry Andric       Bld.add(MI->getOperand(Idx));
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
1930b57cec5SDimitry Andric         .add(MI->getOperand(0))
1940b57cec5SDimitry Andric         .addReg(Reg);
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric     return true;
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   double getExtraCost(const MachineInstr *MI,
2000b57cec5SDimitry Andric                       MachineRegisterInfo *MRI) const override {
2010b57cec5SDimitry Andric     // Assuming instructions have the same cost, and that COPY is in the same
2020b57cec5SDimitry Andric     // domain so it will be eliminated.
2030b57cec5SDimitry Andric     return 0;
2040b57cec5SDimitry Andric   }
2050b57cec5SDimitry Andric };
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric /// An Instruction Converter for replacing COPY instructions.
2080b57cec5SDimitry Andric class InstrCOPYReplacer : public InstrReplacer {
2090b57cec5SDimitry Andric public:
2100b57cec5SDimitry Andric   RegDomain DstDomain;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
2130b57cec5SDimitry Andric       : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   bool isLegal(const MachineInstr *MI,
2160b57cec5SDimitry Andric                const TargetInstrInfo *TII) const override {
2170b57cec5SDimitry Andric     if (!InstrConverterBase::isLegal(MI, TII))
2180b57cec5SDimitry Andric       return false;
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric     // Don't allow copies to/flow GR8/GR16 physical registers.
2210b57cec5SDimitry Andric     // FIXME: Is there some better way to support this?
2228bcb0991SDimitry Andric     Register DstReg = MI->getOperand(0).getReg();
2238bcb0991SDimitry Andric     if (Register::isPhysicalRegister(DstReg) &&
2240b57cec5SDimitry Andric         (X86::GR8RegClass.contains(DstReg) ||
2250b57cec5SDimitry Andric          X86::GR16RegClass.contains(DstReg)))
2260b57cec5SDimitry Andric       return false;
2278bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(1).getReg();
2288bcb0991SDimitry Andric     if (Register::isPhysicalRegister(SrcReg) &&
2290b57cec5SDimitry Andric         (X86::GR8RegClass.contains(SrcReg) ||
2300b57cec5SDimitry Andric          X86::GR16RegClass.contains(SrcReg)))
2310b57cec5SDimitry Andric       return false;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     return true;
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   double getExtraCost(const MachineInstr *MI,
2370b57cec5SDimitry Andric                       MachineRegisterInfo *MRI) const override {
2380b57cec5SDimitry Andric     assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     for (auto &MO : MI->operands()) {
2410b57cec5SDimitry Andric       // Physical registers will not be converted. Assume that converting the
2420b57cec5SDimitry Andric       // COPY to the destination domain will eventually result in a actual
2430b57cec5SDimitry Andric       // instruction.
2448bcb0991SDimitry Andric       if (Register::isPhysicalRegister(MO.getReg()))
2450b57cec5SDimitry Andric         return 1;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric       RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
2480b57cec5SDimitry Andric                                      MRI->getTargetRegisterInfo());
2490b57cec5SDimitry Andric       // Converting a cross domain COPY to a same domain COPY should eliminate
2500b57cec5SDimitry Andric       // an insturction
2510b57cec5SDimitry Andric       if (OpDomain == DstDomain)
2520b57cec5SDimitry Andric         return -1;
2530b57cec5SDimitry Andric     }
2540b57cec5SDimitry Andric     return 0;
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric };
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric /// An Instruction Converter which replaces an instruction with a COPY.
2590b57cec5SDimitry Andric class InstrReplaceWithCopy : public InstrConverterBase {
2600b57cec5SDimitry Andric public:
2610b57cec5SDimitry Andric   // Source instruction operand Index, to be used as the COPY source.
2620b57cec5SDimitry Andric   unsigned SrcOpIdx;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
2650b57cec5SDimitry Andric       : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
2680b57cec5SDimitry Andric                     MachineRegisterInfo *MRI) const override {
2690b57cec5SDimitry Andric     assert(isLegal(MI, TII) && "Cannot convert instruction");
2700b57cec5SDimitry Andric     BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
2710b57cec5SDimitry Andric             TII->get(TargetOpcode::COPY))
2720b57cec5SDimitry Andric         .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
2730b57cec5SDimitry Andric     return true;
2740b57cec5SDimitry Andric   }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   double getExtraCost(const MachineInstr *MI,
2770b57cec5SDimitry Andric                       MachineRegisterInfo *MRI) const override {
2780b57cec5SDimitry Andric     return 0;
2790b57cec5SDimitry Andric   }
2800b57cec5SDimitry Andric };
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric // Key type to be used by the Instruction Converters map.
2830b57cec5SDimitry Andric // A converter is identified by <destination domain, source opcode>
2840b57cec5SDimitry Andric typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
2850b57cec5SDimitry Andric 
286*5ffd83dbSDimitry Andric typedef DenseMap<InstrConverterBaseKeyTy, std::unique_ptr<InstrConverterBase>>
2870b57cec5SDimitry Andric     InstrConverterBaseMap;
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric /// A closure is a set of virtual register representing all of the edges in
2900b57cec5SDimitry Andric /// the closure, as well as all of the instructions connected by those edges.
2910b57cec5SDimitry Andric ///
2920b57cec5SDimitry Andric /// A closure may encompass virtual registers in the same register bank that
2930b57cec5SDimitry Andric /// have different widths. For example, it may contain 32-bit GPRs as well as
2940b57cec5SDimitry Andric /// 64-bit GPRs.
2950b57cec5SDimitry Andric ///
2960b57cec5SDimitry Andric /// A closure that computes an address (i.e. defines a virtual register that is
2970b57cec5SDimitry Andric /// used in a memory operand) excludes the instructions that contain memory
2980b57cec5SDimitry Andric /// operands using the address. Such an instruction will be included in a
2990b57cec5SDimitry Andric /// different closure that manipulates the loaded or stored value.
3000b57cec5SDimitry Andric class Closure {
3010b57cec5SDimitry Andric private:
3020b57cec5SDimitry Andric   /// Virtual registers in the closure.
3030b57cec5SDimitry Andric   DenseSet<unsigned> Edges;
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   /// Instructions in the closure.
3060b57cec5SDimitry Andric   SmallVector<MachineInstr *, 8> Instrs;
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric   /// Domains which this closure can legally be reassigned to.
3090b57cec5SDimitry Andric   std::bitset<NumDomains> LegalDstDomains;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   /// An ID to uniquely identify this closure, even when it gets
3120b57cec5SDimitry Andric   /// moved around
3130b57cec5SDimitry Andric   unsigned ID;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric public:
3160b57cec5SDimitry Andric   Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
3170b57cec5SDimitry Andric     for (RegDomain D : LegalDstDomainList)
3180b57cec5SDimitry Andric       LegalDstDomains.set(D);
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   /// Mark this closure as illegal for reassignment to all domains.
3220b57cec5SDimitry Andric   void setAllIllegal() { LegalDstDomains.reset(); }
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   /// \returns true if this closure has domains which are legal to reassign to.
3250b57cec5SDimitry Andric   bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   /// \returns true if is legal to reassign this closure to domain \p RD.
3280b57cec5SDimitry Andric   bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   /// Mark this closure as illegal for reassignment to domain \p RD.
3310b57cec5SDimitry Andric   void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   bool empty() const { return Edges.empty(); }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   bool insertEdge(unsigned Reg) {
3360b57cec5SDimitry Andric     return Edges.insert(Reg).second;
3370b57cec5SDimitry Andric   }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   using const_edge_iterator = DenseSet<unsigned>::const_iterator;
3400b57cec5SDimitry Andric   iterator_range<const_edge_iterator> edges() const {
3410b57cec5SDimitry Andric     return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   void addInstruction(MachineInstr *I) {
3450b57cec5SDimitry Andric     Instrs.push_back(I);
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   ArrayRef<MachineInstr *> instructions() const {
3490b57cec5SDimitry Andric     return Instrs;
3500b57cec5SDimitry Andric   }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {
3530b57cec5SDimitry Andric     dbgs() << "Registers: ";
3540b57cec5SDimitry Andric     bool First = true;
3550b57cec5SDimitry Andric     for (unsigned Reg : Edges) {
3560b57cec5SDimitry Andric       if (!First)
3570b57cec5SDimitry Andric         dbgs() << ", ";
3580b57cec5SDimitry Andric       First = false;
3590b57cec5SDimitry Andric       dbgs() << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);
3600b57cec5SDimitry Andric     }
3610b57cec5SDimitry Andric     dbgs() << "\n" << "Instructions:";
3620b57cec5SDimitry Andric     for (MachineInstr *MI : Instrs) {
3630b57cec5SDimitry Andric       dbgs() << "\n  ";
3640b57cec5SDimitry Andric       MI->print(dbgs());
3650b57cec5SDimitry Andric     }
3660b57cec5SDimitry Andric     dbgs() << "\n";
3670b57cec5SDimitry Andric   }
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   unsigned getID() const {
3700b57cec5SDimitry Andric     return ID;
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric };
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric class X86DomainReassignment : public MachineFunctionPass {
376480093f4SDimitry Andric   const X86Subtarget *STI = nullptr;
377480093f4SDimitry Andric   MachineRegisterInfo *MRI = nullptr;
378480093f4SDimitry Andric   const X86InstrInfo *TII = nullptr;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   /// All edges that are included in some closure
3810b57cec5SDimitry Andric   DenseSet<unsigned> EnclosedEdges;
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric   /// All instructions that are included in some closure.
3840b57cec5SDimitry Andric   DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric public:
3870b57cec5SDimitry Andric   static char ID;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   X86DomainReassignment() : MachineFunctionPass(ID) { }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
3940b57cec5SDimitry Andric     AU.setPreservesCFG();
3950b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   StringRef getPassName() const override {
3990b57cec5SDimitry Andric     return "X86 Domain Reassignment Pass";
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric private:
4030b57cec5SDimitry Andric   /// A map of available Instruction Converters.
4040b57cec5SDimitry Andric   InstrConverterBaseMap Converters;
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   /// Initialize Converters map.
4070b57cec5SDimitry Andric   void initConverters();
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   /// Starting from \Reg, expand the closure as much as possible.
4100b57cec5SDimitry Andric   void buildClosure(Closure &, unsigned Reg);
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   /// Enqueue \p Reg to be considered for addition to the closure.
4130b57cec5SDimitry Andric   void visitRegister(Closure &, unsigned Reg, RegDomain &Domain,
4140b57cec5SDimitry Andric                      SmallVectorImpl<unsigned> &Worklist);
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   /// Reassign the closure to \p Domain.
4170b57cec5SDimitry Andric   void reassign(const Closure &C, RegDomain Domain) const;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   /// Add \p MI to the closure.
4200b57cec5SDimitry Andric   void encloseInstr(Closure &C, MachineInstr *MI);
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   /// /returns true if it is profitable to reassign the closure to \p Domain.
4230b57cec5SDimitry Andric   bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   /// Calculate the total cost of reassigning the closure to \p Domain.
4260b57cec5SDimitry Andric   double calculateCost(const Closure &C, RegDomain Domain) const;
4270b57cec5SDimitry Andric };
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric char X86DomainReassignment::ID = 0;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric } // End anonymous namespace.
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric void X86DomainReassignment::visitRegister(Closure &C, unsigned Reg,
4340b57cec5SDimitry Andric                                           RegDomain &Domain,
4350b57cec5SDimitry Andric                                           SmallVectorImpl<unsigned> &Worklist) {
4360b57cec5SDimitry Andric   if (EnclosedEdges.count(Reg))
4370b57cec5SDimitry Andric     return;
4380b57cec5SDimitry Andric 
4398bcb0991SDimitry Andric   if (!Register::isVirtualRegister(Reg))
4400b57cec5SDimitry Andric     return;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   if (!MRI->hasOneDef(Reg))
4430b57cec5SDimitry Andric     return;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
4460b57cec5SDimitry Andric   // First edge in closure sets the domain.
4470b57cec5SDimitry Andric   if (Domain == NoDomain)
4480b57cec5SDimitry Andric     Domain = RD;
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric   if (Domain != RD)
4510b57cec5SDimitry Andric     return;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   Worklist.push_back(Reg);
4540b57cec5SDimitry Andric }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric void X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
4570b57cec5SDimitry Andric   auto I = EnclosedInstrs.find(MI);
4580b57cec5SDimitry Andric   if (I != EnclosedInstrs.end()) {
4590b57cec5SDimitry Andric     if (I->second != C.getID())
4600b57cec5SDimitry Andric       // Instruction already belongs to another closure, avoid conflicts between
4610b57cec5SDimitry Andric       // closure and mark this closure as illegal.
4620b57cec5SDimitry Andric       C.setAllIllegal();
4630b57cec5SDimitry Andric     return;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   EnclosedInstrs[MI] = C.getID();
4670b57cec5SDimitry Andric   C.addInstruction(MI);
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   // Mark closure as illegal for reassignment to domains, if there is no
4700b57cec5SDimitry Andric   // converter for the instruction or if the converter cannot convert the
4710b57cec5SDimitry Andric   // instruction.
4720b57cec5SDimitry Andric   for (int i = 0; i != NumDomains; ++i) {
4730b57cec5SDimitry Andric     if (C.isLegal((RegDomain)i)) {
474*5ffd83dbSDimitry Andric       auto I = Converters.find({i, MI->getOpcode()});
475*5ffd83dbSDimitry Andric       if (I == Converters.end() || !I->second->isLegal(MI, TII))
4760b57cec5SDimitry Andric         C.setIllegal((RegDomain)i);
4770b57cec5SDimitry Andric     }
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric double X86DomainReassignment::calculateCost(const Closure &C,
4820b57cec5SDimitry Andric                                             RegDomain DstDomain) const {
4830b57cec5SDimitry Andric   assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   double Cost = 0.0;
4860b57cec5SDimitry Andric   for (auto *MI : C.instructions())
487*5ffd83dbSDimitry Andric     Cost += Converters.find({DstDomain, MI->getOpcode()})
488*5ffd83dbSDimitry Andric                 ->second->getExtraCost(MI, MRI);
4890b57cec5SDimitry Andric   return Cost;
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
4930b57cec5SDimitry Andric                                                      RegDomain Domain) const {
4940b57cec5SDimitry Andric   return calculateCost(C, Domain) < 0.0;
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
4980b57cec5SDimitry Andric   assert(C.isLegal(Domain) && "Cannot convert illegal closure");
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   // Iterate all instructions in the closure, convert each one using the
5010b57cec5SDimitry Andric   // appropriate converter.
5020b57cec5SDimitry Andric   SmallVector<MachineInstr *, 8> ToErase;
5030b57cec5SDimitry Andric   for (auto *MI : C.instructions())
504*5ffd83dbSDimitry Andric     if (Converters.find({Domain, MI->getOpcode()})
505*5ffd83dbSDimitry Andric             ->second->convertInstr(MI, TII, MRI))
5060b57cec5SDimitry Andric       ToErase.push_back(MI);
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   // Iterate all registers in the closure, replace them with registers in the
5090b57cec5SDimitry Andric   // destination domain.
5100b57cec5SDimitry Andric   for (unsigned Reg : C.edges()) {
5110b57cec5SDimitry Andric     MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
5120b57cec5SDimitry Andric     for (auto &MO : MRI->use_operands(Reg)) {
5130b57cec5SDimitry Andric       if (MO.isReg())
5140b57cec5SDimitry Andric         // Remove all subregister references as they are not valid in the
5150b57cec5SDimitry Andric         // destination domain.
5160b57cec5SDimitry Andric         MO.setSubReg(0);
5170b57cec5SDimitry Andric     }
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   for (auto MI : ToErase)
5210b57cec5SDimitry Andric     MI->eraseFromParent();
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric /// \returns true when \p Reg is used as part of an address calculation in \p
5250b57cec5SDimitry Andric /// MI.
5260b57cec5SDimitry Andric static bool usedAsAddr(const MachineInstr &MI, unsigned Reg,
5270b57cec5SDimitry Andric                        const TargetInstrInfo *TII) {
5280b57cec5SDimitry Andric   if (!MI.mayLoadOrStore())
5290b57cec5SDimitry Andric     return false;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   const MCInstrDesc &Desc = TII->get(MI.getOpcode());
5320b57cec5SDimitry Andric   int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
5330b57cec5SDimitry Andric   if (MemOpStart == -1)
5340b57cec5SDimitry Andric     return false;
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   MemOpStart += X86II::getOperandBias(Desc);
5370b57cec5SDimitry Andric   for (unsigned MemOpIdx = MemOpStart,
5380b57cec5SDimitry Andric                 MemOpEnd = MemOpStart + X86::AddrNumOperands;
5390b57cec5SDimitry Andric        MemOpIdx < MemOpEnd; ++MemOpIdx) {
5400b57cec5SDimitry Andric     auto &Op = MI.getOperand(MemOpIdx);
5410b57cec5SDimitry Andric     if (Op.isReg() && Op.getReg() == Reg)
5420b57cec5SDimitry Andric       return true;
5430b57cec5SDimitry Andric   }
5440b57cec5SDimitry Andric   return false;
5450b57cec5SDimitry Andric }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric void X86DomainReassignment::buildClosure(Closure &C, unsigned Reg) {
5480b57cec5SDimitry Andric   SmallVector<unsigned, 4> Worklist;
5490b57cec5SDimitry Andric   RegDomain Domain = NoDomain;
5500b57cec5SDimitry Andric   visitRegister(C, Reg, Domain, Worklist);
5510b57cec5SDimitry Andric   while (!Worklist.empty()) {
5520b57cec5SDimitry Andric     unsigned CurReg = Worklist.pop_back_val();
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     // Register already in this closure.
5550b57cec5SDimitry Andric     if (!C.insertEdge(CurReg))
5560b57cec5SDimitry Andric       continue;
5570b57cec5SDimitry Andric     EnclosedEdges.insert(Reg);
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric     MachineInstr *DefMI = MRI->getVRegDef(CurReg);
5600b57cec5SDimitry Andric     encloseInstr(C, DefMI);
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric     // Add register used by the defining MI to the worklist.
5630b57cec5SDimitry Andric     // Do not add registers which are used in address calculation, they will be
5640b57cec5SDimitry Andric     // added to a different closure.
5650b57cec5SDimitry Andric     int OpEnd = DefMI->getNumOperands();
5660b57cec5SDimitry Andric     const MCInstrDesc &Desc = DefMI->getDesc();
5670b57cec5SDimitry Andric     int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
5680b57cec5SDimitry Andric     if (MemOp != -1)
5690b57cec5SDimitry Andric       MemOp += X86II::getOperandBias(Desc);
5700b57cec5SDimitry Andric     for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
5710b57cec5SDimitry Andric       if (OpIdx == MemOp) {
5720b57cec5SDimitry Andric         // skip address calculation.
5730b57cec5SDimitry Andric         OpIdx += (X86::AddrNumOperands - 1);
5740b57cec5SDimitry Andric         continue;
5750b57cec5SDimitry Andric       }
5760b57cec5SDimitry Andric       auto &Op = DefMI->getOperand(OpIdx);
5770b57cec5SDimitry Andric       if (!Op.isReg() || !Op.isUse())
5780b57cec5SDimitry Andric         continue;
5790b57cec5SDimitry Andric       visitRegister(C, Op.getReg(), Domain, Worklist);
5800b57cec5SDimitry Andric     }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric     // Expand closure through register uses.
5830b57cec5SDimitry Andric     for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
5840b57cec5SDimitry Andric       // We would like to avoid converting closures which calculare addresses,
5850b57cec5SDimitry Andric       // as this should remain in GPRs.
5860b57cec5SDimitry Andric       if (usedAsAddr(UseMI, CurReg, TII)) {
5870b57cec5SDimitry Andric         C.setAllIllegal();
5880b57cec5SDimitry Andric         continue;
5890b57cec5SDimitry Andric       }
5900b57cec5SDimitry Andric       encloseInstr(C, &UseMI);
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric       for (auto &DefOp : UseMI.defs()) {
5930b57cec5SDimitry Andric         if (!DefOp.isReg())
5940b57cec5SDimitry Andric           continue;
5950b57cec5SDimitry Andric 
5968bcb0991SDimitry Andric         Register DefReg = DefOp.getReg();
5978bcb0991SDimitry Andric         if (!Register::isVirtualRegister(DefReg)) {
5980b57cec5SDimitry Andric           C.setAllIllegal();
5990b57cec5SDimitry Andric           continue;
6000b57cec5SDimitry Andric         }
6010b57cec5SDimitry Andric         visitRegister(C, DefReg, Domain, Worklist);
6020b57cec5SDimitry Andric       }
6030b57cec5SDimitry Andric     }
6040b57cec5SDimitry Andric   }
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric void X86DomainReassignment::initConverters() {
6080b57cec5SDimitry Andric   Converters[{MaskDomain, TargetOpcode::PHI}] =
609*5ffd83dbSDimitry Andric       std::make_unique<InstrIgnore>(TargetOpcode::PHI);
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
612*5ffd83dbSDimitry Andric       std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
615*5ffd83dbSDimitry Andric       std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   Converters[{MaskDomain, TargetOpcode::COPY}] =
618*5ffd83dbSDimitry Andric       std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
619*5ffd83dbSDimitry Andric                                           TargetOpcode::COPY);
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
622*5ffd83dbSDimitry Andric     Converters[{MaskDomain, From}] =
623*5ffd83dbSDimitry Andric         std::make_unique<InstrReplacerDstCOPY>(From, To);
6240b57cec5SDimitry Andric   };
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   createReplacerDstCOPY(X86::MOVZX32rm16, X86::KMOVWkm);
6270b57cec5SDimitry Andric   createReplacerDstCOPY(X86::MOVZX64rm16, X86::KMOVWkm);
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric   createReplacerDstCOPY(X86::MOVZX32rr16, X86::KMOVWkk);
6300b57cec5SDimitry Andric   createReplacerDstCOPY(X86::MOVZX64rr16, X86::KMOVWkk);
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   if (STI->hasDQI()) {
6330b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX16rm8, X86::KMOVBkm);
6340b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX32rm8, X86::KMOVBkm);
6350b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX64rm8, X86::KMOVBkm);
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX16rr8, X86::KMOVBkk);
6380b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX32rr8, X86::KMOVBkk);
6390b57cec5SDimitry Andric     createReplacerDstCOPY(X86::MOVZX64rr8, X86::KMOVBkk);
6400b57cec5SDimitry Andric   }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   auto createReplacer = [&](unsigned From, unsigned To) {
643*5ffd83dbSDimitry Andric     Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
6440b57cec5SDimitry Andric   };
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   createReplacer(X86::MOV16rm, X86::KMOVWkm);
6470b57cec5SDimitry Andric   createReplacer(X86::MOV16mr, X86::KMOVWmk);
6480b57cec5SDimitry Andric   createReplacer(X86::MOV16rr, X86::KMOVWkk);
6490b57cec5SDimitry Andric   createReplacer(X86::SHR16ri, X86::KSHIFTRWri);
6500b57cec5SDimitry Andric   createReplacer(X86::SHL16ri, X86::KSHIFTLWri);
6510b57cec5SDimitry Andric   createReplacer(X86::NOT16r, X86::KNOTWrr);
6520b57cec5SDimitry Andric   createReplacer(X86::OR16rr, X86::KORWrr);
6530b57cec5SDimitry Andric   createReplacer(X86::AND16rr, X86::KANDWrr);
6540b57cec5SDimitry Andric   createReplacer(X86::XOR16rr, X86::KXORWrr);
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   if (STI->hasBWI()) {
6570b57cec5SDimitry Andric     createReplacer(X86::MOV32rm, X86::KMOVDkm);
6580b57cec5SDimitry Andric     createReplacer(X86::MOV64rm, X86::KMOVQkm);
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric     createReplacer(X86::MOV32mr, X86::KMOVDmk);
6610b57cec5SDimitry Andric     createReplacer(X86::MOV64mr, X86::KMOVQmk);
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric     createReplacer(X86::MOV32rr, X86::KMOVDkk);
6640b57cec5SDimitry Andric     createReplacer(X86::MOV64rr, X86::KMOVQkk);
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     createReplacer(X86::SHR32ri, X86::KSHIFTRDri);
6670b57cec5SDimitry Andric     createReplacer(X86::SHR64ri, X86::KSHIFTRQri);
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric     createReplacer(X86::SHL32ri, X86::KSHIFTLDri);
6700b57cec5SDimitry Andric     createReplacer(X86::SHL64ri, X86::KSHIFTLQri);
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric     createReplacer(X86::ADD32rr, X86::KADDDrr);
6730b57cec5SDimitry Andric     createReplacer(X86::ADD64rr, X86::KADDQrr);
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric     createReplacer(X86::NOT32r, X86::KNOTDrr);
6760b57cec5SDimitry Andric     createReplacer(X86::NOT64r, X86::KNOTQrr);
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric     createReplacer(X86::OR32rr, X86::KORDrr);
6790b57cec5SDimitry Andric     createReplacer(X86::OR64rr, X86::KORQrr);
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric     createReplacer(X86::AND32rr, X86::KANDDrr);
6820b57cec5SDimitry Andric     createReplacer(X86::AND64rr, X86::KANDQrr);
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric     createReplacer(X86::ANDN32rr, X86::KANDNDrr);
6850b57cec5SDimitry Andric     createReplacer(X86::ANDN64rr, X86::KANDNQrr);
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric     createReplacer(X86::XOR32rr, X86::KXORDrr);
6880b57cec5SDimitry Andric     createReplacer(X86::XOR64rr, X86::KXORQrr);
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric     // TODO: KTEST is not a replacement for TEST due to flag differences. Need
6910b57cec5SDimitry Andric     // to prove only Z flag is used.
6920b57cec5SDimitry Andric     //createReplacer(X86::TEST32rr, X86::KTESTDrr);
6930b57cec5SDimitry Andric     //createReplacer(X86::TEST64rr, X86::KTESTQrr);
6940b57cec5SDimitry Andric   }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   if (STI->hasDQI()) {
6970b57cec5SDimitry Andric     createReplacer(X86::ADD8rr, X86::KADDBrr);
6980b57cec5SDimitry Andric     createReplacer(X86::ADD16rr, X86::KADDWrr);
6990b57cec5SDimitry Andric 
7000b57cec5SDimitry Andric     createReplacer(X86::AND8rr, X86::KANDBrr);
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     createReplacer(X86::MOV8rm, X86::KMOVBkm);
7030b57cec5SDimitry Andric     createReplacer(X86::MOV8mr, X86::KMOVBmk);
7040b57cec5SDimitry Andric     createReplacer(X86::MOV8rr, X86::KMOVBkk);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     createReplacer(X86::NOT8r, X86::KNOTBrr);
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric     createReplacer(X86::OR8rr, X86::KORBrr);
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric     createReplacer(X86::SHR8ri, X86::KSHIFTRBri);
7110b57cec5SDimitry Andric     createReplacer(X86::SHL8ri, X86::KSHIFTLBri);
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric     // TODO: KTEST is not a replacement for TEST due to flag differences. Need
7140b57cec5SDimitry Andric     // to prove only Z flag is used.
7150b57cec5SDimitry Andric     //createReplacer(X86::TEST8rr, X86::KTESTBrr);
7160b57cec5SDimitry Andric     //createReplacer(X86::TEST16rr, X86::KTESTWrr);
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric     createReplacer(X86::XOR8rr, X86::KXORBrr);
7190b57cec5SDimitry Andric   }
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
7230b57cec5SDimitry Andric   if (skipFunction(MF.getFunction()))
7240b57cec5SDimitry Andric     return false;
7250b57cec5SDimitry Andric   if (DisableX86DomainReassignment)
7260b57cec5SDimitry Andric     return false;
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric   LLVM_DEBUG(
7290b57cec5SDimitry Andric       dbgs() << "***** Machine Function before Domain Reassignment *****\n");
7300b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs()));
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   STI = &MF.getSubtarget<X86Subtarget>();
7330b57cec5SDimitry Andric   // GPR->K is the only transformation currently supported, bail out early if no
7340b57cec5SDimitry Andric   // AVX512.
7350b57cec5SDimitry Andric   // TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and
7360b57cec5SDimitry Andric   // VK64 for GR32/GR64, but those aren't legal classes on KNL. If the register
7370b57cec5SDimitry Andric   // coalescer doesn't clean it up and we generate a spill we will crash.
7380b57cec5SDimitry Andric   if (!STI->hasAVX512() || !STI->hasBWI())
7390b57cec5SDimitry Andric     return false;
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   MRI = &MF.getRegInfo();
7420b57cec5SDimitry Andric   assert(MRI->isSSA() && "Expected MIR to be in SSA form");
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   TII = STI->getInstrInfo();
7450b57cec5SDimitry Andric   initConverters();
7460b57cec5SDimitry Andric   bool Changed = false;
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric   EnclosedEdges.clear();
7490b57cec5SDimitry Andric   EnclosedInstrs.clear();
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   std::vector<Closure> Closures;
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   // Go over all virtual registers and calculate a closure.
7540b57cec5SDimitry Andric   unsigned ClosureID = 0;
7550b57cec5SDimitry Andric   for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
7568bcb0991SDimitry Andric     unsigned Reg = Register::index2VirtReg(Idx);
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric     // GPR only current source domain supported.
7590b57cec5SDimitry Andric     if (!isGPR(MRI->getRegClass(Reg)))
7600b57cec5SDimitry Andric       continue;
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric     // Register already in closure.
7630b57cec5SDimitry Andric     if (EnclosedEdges.count(Reg))
7640b57cec5SDimitry Andric       continue;
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     // Calculate closure starting with Reg.
7670b57cec5SDimitry Andric     Closure C(ClosureID++, {MaskDomain});
7680b57cec5SDimitry Andric     buildClosure(C, Reg);
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric     // Collect all closures that can potentially be converted.
7710b57cec5SDimitry Andric     if (!C.empty() && C.isLegal(MaskDomain))
7720b57cec5SDimitry Andric       Closures.push_back(std::move(C));
7730b57cec5SDimitry Andric   }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   for (Closure &C : Closures) {
7760b57cec5SDimitry Andric     LLVM_DEBUG(C.dump(MRI));
7770b57cec5SDimitry Andric     if (isReassignmentProfitable(C, MaskDomain)) {
7780b57cec5SDimitry Andric       reassign(C, MaskDomain);
7790b57cec5SDimitry Andric       ++NumClosuresConverted;
7800b57cec5SDimitry Andric       Changed = true;
7810b57cec5SDimitry Andric     }
7820b57cec5SDimitry Andric   }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   LLVM_DEBUG(
7850b57cec5SDimitry Andric       dbgs() << "***** Machine Function after Domain Reassignment *****\n");
7860b57cec5SDimitry Andric   LLVM_DEBUG(MF.print(dbgs()));
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   return Changed;
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
7920b57cec5SDimitry Andric                 "X86 Domain Reassignment Pass", false, false)
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric /// Returns an instance of the Domain Reassignment pass.
7950b57cec5SDimitry Andric FunctionPass *llvm::createX86DomainReassignmentPass() {
7960b57cec5SDimitry Andric   return new X86DomainReassignment();
7970b57cec5SDimitry Andric }
798