33#define DEBUG_TYPE "x86-domain-reassignment"
35STATISTIC(NumClosuresConverted,
"Number of closures converted by the pass");
42enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
46 return X86::VK16RegClass.hasSubClassEq(RC);
51 if (
TRI->isGeneralPurposeRegisterClass(RC))
62 if (X86::GR8RegClass.hasSubClassEq(SrcRC))
63 return &X86::VK8RegClass;
64 if (X86::GR16RegClass.hasSubClassEq(SrcRC))
65 return &X86::VK16RegClass;
66 if (X86::GR32RegClass.hasSubClassEq(SrcRC))
67 return &X86::VK32RegClass;
68 if (X86::GR64RegClass.hasSubClassEq(SrcRC))
69 return &X86::VK64RegClass;
75class InstrConverterBase {
80 InstrConverterBase(
unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
82 virtual ~InstrConverterBase() =
default;
85 virtual bool isLegal(
const MachineInstr *
MI,
86 const TargetInstrInfo *
TII)
const {
87 assert(
MI->getOpcode() == SrcOpcode &&
88 "Wrong instruction passed to converter");
95 virtual bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
96 MachineRegisterInfo *
MRI)
const = 0;
99 virtual double getExtraCost(
const MachineInstr *
MI,
100 MachineRegisterInfo *
MRI)
const = 0;
106class InstrIgnore :
public InstrConverterBase {
108 InstrIgnore(
unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
110 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
111 MachineRegisterInfo *
MRI)
const override {
112 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
116 double getExtraCost(
const MachineInstr *
MI,
117 MachineRegisterInfo *
MRI)
const override {
123class InstrReplacer :
public InstrConverterBase {
128 InstrReplacer(
unsigned SrcOpcode,
unsigned DstOpcode)
129 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
131 bool isLegal(
const MachineInstr *
MI,
132 const TargetInstrInfo *
TII)
const override {
133 if (!InstrConverterBase::isLegal(
MI,
TII))
137 for (
const auto &MO :
MI->implicit_operands())
138 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
139 !
TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
144 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
145 MachineRegisterInfo *
MRI)
const override {
146 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
147 MachineInstrBuilder Bld =
151 for (
auto &
Op :
MI->explicit_operands())
156 double getExtraCost(
const MachineInstr *
MI,
157 MachineRegisterInfo *
MRI)
const override {
165class InstrReplacerDstCOPY :
public InstrConverterBase {
169 InstrReplacerDstCOPY(
unsigned SrcOpcode,
unsigned DstOpcode)
170 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
172 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
173 MachineRegisterInfo *
MRI)
const override {
174 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
175 MachineBasicBlock *
MBB =
MI->getParent();
179 MRI->createVirtualRegister(
TII->getRegClass(
TII->get(DstOpcode), 0));
185 .
add(
MI->getOperand(0))
191 double getExtraCost(
const MachineInstr *
MI,
192 MachineRegisterInfo *
MRI)
const override {
200class InstrCOPYReplacer :
public InstrReplacer {
204 InstrCOPYReplacer(
unsigned SrcOpcode, RegDomain DstDomain,
unsigned DstOpcode)
205 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
207 bool isLegal(
const MachineInstr *
MI,
208 const TargetInstrInfo *
TII)
const override {
209 if (!InstrConverterBase::isLegal(
MI,
TII))
215 if (DstReg.
isPhysical() && (X86::GR8RegClass.contains(DstReg) ||
216 X86::GR16RegClass.contains(DstReg)))
219 if (SrcReg.
isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||
220 X86::GR16RegClass.contains(SrcReg)))
226 double getExtraCost(
const MachineInstr *
MI,
227 MachineRegisterInfo *
MRI)
const override {
228 assert(
MI->getOpcode() == TargetOpcode::COPY &&
"Expected a COPY");
230 for (
const auto &MO :
MI->operands()) {
234 if (MO.getReg().isPhysical())
237 RegDomain OpDomain =
getDomain(
MRI->getRegClass(MO.getReg()),
238 MRI->getTargetRegisterInfo());
241 if (OpDomain == DstDomain)
249class InstrReplaceWithCopy :
public InstrConverterBase {
254 InstrReplaceWithCopy(
unsigned SrcOpcode,
unsigned SrcOpIdx)
255 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
257 bool convertInstr(MachineInstr *
MI,
const TargetInstrInfo *
TII,
258 MachineRegisterInfo *
MRI)
const override {
259 assert(isLegal(
MI,
TII) &&
"Cannot convert instruction");
261 TII->get(TargetOpcode::COPY))
262 .
add({
MI->getOperand(0),
MI->getOperand(SrcOpIdx)});
266 double getExtraCost(
const MachineInstr *
MI,
267 MachineRegisterInfo *
MRI)
const override {
274typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
277 InstrConverterBaseMap;
293 DenseSet<Register> Edges;
296 SmallVector<MachineInstr *, 8> Instrs;
299 std::bitset<NumDomains> LegalDstDomains;
306 Closure(
unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
307 for (RegDomain
D : LegalDstDomainList)
308 LegalDstDomains.set(
D);
312 void setAllIllegal() { LegalDstDomains.reset(); }
315 bool hasLegalDstDomain()
const {
return LegalDstDomains.any(); }
318 bool isLegal(RegDomain RD)
const {
return LegalDstDomains[RD]; }
321 void setIllegal(RegDomain RD) { LegalDstDomains[RD] =
false; }
323 bool empty()
const {
return Edges.empty(); }
325 bool insertEdge(
Register Reg) {
return Edges.insert(
Reg).second; }
327 using const_edge_iterator = DenseSet<Register>::const_iterator;
330 void addInstruction(MachineInstr *
I) {
339 dbgs() <<
"Registers: ";
343 dbgs() <<
"\n" <<
"Instructions:";
344 for (MachineInstr *
MI : Instrs) {
351 unsigned getID()
const {
357class X86DomainReassignmentImpl {
359 bool runOnMachineFunction(MachineFunction &MF);
362 const X86Subtarget *STI =
nullptr;
363 MachineRegisterInfo *MRI =
nullptr;
364 const X86InstrInfo *TII =
nullptr;
367 DenseMap<Register, unsigned> EnclosedEdges;
370 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
373 InstrConverterBaseMap Converters;
376 void initConverters();
384 SmallVectorImpl<Register> &Worklist);
387 void reassign(
const Closure &
C, RegDomain
Domain)
const;
391 bool encloseInstr(Closure &
C, MachineInstr *
MI);
394 bool isReassignmentProfitable(
const Closure &
C, RegDomain
Domain)
const;
397 double calculateCost(
const Closure &
C, RegDomain
Domain)
const;
404 X86DomainReassignmentLegacy() : MachineFunctionPass(ID) {}
406 bool runOnMachineFunction(MachineFunction &MF)
override;
408 void getAnalysisUsage(AnalysisUsage &AU)
const override {
413 StringRef getPassName()
const override {
414 return "X86 Domain Reassignment Pass";
418char X86DomainReassignmentLegacy::ID = 0;
422bool X86DomainReassignmentImpl::visitRegister(
428 auto I = EnclosedEdges.find(
Reg);
429 if (
I != EnclosedEdges.end()) {
430 if (
I->second !=
C.getID()) {
452bool X86DomainReassignmentImpl::encloseInstr(Closure &
C, MachineInstr *
MI) {
455 if (
I->second !=
C.getID()) {
464 C.addInstruction(
MI);
469 for (
int i = 0; i != NumDomains; ++i) {
470 if (
C.isLegal((RegDomain)i)) {
471 auto I = Converters.find({i,
MI->getOpcode()});
472 if (
I == Converters.end() || !
I->second->isLegal(
MI,
TII))
473 C.setIllegal((RegDomain)i);
476 return C.hasLegalDstDomain();
479double X86DomainReassignmentImpl::calculateCost(
const Closure &
C,
480 RegDomain DstDomain)
const {
481 assert(
C.isLegal(DstDomain) &&
"Cannot calculate cost for illegal closure");
484 for (
auto *
MI :
C.instructions())
485 Cost += Converters.find({DstDomain,
MI->getOpcode()})
486 ->second->getExtraCost(
MI,
MRI);
490bool X86DomainReassignmentImpl::isReassignmentProfitable(
491 const Closure &
C, RegDomain
Domain)
const {
492 return calculateCost(
C,
Domain) < 0.0;
495void X86DomainReassignmentImpl::reassign(
const Closure &
C,
497 assert(
C.isLegal(
Domain) &&
"Cannot convert illegal closure");
501 SmallVector<MachineInstr *, 8> ToErase;
502 for (
auto *
MI :
C.instructions())
503 if (Converters.find({Domain, MI->getOpcode()})
504 ->second->convertInstr(
MI,
TII,
MRI))
511 for (
auto &MO :
MRI->use_operands(
Reg)) {
519 for (
auto *
MI : ToErase)
520 MI->eraseFromParent();
527 if (!
MI.mayLoadOrStore())
532 if (MemOpStart == -1)
536 for (
unsigned MemOpIdx = MemOpStart,
538 MemOpIdx < MemOpEnd; ++MemOpIdx) {
540 if (
Op.isReg() &&
Op.getReg() ==
Reg)
546void X86DomainReassignmentImpl::buildClosure(Closure &
C,
Register Reg) {
548 RegDomain
Domain = NoDomain;
550 while (!Worklist.
empty()) {
554 if (!
C.insertEdge(CurReg))
556 EnclosedEdges[
Reg] =
C.getID();
558 MachineInstr *
DefMI =
MRI->getVRegDef(CurReg);
559 if (!encloseInstr(
C,
DefMI))
571 if (
OpIdx == MemOp) {
577 if (!
Op.isReg() || !
Op.isUse())
579 if (!visitRegister(
C,
Op.getReg(),
Domain, Worklist))
584 for (
auto &
UseMI :
MRI->use_nodbg_instructions(CurReg)) {
591 if (!encloseInstr(
C, &
UseMI))
594 for (
auto &DefOp :
UseMI.defs()) {
603 if (!visitRegister(
C, DefReg,
Domain, Worklist))
610void X86DomainReassignmentImpl::initConverters() {
611 Converters[{MaskDomain, TargetOpcode::PHI}] =
612 std::make_unique<InstrIgnore>(TargetOpcode::PHI);
614 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
615 std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
617 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
618 std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
620 Converters[{MaskDomain, TargetOpcode::COPY}] =
621 std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
624 auto createReplacerDstCOPY = [&](
unsigned From,
unsigned To) {
625 Converters[{MaskDomain, From}] =
626 std::make_unique<InstrReplacerDstCOPY>(From, To);
629#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC
646 auto createReplacer = [&](
unsigned From,
unsigned To) {
647 Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
653 createReplacer(X86::SHR16ri, X86::KSHIFTRWki);
654 createReplacer(X86::SHL16ri, X86::KSHIFTLWki);
655 createReplacer(X86::NOT16r, X86::KNOTWkk);
656 createReplacer(X86::OR16rr, X86::KORWkk);
657 createReplacer(X86::AND16rr, X86::KANDWkk);
658 createReplacer(X86::XOR16rr, X86::KXORWkk);
660 bool HasNDD = STI->hasNDD();
662 createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWki);
663 createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWki);
664 createReplacer(X86::NOT16r_ND, X86::KNOTWkk);
665 createReplacer(X86::OR16rr_ND, X86::KORWkk);
666 createReplacer(X86::AND16rr_ND, X86::KANDWkk);
667 createReplacer(X86::XOR16rr_ND, X86::KXORWkk);
680 createReplacer(X86::SHR32ri, X86::KSHIFTRDki);
681 createReplacer(X86::SHR64ri, X86::KSHIFTRQki);
683 createReplacer(X86::SHL32ri, X86::KSHIFTLDki);
684 createReplacer(X86::SHL64ri, X86::KSHIFTLQki);
686 createReplacer(X86::ADD32rr, X86::KADDDkk);
687 createReplacer(X86::ADD64rr, X86::KADDQkk);
689 createReplacer(X86::NOT32r, X86::KNOTDkk);
690 createReplacer(X86::NOT64r, X86::KNOTQkk);
692 createReplacer(X86::OR32rr, X86::KORDkk);
693 createReplacer(X86::OR64rr, X86::KORQkk);
695 createReplacer(X86::AND32rr, X86::KANDDkk);
696 createReplacer(X86::AND64rr, X86::KANDQkk);
698 createReplacer(X86::ANDN32rr, X86::KANDNDkk);
699 createReplacer(X86::ANDN64rr, X86::KANDNQkk);
701 createReplacer(X86::XOR32rr, X86::KXORDkk);
702 createReplacer(X86::XOR64rr, X86::KXORQkk);
705 createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDki);
706 createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDki);
707 createReplacer(X86::ADD32rr_ND, X86::KADDDkk);
708 createReplacer(X86::NOT32r_ND, X86::KNOTDkk);
709 createReplacer(X86::OR32rr_ND, X86::KORDkk);
710 createReplacer(X86::AND32rr_ND, X86::KANDDkk);
711 createReplacer(X86::XOR32rr_ND, X86::KXORDkk);
712 createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQki);
713 createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQki);
714 createReplacer(X86::ADD64rr_ND, X86::KADDQkk);
715 createReplacer(X86::NOT64r_ND, X86::KNOTQkk);
716 createReplacer(X86::OR64rr_ND, X86::KORQkk);
717 createReplacer(X86::AND64rr_ND, X86::KANDQkk);
718 createReplacer(X86::XOR64rr_ND, X86::KXORQkk);
728 createReplacer(X86::ADD8rr, X86::KADDBkk);
729 createReplacer(X86::ADD16rr, X86::KADDWkk);
731 createReplacer(X86::AND8rr, X86::KANDBkk);
737 createReplacer(X86::NOT8r, X86::KNOTBkk);
739 createReplacer(X86::OR8rr, X86::KORBkk);
741 createReplacer(X86::SHR8ri, X86::KSHIFTRBki);
742 createReplacer(X86::SHL8ri, X86::KSHIFTLBki);
749 createReplacer(X86::XOR8rr, X86::KXORBkk);
752 createReplacer(X86::ADD8rr_ND, X86::KADDBkk);
753 createReplacer(X86::ADD16rr_ND, X86::KADDWkk);
754 createReplacer(X86::AND8rr_ND, X86::KANDBkk);
755 createReplacer(X86::NOT8r_ND, X86::KNOTBkk);
756 createReplacer(X86::OR8rr_ND, X86::KORBkk);
757 createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBki);
758 createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBki);
759 createReplacer(X86::XOR8rr_ND, X86::KXORBkk);
762#undef GET_EGPR_IF_ENABLED
765bool X86DomainReassignmentImpl::runOnMachineFunction(MachineFunction &MF) {
770 dbgs() <<
"***** Machine Function before Domain Reassignment *****\n");
783 assert(
MRI->isSSA() &&
"Expected MIR to be in SSA form");
789 EnclosedEdges.clear();
790 EnclosedInstrs.
clear();
792 std::vector<Closure> Closures;
795 unsigned ClosureID = 0;
796 for (
unsigned Idx = 0; Idx <
MRI->getNumVirtRegs(); ++Idx) {
800 if (
MRI->reg_nodbg_empty(
Reg))
804 if (!
MRI->getTargetRegisterInfo()->isGeneralPurposeRegisterClass(
809 if (EnclosedEdges.contains(
Reg))
813 Closure
C(ClosureID++, {MaskDomain});
814 buildClosure(
C,
Reg);
817 if (!
C.empty() &&
C.isLegal(MaskDomain))
818 Closures.push_back(std::move(
C));
821 for (Closure &
C : Closures) {
823 if (isReassignmentProfitable(
C, MaskDomain)) {
824 reassign(
C, MaskDomain);
825 ++NumClosuresConverted;
831 dbgs() <<
"***** Machine Function after Domain Reassignment *****\n");
837bool X86DomainReassignmentLegacy::runOnMachineFunction(MachineFunction &MF) {
840 X86DomainReassignmentImpl Impl;
841 return Impl.runOnMachineFunction(MF);
845 "X86 Domain Reassignment Pass",
false,
false)
849 return new X86DomainReassignmentLegacy();
855 X86DomainReassignmentImpl Impl;
856 bool Changed = Impl.runOnMachineFunction(MF);
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:
Represents analyses that only rely on functions' control flow.
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
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...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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)
FunctionPass * createX86DomainReassignmentLegacyPass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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 > >
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.