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 {
358 const X86Subtarget *STI =
nullptr;
359 MachineRegisterInfo *MRI =
nullptr;
360 const X86InstrInfo *TII =
nullptr;
363 DenseMap<Register, unsigned> EnclosedEdges;
366 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
371 X86DomainReassignment() : MachineFunctionPass(ID) { }
373 bool runOnMachineFunction(MachineFunction &MF)
override;
375 void getAnalysisUsage(AnalysisUsage &AU)
const override {
380 StringRef getPassName()
const override {
381 return "X86 Domain Reassignment Pass";
386 InstrConverterBaseMap Converters;
389 void initConverters();
397 SmallVectorImpl<Register> &Worklist);
400 void reassign(
const Closure &
C, RegDomain
Domain)
const;
404 bool encloseInstr(Closure &
C, MachineInstr *
MI);
407 bool isReassignmentProfitable(
const Closure &
C, RegDomain
Domain)
const;
410 double calculateCost(
const Closure &
C, RegDomain
Domain)
const;
413char X86DomainReassignment::ID = 0;
417bool X86DomainReassignment::visitRegister(Closure &
C,
Register Reg,
423 auto I = EnclosedEdges.find(
Reg);
424 if (
I != EnclosedEdges.end()) {
425 if (
I->second !=
C.getID()) {
447bool X86DomainReassignment::encloseInstr(Closure &
C, MachineInstr *
MI) {
450 if (
I->second !=
C.getID()) {
459 C.addInstruction(
MI);
464 for (
int i = 0; i != NumDomains; ++i) {
465 if (
C.isLegal((RegDomain)i)) {
466 auto I = Converters.find({i,
MI->getOpcode()});
467 if (
I == Converters.end() || !
I->second->isLegal(
MI,
TII))
468 C.setIllegal((RegDomain)i);
471 return C.hasLegalDstDomain();
474double X86DomainReassignment::calculateCost(
const Closure &
C,
475 RegDomain DstDomain)
const {
476 assert(
C.isLegal(DstDomain) &&
"Cannot calculate cost for illegal closure");
479 for (
auto *
MI :
C.instructions())
480 Cost += Converters.find({DstDomain,
MI->getOpcode()})
481 ->second->getExtraCost(
MI,
MRI);
485bool X86DomainReassignment::isReassignmentProfitable(
const Closure &
C,
487 return calculateCost(
C,
Domain) < 0.0;
490void X86DomainReassignment::reassign(
const Closure &
C, RegDomain
Domain)
const {
491 assert(
C.isLegal(
Domain) &&
"Cannot convert illegal closure");
495 SmallVector<MachineInstr *, 8> ToErase;
496 for (
auto *
MI :
C.instructions())
497 if (Converters.find({Domain, MI->getOpcode()})
498 ->second->convertInstr(
MI,
TII,
MRI))
505 for (
auto &MO :
MRI->use_operands(
Reg)) {
513 for (
auto *
MI : ToErase)
514 MI->eraseFromParent();
521 if (!
MI.mayLoadOrStore())
526 if (MemOpStart == -1)
530 for (
unsigned MemOpIdx = MemOpStart,
532 MemOpIdx < MemOpEnd; ++MemOpIdx) {
534 if (
Op.isReg() &&
Op.getReg() ==
Reg)
540void X86DomainReassignment::buildClosure(Closure &
C,
Register Reg) {
542 RegDomain
Domain = NoDomain;
544 while (!Worklist.
empty()) {
548 if (!
C.insertEdge(CurReg))
550 EnclosedEdges[
Reg] =
C.getID();
552 MachineInstr *
DefMI =
MRI->getVRegDef(CurReg);
553 if (!encloseInstr(
C,
DefMI))
565 if (
OpIdx == MemOp) {
571 if (!
Op.isReg() || !
Op.isUse())
573 if (!visitRegister(
C,
Op.getReg(),
Domain, Worklist))
578 for (
auto &
UseMI :
MRI->use_nodbg_instructions(CurReg)) {
585 if (!encloseInstr(
C, &
UseMI))
588 for (
auto &DefOp :
UseMI.defs()) {
597 if (!visitRegister(
C, DefReg,
Domain, Worklist))
604void X86DomainReassignment::initConverters() {
605 Converters[{MaskDomain, TargetOpcode::PHI}] =
606 std::make_unique<InstrIgnore>(TargetOpcode::PHI);
608 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
609 std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
611 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
612 std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
614 Converters[{MaskDomain, TargetOpcode::COPY}] =
615 std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
618 auto createReplacerDstCOPY = [&](
unsigned From,
unsigned To) {
619 Converters[{MaskDomain, From}] =
620 std::make_unique<InstrReplacerDstCOPY>(From, To);
623#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC
640 auto createReplacer = [&](
unsigned From,
unsigned To) {
641 Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
647 createReplacer(X86::SHR16ri, X86::KSHIFTRWki);
648 createReplacer(X86::SHL16ri, X86::KSHIFTLWki);
649 createReplacer(X86::NOT16r, X86::KNOTWkk);
650 createReplacer(X86::OR16rr, X86::KORWkk);
651 createReplacer(X86::AND16rr, X86::KANDWkk);
652 createReplacer(X86::XOR16rr, X86::KXORWkk);
654 bool HasNDD = STI->hasNDD();
656 createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWki);
657 createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWki);
658 createReplacer(X86::NOT16r_ND, X86::KNOTWkk);
659 createReplacer(X86::OR16rr_ND, X86::KORWkk);
660 createReplacer(X86::AND16rr_ND, X86::KANDWkk);
661 createReplacer(X86::XOR16rr_ND, X86::KXORWkk);
674 createReplacer(X86::SHR32ri, X86::KSHIFTRDki);
675 createReplacer(X86::SHR64ri, X86::KSHIFTRQki);
677 createReplacer(X86::SHL32ri, X86::KSHIFTLDki);
678 createReplacer(X86::SHL64ri, X86::KSHIFTLQki);
680 createReplacer(X86::ADD32rr, X86::KADDDkk);
681 createReplacer(X86::ADD64rr, X86::KADDQkk);
683 createReplacer(X86::NOT32r, X86::KNOTDkk);
684 createReplacer(X86::NOT64r, X86::KNOTQkk);
686 createReplacer(X86::OR32rr, X86::KORDkk);
687 createReplacer(X86::OR64rr, X86::KORQkk);
689 createReplacer(X86::AND32rr, X86::KANDDkk);
690 createReplacer(X86::AND64rr, X86::KANDQkk);
692 createReplacer(X86::ANDN32rr, X86::KANDNDkk);
693 createReplacer(X86::ANDN64rr, X86::KANDNQkk);
695 createReplacer(X86::XOR32rr, X86::KXORDkk);
696 createReplacer(X86::XOR64rr, X86::KXORQkk);
699 createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDki);
700 createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDki);
701 createReplacer(X86::ADD32rr_ND, X86::KADDDkk);
702 createReplacer(X86::NOT32r_ND, X86::KNOTDkk);
703 createReplacer(X86::OR32rr_ND, X86::KORDkk);
704 createReplacer(X86::AND32rr_ND, X86::KANDDkk);
705 createReplacer(X86::XOR32rr_ND, X86::KXORDkk);
706 createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQki);
707 createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQki);
708 createReplacer(X86::ADD64rr_ND, X86::KADDQkk);
709 createReplacer(X86::NOT64r_ND, X86::KNOTQkk);
710 createReplacer(X86::OR64rr_ND, X86::KORQkk);
711 createReplacer(X86::AND64rr_ND, X86::KANDQkk);
712 createReplacer(X86::XOR64rr_ND, X86::KXORQkk);
722 createReplacer(X86::ADD8rr, X86::KADDBkk);
723 createReplacer(X86::ADD16rr, X86::KADDWkk);
725 createReplacer(X86::AND8rr, X86::KANDBkk);
731 createReplacer(X86::NOT8r, X86::KNOTBkk);
733 createReplacer(X86::OR8rr, X86::KORBkk);
735 createReplacer(X86::SHR8ri, X86::KSHIFTRBki);
736 createReplacer(X86::SHL8ri, X86::KSHIFTLBki);
743 createReplacer(X86::XOR8rr, X86::KXORBkk);
746 createReplacer(X86::ADD8rr_ND, X86::KADDBkk);
747 createReplacer(X86::ADD16rr_ND, X86::KADDWkk);
748 createReplacer(X86::AND8rr_ND, X86::KANDBkk);
749 createReplacer(X86::NOT8r_ND, X86::KNOTBkk);
750 createReplacer(X86::OR8rr_ND, X86::KORBkk);
751 createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBki);
752 createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBki);
753 createReplacer(X86::XOR8rr_ND, X86::KXORBkk);
756#undef GET_EGPR_IF_ENABLED
759bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
766 dbgs() <<
"***** Machine Function before Domain Reassignment *****\n");
779 assert(
MRI->isSSA() &&
"Expected MIR to be in SSA form");
785 EnclosedEdges.clear();
786 EnclosedInstrs.
clear();
788 std::vector<Closure> Closures;
791 unsigned ClosureID = 0;
792 for (
unsigned Idx = 0; Idx <
MRI->getNumVirtRegs(); ++Idx) {
796 if (
MRI->reg_nodbg_empty(
Reg))
800 if (!
MRI->getTargetRegisterInfo()->isGeneralPurposeRegisterClass(
805 if (EnclosedEdges.contains(
Reg))
809 Closure
C(ClosureID++, {MaskDomain});
810 buildClosure(
C,
Reg);
813 if (!
C.empty() &&
C.isLegal(MaskDomain))
814 Closures.push_back(std::move(
C));
817 for (Closure &
C : Closures) {
819 if (isReassignmentProfitable(
C, MaskDomain)) {
820 reassign(
C, MaskDomain);
821 ++NumClosuresConverted;
827 dbgs() <<
"***** Machine Function after Domain Reassignment *****\n");
834 "X86 Domain Reassignment Pass",
false,
false)
838 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 > >
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.