192d5ce3bSGuy Blank //===--- X86DomainReassignment.cpp - Selectively switch register classes---===//
292d5ce3bSGuy Blank //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
692d5ce3bSGuy Blank //
792d5ce3bSGuy Blank //===----------------------------------------------------------------------===//
892d5ce3bSGuy Blank //
992d5ce3bSGuy Blank // This pass attempts to find instruction chains (closures) in one domain,
1092d5ce3bSGuy Blank // and convert them to equivalent instructions in a different domain,
1192d5ce3bSGuy Blank // if profitable.
1292d5ce3bSGuy Blank //
1392d5ce3bSGuy Blank //===----------------------------------------------------------------------===//
1492d5ce3bSGuy Blank 
1592d5ce3bSGuy Blank #include "X86.h"
1692d5ce3bSGuy Blank #include "X86InstrInfo.h"
1792d5ce3bSGuy Blank #include "X86Subtarget.h"
18*5d5aba78SXiang1 Zhang #include "llvm/ADT/BitVector.h"
1992d5ce3bSGuy Blank #include "llvm/ADT/DenseMap.h"
2092d5ce3bSGuy Blank #include "llvm/ADT/DenseMapInfo.h"
2192d5ce3bSGuy Blank #include "llvm/ADT/STLExtras.h"
2292d5ce3bSGuy Blank #include "llvm/ADT/SmallVector.h"
2392d5ce3bSGuy Blank #include "llvm/ADT/Statistic.h"
2492d5ce3bSGuy Blank #include "llvm/CodeGen/MachineFunctionPass.h"
2592d5ce3bSGuy Blank #include "llvm/CodeGen/MachineInstrBuilder.h"
2692d5ce3bSGuy Blank #include "llvm/CodeGen/MachineRegisterInfo.h"
27b3bde2eaSDavid Blaikie #include "llvm/CodeGen/TargetRegisterInfo.h"
2892d5ce3bSGuy Blank #include "llvm/Support/Debug.h"
29e07153a8SKeno Fischer #include "llvm/Support/Printable.h"
305992535eSCraig Topper #include <bitset>
3192d5ce3bSGuy Blank 
3292d5ce3bSGuy Blank using namespace llvm;
3392d5ce3bSGuy Blank 
3492d5ce3bSGuy Blank #define DEBUG_TYPE "x86-domain-reassignment"
3592d5ce3bSGuy Blank 
3692d5ce3bSGuy Blank STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
3792d5ce3bSGuy Blank 
3892d5ce3bSGuy Blank static cl::opt<bool> DisableX86DomainReassignment(
3992d5ce3bSGuy Blank     "disable-x86-domain-reassignment", cl::Hidden,
4092d5ce3bSGuy Blank     cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
4192d5ce3bSGuy Blank 
4292d5ce3bSGuy Blank namespace {
435992535eSCraig Topper enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
4492d5ce3bSGuy Blank 
isGPR(const TargetRegisterClass * RC)4592d5ce3bSGuy Blank static bool isGPR(const TargetRegisterClass *RC) {
4692d5ce3bSGuy Blank   return X86::GR64RegClass.hasSubClassEq(RC) ||
4792d5ce3bSGuy Blank          X86::GR32RegClass.hasSubClassEq(RC) ||
4892d5ce3bSGuy Blank          X86::GR16RegClass.hasSubClassEq(RC) ||
4992d5ce3bSGuy Blank          X86::GR8RegClass.hasSubClassEq(RC);
5092d5ce3bSGuy Blank }
5192d5ce3bSGuy Blank 
isMask(const TargetRegisterClass * RC,const TargetRegisterInfo * TRI)5292d5ce3bSGuy Blank static bool isMask(const TargetRegisterClass *RC,
5392d5ce3bSGuy Blank                    const TargetRegisterInfo *TRI) {
5492d5ce3bSGuy Blank   return X86::VK16RegClass.hasSubClassEq(RC);
5592d5ce3bSGuy Blank }
5692d5ce3bSGuy Blank 
getDomain(const TargetRegisterClass * RC,const TargetRegisterInfo * TRI)5792d5ce3bSGuy Blank static RegDomain getDomain(const TargetRegisterClass *RC,
5892d5ce3bSGuy Blank                            const TargetRegisterInfo *TRI) {
5992d5ce3bSGuy Blank   if (isGPR(RC))
6092d5ce3bSGuy Blank     return GPRDomain;
6192d5ce3bSGuy Blank   if (isMask(RC, TRI))
6292d5ce3bSGuy Blank     return MaskDomain;
6392d5ce3bSGuy Blank   return OtherDomain;
6492d5ce3bSGuy Blank }
6592d5ce3bSGuy Blank 
6692d5ce3bSGuy Blank /// Return a register class equivalent to \p SrcRC, in \p Domain.
getDstRC(const TargetRegisterClass * SrcRC,RegDomain Domain)6792d5ce3bSGuy Blank static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,
6892d5ce3bSGuy Blank                                            RegDomain Domain) {
6992d5ce3bSGuy Blank   assert(Domain == MaskDomain && "add domain");
70f3cefdd3SGuy Blank   if (X86::GR8RegClass.hasSubClassEq(SrcRC))
7192d5ce3bSGuy Blank     return &X86::VK8RegClass;
72f3cefdd3SGuy Blank   if (X86::GR16RegClass.hasSubClassEq(SrcRC))
7392d5ce3bSGuy Blank     return &X86::VK16RegClass;
74f3cefdd3SGuy Blank   if (X86::GR32RegClass.hasSubClassEq(SrcRC))
7592d5ce3bSGuy Blank     return &X86::VK32RegClass;
76f3cefdd3SGuy Blank   if (X86::GR64RegClass.hasSubClassEq(SrcRC))
7792d5ce3bSGuy Blank     return &X86::VK64RegClass;
7892d5ce3bSGuy Blank   llvm_unreachable("add register class");
7992d5ce3bSGuy Blank   return nullptr;
8092d5ce3bSGuy Blank }
8192d5ce3bSGuy Blank 
8292d5ce3bSGuy Blank /// Abstract Instruction Converter class.
8392d5ce3bSGuy Blank class InstrConverterBase {
8492d5ce3bSGuy Blank protected:
8592d5ce3bSGuy Blank   unsigned SrcOpcode;
8692d5ce3bSGuy Blank 
8792d5ce3bSGuy Blank public:
InstrConverterBase(unsigned SrcOpcode)8892d5ce3bSGuy Blank   InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
8992d5ce3bSGuy Blank 
903a3cb929SKazu Hirata   virtual ~InstrConverterBase() = default;
9192d5ce3bSGuy Blank 
9292d5ce3bSGuy Blank   /// \returns true if \p MI is legal to convert.
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const9392d5ce3bSGuy Blank   virtual bool isLegal(const MachineInstr *MI,
9492d5ce3bSGuy Blank                        const TargetInstrInfo *TII) const {
9592d5ce3bSGuy Blank     assert(MI->getOpcode() == SrcOpcode &&
9692d5ce3bSGuy Blank            "Wrong instruction passed to converter");
9792d5ce3bSGuy Blank     return true;
9892d5ce3bSGuy Blank   }
9992d5ce3bSGuy Blank 
10092d5ce3bSGuy Blank   /// Applies conversion to \p MI.
10192d5ce3bSGuy Blank   ///
10292d5ce3bSGuy Blank   /// \returns true if \p MI is no longer need, and can be deleted.
10392d5ce3bSGuy Blank   virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
10492d5ce3bSGuy Blank                             MachineRegisterInfo *MRI) const = 0;
10592d5ce3bSGuy Blank 
10692d5ce3bSGuy Blank   /// \returns the cost increment incurred by converting \p MI.
10792d5ce3bSGuy Blank   virtual double getExtraCost(const MachineInstr *MI,
10892d5ce3bSGuy Blank                               MachineRegisterInfo *MRI) const = 0;
10992d5ce3bSGuy Blank };
11092d5ce3bSGuy Blank 
11192d5ce3bSGuy Blank /// An Instruction Converter which ignores the given instruction.
11292d5ce3bSGuy Blank /// For example, PHI instructions can be safely ignored since only the registers
11392d5ce3bSGuy Blank /// need to change.
11492d5ce3bSGuy Blank class InstrIgnore : public InstrConverterBase {
11592d5ce3bSGuy Blank public:
InstrIgnore(unsigned SrcOpcode)11692d5ce3bSGuy Blank   InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
11792d5ce3bSGuy Blank 
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const11892d5ce3bSGuy Blank   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
11992d5ce3bSGuy Blank                     MachineRegisterInfo *MRI) const override {
12092d5ce3bSGuy Blank     assert(isLegal(MI, TII) && "Cannot convert instruction");
12192d5ce3bSGuy Blank     return false;
12292d5ce3bSGuy Blank   }
12392d5ce3bSGuy Blank 
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const12492d5ce3bSGuy Blank   double getExtraCost(const MachineInstr *MI,
12592d5ce3bSGuy Blank                       MachineRegisterInfo *MRI) const override {
12692d5ce3bSGuy Blank     return 0;
12792d5ce3bSGuy Blank   }
12892d5ce3bSGuy Blank };
12992d5ce3bSGuy Blank 
13092d5ce3bSGuy Blank /// An Instruction Converter which replaces an instruction with another.
13192d5ce3bSGuy Blank class InstrReplacer : public InstrConverterBase {
13292d5ce3bSGuy Blank public:
13392d5ce3bSGuy Blank   /// Opcode of the destination instruction.
13492d5ce3bSGuy Blank   unsigned DstOpcode;
13592d5ce3bSGuy Blank 
InstrReplacer(unsigned SrcOpcode,unsigned DstOpcode)13692d5ce3bSGuy Blank   InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)
13792d5ce3bSGuy Blank       : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
13892d5ce3bSGuy Blank 
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const13992d5ce3bSGuy Blank   bool isLegal(const MachineInstr *MI,
14092d5ce3bSGuy Blank                const TargetInstrInfo *TII) const override {
14192d5ce3bSGuy Blank     if (!InstrConverterBase::isLegal(MI, TII))
14292d5ce3bSGuy Blank       return false;
14392d5ce3bSGuy Blank     // It's illegal to replace an instruction that implicitly defines a register
14492d5ce3bSGuy Blank     // with an instruction that doesn't, unless that register dead.
1450729ae36SSimon Pilgrim     for (const auto &MO : MI->implicit_operands())
14692d5ce3bSGuy Blank       if (MO.isReg() && MO.isDef() && !MO.isDead() &&
14792d5ce3bSGuy Blank           !TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
14892d5ce3bSGuy Blank         return false;
14992d5ce3bSGuy Blank     return true;
15092d5ce3bSGuy Blank   }
15192d5ce3bSGuy Blank 
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const15292d5ce3bSGuy Blank   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
15392d5ce3bSGuy Blank                     MachineRegisterInfo *MRI) const override {
15492d5ce3bSGuy Blank     assert(isLegal(MI, TII) && "Cannot convert instruction");
15592d5ce3bSGuy Blank     MachineInstrBuilder Bld =
15692d5ce3bSGuy Blank         BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));
15792d5ce3bSGuy Blank     // Transfer explicit operands from original instruction. Implicit operands
15892d5ce3bSGuy Blank     // are handled by BuildMI.
15992d5ce3bSGuy Blank     for (auto &Op : MI->explicit_operands())
16092d5ce3bSGuy Blank       Bld.add(Op);
16192d5ce3bSGuy Blank     return true;
16292d5ce3bSGuy Blank   }
16392d5ce3bSGuy Blank 
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const16492d5ce3bSGuy Blank   double getExtraCost(const MachineInstr *MI,
16592d5ce3bSGuy Blank                       MachineRegisterInfo *MRI) const override {
16692d5ce3bSGuy Blank     // Assuming instructions have the same cost.
16792d5ce3bSGuy Blank     return 0;
16892d5ce3bSGuy Blank   }
16992d5ce3bSGuy Blank };
17092d5ce3bSGuy Blank 
17192d5ce3bSGuy Blank /// An Instruction Converter which replaces an instruction with another, and
17292d5ce3bSGuy Blank /// adds a COPY from the new instruction's destination to the old one's.
17392d5ce3bSGuy Blank class InstrReplacerDstCOPY : public InstrConverterBase {
17492d5ce3bSGuy Blank public:
17592d5ce3bSGuy Blank   unsigned DstOpcode;
17692d5ce3bSGuy Blank 
InstrReplacerDstCOPY(unsigned SrcOpcode,unsigned DstOpcode)17792d5ce3bSGuy Blank   InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)
17892d5ce3bSGuy Blank       : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
17992d5ce3bSGuy Blank 
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const18092d5ce3bSGuy Blank   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
18192d5ce3bSGuy Blank                     MachineRegisterInfo *MRI) const override {
18292d5ce3bSGuy Blank     assert(isLegal(MI, TII) && "Cannot convert instruction");
18392d5ce3bSGuy Blank     MachineBasicBlock *MBB = MI->getParent();
1840729ae36SSimon Pilgrim     const DebugLoc &DL = MI->getDebugLoc();
18592d5ce3bSGuy Blank 
1860c476111SDaniel Sanders     Register Reg = MRI->createVirtualRegister(
18792d5ce3bSGuy Blank         TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo(),
18892d5ce3bSGuy Blank                          *MBB->getParent()));
18992d5ce3bSGuy Blank     MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
190259cd6f8SKazu Hirata     for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
191259cd6f8SKazu Hirata       Bld.add(MO);
19292d5ce3bSGuy Blank 
19392d5ce3bSGuy Blank     BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
19492d5ce3bSGuy Blank         .add(MI->getOperand(0))
19592d5ce3bSGuy Blank         .addReg(Reg);
19692d5ce3bSGuy Blank 
19792d5ce3bSGuy Blank     return true;
19892d5ce3bSGuy Blank   }
19992d5ce3bSGuy Blank 
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const20092d5ce3bSGuy Blank   double getExtraCost(const MachineInstr *MI,
20192d5ce3bSGuy Blank                       MachineRegisterInfo *MRI) const override {
20292d5ce3bSGuy Blank     // Assuming instructions have the same cost, and that COPY is in the same
20392d5ce3bSGuy Blank     // domain so it will be eliminated.
20492d5ce3bSGuy Blank     return 0;
20592d5ce3bSGuy Blank   }
20692d5ce3bSGuy Blank };
20792d5ce3bSGuy Blank 
20892d5ce3bSGuy Blank /// An Instruction Converter for replacing COPY instructions.
20992d5ce3bSGuy Blank class InstrCOPYReplacer : public InstrReplacer {
21092d5ce3bSGuy Blank public:
21192d5ce3bSGuy Blank   RegDomain DstDomain;
21292d5ce3bSGuy Blank 
InstrCOPYReplacer(unsigned SrcOpcode,RegDomain DstDomain,unsigned DstOpcode)21392d5ce3bSGuy Blank   InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
21492d5ce3bSGuy Blank       : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
21592d5ce3bSGuy Blank 
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const21667d9dbdbSCraig Topper   bool isLegal(const MachineInstr *MI,
21767d9dbdbSCraig Topper                const TargetInstrInfo *TII) const override {
21867d9dbdbSCraig Topper     if (!InstrConverterBase::isLegal(MI, TII))
21967d9dbdbSCraig Topper       return false;
22067d9dbdbSCraig Topper 
22167d9dbdbSCraig Topper     // Don't allow copies to/flow GR8/GR16 physical registers.
22267d9dbdbSCraig Topper     // FIXME: Is there some better way to support this?
2230c476111SDaniel Sanders     Register DstReg = MI->getOperand(0).getReg();
2243726b144SGaurav Jain     if (DstReg.isPhysical() && (X86::GR8RegClass.contains(DstReg) ||
22567d9dbdbSCraig Topper                                 X86::GR16RegClass.contains(DstReg)))
22667d9dbdbSCraig Topper       return false;
2270c476111SDaniel Sanders     Register SrcReg = MI->getOperand(1).getReg();
2283726b144SGaurav Jain     if (SrcReg.isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||
22967d9dbdbSCraig Topper                                 X86::GR16RegClass.contains(SrcReg)))
23067d9dbdbSCraig Topper       return false;
23167d9dbdbSCraig Topper 
23267d9dbdbSCraig Topper     return true;
23367d9dbdbSCraig Topper   }
23467d9dbdbSCraig Topper 
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const23592d5ce3bSGuy Blank   double getExtraCost(const MachineInstr *MI,
23692d5ce3bSGuy Blank                       MachineRegisterInfo *MRI) const override {
23792d5ce3bSGuy Blank     assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
23892d5ce3bSGuy Blank 
2390729ae36SSimon Pilgrim     for (const auto &MO : MI->operands()) {
24092d5ce3bSGuy Blank       // Physical registers will not be converted. Assume that converting the
24192d5ce3bSGuy Blank       // COPY to the destination domain will eventually result in a actual
24292d5ce3bSGuy Blank       // instruction.
2432bea69bfSDaniel Sanders       if (Register::isPhysicalRegister(MO.getReg()))
24492d5ce3bSGuy Blank         return 1;
24592d5ce3bSGuy Blank 
24692d5ce3bSGuy Blank       RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
24792d5ce3bSGuy Blank                                      MRI->getTargetRegisterInfo());
24892d5ce3bSGuy Blank       // Converting a cross domain COPY to a same domain COPY should eliminate
24992d5ce3bSGuy Blank       // an insturction
25092d5ce3bSGuy Blank       if (OpDomain == DstDomain)
25192d5ce3bSGuy Blank         return -1;
25292d5ce3bSGuy Blank     }
25392d5ce3bSGuy Blank     return 0;
25492d5ce3bSGuy Blank   }
25592d5ce3bSGuy Blank };
25692d5ce3bSGuy Blank 
25792d5ce3bSGuy Blank /// An Instruction Converter which replaces an instruction with a COPY.
25892d5ce3bSGuy Blank class InstrReplaceWithCopy : public InstrConverterBase {
25992d5ce3bSGuy Blank public:
26092d5ce3bSGuy Blank   // Source instruction operand Index, to be used as the COPY source.
26192d5ce3bSGuy Blank   unsigned SrcOpIdx;
26292d5ce3bSGuy Blank 
InstrReplaceWithCopy(unsigned SrcOpcode,unsigned SrcOpIdx)26392d5ce3bSGuy Blank   InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
26492d5ce3bSGuy Blank       : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
26592d5ce3bSGuy Blank 
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const26692d5ce3bSGuy Blank   bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
26792d5ce3bSGuy Blank                     MachineRegisterInfo *MRI) const override {
26892d5ce3bSGuy Blank     assert(isLegal(MI, TII) && "Cannot convert instruction");
26992d5ce3bSGuy Blank     BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
27092d5ce3bSGuy Blank             TII->get(TargetOpcode::COPY))
27192d5ce3bSGuy Blank         .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
27292d5ce3bSGuy Blank     return true;
27392d5ce3bSGuy Blank   }
27492d5ce3bSGuy Blank 
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const27592d5ce3bSGuy Blank   double getExtraCost(const MachineInstr *MI,
27692d5ce3bSGuy Blank                       MachineRegisterInfo *MRI) const override {
27792d5ce3bSGuy Blank     return 0;
27892d5ce3bSGuy Blank   }
27992d5ce3bSGuy Blank };
28092d5ce3bSGuy Blank 
28192d5ce3bSGuy Blank // Key type to be used by the Instruction Converters map.
28292d5ce3bSGuy Blank // A converter is identified by <destination domain, source opcode>
28392d5ce3bSGuy Blank typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
28492d5ce3bSGuy Blank 
285eadb5967SDavid Blaikie typedef DenseMap<InstrConverterBaseKeyTy, std::unique_ptr<InstrConverterBase>>
28692d5ce3bSGuy Blank     InstrConverterBaseMap;
28792d5ce3bSGuy Blank 
28892d5ce3bSGuy Blank /// A closure is a set of virtual register representing all of the edges in
28992d5ce3bSGuy Blank /// the closure, as well as all of the instructions connected by those edges.
29092d5ce3bSGuy Blank ///
29192d5ce3bSGuy Blank /// A closure may encompass virtual registers in the same register bank that
29292d5ce3bSGuy Blank /// have different widths. For example, it may contain 32-bit GPRs as well as
29392d5ce3bSGuy Blank /// 64-bit GPRs.
29492d5ce3bSGuy Blank ///
29592d5ce3bSGuy Blank /// A closure that computes an address (i.e. defines a virtual register that is
29692d5ce3bSGuy Blank /// used in a memory operand) excludes the instructions that contain memory
29792d5ce3bSGuy Blank /// operands using the address. Such an instruction will be included in a
29892d5ce3bSGuy Blank /// different closure that manipulates the loaded or stored value.
29992d5ce3bSGuy Blank class Closure {
30092d5ce3bSGuy Blank private:
30192d5ce3bSGuy Blank   /// Virtual registers in the closure.
3023726b144SGaurav Jain   DenseSet<Register> Edges;
30392d5ce3bSGuy Blank 
30492d5ce3bSGuy Blank   /// Instructions in the closure.
30592d5ce3bSGuy Blank   SmallVector<MachineInstr *, 8> Instrs;
30692d5ce3bSGuy Blank 
30792d5ce3bSGuy Blank   /// Domains which this closure can legally be reassigned to.
3085992535eSCraig Topper   std::bitset<NumDomains> LegalDstDomains;
30992d5ce3bSGuy Blank 
310e07153a8SKeno Fischer   /// An ID to uniquely identify this closure, even when it gets
311e07153a8SKeno Fischer   /// moved around
312e07153a8SKeno Fischer   unsigned ID;
313e07153a8SKeno Fischer 
31492d5ce3bSGuy Blank public:
Closure(unsigned ID,std::initializer_list<RegDomain> LegalDstDomainList)315e07153a8SKeno Fischer   Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
3165992535eSCraig Topper     for (RegDomain D : LegalDstDomainList)
3175992535eSCraig Topper       LegalDstDomains.set(D);
3185992535eSCraig Topper   }
31992d5ce3bSGuy Blank 
32092d5ce3bSGuy Blank   /// Mark this closure as illegal for reassignment to all domains.
setAllIllegal()3215992535eSCraig Topper   void setAllIllegal() { LegalDstDomains.reset(); }
32292d5ce3bSGuy Blank 
32392d5ce3bSGuy Blank   /// \returns true if this closure has domains which are legal to reassign to.
hasLegalDstDomain() const3245992535eSCraig Topper   bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
32592d5ce3bSGuy Blank 
32692d5ce3bSGuy Blank   /// \returns true if is legal to reassign this closure to domain \p RD.
isLegal(RegDomain RD) const3275992535eSCraig Topper   bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
32892d5ce3bSGuy Blank 
3298ec56325SCraig Topper   /// Mark this closure as illegal for reassignment to domain \p RD.
setIllegal(RegDomain RD)3308ec56325SCraig Topper   void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
3318ec56325SCraig Topper 
empty() const33292d5ce3bSGuy Blank   bool empty() const { return Edges.empty(); }
3338ec56325SCraig Topper 
insertEdge(Register Reg)3343726b144SGaurav Jain   bool insertEdge(Register Reg) { return Edges.insert(Reg).second; }
3358ec56325SCraig Topper 
3363726b144SGaurav Jain   using const_edge_iterator = DenseSet<Register>::const_iterator;
edges() const3378ec56325SCraig Topper   iterator_range<const_edge_iterator> edges() const {
3388ec56325SCraig Topper     return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());
3398ec56325SCraig Topper   }
3408ec56325SCraig Topper 
addInstruction(MachineInstr * I)3418ec56325SCraig Topper   void addInstruction(MachineInstr *I) {
3428ec56325SCraig Topper     Instrs.push_back(I);
3438ec56325SCraig Topper   }
3448ec56325SCraig Topper 
instructions() const3458ec56325SCraig Topper   ArrayRef<MachineInstr *> instructions() const {
3468ec56325SCraig Topper     return Instrs;
3478ec56325SCraig Topper   }
3488ec56325SCraig Topper 
dump(const MachineRegisterInfo * MRI) const349e07153a8SKeno Fischer   LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {
350e07153a8SKeno Fischer     dbgs() << "Registers: ";
351e07153a8SKeno Fischer     bool First = true;
3523726b144SGaurav Jain     for (Register Reg : Edges) {
353e07153a8SKeno Fischer       if (!First)
354e07153a8SKeno Fischer         dbgs() << ", ";
355e07153a8SKeno Fischer       First = false;
356e07153a8SKeno Fischer       dbgs() << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);
357e07153a8SKeno Fischer     }
358e07153a8SKeno Fischer     dbgs() << "\n" << "Instructions:";
359e07153a8SKeno Fischer     for (MachineInstr *MI : Instrs) {
360e07153a8SKeno Fischer       dbgs() << "\n  ";
361e07153a8SKeno Fischer       MI->print(dbgs());
362e07153a8SKeno Fischer     }
363e07153a8SKeno Fischer     dbgs() << "\n";
364e07153a8SKeno Fischer   }
365e07153a8SKeno Fischer 
getID() const366e07153a8SKeno Fischer   unsigned getID() const {
367e07153a8SKeno Fischer     return ID;
368e07153a8SKeno Fischer   }
369e07153a8SKeno Fischer 
37092d5ce3bSGuy Blank };
37192d5ce3bSGuy Blank 
37292d5ce3bSGuy Blank class X86DomainReassignment : public MachineFunctionPass {
373eabd405eSSimon Pilgrim   const X86Subtarget *STI = nullptr;
374eabd405eSSimon Pilgrim   MachineRegisterInfo *MRI = nullptr;
375eabd405eSSimon Pilgrim   const X86InstrInfo *TII = nullptr;
3768ec56325SCraig Topper 
3778ec56325SCraig Topper   /// All edges that are included in some closure
378*5d5aba78SXiang1 Zhang   BitVector EnclosedEdges{8, false};
3798ec56325SCraig Topper 
3808ec56325SCraig Topper   /// All instructions that are included in some closure.
381e07153a8SKeno Fischer   DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
3828ec56325SCraig Topper 
38392d5ce3bSGuy Blank public:
38492d5ce3bSGuy Blank   static char ID;
38592d5ce3bSGuy Blank 
X86DomainReassignment()386f3356722STom Stellard   X86DomainReassignment() : MachineFunctionPass(ID) { }
38792d5ce3bSGuy Blank 
38892d5ce3bSGuy Blank   bool runOnMachineFunction(MachineFunction &MF) override;
38992d5ce3bSGuy Blank 
getAnalysisUsage(AnalysisUsage & AU) const39092d5ce3bSGuy Blank   void getAnalysisUsage(AnalysisUsage &AU) const override {
39192d5ce3bSGuy Blank     AU.setPreservesCFG();
39292d5ce3bSGuy Blank     MachineFunctionPass::getAnalysisUsage(AU);
39392d5ce3bSGuy Blank   }
39492d5ce3bSGuy Blank 
getPassName() const39592d5ce3bSGuy Blank   StringRef getPassName() const override {
39692d5ce3bSGuy Blank     return "X86 Domain Reassignment Pass";
39792d5ce3bSGuy Blank   }
39892d5ce3bSGuy Blank 
39992d5ce3bSGuy Blank private:
40092d5ce3bSGuy Blank   /// A map of available Instruction Converters.
40192d5ce3bSGuy Blank   InstrConverterBaseMap Converters;
40292d5ce3bSGuy Blank 
40392d5ce3bSGuy Blank   /// Initialize Converters map.
40492d5ce3bSGuy Blank   void initConverters();
4058ec56325SCraig Topper 
4068ec56325SCraig Topper   /// Starting from \Reg, expand the closure as much as possible.
4073726b144SGaurav Jain   void buildClosure(Closure &, Register Reg);
4088ec56325SCraig Topper 
4098ec56325SCraig Topper   /// Enqueue \p Reg to be considered for addition to the closure.
4103726b144SGaurav Jain   void visitRegister(Closure &, Register Reg, RegDomain &Domain,
4118ec56325SCraig Topper                      SmallVectorImpl<unsigned> &Worklist);
4128ec56325SCraig Topper 
4138ec56325SCraig Topper   /// Reassign the closure to \p Domain.
4148ec56325SCraig Topper   void reassign(const Closure &C, RegDomain Domain) const;
4158ec56325SCraig Topper 
4168ec56325SCraig Topper   /// Add \p MI to the closure.
4178ec56325SCraig Topper   void encloseInstr(Closure &C, MachineInstr *MI);
4188ec56325SCraig Topper 
4198ec56325SCraig Topper   /// /returns true if it is profitable to reassign the closure to \p Domain.
4208ec56325SCraig Topper   bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
4218ec56325SCraig Topper 
4228ec56325SCraig Topper   /// Calculate the total cost of reassigning the closure to \p Domain.
4238ec56325SCraig Topper   double calculateCost(const Closure &C, RegDomain Domain) const;
42492d5ce3bSGuy Blank };
42592d5ce3bSGuy Blank 
42692d5ce3bSGuy Blank char X86DomainReassignment::ID = 0;
42792d5ce3bSGuy Blank 
42892d5ce3bSGuy Blank } // End anonymous namespace.
42992d5ce3bSGuy Blank 
visitRegister(Closure & C,Register Reg,RegDomain & Domain,SmallVectorImpl<unsigned> & Worklist)4303726b144SGaurav Jain void X86DomainReassignment::visitRegister(Closure &C, Register Reg,
4318ec56325SCraig Topper                                           RegDomain &Domain,
4328ec56325SCraig Topper                                           SmallVectorImpl<unsigned> &Worklist) {
433*5d5aba78SXiang1 Zhang   if (!Reg.isVirtual())
43492d5ce3bSGuy Blank     return;
43592d5ce3bSGuy Blank 
436*5d5aba78SXiang1 Zhang   if (EnclosedEdges.test(Register::virtReg2Index(Reg)))
43792d5ce3bSGuy Blank     return;
43892d5ce3bSGuy Blank 
43992d5ce3bSGuy Blank   if (!MRI->hasOneDef(Reg))
44092d5ce3bSGuy Blank     return;
44192d5ce3bSGuy Blank 
44292d5ce3bSGuy Blank   RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
44392d5ce3bSGuy Blank   // First edge in closure sets the domain.
44492d5ce3bSGuy Blank   if (Domain == NoDomain)
44592d5ce3bSGuy Blank     Domain = RD;
44692d5ce3bSGuy Blank 
44792d5ce3bSGuy Blank   if (Domain != RD)
44892d5ce3bSGuy Blank     return;
44992d5ce3bSGuy Blank 
45092d5ce3bSGuy Blank   Worklist.push_back(Reg);
45192d5ce3bSGuy Blank }
45292d5ce3bSGuy Blank 
encloseInstr(Closure & C,MachineInstr * MI)4538ec56325SCraig Topper void X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
45492d5ce3bSGuy Blank   auto I = EnclosedInstrs.find(MI);
45592d5ce3bSGuy Blank   if (I != EnclosedInstrs.end()) {
456e07153a8SKeno Fischer     if (I->second != C.getID())
45792d5ce3bSGuy Blank       // Instruction already belongs to another closure, avoid conflicts between
45892d5ce3bSGuy Blank       // closure and mark this closure as illegal.
4598ec56325SCraig Topper       C.setAllIllegal();
46092d5ce3bSGuy Blank     return;
46192d5ce3bSGuy Blank   }
46292d5ce3bSGuy Blank 
463e07153a8SKeno Fischer   EnclosedInstrs[MI] = C.getID();
4648ec56325SCraig Topper   C.addInstruction(MI);
46592d5ce3bSGuy Blank 
46692d5ce3bSGuy Blank   // Mark closure as illegal for reassignment to domains, if there is no
46792d5ce3bSGuy Blank   // converter for the instruction or if the converter cannot convert the
46892d5ce3bSGuy Blank   // instruction.
4698ec56325SCraig Topper   for (int i = 0; i != NumDomains; ++i) {
4708ec56325SCraig Topper     if (C.isLegal((RegDomain)i)) {
471eadb5967SDavid Blaikie       auto I = Converters.find({i, MI->getOpcode()});
472eadb5967SDavid Blaikie       if (I == Converters.end() || !I->second->isLegal(MI, TII))
4738ec56325SCraig Topper         C.setIllegal((RegDomain)i);
4745992535eSCraig Topper     }
4755992535eSCraig Topper   }
47692d5ce3bSGuy Blank }
47792d5ce3bSGuy Blank 
calculateCost(const Closure & C,RegDomain DstDomain) const4788ec56325SCraig Topper double X86DomainReassignment::calculateCost(const Closure &C,
4798ec56325SCraig Topper                                             RegDomain DstDomain) const {
4808ec56325SCraig Topper   assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
48192d5ce3bSGuy Blank 
48292d5ce3bSGuy Blank   double Cost = 0.0;
4838ec56325SCraig Topper   for (auto *MI : C.instructions())
484eadb5967SDavid Blaikie     Cost += Converters.find({DstDomain, MI->getOpcode()})
485eadb5967SDavid Blaikie                 ->second->getExtraCost(MI, MRI);
48692d5ce3bSGuy Blank   return Cost;
48792d5ce3bSGuy Blank }
48892d5ce3bSGuy Blank 
isReassignmentProfitable(const Closure & C,RegDomain Domain) const4898ec56325SCraig Topper bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
4908ec56325SCraig Topper                                                      RegDomain Domain) const {
4918ec56325SCraig Topper   return calculateCost(C, Domain) < 0.0;
49292d5ce3bSGuy Blank }
49392d5ce3bSGuy Blank 
reassign(const Closure & C,RegDomain Domain) const4948ec56325SCraig Topper void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
4958ec56325SCraig Topper   assert(C.isLegal(Domain) && "Cannot convert illegal closure");
49692d5ce3bSGuy Blank 
49792d5ce3bSGuy Blank   // Iterate all instructions in the closure, convert each one using the
49892d5ce3bSGuy Blank   // appropriate converter.
49992d5ce3bSGuy Blank   SmallVector<MachineInstr *, 8> ToErase;
5008ec56325SCraig Topper   for (auto *MI : C.instructions())
501eadb5967SDavid Blaikie     if (Converters.find({Domain, MI->getOpcode()})
502eadb5967SDavid Blaikie             ->second->convertInstr(MI, TII, MRI))
50392d5ce3bSGuy Blank       ToErase.push_back(MI);
50492d5ce3bSGuy Blank 
50592d5ce3bSGuy Blank   // Iterate all registers in the closure, replace them with registers in the
50692d5ce3bSGuy Blank   // destination domain.
5073726b144SGaurav Jain   for (Register Reg : C.edges()) {
50892d5ce3bSGuy Blank     MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
50992d5ce3bSGuy Blank     for (auto &MO : MRI->use_operands(Reg)) {
51092d5ce3bSGuy Blank       if (MO.isReg())
51192d5ce3bSGuy Blank         // Remove all subregister references as they are not valid in the
51292d5ce3bSGuy Blank         // destination domain.
51392d5ce3bSGuy Blank         MO.setSubReg(0);
51492d5ce3bSGuy Blank     }
51592d5ce3bSGuy Blank   }
51692d5ce3bSGuy Blank 
5170729ae36SSimon Pilgrim   for (auto *MI : ToErase)
51892d5ce3bSGuy Blank     MI->eraseFromParent();
51992d5ce3bSGuy Blank }
52092d5ce3bSGuy Blank 
52192d5ce3bSGuy Blank /// \returns true when \p Reg is used as part of an address calculation in \p
52292d5ce3bSGuy Blank /// MI.
usedAsAddr(const MachineInstr & MI,Register Reg,const TargetInstrInfo * TII)5233726b144SGaurav Jain static bool usedAsAddr(const MachineInstr &MI, Register Reg,
52492d5ce3bSGuy Blank                        const TargetInstrInfo *TII) {
52592d5ce3bSGuy Blank   if (!MI.mayLoadOrStore())
52692d5ce3bSGuy Blank     return false;
52792d5ce3bSGuy Blank 
52892d5ce3bSGuy Blank   const MCInstrDesc &Desc = TII->get(MI.getOpcode());
52992d5ce3bSGuy Blank   int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
53092d5ce3bSGuy Blank   if (MemOpStart == -1)
53192d5ce3bSGuy Blank     return false;
53292d5ce3bSGuy Blank 
53392d5ce3bSGuy Blank   MemOpStart += X86II::getOperandBias(Desc);
53492d5ce3bSGuy Blank   for (unsigned MemOpIdx = MemOpStart,
53592d5ce3bSGuy Blank                 MemOpEnd = MemOpStart + X86::AddrNumOperands;
53692d5ce3bSGuy Blank        MemOpIdx < MemOpEnd; ++MemOpIdx) {
5370729ae36SSimon Pilgrim     const MachineOperand &Op = MI.getOperand(MemOpIdx);
53892d5ce3bSGuy Blank     if (Op.isReg() && Op.getReg() == Reg)
53992d5ce3bSGuy Blank       return true;
54092d5ce3bSGuy Blank   }
54192d5ce3bSGuy Blank   return false;
54292d5ce3bSGuy Blank }
54392d5ce3bSGuy Blank 
buildClosure(Closure & C,Register Reg)5443726b144SGaurav Jain void X86DomainReassignment::buildClosure(Closure &C, Register Reg) {
54592d5ce3bSGuy Blank   SmallVector<unsigned, 4> Worklist;
5468ec56325SCraig Topper   RegDomain Domain = NoDomain;
5478ec56325SCraig Topper   visitRegister(C, Reg, Domain, Worklist);
54892d5ce3bSGuy Blank   while (!Worklist.empty()) {
54992d5ce3bSGuy Blank     unsigned CurReg = Worklist.pop_back_val();
55092d5ce3bSGuy Blank 
55192d5ce3bSGuy Blank     // Register already in this closure.
5528ec56325SCraig Topper     if (!C.insertEdge(CurReg))
55392d5ce3bSGuy Blank       continue;
554*5d5aba78SXiang1 Zhang     EnclosedEdges.set(Register::virtReg2Index(Reg));
55592d5ce3bSGuy Blank 
55692d5ce3bSGuy Blank     MachineInstr *DefMI = MRI->getVRegDef(CurReg);
5578ec56325SCraig Topper     encloseInstr(C, DefMI);
55892d5ce3bSGuy Blank 
55992d5ce3bSGuy Blank     // Add register used by the defining MI to the worklist.
56092d5ce3bSGuy Blank     // Do not add registers which are used in address calculation, they will be
56192d5ce3bSGuy Blank     // added to a different closure.
56292d5ce3bSGuy Blank     int OpEnd = DefMI->getNumOperands();
56392d5ce3bSGuy Blank     const MCInstrDesc &Desc = DefMI->getDesc();
56492d5ce3bSGuy Blank     int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
56592d5ce3bSGuy Blank     if (MemOp != -1)
56692d5ce3bSGuy Blank       MemOp += X86II::getOperandBias(Desc);
56792d5ce3bSGuy Blank     for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
56892d5ce3bSGuy Blank       if (OpIdx == MemOp) {
56992d5ce3bSGuy Blank         // skip address calculation.
57092d5ce3bSGuy Blank         OpIdx += (X86::AddrNumOperands - 1);
57192d5ce3bSGuy Blank         continue;
57292d5ce3bSGuy Blank       }
57392d5ce3bSGuy Blank       auto &Op = DefMI->getOperand(OpIdx);
57492d5ce3bSGuy Blank       if (!Op.isReg() || !Op.isUse())
57592d5ce3bSGuy Blank         continue;
5768ec56325SCraig Topper       visitRegister(C, Op.getReg(), Domain, Worklist);
57792d5ce3bSGuy Blank     }
57892d5ce3bSGuy Blank 
57992d5ce3bSGuy Blank     // Expand closure through register uses.
58092d5ce3bSGuy Blank     for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
58192d5ce3bSGuy Blank       // We would like to avoid converting closures which calculare addresses,
58292d5ce3bSGuy Blank       // as this should remain in GPRs.
58392d5ce3bSGuy Blank       if (usedAsAddr(UseMI, CurReg, TII)) {
5848ec56325SCraig Topper         C.setAllIllegal();
58592d5ce3bSGuy Blank         continue;
58692d5ce3bSGuy Blank       }
5878ec56325SCraig Topper       encloseInstr(C, &UseMI);
58892d5ce3bSGuy Blank 
58992d5ce3bSGuy Blank       for (auto &DefOp : UseMI.defs()) {
59092d5ce3bSGuy Blank         if (!DefOp.isReg())
59192d5ce3bSGuy Blank           continue;
59292d5ce3bSGuy Blank 
5930c476111SDaniel Sanders         Register DefReg = DefOp.getReg();
5943726b144SGaurav Jain         if (!DefReg.isVirtual()) {
5958ec56325SCraig Topper           C.setAllIllegal();
59692d5ce3bSGuy Blank           continue;
59792d5ce3bSGuy Blank         }
5988ec56325SCraig Topper         visitRegister(C, DefReg, Domain, Worklist);
59992d5ce3bSGuy Blank       }
60092d5ce3bSGuy Blank     }
60192d5ce3bSGuy Blank   }
60292d5ce3bSGuy Blank }
60392d5ce3bSGuy Blank 
initConverters()60492d5ce3bSGuy Blank void X86DomainReassignment::initConverters() {
60592d5ce3bSGuy Blank   Converters[{MaskDomain, TargetOpcode::PHI}] =
606eadb5967SDavid Blaikie       std::make_unique<InstrIgnore>(TargetOpcode::PHI);
60792d5ce3bSGuy Blank 
60892d5ce3bSGuy Blank   Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
609eadb5967SDavid Blaikie       std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
61092d5ce3bSGuy Blank 
61192d5ce3bSGuy Blank   Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
612eadb5967SDavid Blaikie       std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
61392d5ce3bSGuy Blank 
61492d5ce3bSGuy Blank   Converters[{MaskDomain, TargetOpcode::COPY}] =
615eadb5967SDavid Blaikie       std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
616eadb5967SDavid Blaikie                                           TargetOpcode::COPY);
61792d5ce3bSGuy Blank 
61892d5ce3bSGuy Blank   auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
619eadb5967SDavid Blaikie     Converters[{MaskDomain, From}] =
620eadb5967SDavid Blaikie         std::make_unique<InstrReplacerDstCOPY>(From, To);
62192d5ce3bSGuy Blank   };
62292d5ce3bSGuy Blank 
62392d5ce3bSGuy Blank   createReplacerDstCOPY(X86::MOVZX32rm16, X86::KMOVWkm);
62492d5ce3bSGuy Blank   createReplacerDstCOPY(X86::MOVZX64rm16, X86::KMOVWkm);
62592d5ce3bSGuy Blank 
62692d5ce3bSGuy Blank   createReplacerDstCOPY(X86::MOVZX32rr16, X86::KMOVWkk);
62792d5ce3bSGuy Blank   createReplacerDstCOPY(X86::MOVZX64rr16, X86::KMOVWkk);
62892d5ce3bSGuy Blank 
62992d5ce3bSGuy Blank   if (STI->hasDQI()) {
63092d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX16rm8, X86::KMOVBkm);
63192d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX32rm8, X86::KMOVBkm);
63292d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX64rm8, X86::KMOVBkm);
63392d5ce3bSGuy Blank 
63492d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX16rr8, X86::KMOVBkk);
63592d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX32rr8, X86::KMOVBkk);
63692d5ce3bSGuy Blank     createReplacerDstCOPY(X86::MOVZX64rr8, X86::KMOVBkk);
63792d5ce3bSGuy Blank   }
63892d5ce3bSGuy Blank 
63992d5ce3bSGuy Blank   auto createReplacer = [&](unsigned From, unsigned To) {
640eadb5967SDavid Blaikie     Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
64192d5ce3bSGuy Blank   };
64292d5ce3bSGuy Blank 
64392d5ce3bSGuy Blank   createReplacer(X86::MOV16rm, X86::KMOVWkm);
64492d5ce3bSGuy Blank   createReplacer(X86::MOV16mr, X86::KMOVWmk);
64592d5ce3bSGuy Blank   createReplacer(X86::MOV16rr, X86::KMOVWkk);
64692d5ce3bSGuy Blank   createReplacer(X86::SHR16ri, X86::KSHIFTRWri);
64792d5ce3bSGuy Blank   createReplacer(X86::SHL16ri, X86::KSHIFTLWri);
64892d5ce3bSGuy Blank   createReplacer(X86::NOT16r, X86::KNOTWrr);
64992d5ce3bSGuy Blank   createReplacer(X86::OR16rr, X86::KORWrr);
65092d5ce3bSGuy Blank   createReplacer(X86::AND16rr, X86::KANDWrr);
65192d5ce3bSGuy Blank   createReplacer(X86::XOR16rr, X86::KXORWrr);
65292d5ce3bSGuy Blank 
65392d5ce3bSGuy Blank   if (STI->hasBWI()) {
65492d5ce3bSGuy Blank     createReplacer(X86::MOV32rm, X86::KMOVDkm);
65592d5ce3bSGuy Blank     createReplacer(X86::MOV64rm, X86::KMOVQkm);
65692d5ce3bSGuy Blank 
65792d5ce3bSGuy Blank     createReplacer(X86::MOV32mr, X86::KMOVDmk);
65892d5ce3bSGuy Blank     createReplacer(X86::MOV64mr, X86::KMOVQmk);
65992d5ce3bSGuy Blank 
66092d5ce3bSGuy Blank     createReplacer(X86::MOV32rr, X86::KMOVDkk);
66192d5ce3bSGuy Blank     createReplacer(X86::MOV64rr, X86::KMOVQkk);
66292d5ce3bSGuy Blank 
66392d5ce3bSGuy Blank     createReplacer(X86::SHR32ri, X86::KSHIFTRDri);
66492d5ce3bSGuy Blank     createReplacer(X86::SHR64ri, X86::KSHIFTRQri);
66592d5ce3bSGuy Blank 
66692d5ce3bSGuy Blank     createReplacer(X86::SHL32ri, X86::KSHIFTLDri);
66792d5ce3bSGuy Blank     createReplacer(X86::SHL64ri, X86::KSHIFTLQri);
66892d5ce3bSGuy Blank 
66992d5ce3bSGuy Blank     createReplacer(X86::ADD32rr, X86::KADDDrr);
67092d5ce3bSGuy Blank     createReplacer(X86::ADD64rr, X86::KADDQrr);
67192d5ce3bSGuy Blank 
67292d5ce3bSGuy Blank     createReplacer(X86::NOT32r, X86::KNOTDrr);
67392d5ce3bSGuy Blank     createReplacer(X86::NOT64r, X86::KNOTQrr);
67492d5ce3bSGuy Blank 
67592d5ce3bSGuy Blank     createReplacer(X86::OR32rr, X86::KORDrr);
67692d5ce3bSGuy Blank     createReplacer(X86::OR64rr, X86::KORQrr);
67792d5ce3bSGuy Blank 
67892d5ce3bSGuy Blank     createReplacer(X86::AND32rr, X86::KANDDrr);
67992d5ce3bSGuy Blank     createReplacer(X86::AND64rr, X86::KANDQrr);
68092d5ce3bSGuy Blank 
68192d5ce3bSGuy Blank     createReplacer(X86::ANDN32rr, X86::KANDNDrr);
68292d5ce3bSGuy Blank     createReplacer(X86::ANDN64rr, X86::KANDNQrr);
68392d5ce3bSGuy Blank 
68492d5ce3bSGuy Blank     createReplacer(X86::XOR32rr, X86::KXORDrr);
68592d5ce3bSGuy Blank     createReplacer(X86::XOR64rr, X86::KXORQrr);
68692d5ce3bSGuy Blank 
687f5465f98SCraig Topper     // TODO: KTEST is not a replacement for TEST due to flag differences. Need
688f5465f98SCraig Topper     // to prove only Z flag is used.
689f5465f98SCraig Topper     //createReplacer(X86::TEST32rr, X86::KTESTDrr);
690f5465f98SCraig Topper     //createReplacer(X86::TEST64rr, X86::KTESTQrr);
69192d5ce3bSGuy Blank   }
69292d5ce3bSGuy Blank 
69392d5ce3bSGuy Blank   if (STI->hasDQI()) {
69492d5ce3bSGuy Blank     createReplacer(X86::ADD8rr, X86::KADDBrr);
69592d5ce3bSGuy Blank     createReplacer(X86::ADD16rr, X86::KADDWrr);
69692d5ce3bSGuy Blank 
69792d5ce3bSGuy Blank     createReplacer(X86::AND8rr, X86::KANDBrr);
69892d5ce3bSGuy Blank 
69992d5ce3bSGuy Blank     createReplacer(X86::MOV8rm, X86::KMOVBkm);
70092d5ce3bSGuy Blank     createReplacer(X86::MOV8mr, X86::KMOVBmk);
70192d5ce3bSGuy Blank     createReplacer(X86::MOV8rr, X86::KMOVBkk);
70292d5ce3bSGuy Blank 
70392d5ce3bSGuy Blank     createReplacer(X86::NOT8r, X86::KNOTBrr);
70492d5ce3bSGuy Blank 
70592d5ce3bSGuy Blank     createReplacer(X86::OR8rr, X86::KORBrr);
70692d5ce3bSGuy Blank 
70792d5ce3bSGuy Blank     createReplacer(X86::SHR8ri, X86::KSHIFTRBri);
70892d5ce3bSGuy Blank     createReplacer(X86::SHL8ri, X86::KSHIFTLBri);
70992d5ce3bSGuy Blank 
710f5465f98SCraig Topper     // TODO: KTEST is not a replacement for TEST due to flag differences. Need
711f5465f98SCraig Topper     // to prove only Z flag is used.
712f5465f98SCraig Topper     //createReplacer(X86::TEST8rr, X86::KTESTBrr);
713f5465f98SCraig Topper     //createReplacer(X86::TEST16rr, X86::KTESTWrr);
71492d5ce3bSGuy Blank 
71592d5ce3bSGuy Blank     createReplacer(X86::XOR8rr, X86::KXORBrr);
71692d5ce3bSGuy Blank   }
71792d5ce3bSGuy Blank }
71892d5ce3bSGuy Blank 
runOnMachineFunction(MachineFunction & MF)71992d5ce3bSGuy Blank bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
720f1caa283SMatthias Braun   if (skipFunction(MF.getFunction()))
72192d5ce3bSGuy Blank     return false;
72292d5ce3bSGuy Blank   if (DisableX86DomainReassignment)
72392d5ce3bSGuy Blank     return false;
72492d5ce3bSGuy Blank 
725d34e60caSNicola Zaghen   LLVM_DEBUG(
726d34e60caSNicola Zaghen       dbgs() << "***** Machine Function before Domain Reassignment *****\n");
727d34e60caSNicola Zaghen   LLVM_DEBUG(MF.print(dbgs()));
72892d5ce3bSGuy Blank 
72992d5ce3bSGuy Blank   STI = &MF.getSubtarget<X86Subtarget>();
73092d5ce3bSGuy Blank   // GPR->K is the only transformation currently supported, bail out early if no
73192d5ce3bSGuy Blank   // AVX512.
7325d20eb24SCraig Topper   // TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and
7335d20eb24SCraig Topper   // VK64 for GR32/GR64, but those aren't legal classes on KNL. If the register
7345d20eb24SCraig Topper   // coalescer doesn't clean it up and we generate a spill we will crash.
7355d20eb24SCraig Topper   if (!STI->hasAVX512() || !STI->hasBWI())
73692d5ce3bSGuy Blank     return false;
73792d5ce3bSGuy Blank 
73892d5ce3bSGuy Blank   MRI = &MF.getRegInfo();
73992d5ce3bSGuy Blank   assert(MRI->isSSA() && "Expected MIR to be in SSA form");
74092d5ce3bSGuy Blank 
74192d5ce3bSGuy Blank   TII = STI->getInstrInfo();
74292d5ce3bSGuy Blank   initConverters();
74392d5ce3bSGuy Blank   bool Changed = false;
74492d5ce3bSGuy Blank 
7458ec56325SCraig Topper   EnclosedEdges.clear();
746*5d5aba78SXiang1 Zhang   EnclosedEdges.resize(MRI->getNumVirtRegs());
7478ec56325SCraig Topper   EnclosedInstrs.clear();
74892d5ce3bSGuy Blank 
74992d5ce3bSGuy Blank   std::vector<Closure> Closures;
75092d5ce3bSGuy Blank 
75192d5ce3bSGuy Blank   // Go over all virtual registers and calculate a closure.
752e07153a8SKeno Fischer   unsigned ClosureID = 0;
75392d5ce3bSGuy Blank   for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
7543726b144SGaurav Jain     Register Reg = Register::index2VirtReg(Idx);
75592d5ce3bSGuy Blank 
75692d5ce3bSGuy Blank     // GPR only current source domain supported.
75792d5ce3bSGuy Blank     if (!isGPR(MRI->getRegClass(Reg)))
75892d5ce3bSGuy Blank       continue;
75992d5ce3bSGuy Blank 
76092d5ce3bSGuy Blank     // Register already in closure.
761*5d5aba78SXiang1 Zhang     if (EnclosedEdges.test(Idx))
76292d5ce3bSGuy Blank       continue;
76392d5ce3bSGuy Blank 
76492d5ce3bSGuy Blank     // Calculate closure starting with Reg.
765e07153a8SKeno Fischer     Closure C(ClosureID++, {MaskDomain});
7668ec56325SCraig Topper     buildClosure(C, Reg);
76792d5ce3bSGuy Blank 
76892d5ce3bSGuy Blank     // Collect all closures that can potentially be converted.
76992d5ce3bSGuy Blank     if (!C.empty() && C.isLegal(MaskDomain))
77092d5ce3bSGuy Blank       Closures.push_back(std::move(C));
77192d5ce3bSGuy Blank   }
77292d5ce3bSGuy Blank 
773e07153a8SKeno Fischer   for (Closure &C : Closures) {
77403d0b91fSNicola Zaghen     LLVM_DEBUG(C.dump(MRI));
7758ec56325SCraig Topper     if (isReassignmentProfitable(C, MaskDomain)) {
7768ec56325SCraig Topper       reassign(C, MaskDomain);
77792d5ce3bSGuy Blank       ++NumClosuresConverted;
77892d5ce3bSGuy Blank       Changed = true;
77992d5ce3bSGuy Blank     }
780e07153a8SKeno Fischer   }
78192d5ce3bSGuy Blank 
782d34e60caSNicola Zaghen   LLVM_DEBUG(
783d34e60caSNicola Zaghen       dbgs() << "***** Machine Function after Domain Reassignment *****\n");
784d34e60caSNicola Zaghen   LLVM_DEBUG(MF.print(dbgs()));
78592d5ce3bSGuy Blank 
78692d5ce3bSGuy Blank   return Changed;
78792d5ce3bSGuy Blank }
78892d5ce3bSGuy Blank 
78992d5ce3bSGuy Blank INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
7901afddd41SHaojian Wu                 "X86 Domain Reassignment Pass", false, false)
79192d5ce3bSGuy Blank 
79292d5ce3bSGuy Blank /// Returns an instance of the Domain Reassignment pass.
createX86DomainReassignmentPass()79392d5ce3bSGuy Blank FunctionPass *llvm::createX86DomainReassignmentPass() {
79492d5ce3bSGuy Blank   return new X86DomainReassignment();
79592d5ce3bSGuy Blank }
796