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