32#define DEBUG_TYPE "x86-domain-reassignment"
34STATISTIC(NumClosuresConverted,
"Number of closures converted by the pass");
41enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
45 return X86::VK16RegClass.hasSubClassEq(RC);
50 if (
TRI->isGeneralPurposeRegisterClass(RC))
61 if (X86::GR8RegClass.hasSubClassEq(SrcRC))
62 return &X86::VK8RegClass;
63 if (X86::GR16RegClass.hasSubClassEq(SrcRC))
64 return &X86::VK16RegClass;
65 if (X86::GR32RegClass.hasSubClassEq(SrcRC))
66 return &X86::VK32RegClass;
67 if (X86::GR64RegClass.hasSubClassEq(SrcRC))
68 return &X86::VK64RegClass;
74class InstrConverterBase {
79 InstrConverterBase(
unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
81 virtual ~InstrConverterBase() =
default;
84 virtual bool isLegal(
const MachineInstr *
MI,
85 const TargetInstrInfo *
TII)
const {
86 assert(
MI->getOpcode() == SrcOpcode &&
87 "Wrong instruction passed to converter");
94 virtual bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
95 MachineRegisterInfo *
MRI)
const = 0;
98 virtual double getExtraCost(
const MachineInstr *
MI,
99 MachineRegisterInfo *
MRI)
const = 0;
105class InstrIgnore :
public InstrConverterBase {
107 InstrIgnore(
unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
109 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
110 MachineRegisterInfo *
MRI)
const override {
111 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
115 double getExtraCost(
const MachineInstr *
MI,
116 MachineRegisterInfo *
MRI)
const override {
122class InstrReplacer :
public InstrConverterBase {
127 InstrReplacer(
unsigned SrcOpcode,
unsigned DstOpcode)
128 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
130 bool isLegal(
const MachineInstr *
MI,
131 const TargetInstrInfo *
TII)
const override {
132 if (!InstrConverterBase::isLegal(
MI,
TII))
136 for (
const auto &MO :
MI->implicit_operands())
137 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
138 !
TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
143 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
144 MachineRegisterInfo *
MRI)
const override {
145 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
146 MachineInstrBuilder Bld =
150 for (
auto &
Op :
MI->explicit_operands())
155 double getExtraCost(
const MachineInstr *
MI,
156 MachineRegisterInfo *
MRI)
const override {
164class InstrReplacerDstCOPY :
public InstrConverterBase {
168 InstrReplacerDstCOPY(
unsigned SrcOpcode,
unsigned DstOpcode)
169 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
171 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
172 MachineRegisterInfo *
MRI)
const override {
173 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
174 MachineBasicBlock *
MBB =
MI->getParent();
178 TII->getRegClass(
TII->get(DstOpcode), 0,
MRI->getTargetRegisterInfo()));
184 .
add(
MI->getOperand(0))
190 double getExtraCost(
const MachineInstr *
MI,
191 MachineRegisterInfo *
MRI)
const override {
199class InstrCOPYReplacer :
public InstrReplacer {
203 InstrCOPYReplacer(
unsigned SrcOpcode, RegDomain DstDomain,
unsigned DstOpcode)
204 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
206 bool isLegal(
const MachineInstr *
MI,
207 const TargetInstrInfo *
TII)
const override {
208 if (!InstrConverterBase::isLegal(
MI,
TII))
214 if (DstReg.
isPhysical() && (X86::GR8RegClass.contains(DstReg) ||
215 X86::GR16RegClass.contains(DstReg)))
218 if (SrcReg.
isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||
219 X86::GR16RegClass.contains(SrcReg)))
225 double getExtraCost(
const MachineInstr *
MI,
226 MachineRegisterInfo *
MRI)
const override {
227 assert(
MI->getOpcode() == TargetOpcode::COPY &&
"Expected a COPY");
229 for (
const auto &MO :
MI->operands()) {
233 if (MO.getReg().isPhysical())
236 RegDomain OpDomain =
getDomain(
MRI->getRegClass(MO.getReg()),
237 MRI->getTargetRegisterInfo());
240 if (OpDomain == DstDomain)
248class InstrReplaceWithCopy :
public InstrConverterBase {
253 InstrReplaceWithCopy(
unsigned SrcOpcode,
unsigned SrcOpIdx)
254 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
256 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
257 MachineRegisterInfo *
MRI)
const override {
258 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
260 TII->get(TargetOpcode::COPY))
261 .
add({
MI->getOperand(0),
MI->getOperand(SrcOpIdx)});
265 double getExtraCost(
const MachineInstr *
MI,
266 MachineRegisterInfo *
MRI)
const override {
273typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
276 InstrConverterBaseMap;
292 DenseSet<Register> Edges;
295 SmallVector<MachineInstr *, 8> Instrs;
298 std::bitset<NumDomains> LegalDstDomains;
305 Closure(
unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
306 for (RegDomain
D : LegalDstDomainList)
307 LegalDstDomains.set(
D);
311 void setAllIllegal() { LegalDstDomains.reset(); }
314 bool hasLegalDstDomain()
const {
return LegalDstDomains.any(); }
317 bool isLegal(RegDomain RD)
const {
return LegalDstDomains[RD]; }
320 void setIllegal(RegDomain RD) { LegalDstDomains[RD] =
false; }
322 bool empty()
const {
return Edges.empty(); }
324 bool insertEdge(
Register Reg) {
return Edges.insert(
Reg).second; }
326 using const_edge_iterator = DenseSet<Register>::const_iterator;
329 void addInstruction(MachineInstr *
I) {
338 dbgs() <<
"Registers: ";
346 dbgs() <<
"\n" <<
"Instructions:";
347 for (MachineInstr *
MI : Instrs) {
354 unsigned getID()
const {
361 const X86Subtarget *STI =
nullptr;
362 MachineRegisterInfo *MRI =
nullptr;
363 const X86InstrInfo *TII =
nullptr;
366 DenseMap<Register, unsigned> EnclosedEdges;
369 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
374 X86DomainReassignment() : MachineFunctionPass(ID) { }
376 bool runOnMachineFunction(MachineFunction &MF)
override;
378 void getAnalysisUsage(AnalysisUsage &AU)
const override {
383 StringRef getPassName()
const override {
384 return "X86 Domain Reassignment Pass";
389 InstrConverterBaseMap Converters;
392 void initConverters();
400 SmallVectorImpl<Register> &Worklist);
403 void reassign(
const Closure &
C, RegDomain
Domain)
const;
407 bool encloseInstr(Closure &
C, MachineInstr *
MI);
410 bool isReassignmentProfitable(
const Closure &
C, RegDomain
Domain)
const;
413 double calculateCost(
const Closure &
C, RegDomain
Domain)
const;
416char X86DomainReassignment::ID = 0;
420bool X86DomainReassignment::visitRegister(Closure &
C,
Register Reg,
426 auto I = EnclosedEdges.find(
Reg);
427 if (
I != EnclosedEdges.end()) {
428 if (
I->second !=
C.getID()) {
450bool X86DomainReassignment::encloseInstr(Closure &
C, MachineInstr *
MI) {
453 if (
I->second !=
C.getID()) {
462 C.addInstruction(
MI);
467 for (
int i = 0; i != NumDomains; ++i) {
468 if (
C.isLegal((RegDomain)i)) {
469 auto I = Converters.find({i,
MI->getOpcode()});
470 if (
I == Converters.end() || !
I->second->isLegal(
MI,
TII))
471 C.setIllegal((RegDomain)i);
474 return C.hasLegalDstDomain();
477double X86DomainReassignment::calculateCost(
const Closure &
C,
478 RegDomain DstDomain)
const {
479 assert(
C.isLegal(DstDomain) &&
"Cannot calculate cost for illegal closure");
482 for (
auto *
MI :
C.instructions())
483 Cost += Converters.find({DstDomain,
MI->getOpcode()})
484 ->second->getExtraCost(
MI,
MRI);
488bool X86DomainReassignment::isReassignmentProfitable(
const Closure &
C,
490 return calculateCost(
C,
Domain) < 0.0;
493void X86DomainReassignment::reassign(
const Closure &
C, RegDomain
Domain)
const {
494 assert(
C.isLegal(
Domain) &&
"Cannot convert illegal closure");
498 SmallVector<MachineInstr *, 8> ToErase;
499 for (
auto *
MI :
C.instructions())
500 if (Converters.find({Domain, MI->getOpcode()})
501 ->second->convertInstr(
MI,
TII,
MRI))
508 for (
auto &MO :
MRI->use_operands(
Reg)) {
516 for (
auto *
MI : ToErase)
517 MI->eraseFromParent();
524 if (!
MI.mayLoadOrStore())
529 if (MemOpStart == -1)
533 for (
unsigned MemOpIdx = MemOpStart,
535 MemOpIdx < MemOpEnd; ++MemOpIdx) {
537 if (
Op.isReg() &&
Op.getReg() ==
Reg)
543void X86DomainReassignment::buildClosure(Closure &
C,
Register Reg) {
545 RegDomain
Domain = NoDomain;
547 while (!Worklist.
empty()) {
551 if (!
C.insertEdge(CurReg))
553 EnclosedEdges[
Reg] =
C.getID();
555 MachineInstr *
DefMI =
MRI->getVRegDef(CurReg);
556 if (!encloseInstr(
C,
DefMI))
568 if (
OpIdx == MemOp) {
574 if (!
Op.isReg() || !
Op.isUse())
576 if (!visitRegister(
C,
Op.getReg(),
Domain, Worklist))
581 for (
auto &
UseMI :
MRI->use_nodbg_instructions(CurReg)) {
588 if (!encloseInstr(
C, &
UseMI))
591 for (
auto &DefOp :
UseMI.defs()) {
600 if (!visitRegister(
C, DefReg,
Domain, Worklist))
607void X86DomainReassignment::initConverters() {
608 Converters[{MaskDomain, TargetOpcode::PHI}] =
609 std::make_unique<InstrIgnore>(TargetOpcode::PHI);
611 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
612 std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
614 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
615 std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
617 Converters[{MaskDomain, TargetOpcode::COPY}] =
618 std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
621 auto createReplacerDstCOPY = [&](
unsigned From,
unsigned To) {
622 Converters[{MaskDomain, From}] =
623 std::make_unique<InstrReplacerDstCOPY>(From, To);
626#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC
643 auto createReplacer = [&](
unsigned From,
unsigned To) {
644 Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
650 createReplacer(X86::SHR16ri, X86::KSHIFTRWki);
651 createReplacer(X86::SHL16ri, X86::KSHIFTLWki);
652 createReplacer(X86::NOT16r, X86::KNOTWkk);
653 createReplacer(X86::OR16rr, X86::KORWkk);
654 createReplacer(X86::AND16rr, X86::KANDWkk);
655 createReplacer(X86::XOR16rr, X86::KXORWkk);
657 bool HasNDD = STI->hasNDD();
659 createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWki);
660 createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWki);
661 createReplacer(X86::NOT16r_ND, X86::KNOTWkk);
662 createReplacer(X86::OR16rr_ND, X86::KORWkk);
663 createReplacer(X86::AND16rr_ND, X86::KANDWkk);
664 createReplacer(X86::XOR16rr_ND, X86::KXORWkk);
677 createReplacer(X86::SHR32ri, X86::KSHIFTRDki);
678 createReplacer(X86::SHR64ri, X86::KSHIFTRQki);
680 createReplacer(X86::SHL32ri, X86::KSHIFTLDki);
681 createReplacer(X86::SHL64ri, X86::KSHIFTLQki);
683 createReplacer(X86::ADD32rr, X86::KADDDkk);
684 createReplacer(X86::ADD64rr, X86::KADDQkk);
686 createReplacer(X86::NOT32r, X86::KNOTDkk);
687 createReplacer(X86::NOT64r, X86::KNOTQkk);
689 createReplacer(X86::OR32rr, X86::KORDkk);
690 createReplacer(X86::OR64rr, X86::KORQkk);
692 createReplacer(X86::AND32rr, X86::KANDDkk);
693 createReplacer(X86::AND64rr, X86::KANDQkk);
695 createReplacer(X86::ANDN32rr, X86::KANDNDkk);
696 createReplacer(X86::ANDN64rr, X86::KANDNQkk);
698 createReplacer(X86::XOR32rr, X86::KXORDkk);
699 createReplacer(X86::XOR64rr, X86::KXORQkk);
702 createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDki);
703 createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDki);
704 createReplacer(X86::ADD32rr_ND, X86::KADDDkk);
705 createReplacer(X86::NOT32r_ND, X86::KNOTDkk);
706 createReplacer(X86::OR32rr_ND, X86::KORDkk);
707 createReplacer(X86::AND32rr_ND, X86::KANDDkk);
708 createReplacer(X86::XOR32rr_ND, X86::KXORDkk);
709 createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQki);
710 createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQki);
711 createReplacer(X86::ADD64rr_ND, X86::KADDQkk);
712 createReplacer(X86::NOT64r_ND, X86::KNOTQkk);
713 createReplacer(X86::OR64rr_ND, X86::KORQkk);
714 createReplacer(X86::AND64rr_ND, X86::KANDQkk);
715 createReplacer(X86::XOR64rr_ND, X86::KXORQkk);
725 createReplacer(X86::ADD8rr, X86::KADDBkk);
726 createReplacer(X86::ADD16rr, X86::KADDWkk);
728 createReplacer(X86::AND8rr, X86::KANDBkk);
734 createReplacer(X86::NOT8r, X86::KNOTBkk);
736 createReplacer(X86::OR8rr, X86::KORBkk);
738 createReplacer(X86::SHR8ri, X86::KSHIFTRBki);
739 createReplacer(X86::SHL8ri, X86::KSHIFTLBki);
746 createReplacer(X86::XOR8rr, X86::KXORBkk);
749 createReplacer(X86::ADD8rr_ND, X86::KADDBkk);
750 createReplacer(X86::ADD16rr_ND, X86::KADDWkk);
751 createReplacer(X86::AND8rr_ND, X86::KANDBkk);
752 createReplacer(X86::NOT8r_ND, X86::KNOTBkk);
753 createReplacer(X86::OR8rr_ND, X86::KORBkk);
754 createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBki);
755 createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBki);
756 createReplacer(X86::XOR8rr_ND, X86::KXORBkk);
759#undef GET_EGPR_IF_ENABLED
762bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
769 dbgs() <<
"***** Machine Function before Domain Reassignment *****\n");
782 assert(
MRI->isSSA() &&
"Expected MIR to be in SSA form");
788 EnclosedEdges.clear();
789 EnclosedInstrs.
clear();
791 std::vector<Closure> Closures;
794 unsigned ClosureID = 0;
795 for (
unsigned Idx = 0; Idx <
MRI->getNumVirtRegs(); ++Idx) {
799 if (
MRI->reg_nodbg_empty(
Reg))
803 if (!
MRI->getTargetRegisterInfo()->isGeneralPurposeRegisterClass(
808 if (EnclosedEdges.contains(
Reg))
812 Closure
C(ClosureID++, {MaskDomain});
813 buildClosure(
C,
Reg);
816 if (!
C.empty() &&
C.isLegal(MaskDomain))
817 Closures.push_back(std::move(
C));
820 for (Closure &
C : Closures) {
822 if (isReassignmentProfitable(
C, MaskDomain)) {
823 reassign(
C, MaskDomain);
824 ++NumClosuresConverted;
830 dbgs() <<
"***** Machine Function after Domain Reassignment *****\n");
837 "X86 Domain Reassignment Pass",
false,
false)
841 return new X86DomainReassignment();
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file defines the DenseMap class.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
#define GET_EGPR_IF_ENABLED(OPC)
static cl::opt< bool > DisableX86DomainReassignment("disable-x86-domain-reassignment", cl::Hidden, cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false))
static bool usedAsAddr(const MachineInstr &MI, Register Reg, const TargetInstrInfo *TII)
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
FunctionPass class - This class is used to implement most global optimizations.
Describe properties that are true of each instruction in the target description file.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
const X86InstrInfo * getInstrInfo() const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
int getMemoryOperandNo(uint64_t TSFlags)
unsigned getOperandBias(const MCInstrDesc &Desc)
Compute whether all of the def operands are repeated in the uses and therefore should be skipped.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createX86DomainReassignmentPass()
Return a Machine IR pass that reassigns instruction chains from one domain to another,...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.