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