34 #define DEBUG_TYPE "x86-domain-reassignment" 36 STATISTIC(NumClosuresConverted,
"Number of closures converted by the pass");
43 enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
46 return X86::GR64RegClass.hasSubClassEq(RC) ||
47 X86::GR32RegClass.hasSubClassEq(RC) ||
48 X86::GR16RegClass.hasSubClassEq(RC) ||
49 X86::GR8RegClass.hasSubClassEq(RC);
54 return X86::VK16RegClass.hasSubClassEq(RC);
69 assert(Domain == MaskDomain &&
"add domain");
70 if (X86::GR8RegClass.hasSubClassEq(SrcRC))
71 return &X86::VK8RegClass;
72 if (X86::GR16RegClass.hasSubClassEq(SrcRC))
73 return &X86::VK16RegClass;
74 if (X86::GR32RegClass.hasSubClassEq(SrcRC))
75 return &X86::VK32RegClass;
76 if (X86::GR64RegClass.hasSubClassEq(SrcRC))
77 return &X86::VK64RegClass;
83 class InstrConverterBase {
88 InstrConverterBase(
unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
90 virtual ~InstrConverterBase() {}
96 "Wrong instruction passed to converter");
114 class InstrIgnore :
public InstrConverterBase {
116 InstrIgnore(
unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
120 assert(isLegal(MI, TII) &&
"Cannot convert instruction");
131 class InstrReplacer :
public InstrConverterBase {
136 InstrReplacer(
unsigned SrcOpcode,
unsigned DstOpcode)
137 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
141 if (!InstrConverterBase::isLegal(MI, TII))
146 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
154 assert(isLegal(MI, TII) &&
"Cannot convert instruction");
173 class InstrReplacerDstCOPY :
public InstrConverterBase {
177 InstrReplacerDstCOPY(
unsigned SrcOpcode,
unsigned DstOpcode)
178 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
182 assert(isLegal(MI, TII) &&
"Cannot convert instruction");
190 for (
unsigned Idx = 1, End = MI->
getNumOperands(); Idx < End; ++Idx)
193 BuildMI(*MBB, MI, DL, TII->
get(TargetOpcode::COPY))
209 class InstrCOPYReplacer :
public InstrReplacer {
213 InstrCOPYReplacer(
unsigned SrcOpcode,
RegDomain DstDomain,
unsigned DstOpcode)
214 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
218 if (!InstrConverterBase::isLegal(MI, TII))
225 (X86::GR8RegClass.
contains(DstReg) ||
226 X86::GR16RegClass.
contains(DstReg)))
230 (X86::GR8RegClass.
contains(SrcReg) ||
231 X86::GR16RegClass.
contains(SrcReg)))
252 if (OpDomain == DstDomain)
260 class InstrReplaceWithCopy :
public InstrConverterBase {
265 InstrReplaceWithCopy(
unsigned SrcOpcode,
unsigned SrcOpIdx)
266 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
270 assert(isLegal(MI, TII) &&
"Cannot convert instruction");
272 TII->
get(TargetOpcode::COPY))
285 typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
288 InstrConverterBaseMap;
310 std::bitset<NumDomains> LegalDstDomains;
317 Closure(
unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) :
ID(ID) {
319 LegalDstDomains.set(
D);
323 void setAllIllegal() { LegalDstDomains.reset(); }
326 bool hasLegalDstDomain()
const {
return LegalDstDomains.any(); }
329 bool isLegal(
RegDomain RD)
const {
return LegalDstDomains[RD]; }
332 void setIllegal(
RegDomain RD) { LegalDstDomains[RD] =
false; }
336 bool insertEdge(
unsigned Reg) {
337 return Edges.
insert(Reg).second;
354 dbgs() <<
"Registers: ";
356 for (
unsigned Reg : Edges) {
362 dbgs() <<
"\n" <<
"Instructions:";
370 unsigned getID()
const {
402 return "X86 Domain Reassignment Pass";
407 InstrConverterBaseMap Converters;
410 void initConverters();
413 void buildClosure(Closure &,
unsigned Reg);
416 void visitRegister(Closure &,
unsigned Reg,
RegDomain &Domain,
420 void reassign(
const Closure &
C,
RegDomain Domain)
const;
426 bool isReassignmentProfitable(
const Closure &C,
RegDomain Domain)
const;
429 double calculateCost(
const Closure &C,
RegDomain Domain)
const;
436 void X86DomainReassignment::visitRegister(Closure &
C,
unsigned Reg,
439 if (EnclosedEdges.count(Reg))
445 if (!
MRI->hasOneDef(Reg))
448 RegDomain RD = getDomain(
MRI->getRegClass(Reg),
MRI->getTargetRegisterInfo());
450 if (Domain == NoDomain)
459 void X86DomainReassignment::encloseInstr(Closure &C,
MachineInstr *
MI) {
460 auto I = EnclosedInstrs.find(MI);
461 if (
I != EnclosedInstrs.end()) {
462 if (
I->second != C.getID())
469 EnclosedInstrs[
MI] = C.getID();
470 C.addInstruction(MI);
475 for (
int i = 0; i != NumDomains; ++i) {
477 InstrConverterBase *IC = Converters.lookup({i, MI->
getOpcode()});
478 if (!IC || !IC->isLegal(MI,
TII))
484 double X86DomainReassignment::calculateCost(
const Closure &C,
486 assert(C.isLegal(DstDomain) &&
"Cannot calculate cost for illegal closure");
489 for (
auto *MI : C.instructions())
491 Converters.lookup({DstDomain, MI->getOpcode()})->getExtraCost(MI,
MRI);
495 bool X86DomainReassignment::isReassignmentProfitable(
const Closure &C,
497 return calculateCost(C, Domain) < 0.0;
500 void X86DomainReassignment::reassign(
const Closure &C,
RegDomain Domain)
const {
501 assert(C.isLegal(Domain) &&
"Cannot convert illegal closure");
506 for (
auto *MI : C.instructions())
507 if (Converters.lookup({Domain, MI->getOpcode()})
508 ->convertInstr(MI,
TII,
MRI))
513 for (
unsigned Reg : C.edges()) {
514 MRI->setRegClass(Reg, getDstRC(
MRI->getRegClass(Reg), Domain));
515 for (
auto &MO :
MRI->use_operands(Reg)) {
523 for (
auto MI : ToErase)
536 if (MemOpStart == -1)
540 for (
unsigned MemOpIdx = MemOpStart,
542 MemOpIdx < MemOpEnd; ++MemOpIdx) {
544 if (
Op.isReg() &&
Op.getReg() ==
Reg)
550 void X86DomainReassignment::buildClosure(Closure &C,
unsigned Reg) {
553 visitRegister(C, Reg, Domain, Worklist);
554 while (!Worklist.
empty()) {
558 if (!C.insertEdge(CurReg))
562 encloseInstr(C, DefMI);
572 for (
int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
573 if (OpIdx == MemOp) {
579 if (!
Op.isReg() || !
Op.isUse())
581 visitRegister(C,
Op.getReg(), Domain, Worklist);
585 for (
auto &
UseMI :
MRI->use_nodbg_instructions(CurReg)) {
592 encloseInstr(C, &
UseMI);
594 for (
auto &DefOp :
UseMI.defs()) {
598 unsigned DefReg = DefOp.getReg();
603 visitRegister(C, DefReg, Domain, Worklist);
609 void X86DomainReassignment::initConverters() {
610 Converters[{MaskDomain, TargetOpcode::PHI}] =
611 new InstrIgnore(TargetOpcode::PHI);
613 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
614 new InstrIgnore(TargetOpcode::IMPLICIT_DEF);
616 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
617 new InstrReplaceWithCopy(TargetOpcode::INSERT_SUBREG, 2);
619 Converters[{MaskDomain, TargetOpcode::COPY}] =
620 new InstrCOPYReplacer(TargetOpcode::COPY, MaskDomain, TargetOpcode::COPY);
622 auto createReplacerDstCOPY = [&](
unsigned From,
unsigned To) {
623 Converters[{MaskDomain, From}] =
new InstrReplacerDstCOPY(From, To);
626 createReplacerDstCOPY(X86::MOVZX32rm16, X86::KMOVWkm);
627 createReplacerDstCOPY(X86::MOVZX64rm16, X86::KMOVWkm);
629 createReplacerDstCOPY(X86::MOVZX32rr16, X86::KMOVWkk);
630 createReplacerDstCOPY(X86::MOVZX64rr16, X86::KMOVWkk);
633 createReplacerDstCOPY(X86::MOVZX16rm8, X86::KMOVBkm);
634 createReplacerDstCOPY(X86::MOVZX32rm8, X86::KMOVBkm);
635 createReplacerDstCOPY(X86::MOVZX64rm8, X86::KMOVBkm);
637 createReplacerDstCOPY(X86::MOVZX16rr8, X86::KMOVBkk);
638 createReplacerDstCOPY(X86::MOVZX32rr8, X86::KMOVBkk);
639 createReplacerDstCOPY(X86::MOVZX64rr8, X86::KMOVBkk);
642 auto createReplacer = [&](
unsigned From,
unsigned To) {
643 Converters[{MaskDomain, From}] =
new InstrReplacer(From, To);
646 createReplacer(X86::MOV16rm, X86::KMOVWkm);
647 createReplacer(X86::MOV16mr, X86::KMOVWmk);
648 createReplacer(X86::MOV16rr, X86::KMOVWkk);
649 createReplacer(X86::SHR16ri, X86::KSHIFTRWri);
650 createReplacer(X86::SHL16ri, X86::KSHIFTLWri);
651 createReplacer(X86::NOT16r, X86::KNOTWrr);
652 createReplacer(X86::OR16rr, X86::KORWrr);
653 createReplacer(X86::AND16rr, X86::KANDWrr);
654 createReplacer(X86::XOR16rr, X86::KXORWrr);
657 createReplacer(X86::MOV32rm, X86::KMOVDkm);
658 createReplacer(X86::MOV64rm, X86::KMOVQkm);
660 createReplacer(X86::MOV32mr, X86::KMOVDmk);
661 createReplacer(X86::MOV64mr, X86::KMOVQmk);
663 createReplacer(X86::MOV32rr, X86::KMOVDkk);
664 createReplacer(X86::MOV64rr, X86::KMOVQkk);
666 createReplacer(X86::SHR32ri, X86::KSHIFTRDri);
667 createReplacer(X86::SHR64ri, X86::KSHIFTRQri);
669 createReplacer(X86::SHL32ri, X86::KSHIFTLDri);
670 createReplacer(X86::SHL64ri, X86::KSHIFTLQri);
672 createReplacer(X86::ADD32rr, X86::KADDDrr);
673 createReplacer(X86::ADD64rr, X86::KADDQrr);
675 createReplacer(X86::NOT32r, X86::KNOTDrr);
676 createReplacer(X86::NOT64r, X86::KNOTQrr);
678 createReplacer(X86::OR32rr, X86::KORDrr);
679 createReplacer(X86::OR64rr, X86::KORQrr);
681 createReplacer(X86::AND32rr, X86::KANDDrr);
682 createReplacer(X86::AND64rr, X86::KANDQrr);
684 createReplacer(X86::ANDN32rr, X86::KANDNDrr);
685 createReplacer(X86::ANDN64rr, X86::KANDNQrr);
687 createReplacer(X86::XOR32rr, X86::KXORDrr);
688 createReplacer(X86::XOR64rr, X86::KXORQrr);
697 createReplacer(X86::ADD8rr, X86::KADDBrr);
698 createReplacer(X86::ADD16rr, X86::KADDWrr);
700 createReplacer(X86::AND8rr, X86::KANDBrr);
702 createReplacer(X86::MOV8rm, X86::KMOVBkm);
703 createReplacer(X86::MOV8mr, X86::KMOVBmk);
704 createReplacer(X86::MOV8rr, X86::KMOVBkk);
706 createReplacer(X86::NOT8r, X86::KNOTBrr);
708 createReplacer(X86::OR8rr, X86::KORBrr);
710 createReplacer(X86::SHR8ri, X86::KSHIFTRBri);
711 createReplacer(X86::SHL8ri, X86::KSHIFTLBri);
718 createReplacer(X86::XOR8rr, X86::KXORBrr);
722 bool X86DomainReassignment::runOnMachineFunction(
MachineFunction &MF) {
729 dbgs() <<
"***** Machine Function before Domain Reassignment *****\n");
738 if (!STI->hasAVX512() || !STI->hasBWI())
742 assert(
MRI->isSSA() &&
"Expected MIR to be in SSA form");
744 TII = STI->getInstrInfo();
746 bool Changed =
false;
748 EnclosedEdges.clear();
749 EnclosedInstrs.clear();
751 std::vector<Closure> Closures;
754 unsigned ClosureID = 0;
755 for (
unsigned Idx = 0; Idx <
MRI->getNumVirtRegs(); ++Idx) {
759 if (!isGPR(
MRI->getRegClass(Reg)))
763 if (EnclosedEdges.count(Reg))
767 Closure
C(ClosureID++, {MaskDomain});
768 buildClosure(C, Reg);
771 if (!C.empty() && C.isLegal(MaskDomain))
772 Closures.push_back(std::move(C));
775 for (Closure &C : Closures) {
777 if (isReassignmentProfitable(C, MaskDomain)) {
778 reassign(C, MaskDomain);
779 ++NumClosuresConverted;
787 dbgs() <<
"***** Machine Function after Domain Reassignment *****\n");
794 "X86 Domain Reassignment Pass",
false,
false)
798 return new X86DomainReassignment();
void DeleteContainerSeconds(Container &C)
In a container of pairs (usually a map) whose second element is a pointer, deletes the second element...
const MachineInstrBuilder & add(const MachineOperand &MO) const
static bool usedAsAddr(const MachineInstr &MI, unsigned Reg, const TargetInstrInfo *TII)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
This class represents lattice values for constants.
iterator_range< mop_iterator > explicit_operands()
static unsigned index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
AddrNumOperands - Total number of operands in a memory reference.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
STATISTIC(NumFunctions, "Total number of functions")
unsigned const TargetRegisterInfo * TRI
iterator_range< mop_iterator > operands()
FunctionPass * createX86DomainReassignmentPass()
Return a Machine IR pass that reassigns instruction chains from one domain to another, when profitable.
return AArch64::GPR64RegClass contains(Reg)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
unsigned getNumOperands() const
Retuns the total number of operands.
const TargetRegisterClass * getRegClass(const MCInstrDesc &MCID, unsigned OpNum, const TargetRegisterInfo *TRI, const MachineFunction &MF) const
Given a machine instruction descriptor, returns the register class constraint for OpNum...
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment", "X86 Domain Reassignment Pass", false, false) FunctionPass *llvm
Returns an instance of the Domain Reassignment pass.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
static int getID(struct InternalInstruction *insn, const void *miiArg)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
TargetInstrInfo - Interface to description of machine instruction set.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
initializer< Ty > init(const Ty &Val)
const TargetRegisterInfo * getTargetRegisterInfo() const
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
MachineInstrBuilder & UseMI
std::pair< iterator, bool > insert(const ValueT &V)
Represent the analysis usage information of a pass.
FunctionPass class - This class is used to implement most global optimizations.
unsigned getOperandBias(const MCInstrDesc &Desc)
getOperandBias - compute whether all of the def operands are repeated in the uses and therefore shoul...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void initializeX86DomainReassignmentPass(PassRegistry &)
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
BlockVerifier::State From
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
MachineInstrBuilder MachineInstrBuilder & DefMI
LLVM_NODISCARD T pop_back_val()
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
void setPreservesCFG()
This function should be called by the pass, iff they do not:
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A range adaptor for a pair of iterators.
iterator_range< mop_iterator > implicit_operands()
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
static cl::opt< bool > DisableX86DomainReassignment("disable-x86-domain-reassignment", cl::Hidden, cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false))
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
LLVM_NODISCARD bool empty() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StringRef - Represent a constant reference to a string, i.e.
inst_range instructions(Function *F)
bool hasImplicitDefOfPhysReg(unsigned Reg, const MCRegisterInfo *MRI=nullptr) const
Return true if this instruction implicitly defines the specified physical register.
const MachineOperand & getOperand(unsigned i) const
unsigned createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
int getMemoryOperandNo(uint64_t TSFlags)
getMemoryOperandNo - The function returns the MCInst operand # for the first field of the memory oper...