Path: blob/main/contrib/llvm-project/llvm/lib/Target/X86/X86DomainReassignment.cpp
35266 views
//===--- X86DomainReassignment.cpp - Selectively switch register classes---===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This pass attempts to find instruction chains (closures) in one domain,9// and convert them to equivalent instructions in a different domain,10// if profitable.11//12//===----------------------------------------------------------------------===//1314#include "X86.h"15#include "X86InstrInfo.h"16#include "X86Subtarget.h"17#include "llvm/ADT/BitVector.h"18#include "llvm/ADT/DenseMap.h"19#include "llvm/ADT/STLExtras.h"20#include "llvm/ADT/SmallVector.h"21#include "llvm/ADT/Statistic.h"22#include "llvm/CodeGen/MachineFunctionPass.h"23#include "llvm/CodeGen/MachineInstrBuilder.h"24#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/TargetRegisterInfo.h"26#include "llvm/Support/Debug.h"27#include "llvm/Support/Printable.h"28#include <bitset>2930using namespace llvm;3132#define DEBUG_TYPE "x86-domain-reassignment"3334STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");3536static cl::opt<bool> DisableX86DomainReassignment(37"disable-x86-domain-reassignment", cl::Hidden,38cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));3940namespace {41enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };4243static bool isGPR(const TargetRegisterClass *RC) {44return X86::GR64RegClass.hasSubClassEq(RC) ||45X86::GR32RegClass.hasSubClassEq(RC) ||46X86::GR16RegClass.hasSubClassEq(RC) ||47X86::GR8RegClass.hasSubClassEq(RC);48}4950static bool isMask(const TargetRegisterClass *RC,51const TargetRegisterInfo *TRI) {52return X86::VK16RegClass.hasSubClassEq(RC);53}5455static RegDomain getDomain(const TargetRegisterClass *RC,56const TargetRegisterInfo *TRI) {57if (isGPR(RC))58return GPRDomain;59if (isMask(RC, TRI))60return MaskDomain;61return OtherDomain;62}6364/// Return a register class equivalent to \p SrcRC, in \p Domain.65static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,66RegDomain Domain) {67assert(Domain == MaskDomain && "add domain");68if (X86::GR8RegClass.hasSubClassEq(SrcRC))69return &X86::VK8RegClass;70if (X86::GR16RegClass.hasSubClassEq(SrcRC))71return &X86::VK16RegClass;72if (X86::GR32RegClass.hasSubClassEq(SrcRC))73return &X86::VK32RegClass;74if (X86::GR64RegClass.hasSubClassEq(SrcRC))75return &X86::VK64RegClass;76llvm_unreachable("add register class");77return nullptr;78}7980/// Abstract Instruction Converter class.81class InstrConverterBase {82protected:83unsigned SrcOpcode;8485public:86InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}8788virtual ~InstrConverterBase() = default;8990/// \returns true if \p MI is legal to convert.91virtual bool isLegal(const MachineInstr *MI,92const TargetInstrInfo *TII) const {93assert(MI->getOpcode() == SrcOpcode &&94"Wrong instruction passed to converter");95return true;96}9798/// Applies conversion to \p MI.99///100/// \returns true if \p MI is no longer need, and can be deleted.101virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,102MachineRegisterInfo *MRI) const = 0;103104/// \returns the cost increment incurred by converting \p MI.105virtual double getExtraCost(const MachineInstr *MI,106MachineRegisterInfo *MRI) const = 0;107};108109/// An Instruction Converter which ignores the given instruction.110/// For example, PHI instructions can be safely ignored since only the registers111/// need to change.112class InstrIgnore : public InstrConverterBase {113public:114InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}115116bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,117MachineRegisterInfo *MRI) const override {118assert(isLegal(MI, TII) && "Cannot convert instruction");119return false;120}121122double getExtraCost(const MachineInstr *MI,123MachineRegisterInfo *MRI) const override {124return 0;125}126};127128/// An Instruction Converter which replaces an instruction with another.129class InstrReplacer : public InstrConverterBase {130public:131/// Opcode of the destination instruction.132unsigned DstOpcode;133134InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)135: InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}136137bool isLegal(const MachineInstr *MI,138const TargetInstrInfo *TII) const override {139if (!InstrConverterBase::isLegal(MI, TII))140return false;141// It's illegal to replace an instruction that implicitly defines a register142// with an instruction that doesn't, unless that register dead.143for (const auto &MO : MI->implicit_operands())144if (MO.isReg() && MO.isDef() && !MO.isDead() &&145!TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))146return false;147return true;148}149150bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,151MachineRegisterInfo *MRI) const override {152assert(isLegal(MI, TII) && "Cannot convert instruction");153MachineInstrBuilder Bld =154BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));155// Transfer explicit operands from original instruction. Implicit operands156// are handled by BuildMI.157for (auto &Op : MI->explicit_operands())158Bld.add(Op);159return true;160}161162double getExtraCost(const MachineInstr *MI,163MachineRegisterInfo *MRI) const override {164// Assuming instructions have the same cost.165return 0;166}167};168169/// An Instruction Converter which replaces an instruction with another, and170/// adds a COPY from the new instruction's destination to the old one's.171class InstrReplacerDstCOPY : public InstrConverterBase {172public:173unsigned DstOpcode;174175InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)176: InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}177178bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,179MachineRegisterInfo *MRI) const override {180assert(isLegal(MI, TII) && "Cannot convert instruction");181MachineBasicBlock *MBB = MI->getParent();182const DebugLoc &DL = MI->getDebugLoc();183184Register Reg = MRI->createVirtualRegister(185TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo(),186*MBB->getParent()));187MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);188for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))189Bld.add(MO);190191BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))192.add(MI->getOperand(0))193.addReg(Reg);194195return true;196}197198double getExtraCost(const MachineInstr *MI,199MachineRegisterInfo *MRI) const override {200// Assuming instructions have the same cost, and that COPY is in the same201// domain so it will be eliminated.202return 0;203}204};205206/// An Instruction Converter for replacing COPY instructions.207class InstrCOPYReplacer : public InstrReplacer {208public:209RegDomain DstDomain;210211InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)212: InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}213214bool isLegal(const MachineInstr *MI,215const TargetInstrInfo *TII) const override {216if (!InstrConverterBase::isLegal(MI, TII))217return false;218219// Don't allow copies to/flow GR8/GR16 physical registers.220// FIXME: Is there some better way to support this?221Register DstReg = MI->getOperand(0).getReg();222if (DstReg.isPhysical() && (X86::GR8RegClass.contains(DstReg) ||223X86::GR16RegClass.contains(DstReg)))224return false;225Register SrcReg = MI->getOperand(1).getReg();226if (SrcReg.isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||227X86::GR16RegClass.contains(SrcReg)))228return false;229230return true;231}232233double getExtraCost(const MachineInstr *MI,234MachineRegisterInfo *MRI) const override {235assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");236237for (const auto &MO : MI->operands()) {238// Physical registers will not be converted. Assume that converting the239// COPY to the destination domain will eventually result in a actual240// instruction.241if (MO.getReg().isPhysical())242return 1;243244RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),245MRI->getTargetRegisterInfo());246// Converting a cross domain COPY to a same domain COPY should eliminate247// an insturction248if (OpDomain == DstDomain)249return -1;250}251return 0;252}253};254255/// An Instruction Converter which replaces an instruction with a COPY.256class InstrReplaceWithCopy : public InstrConverterBase {257public:258// Source instruction operand Index, to be used as the COPY source.259unsigned SrcOpIdx;260261InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)262: InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}263264bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,265MachineRegisterInfo *MRI) const override {266assert(isLegal(MI, TII) && "Cannot convert instruction");267BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),268TII->get(TargetOpcode::COPY))269.add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});270return true;271}272273double getExtraCost(const MachineInstr *MI,274MachineRegisterInfo *MRI) const override {275return 0;276}277};278279// Key type to be used by the Instruction Converters map.280// A converter is identified by <destination domain, source opcode>281typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;282283typedef DenseMap<InstrConverterBaseKeyTy, std::unique_ptr<InstrConverterBase>>284InstrConverterBaseMap;285286/// A closure is a set of virtual register representing all of the edges in287/// the closure, as well as all of the instructions connected by those edges.288///289/// A closure may encompass virtual registers in the same register bank that290/// have different widths. For example, it may contain 32-bit GPRs as well as291/// 64-bit GPRs.292///293/// A closure that computes an address (i.e. defines a virtual register that is294/// used in a memory operand) excludes the instructions that contain memory295/// operands using the address. Such an instruction will be included in a296/// different closure that manipulates the loaded or stored value.297class Closure {298private:299/// Virtual registers in the closure.300DenseSet<Register> Edges;301302/// Instructions in the closure.303SmallVector<MachineInstr *, 8> Instrs;304305/// Domains which this closure can legally be reassigned to.306std::bitset<NumDomains> LegalDstDomains;307308/// An ID to uniquely identify this closure, even when it gets309/// moved around310unsigned ID;311312public:313Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {314for (RegDomain D : LegalDstDomainList)315LegalDstDomains.set(D);316}317318/// Mark this closure as illegal for reassignment to all domains.319void setAllIllegal() { LegalDstDomains.reset(); }320321/// \returns true if this closure has domains which are legal to reassign to.322bool hasLegalDstDomain() const { return LegalDstDomains.any(); }323324/// \returns true if is legal to reassign this closure to domain \p RD.325bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }326327/// Mark this closure as illegal for reassignment to domain \p RD.328void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }329330bool empty() const { return Edges.empty(); }331332bool insertEdge(Register Reg) { return Edges.insert(Reg).second; }333334using const_edge_iterator = DenseSet<Register>::const_iterator;335iterator_range<const_edge_iterator> edges() const {336return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());337}338339void addInstruction(MachineInstr *I) {340Instrs.push_back(I);341}342343ArrayRef<MachineInstr *> instructions() const {344return Instrs;345}346347LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {348dbgs() << "Registers: ";349bool First = true;350for (Register Reg : Edges) {351if (!First)352dbgs() << ", ";353First = false;354dbgs() << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);355}356dbgs() << "\n" << "Instructions:";357for (MachineInstr *MI : Instrs) {358dbgs() << "\n ";359MI->print(dbgs());360}361dbgs() << "\n";362}363364unsigned getID() const {365return ID;366}367368};369370class X86DomainReassignment : public MachineFunctionPass {371const X86Subtarget *STI = nullptr;372MachineRegisterInfo *MRI = nullptr;373const X86InstrInfo *TII = nullptr;374375/// All edges that are included in some closure376BitVector EnclosedEdges{8, false};377378/// All instructions that are included in some closure.379DenseMap<MachineInstr *, unsigned> EnclosedInstrs;380381public:382static char ID;383384X86DomainReassignment() : MachineFunctionPass(ID) { }385386bool runOnMachineFunction(MachineFunction &MF) override;387388void getAnalysisUsage(AnalysisUsage &AU) const override {389AU.setPreservesCFG();390MachineFunctionPass::getAnalysisUsage(AU);391}392393StringRef getPassName() const override {394return "X86 Domain Reassignment Pass";395}396397private:398/// A map of available Instruction Converters.399InstrConverterBaseMap Converters;400401/// Initialize Converters map.402void initConverters();403404/// Starting from \Reg, expand the closure as much as possible.405void buildClosure(Closure &, Register Reg);406407/// Enqueue \p Reg to be considered for addition to the closure.408void visitRegister(Closure &, Register Reg, RegDomain &Domain,409SmallVectorImpl<unsigned> &Worklist);410411/// Reassign the closure to \p Domain.412void reassign(const Closure &C, RegDomain Domain) const;413414/// Add \p MI to the closure.415void encloseInstr(Closure &C, MachineInstr *MI);416417/// /returns true if it is profitable to reassign the closure to \p Domain.418bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;419420/// Calculate the total cost of reassigning the closure to \p Domain.421double calculateCost(const Closure &C, RegDomain Domain) const;422};423424char X86DomainReassignment::ID = 0;425426} // End anonymous namespace.427428void X86DomainReassignment::visitRegister(Closure &C, Register Reg,429RegDomain &Domain,430SmallVectorImpl<unsigned> &Worklist) {431if (!Reg.isVirtual())432return;433434if (EnclosedEdges.test(Register::virtReg2Index(Reg)))435return;436437if (!MRI->hasOneDef(Reg))438return;439440RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());441// First edge in closure sets the domain.442if (Domain == NoDomain)443Domain = RD;444445if (Domain != RD)446return;447448Worklist.push_back(Reg);449}450451void X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {452auto I = EnclosedInstrs.find(MI);453if (I != EnclosedInstrs.end()) {454if (I->second != C.getID())455// Instruction already belongs to another closure, avoid conflicts between456// closure and mark this closure as illegal.457C.setAllIllegal();458return;459}460461EnclosedInstrs[MI] = C.getID();462C.addInstruction(MI);463464// Mark closure as illegal for reassignment to domains, if there is no465// converter for the instruction or if the converter cannot convert the466// instruction.467for (int i = 0; i != NumDomains; ++i) {468if (C.isLegal((RegDomain)i)) {469auto I = Converters.find({i, MI->getOpcode()});470if (I == Converters.end() || !I->second->isLegal(MI, TII))471C.setIllegal((RegDomain)i);472}473}474}475476double X86DomainReassignment::calculateCost(const Closure &C,477RegDomain DstDomain) const {478assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");479480double Cost = 0.0;481for (auto *MI : C.instructions())482Cost += Converters.find({DstDomain, MI->getOpcode()})483->second->getExtraCost(MI, MRI);484return Cost;485}486487bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,488RegDomain Domain) const {489return calculateCost(C, Domain) < 0.0;490}491492void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {493assert(C.isLegal(Domain) && "Cannot convert illegal closure");494495// Iterate all instructions in the closure, convert each one using the496// appropriate converter.497SmallVector<MachineInstr *, 8> ToErase;498for (auto *MI : C.instructions())499if (Converters.find({Domain, MI->getOpcode()})500->second->convertInstr(MI, TII, MRI))501ToErase.push_back(MI);502503// Iterate all registers in the closure, replace them with registers in the504// destination domain.505for (Register Reg : C.edges()) {506MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));507for (auto &MO : MRI->use_operands(Reg)) {508if (MO.isReg())509// Remove all subregister references as they are not valid in the510// destination domain.511MO.setSubReg(0);512}513}514515for (auto *MI : ToErase)516MI->eraseFromParent();517}518519/// \returns true when \p Reg is used as part of an address calculation in \p520/// MI.521static bool usedAsAddr(const MachineInstr &MI, Register Reg,522const TargetInstrInfo *TII) {523if (!MI.mayLoadOrStore())524return false;525526const MCInstrDesc &Desc = TII->get(MI.getOpcode());527int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);528if (MemOpStart == -1)529return false;530531MemOpStart += X86II::getOperandBias(Desc);532for (unsigned MemOpIdx = MemOpStart,533MemOpEnd = MemOpStart + X86::AddrNumOperands;534MemOpIdx < MemOpEnd; ++MemOpIdx) {535const MachineOperand &Op = MI.getOperand(MemOpIdx);536if (Op.isReg() && Op.getReg() == Reg)537return true;538}539return false;540}541542void X86DomainReassignment::buildClosure(Closure &C, Register Reg) {543SmallVector<unsigned, 4> Worklist;544RegDomain Domain = NoDomain;545visitRegister(C, Reg, Domain, Worklist);546while (!Worklist.empty()) {547unsigned CurReg = Worklist.pop_back_val();548549// Register already in this closure.550if (!C.insertEdge(CurReg))551continue;552EnclosedEdges.set(Register::virtReg2Index(Reg));553554MachineInstr *DefMI = MRI->getVRegDef(CurReg);555encloseInstr(C, DefMI);556557// Add register used by the defining MI to the worklist.558// Do not add registers which are used in address calculation, they will be559// added to a different closure.560int OpEnd = DefMI->getNumOperands();561const MCInstrDesc &Desc = DefMI->getDesc();562int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);563if (MemOp != -1)564MemOp += X86II::getOperandBias(Desc);565for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {566if (OpIdx == MemOp) {567// skip address calculation.568OpIdx += (X86::AddrNumOperands - 1);569continue;570}571auto &Op = DefMI->getOperand(OpIdx);572if (!Op.isReg() || !Op.isUse())573continue;574visitRegister(C, Op.getReg(), Domain, Worklist);575}576577// Expand closure through register uses.578for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {579// We would like to avoid converting closures which calculare addresses,580// as this should remain in GPRs.581if (usedAsAddr(UseMI, CurReg, TII)) {582C.setAllIllegal();583continue;584}585encloseInstr(C, &UseMI);586587for (auto &DefOp : UseMI.defs()) {588if (!DefOp.isReg())589continue;590591Register DefReg = DefOp.getReg();592if (!DefReg.isVirtual()) {593C.setAllIllegal();594continue;595}596visitRegister(C, DefReg, Domain, Worklist);597}598}599}600}601602void X86DomainReassignment::initConverters() {603Converters[{MaskDomain, TargetOpcode::PHI}] =604std::make_unique<InstrIgnore>(TargetOpcode::PHI);605606Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =607std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);608609Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =610std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);611612Converters[{MaskDomain, TargetOpcode::COPY}] =613std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,614TargetOpcode::COPY);615616auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {617Converters[{MaskDomain, From}] =618std::make_unique<InstrReplacerDstCOPY>(From, To);619};620621#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC622createReplacerDstCOPY(X86::MOVZX32rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));623createReplacerDstCOPY(X86::MOVZX64rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));624625createReplacerDstCOPY(X86::MOVZX32rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));626createReplacerDstCOPY(X86::MOVZX64rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));627628if (STI->hasDQI()) {629createReplacerDstCOPY(X86::MOVZX16rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));630createReplacerDstCOPY(X86::MOVZX32rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));631createReplacerDstCOPY(X86::MOVZX64rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));632633createReplacerDstCOPY(X86::MOVZX16rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));634createReplacerDstCOPY(X86::MOVZX32rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));635createReplacerDstCOPY(X86::MOVZX64rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));636}637638auto createReplacer = [&](unsigned From, unsigned To) {639Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);640};641642createReplacer(X86::MOV16rm, GET_EGPR_IF_ENABLED(X86::KMOVWkm));643createReplacer(X86::MOV16mr, GET_EGPR_IF_ENABLED(X86::KMOVWmk));644createReplacer(X86::MOV16rr, GET_EGPR_IF_ENABLED(X86::KMOVWkk));645createReplacer(X86::SHR16ri, X86::KSHIFTRWri);646createReplacer(X86::SHL16ri, X86::KSHIFTLWri);647createReplacer(X86::NOT16r, X86::KNOTWrr);648createReplacer(X86::OR16rr, X86::KORWrr);649createReplacer(X86::AND16rr, X86::KANDWrr);650createReplacer(X86::XOR16rr, X86::KXORWrr);651652bool HasNDD = STI->hasNDD();653if (HasNDD) {654createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWri);655createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWri);656createReplacer(X86::NOT16r_ND, X86::KNOTWrr);657createReplacer(X86::OR16rr_ND, X86::KORWrr);658createReplacer(X86::AND16rr_ND, X86::KANDWrr);659createReplacer(X86::XOR16rr_ND, X86::KXORWrr);660}661662if (STI->hasBWI()) {663createReplacer(X86::MOV32rm, GET_EGPR_IF_ENABLED(X86::KMOVDkm));664createReplacer(X86::MOV64rm, GET_EGPR_IF_ENABLED(X86::KMOVQkm));665666createReplacer(X86::MOV32mr, GET_EGPR_IF_ENABLED(X86::KMOVDmk));667createReplacer(X86::MOV64mr, GET_EGPR_IF_ENABLED(X86::KMOVQmk));668669createReplacer(X86::MOV32rr, GET_EGPR_IF_ENABLED(X86::KMOVDkk));670createReplacer(X86::MOV64rr, GET_EGPR_IF_ENABLED(X86::KMOVQkk));671672createReplacer(X86::SHR32ri, X86::KSHIFTRDri);673createReplacer(X86::SHR64ri, X86::KSHIFTRQri);674675createReplacer(X86::SHL32ri, X86::KSHIFTLDri);676createReplacer(X86::SHL64ri, X86::KSHIFTLQri);677678createReplacer(X86::ADD32rr, X86::KADDDrr);679createReplacer(X86::ADD64rr, X86::KADDQrr);680681createReplacer(X86::NOT32r, X86::KNOTDrr);682createReplacer(X86::NOT64r, X86::KNOTQrr);683684createReplacer(X86::OR32rr, X86::KORDrr);685createReplacer(X86::OR64rr, X86::KORQrr);686687createReplacer(X86::AND32rr, X86::KANDDrr);688createReplacer(X86::AND64rr, X86::KANDQrr);689690createReplacer(X86::ANDN32rr, X86::KANDNDrr);691createReplacer(X86::ANDN64rr, X86::KANDNQrr);692693createReplacer(X86::XOR32rr, X86::KXORDrr);694createReplacer(X86::XOR64rr, X86::KXORQrr);695696if (HasNDD) {697createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDri);698createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDri);699createReplacer(X86::ADD32rr_ND, X86::KADDDrr);700createReplacer(X86::NOT32r_ND, X86::KNOTDrr);701createReplacer(X86::OR32rr_ND, X86::KORDrr);702createReplacer(X86::AND32rr_ND, X86::KANDDrr);703createReplacer(X86::XOR32rr_ND, X86::KXORDrr);704createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQri);705createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQri);706createReplacer(X86::ADD64rr_ND, X86::KADDQrr);707createReplacer(X86::NOT64r_ND, X86::KNOTQrr);708createReplacer(X86::OR64rr_ND, X86::KORQrr);709createReplacer(X86::AND64rr_ND, X86::KANDQrr);710createReplacer(X86::XOR64rr_ND, X86::KXORQrr);711}712713// TODO: KTEST is not a replacement for TEST due to flag differences. Need714// to prove only Z flag is used.715// createReplacer(X86::TEST32rr, X86::KTESTDrr);716// createReplacer(X86::TEST64rr, X86::KTESTQrr);717}718719if (STI->hasDQI()) {720createReplacer(X86::ADD8rr, X86::KADDBrr);721createReplacer(X86::ADD16rr, X86::KADDWrr);722723createReplacer(X86::AND8rr, X86::KANDBrr);724725createReplacer(X86::MOV8rm, GET_EGPR_IF_ENABLED(X86::KMOVBkm));726createReplacer(X86::MOV8mr, GET_EGPR_IF_ENABLED(X86::KMOVBmk));727createReplacer(X86::MOV8rr, GET_EGPR_IF_ENABLED(X86::KMOVBkk));728729createReplacer(X86::NOT8r, X86::KNOTBrr);730731createReplacer(X86::OR8rr, X86::KORBrr);732733createReplacer(X86::SHR8ri, X86::KSHIFTRBri);734createReplacer(X86::SHL8ri, X86::KSHIFTLBri);735736// TODO: KTEST is not a replacement for TEST due to flag differences. Need737// to prove only Z flag is used.738// createReplacer(X86::TEST8rr, X86::KTESTBrr);739// createReplacer(X86::TEST16rr, X86::KTESTWrr);740741createReplacer(X86::XOR8rr, X86::KXORBrr);742743if (HasNDD) {744createReplacer(X86::ADD8rr_ND, X86::KADDBrr);745createReplacer(X86::ADD16rr_ND, X86::KADDWrr);746createReplacer(X86::AND8rr_ND, X86::KANDBrr);747createReplacer(X86::NOT8r_ND, X86::KNOTBrr);748createReplacer(X86::OR8rr_ND, X86::KORBrr);749createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBri);750createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBri);751createReplacer(X86::XOR8rr_ND, X86::KXORBrr);752}753}754#undef GET_EGPR_IF_ENABLED755}756757bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {758if (skipFunction(MF.getFunction()))759return false;760if (DisableX86DomainReassignment)761return false;762763LLVM_DEBUG(764dbgs() << "***** Machine Function before Domain Reassignment *****\n");765LLVM_DEBUG(MF.print(dbgs()));766767STI = &MF.getSubtarget<X86Subtarget>();768// GPR->K is the only transformation currently supported, bail out early if no769// AVX512.770// TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and771// VK64 for GR32/GR64, but those aren't legal classes on KNL. If the register772// coalescer doesn't clean it up and we generate a spill we will crash.773if (!STI->hasAVX512() || !STI->hasBWI())774return false;775776MRI = &MF.getRegInfo();777assert(MRI->isSSA() && "Expected MIR to be in SSA form");778779TII = STI->getInstrInfo();780initConverters();781bool Changed = false;782783EnclosedEdges.clear();784EnclosedEdges.resize(MRI->getNumVirtRegs());785EnclosedInstrs.clear();786787std::vector<Closure> Closures;788789// Go over all virtual registers and calculate a closure.790unsigned ClosureID = 0;791for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {792Register Reg = Register::index2VirtReg(Idx);793794// Skip unused VRegs.795if (MRI->reg_nodbg_empty(Reg))796continue;797798// GPR only current source domain supported.799if (!isGPR(MRI->getRegClass(Reg)))800continue;801802// Register already in closure.803if (EnclosedEdges.test(Idx))804continue;805806// Calculate closure starting with Reg.807Closure C(ClosureID++, {MaskDomain});808buildClosure(C, Reg);809810// Collect all closures that can potentially be converted.811if (!C.empty() && C.isLegal(MaskDomain))812Closures.push_back(std::move(C));813}814815for (Closure &C : Closures) {816LLVM_DEBUG(C.dump(MRI));817if (isReassignmentProfitable(C, MaskDomain)) {818reassign(C, MaskDomain);819++NumClosuresConverted;820Changed = true;821}822}823824LLVM_DEBUG(825dbgs() << "***** Machine Function after Domain Reassignment *****\n");826LLVM_DEBUG(MF.print(dbgs()));827828return Changed;829}830831INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",832"X86 Domain Reassignment Pass", false, false)833834/// Returns an instance of the Domain Reassignment pass.835FunctionPass *llvm::createX86DomainReassignmentPass() {836return new X86DomainReassignment();837}838839840