Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
X86DomainReassignment.cpp
Go to the documentation of this file.
1//===--- X86DomainReassignment.cpp - Selectively switch register classes---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass attempts to find instruction chains (closures) in one domain,
10// and convert them to equivalent instructions in a different domain,
11// if profitable.
12//
13//===----------------------------------------------------------------------===//
14
15#include "X86.h"
16#include "X86InstrInfo.h"
17#include "X86Subtarget.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/STLExtras.h"
21#include "llvm/ADT/Statistic.h"
26#include "llvm/Support/Debug.h"
28#include <bitset>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "x86-domain-reassignment"
33
34STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
35
37 "disable-x86-domain-reassignment", cl::Hidden,
38 cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
39
40namespace {
41enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
42
43static bool isMask(const TargetRegisterClass *RC,
44 const TargetRegisterInfo *TRI) {
45 return X86::VK16RegClass.hasSubClassEq(RC);
46}
47
48static RegDomain getDomain(const TargetRegisterClass *RC,
49 const TargetRegisterInfo *TRI) {
50 if (TRI->isGeneralPurposeRegisterClass(RC))
51 return GPRDomain;
52 if (isMask(RC, TRI))
53 return MaskDomain;
54 return OtherDomain;
55}
56
57/// Return a register class equivalent to \p SrcRC, in \p Domain.
58static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,
59 RegDomain Domain) {
60 assert(Domain == MaskDomain && "add domain");
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;
69 llvm_unreachable("add register class");
70 return nullptr;
71}
72
73/// Abstract Instruction Converter class.
74class InstrConverterBase {
75protected:
76 unsigned SrcOpcode;
77
78public:
79 InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
80
81 virtual ~InstrConverterBase() = default;
82
83 /// \returns true if \p MI is legal to convert.
84 virtual bool isLegal(const MachineInstr *MI,
85 const TargetInstrInfo *TII) const {
86 assert(MI->getOpcode() == SrcOpcode &&
87 "Wrong instruction passed to converter");
88 return true;
89 }
90
91 /// Applies conversion to \p MI.
92 ///
93 /// \returns true if \p MI is no longer need, and can be deleted.
94 virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
95 MachineRegisterInfo *MRI) const = 0;
96
97 /// \returns the cost increment incurred by converting \p MI.
98 virtual double getExtraCost(const MachineInstr *MI,
99 MachineRegisterInfo *MRI) const = 0;
100};
101
102/// An Instruction Converter which ignores the given instruction.
103/// For example, PHI instructions can be safely ignored since only the registers
104/// need to change.
105class InstrIgnore : public InstrConverterBase {
106public:
107 InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
108
109 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
110 MachineRegisterInfo *MRI) const override {
111 assert(isLegal(MI, TII) && "Cannot convert instruction");
112 return false;
113 }
114
115 double getExtraCost(const MachineInstr *MI,
116 MachineRegisterInfo *MRI) const override {
117 return 0;
118 }
119};
120
121/// An Instruction Converter which replaces an instruction with another.
122class InstrReplacer : public InstrConverterBase {
123public:
124 /// Opcode of the destination instruction.
125 unsigned DstOpcode;
126
127 InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)
128 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
129
130 bool isLegal(const MachineInstr *MI,
131 const TargetInstrInfo *TII) const override {
132 if (!InstrConverterBase::isLegal(MI, TII))
133 return false;
134 // It's illegal to replace an instruction that implicitly defines a register
135 // with an instruction that doesn't, unless that register dead.
136 for (const auto &MO : MI->implicit_operands())
137 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
138 !TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
139 return false;
140 return true;
141 }
142
143 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
144 MachineRegisterInfo *MRI) const override {
145 assert(isLegal(MI, TII) && "Cannot convert instruction");
146 MachineInstrBuilder Bld =
147 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));
148 // Transfer explicit operands from original instruction. Implicit operands
149 // are handled by BuildMI.
150 for (auto &Op : MI->explicit_operands())
151 Bld.add(Op);
152 return true;
153 }
154
155 double getExtraCost(const MachineInstr *MI,
156 MachineRegisterInfo *MRI) const override {
157 // Assuming instructions have the same cost.
158 return 0;
159 }
160};
161
162/// An Instruction Converter which replaces an instruction with another, and
163/// adds a COPY from the new instruction's destination to the old one's.
164class InstrReplacerDstCOPY : public InstrConverterBase {
165public:
166 unsigned DstOpcode;
167
168 InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)
169 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
170
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();
175 const DebugLoc &DL = MI->getDebugLoc();
176
177 Register Reg = MRI->createVirtualRegister(
178 TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo()));
179 MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
180 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
181 Bld.add(MO);
182
183 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
184 .add(MI->getOperand(0))
185 .addReg(Reg);
186
187 return true;
188 }
189
190 double getExtraCost(const MachineInstr *MI,
191 MachineRegisterInfo *MRI) const override {
192 // Assuming instructions have the same cost, and that COPY is in the same
193 // domain so it will be eliminated.
194 return 0;
195 }
196};
197
198/// An Instruction Converter for replacing COPY instructions.
199class InstrCOPYReplacer : public InstrReplacer {
200public:
201 RegDomain DstDomain;
202
203 InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
204 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
205
206 bool isLegal(const MachineInstr *MI,
207 const TargetInstrInfo *TII) const override {
208 if (!InstrConverterBase::isLegal(MI, TII))
209 return false;
210
211 // Don't allow copies to/flow GR8/GR16 physical registers.
212 // FIXME: Is there some better way to support this?
213 Register DstReg = MI->getOperand(0).getReg();
214 if (DstReg.isPhysical() && (X86::GR8RegClass.contains(DstReg) ||
215 X86::GR16RegClass.contains(DstReg)))
216 return false;
217 Register SrcReg = MI->getOperand(1).getReg();
218 if (SrcReg.isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||
219 X86::GR16RegClass.contains(SrcReg)))
220 return false;
221
222 return true;
223 }
224
225 double getExtraCost(const MachineInstr *MI,
226 MachineRegisterInfo *MRI) const override {
227 assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
228
229 for (const auto &MO : MI->operands()) {
230 // Physical registers will not be converted. Assume that converting the
231 // COPY to the destination domain will eventually result in a actual
232 // instruction.
233 if (MO.getReg().isPhysical())
234 return 1;
235
236 RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
237 MRI->getTargetRegisterInfo());
238 // Converting a cross domain COPY to a same domain COPY should eliminate
239 // an insturction
240 if (OpDomain == DstDomain)
241 return -1;
242 }
243 return 0;
244 }
245};
246
247/// An Instruction Converter which replaces an instruction with a COPY.
248class InstrReplaceWithCopy : public InstrConverterBase {
249public:
250 // Source instruction operand Index, to be used as the COPY source.
251 unsigned SrcOpIdx;
252
253 InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
254 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
255
256 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
257 MachineRegisterInfo *MRI) const override {
258 assert(isLegal(MI, TII) && "Cannot convert instruction");
259 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
260 TII->get(TargetOpcode::COPY))
261 .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
262 return true;
263 }
264
265 double getExtraCost(const MachineInstr *MI,
266 MachineRegisterInfo *MRI) const override {
267 return 0;
268 }
269};
270
271// Key type to be used by the Instruction Converters map.
272// A converter is identified by <destination domain, source opcode>
273typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
274
276 InstrConverterBaseMap;
277
278/// A closure is a set of virtual register representing all of the edges in
279/// the closure, as well as all of the instructions connected by those edges.
280///
281/// A closure may encompass virtual registers in the same register bank that
282/// have different widths. For example, it may contain 32-bit GPRs as well as
283/// 64-bit GPRs.
284///
285/// A closure that computes an address (i.e. defines a virtual register that is
286/// used in a memory operand) excludes the instructions that contain memory
287/// operands using the address. Such an instruction will be included in a
288/// different closure that manipulates the loaded or stored value.
289class Closure {
290private:
291 /// Virtual registers in the closure.
292 DenseSet<Register> Edges;
293
294 /// Instructions in the closure.
295 SmallVector<MachineInstr *, 8> Instrs;
296
297 /// Domains which this closure can legally be reassigned to.
298 std::bitset<NumDomains> LegalDstDomains;
299
300 /// An ID to uniquely identify this closure, even when it gets
301 /// moved around
302 unsigned ID;
303
304public:
305 Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
306 for (RegDomain D : LegalDstDomainList)
307 LegalDstDomains.set(D);
308 }
309
310 /// Mark this closure as illegal for reassignment to all domains.
311 void setAllIllegal() { LegalDstDomains.reset(); }
312
313 /// \returns true if this closure has domains which are legal to reassign to.
314 bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
315
316 /// \returns true if is legal to reassign this closure to domain \p RD.
317 bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
318
319 /// Mark this closure as illegal for reassignment to domain \p RD.
320 void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
321
322 bool empty() const { return Edges.empty(); }
323
324 bool insertEdge(Register Reg) { return Edges.insert(Reg).second; }
325
326 using const_edge_iterator = DenseSet<Register>::const_iterator;
328 return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());
329 }
330
331 void addInstruction(MachineInstr *I) {
332 Instrs.push_back(I);
333 }
334
336 return Instrs;
337 }
338
339 LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {
340 dbgs() << "Registers: ";
341 bool First = true;
342 for (Register Reg : Edges) {
343 if (!First)
344 dbgs() << ", ";
345 First = false;
346 dbgs() << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);
347 }
348 dbgs() << "\n" << "Instructions:";
349 for (MachineInstr *MI : Instrs) {
350 dbgs() << "\n ";
351 MI->print(dbgs());
352 }
353 dbgs() << "\n";
354 }
355
356 unsigned getID() const {
357 return ID;
358 }
359
360};
361
362class X86DomainReassignment : public MachineFunctionPass {
363 const X86Subtarget *STI = nullptr;
364 MachineRegisterInfo *MRI = nullptr;
365 const X86InstrInfo *TII = nullptr;
366
367 /// All edges that are included in some closure
368 DenseMap<Register, unsigned> EnclosedEdges;
369
370 /// All instructions that are included in some closure.
371 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
372
373public:
374 static char ID;
375
376 X86DomainReassignment() : MachineFunctionPass(ID) { }
377
378 bool runOnMachineFunction(MachineFunction &MF) override;
379
380 void getAnalysisUsage(AnalysisUsage &AU) const override {
381 AU.setPreservesCFG();
383 }
384
385 StringRef getPassName() const override {
386 return "X86 Domain Reassignment Pass";
387 }
388
389private:
390 /// A map of available Instruction Converters.
391 InstrConverterBaseMap Converters;
392
393 /// Initialize Converters map.
394 void initConverters();
395
396 /// Starting from \Reg, expand the closure as much as possible.
397 void buildClosure(Closure &, Register Reg);
398
399 /// Enqueue \p Reg to be considered for addition to the closure.
400 /// Return false if the closure becomes invalid.
401 bool visitRegister(Closure &, Register Reg, RegDomain &Domain,
402 SmallVectorImpl<Register> &Worklist);
403
404 /// Reassign the closure to \p Domain.
405 void reassign(const Closure &C, RegDomain Domain) const;
406
407 /// Add \p MI to the closure.
408 /// Return false if the closure becomes invalid.
409 bool encloseInstr(Closure &C, MachineInstr *MI);
410
411 /// /returns true if it is profitable to reassign the closure to \p Domain.
412 bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
413
414 /// Calculate the total cost of reassigning the closure to \p Domain.
415 double calculateCost(const Closure &C, RegDomain Domain) const;
416};
417
418char X86DomainReassignment::ID = 0;
419
420} // End anonymous namespace.
421
422bool X86DomainReassignment::visitRegister(Closure &C, Register Reg,
423 RegDomain &Domain,
424 SmallVectorImpl<Register> &Worklist) {
425 if (!Reg.isVirtual())
426 return true;
427
428 auto I = EnclosedEdges.find(Reg);
429 if (I != EnclosedEdges.end()) {
430 if (I->second != C.getID()) {
431 C.setAllIllegal();
432 return false;
433 }
434 return true;
435 }
436
437 if (!MRI->hasOneDef(Reg))
438 return true;
439
440 RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
441 // First edge in closure sets the domain.
442 if (Domain == NoDomain)
443 Domain = RD;
444
445 if (Domain != RD)
446 return true;
447
448 Worklist.push_back(Reg);
449 return true;
450}
451
452bool X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
453 auto [I, Inserted] = EnclosedInstrs.try_emplace(MI, C.getID());
454 if (!Inserted) {
455 if (I->second != C.getID()) {
456 // Instruction already belongs to another closure, avoid conflicts between
457 // closure and mark this closure as illegal.
458 C.setAllIllegal();
459 return false;
460 }
461 return true;
462 }
463
464 C.addInstruction(MI);
465
466 // Mark closure as illegal for reassignment to domains, if there is no
467 // converter for the instruction or if the converter cannot convert the
468 // instruction.
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);
474 }
475 }
476 return C.hasLegalDstDomain();
477}
478
479double X86DomainReassignment::calculateCost(const Closure &C,
480 RegDomain DstDomain) const {
481 assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
482
483 double Cost = 0.0;
484 for (auto *MI : C.instructions())
485 Cost += Converters.find({DstDomain, MI->getOpcode()})
486 ->second->getExtraCost(MI, MRI);
487 return Cost;
488}
489
490bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
491 RegDomain Domain) const {
492 return calculateCost(C, Domain) < 0.0;
493}
494
495void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
496 assert(C.isLegal(Domain) && "Cannot convert illegal closure");
497
498 // Iterate all instructions in the closure, convert each one using the
499 // appropriate converter.
500 SmallVector<MachineInstr *, 8> ToErase;
501 for (auto *MI : C.instructions())
502 if (Converters.find({Domain, MI->getOpcode()})
503 ->second->convertInstr(MI, TII, MRI))
504 ToErase.push_back(MI);
505
506 // Iterate all registers in the closure, replace them with registers in the
507 // destination domain.
508 for (Register Reg : C.edges()) {
509 MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
510 for (auto &MO : MRI->use_operands(Reg)) {
511 if (MO.isReg())
512 // Remove all subregister references as they are not valid in the
513 // destination domain.
514 MO.setSubReg(0);
515 }
516 }
517
518 for (auto *MI : ToErase)
519 MI->eraseFromParent();
520}
521
522/// \returns true when \p Reg is used as part of an address calculation in \p
523/// MI.
525 const TargetInstrInfo *TII) {
526 if (!MI.mayLoadOrStore())
527 return false;
528
529 const MCInstrDesc &Desc = TII->get(MI.getOpcode());
530 int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
531 if (MemOpStart == -1)
532 return false;
533
534 MemOpStart += X86II::getOperandBias(Desc);
535 for (unsigned MemOpIdx = MemOpStart,
536 MemOpEnd = MemOpStart + X86::AddrNumOperands;
537 MemOpIdx < MemOpEnd; ++MemOpIdx) {
538 const MachineOperand &Op = MI.getOperand(MemOpIdx);
539 if (Op.isReg() && Op.getReg() == Reg)
540 return true;
541 }
542 return false;
543}
544
545void X86DomainReassignment::buildClosure(Closure &C, Register Reg) {
547 RegDomain Domain = NoDomain;
548 visitRegister(C, Reg, Domain, Worklist);
549 while (!Worklist.empty()) {
550 Register CurReg = Worklist.pop_back_val();
551
552 // Register already in this closure.
553 if (!C.insertEdge(CurReg))
554 continue;
555 EnclosedEdges[Reg] = C.getID();
556
557 MachineInstr *DefMI = MRI->getVRegDef(CurReg);
558 if (!encloseInstr(C, DefMI))
559 return;
560
561 // Add register used by the defining MI to the worklist.
562 // Do not add registers which are used in address calculation, they will be
563 // added to a different closure.
564 int OpEnd = DefMI->getNumOperands();
565 const MCInstrDesc &Desc = DefMI->getDesc();
566 int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
567 if (MemOp != -1)
568 MemOp += X86II::getOperandBias(Desc);
569 for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
570 if (OpIdx == MemOp) {
571 // skip address calculation.
573 continue;
574 }
575 auto &Op = DefMI->getOperand(OpIdx);
576 if (!Op.isReg() || !Op.isUse())
577 continue;
578 if (!visitRegister(C, Op.getReg(), Domain, Worklist))
579 return;
580 }
581
582 // Expand closure through register uses.
583 for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
584 // We would like to avoid converting closures which calculare addresses,
585 // as this should remain in GPRs.
586 if (usedAsAddr(UseMI, CurReg, TII)) {
587 C.setAllIllegal();
588 return;
589 }
590 if (!encloseInstr(C, &UseMI))
591 return;
592
593 for (auto &DefOp : UseMI.defs()) {
594 if (!DefOp.isReg())
595 continue;
596
597 Register DefReg = DefOp.getReg();
598 if (!DefReg.isVirtual()) {
599 C.setAllIllegal();
600 return;
601 }
602 if (!visitRegister(C, DefReg, Domain, Worklist))
603 return;
604 }
605 }
606 }
607}
608
609void X86DomainReassignment::initConverters() {
610 Converters[{MaskDomain, TargetOpcode::PHI}] =
611 std::make_unique<InstrIgnore>(TargetOpcode::PHI);
612
613 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
614 std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
615
616 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
617 std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
618
619 Converters[{MaskDomain, TargetOpcode::COPY}] =
620 std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
621 TargetOpcode::COPY);
622
623 auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
624 Converters[{MaskDomain, From}] =
625 std::make_unique<InstrReplacerDstCOPY>(From, To);
626 };
627
628#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC
629 createReplacerDstCOPY(X86::MOVZX32rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
630 createReplacerDstCOPY(X86::MOVZX64rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
631
632 createReplacerDstCOPY(X86::MOVZX32rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
633 createReplacerDstCOPY(X86::MOVZX64rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
634
635 if (STI->hasDQI()) {
636 createReplacerDstCOPY(X86::MOVZX16rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
637 createReplacerDstCOPY(X86::MOVZX32rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
638 createReplacerDstCOPY(X86::MOVZX64rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
639
640 createReplacerDstCOPY(X86::MOVZX16rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
641 createReplacerDstCOPY(X86::MOVZX32rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
642 createReplacerDstCOPY(X86::MOVZX64rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
643 }
644
645 auto createReplacer = [&](unsigned From, unsigned To) {
646 Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
647 };
648
649 createReplacer(X86::MOV16rm, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
650 createReplacer(X86::MOV16mr, GET_EGPR_IF_ENABLED(X86::KMOVWmk));
651 createReplacer(X86::MOV16rr, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
652 createReplacer(X86::SHR16ri, X86::KSHIFTRWki);
653 createReplacer(X86::SHL16ri, X86::KSHIFTLWki);
654 createReplacer(X86::NOT16r, X86::KNOTWkk);
655 createReplacer(X86::OR16rr, X86::KORWkk);
656 createReplacer(X86::AND16rr, X86::KANDWkk);
657 createReplacer(X86::XOR16rr, X86::KXORWkk);
658
659 bool HasNDD = STI->hasNDD();
660 if (HasNDD) {
661 createReplacer(X86::SHR16ri_ND, X86::KSHIFTRWki);
662 createReplacer(X86::SHL16ri_ND, X86::KSHIFTLWki);
663 createReplacer(X86::NOT16r_ND, X86::KNOTWkk);
664 createReplacer(X86::OR16rr_ND, X86::KORWkk);
665 createReplacer(X86::AND16rr_ND, X86::KANDWkk);
666 createReplacer(X86::XOR16rr_ND, X86::KXORWkk);
667 }
668
669 if (STI->hasBWI()) {
670 createReplacer(X86::MOV32rm, GET_EGPR_IF_ENABLED(X86::KMOVDkm));
671 createReplacer(X86::MOV64rm, GET_EGPR_IF_ENABLED(X86::KMOVQkm));
672
673 createReplacer(X86::MOV32mr, GET_EGPR_IF_ENABLED(X86::KMOVDmk));
674 createReplacer(X86::MOV64mr, GET_EGPR_IF_ENABLED(X86::KMOVQmk));
675
676 createReplacer(X86::MOV32rr, GET_EGPR_IF_ENABLED(X86::KMOVDkk));
677 createReplacer(X86::MOV64rr, GET_EGPR_IF_ENABLED(X86::KMOVQkk));
678
679 createReplacer(X86::SHR32ri, X86::KSHIFTRDki);
680 createReplacer(X86::SHR64ri, X86::KSHIFTRQki);
681
682 createReplacer(X86::SHL32ri, X86::KSHIFTLDki);
683 createReplacer(X86::SHL64ri, X86::KSHIFTLQki);
684
685 createReplacer(X86::ADD32rr, X86::KADDDkk);
686 createReplacer(X86::ADD64rr, X86::KADDQkk);
687
688 createReplacer(X86::NOT32r, X86::KNOTDkk);
689 createReplacer(X86::NOT64r, X86::KNOTQkk);
690
691 createReplacer(X86::OR32rr, X86::KORDkk);
692 createReplacer(X86::OR64rr, X86::KORQkk);
693
694 createReplacer(X86::AND32rr, X86::KANDDkk);
695 createReplacer(X86::AND64rr, X86::KANDQkk);
696
697 createReplacer(X86::ANDN32rr, X86::KANDNDkk);
698 createReplacer(X86::ANDN64rr, X86::KANDNQkk);
699
700 createReplacer(X86::XOR32rr, X86::KXORDkk);
701 createReplacer(X86::XOR64rr, X86::KXORQkk);
702
703 if (HasNDD) {
704 createReplacer(X86::SHR32ri_ND, X86::KSHIFTRDki);
705 createReplacer(X86::SHL32ri_ND, X86::KSHIFTLDki);
706 createReplacer(X86::ADD32rr_ND, X86::KADDDkk);
707 createReplacer(X86::NOT32r_ND, X86::KNOTDkk);
708 createReplacer(X86::OR32rr_ND, X86::KORDkk);
709 createReplacer(X86::AND32rr_ND, X86::KANDDkk);
710 createReplacer(X86::XOR32rr_ND, X86::KXORDkk);
711 createReplacer(X86::SHR64ri_ND, X86::KSHIFTRQki);
712 createReplacer(X86::SHL64ri_ND, X86::KSHIFTLQki);
713 createReplacer(X86::ADD64rr_ND, X86::KADDQkk);
714 createReplacer(X86::NOT64r_ND, X86::KNOTQkk);
715 createReplacer(X86::OR64rr_ND, X86::KORQkk);
716 createReplacer(X86::AND64rr_ND, X86::KANDQkk);
717 createReplacer(X86::XOR64rr_ND, X86::KXORQkk);
718 }
719
720 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
721 // to prove only Z flag is used.
722 // createReplacer(X86::TEST32rr, X86::KTESTDkk);
723 // createReplacer(X86::TEST64rr, X86::KTESTQkk);
724 }
725
726 if (STI->hasDQI()) {
727 createReplacer(X86::ADD8rr, X86::KADDBkk);
728 createReplacer(X86::ADD16rr, X86::KADDWkk);
729
730 createReplacer(X86::AND8rr, X86::KANDBkk);
731
732 createReplacer(X86::MOV8rm, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
733 createReplacer(X86::MOV8mr, GET_EGPR_IF_ENABLED(X86::KMOVBmk));
734 createReplacer(X86::MOV8rr, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
735
736 createReplacer(X86::NOT8r, X86::KNOTBkk);
737
738 createReplacer(X86::OR8rr, X86::KORBkk);
739
740 createReplacer(X86::SHR8ri, X86::KSHIFTRBki);
741 createReplacer(X86::SHL8ri, X86::KSHIFTLBki);
742
743 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
744 // to prove only Z flag is used.
745 // createReplacer(X86::TEST8rr, X86::KTESTBkk);
746 // createReplacer(X86::TEST16rr, X86::KTESTWkk);
747
748 createReplacer(X86::XOR8rr, X86::KXORBkk);
749
750 if (HasNDD) {
751 createReplacer(X86::ADD8rr_ND, X86::KADDBkk);
752 createReplacer(X86::ADD16rr_ND, X86::KADDWkk);
753 createReplacer(X86::AND8rr_ND, X86::KANDBkk);
754 createReplacer(X86::NOT8r_ND, X86::KNOTBkk);
755 createReplacer(X86::OR8rr_ND, X86::KORBkk);
756 createReplacer(X86::SHR8ri_ND, X86::KSHIFTRBki);
757 createReplacer(X86::SHL8ri_ND, X86::KSHIFTLBki);
758 createReplacer(X86::XOR8rr_ND, X86::KXORBkk);
759 }
760 }
761#undef GET_EGPR_IF_ENABLED
762}
763
764bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
765 if (skipFunction(MF.getFunction()))
766 return false;
768 return false;
769
771 dbgs() << "***** Machine Function before Domain Reassignment *****\n");
772 LLVM_DEBUG(MF.print(dbgs()));
773
774 STI = &MF.getSubtarget<X86Subtarget>();
775 // GPR->K is the only transformation currently supported, bail out early if no
776 // AVX512.
777 // TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and
778 // VK64 for GR32/GR64, but those aren't legal classes on KNL. If the register
779 // coalescer doesn't clean it up and we generate a spill we will crash.
780 if (!STI->hasAVX512() || !STI->hasBWI())
781 return false;
782
783 MRI = &MF.getRegInfo();
784 assert(MRI->isSSA() && "Expected MIR to be in SSA form");
785
786 TII = STI->getInstrInfo();
787 initConverters();
788 bool Changed = false;
789
790 EnclosedEdges.clear();
791 EnclosedInstrs.clear();
792
793 std::vector<Closure> Closures;
794
795 // Go over all virtual registers and calculate a closure.
796 unsigned ClosureID = 0;
797 for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
798 Register Reg = Register::index2VirtReg(Idx);
799
800 // Skip unused VRegs.
801 if (MRI->reg_nodbg_empty(Reg))
802 continue;
803
804 // GPR only current source domain supported.
805 if (!MRI->getTargetRegisterInfo()->isGeneralPurposeRegisterClass(
806 MRI->getRegClass(Reg)))
807 continue;
808
809 // Register already in closure.
810 if (EnclosedEdges.contains(Reg))
811 continue;
812
813 // Calculate closure starting with Reg.
814 Closure C(ClosureID++, {MaskDomain});
815 buildClosure(C, Reg);
816
817 // Collect all closures that can potentially be converted.
818 if (!C.empty() && C.isLegal(MaskDomain))
819 Closures.push_back(std::move(C));
820 }
821
822 for (Closure &C : Closures) {
823 LLVM_DEBUG(C.dump(MRI));
824 if (isReassignmentProfitable(C, MaskDomain)) {
825 reassign(C, MaskDomain);
826 ++NumClosuresConverted;
827 Changed = true;
828 }
829 }
830
832 dbgs() << "***** Machine Function after Domain Reassignment *****\n");
833 LLVM_DEBUG(MF.print(dbgs()));
834
835 return Changed;
836}
837
838INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
839 "X86 Domain Reassignment Pass", false, false)
840
841/// Returns an instance of the Domain Reassignment pass.
843 return new X86DomainReassignment();
844}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
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.
Definition Compiler.h:638
static Domain getDomain(const ConstantRange &CR)
This file defines the DenseMap class.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
MachineInstr unsigned OpIdx
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains some templates that are useful if you are working with the STL at all.
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)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
#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:
Definition Pass.cpp:270
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:229
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
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.
Definition Pass.cpp:140
Wrapper class representing virtual and physical registers.
Definition Register.h:19
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:74
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:78
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
bool hasAVX512() const
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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.
@ AddrNumOperands
Definition X86BaseInfo.h:36
initializer< Ty > init(const Ty &Val)
bool empty() const
Definition BasicBlock.h:101
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.
Definition STLExtras.h:318
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.
InstructionCost Cost
FunctionPass * createX86DomainReassignmentPass()
Return a Machine IR pass that reassigns instruction chains from one domain to another,...
Op::Description Desc
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
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.
Definition ModRef.h:71
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.