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"
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");
147 MachineInstrBuilder Bld =
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 =
179 MRI->createVirtualRegister(TII->getRegClass(TII->get(DstOpcode), 0));
180 MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
181 for (const MachineOperand &MO : llvm::drop_begin(MI->operands()))
182 Bld.add(MO);
183
184 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
185 .add(MI->getOperand(0))
186 .addReg(Reg);
187
188 return true;
189 }
190
191 double getExtraCost(const MachineInstr *MI,
192 MachineRegisterInfo *MRI) const override {
193 // Assuming instructions have the same cost, and that COPY is in the same
194 // domain so it will be eliminated.
195 return 0;
196 }
197};
198
199/// An Instruction Converter for replacing COPY instructions.
200class InstrCOPYReplacer : public InstrReplacer {
201public:
202 RegDomain DstDomain;
203
204 InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
205 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
206
207 bool isLegal(const MachineInstr *MI,
208 const TargetInstrInfo *TII) const override {
209 if (!InstrConverterBase::isLegal(MI, TII))
210 return false;
211
212 // Don't allow copies to/flow GR8/GR16 physical registers.
213 // FIXME: Is there some better way to support this?
214 Register DstReg = MI->getOperand(0).getReg();
215 if (DstReg.isPhysical() && (X86::GR8RegClass.contains(DstReg) ||
216 X86::GR16RegClass.contains(DstReg)))
217 return false;
218 Register SrcReg = MI->getOperand(1).getReg();
219 if (SrcReg.isPhysical() && (X86::GR8RegClass.contains(SrcReg) ||
220 X86::GR16RegClass.contains(SrcReg)))
221 return false;
222
223 return true;
224 }
225
226 double getExtraCost(const MachineInstr *MI,
227 MachineRegisterInfo *MRI) const override {
228 assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
229
230 for (const auto &MO : MI->operands()) {
231 // Physical registers will not be converted. Assume that converting the
232 // COPY to the destination domain will eventually result in a actual
233 // instruction.
234 if (MO.getReg().isPhysical())
235 return 1;
236
237 RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
238 MRI->getTargetRegisterInfo());
239 // Converting a cross domain COPY to a same domain COPY should eliminate
240 // an insturction
241 if (OpDomain == DstDomain)
242 return -1;
243 }
244 return 0;
245 }
246};
247
248/// An Instruction Converter which replaces an instruction with a COPY.
249class InstrReplaceWithCopy : public InstrConverterBase {
250public:
251 // Source instruction operand Index, to be used as the COPY source.
252 unsigned SrcOpIdx;
253
254 InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
255 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
256
257 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
258 MachineRegisterInfo *MRI) const override {
259 assert(isLegal(MI, TII) && "Cannot convert instruction");
260 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
261 TII->get(TargetOpcode::COPY))
262 .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
263 return true;
264 }
265
266 double getExtraCost(const MachineInstr *MI,
267 MachineRegisterInfo *MRI) const override {
268 return 0;
269 }
270};
271
272// Key type to be used by the Instruction Converters map.
273// A converter is identified by <destination domain, source opcode>
274typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
275
277 InstrConverterBaseMap;
278
279/// A closure is a set of virtual register representing all of the edges in
280/// the closure, as well as all of the instructions connected by those edges.
281///
282/// A closure may encompass virtual registers in the same register bank that
283/// have different widths. For example, it may contain 32-bit GPRs as well as
284/// 64-bit GPRs.
285///
286/// A closure that computes an address (i.e. defines a virtual register that is
287/// used in a memory operand) excludes the instructions that contain memory
288/// operands using the address. Such an instruction will be included in a
289/// different closure that manipulates the loaded or stored value.
290class Closure {
291private:
292 /// Virtual registers in the closure.
293 DenseSet<Register> Edges;
294
295 /// Instructions in the closure.
296 SmallVector<MachineInstr *, 8> Instrs;
297
298 /// Domains which this closure can legally be reassigned to.
299 std::bitset<NumDomains> LegalDstDomains;
300
301 /// An ID to uniquely identify this closure, even when it gets
302 /// moved around
303 unsigned ID;
304
305public:
306 Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
307 for (RegDomain D : LegalDstDomainList)
308 LegalDstDomains.set(D);
309 }
310
311 /// Mark this closure as illegal for reassignment to all domains.
312 void setAllIllegal() { LegalDstDomains.reset(); }
313
314 /// \returns true if this closure has domains which are legal to reassign to.
315 bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
316
317 /// \returns true if is legal to reassign this closure to domain \p RD.
318 bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
319
320 /// Mark this closure as illegal for reassignment to domain \p RD.
321 void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
322
323 bool empty() const { return Edges.empty(); }
324
325 bool insertEdge(Register Reg) { return Edges.insert(Reg).second; }
326
327 using const_edge_iterator = DenseSet<Register>::const_iterator;
328 iterator_range<const_edge_iterator> edges() const { return Edges; }
329
330 void addInstruction(MachineInstr *I) {
331 Instrs.push_back(I);
332 }
333
335 return Instrs;
336 }
337
338 LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {
339 dbgs() << "Registers: ";
340 ListSeparator LS;
341 for (Register Reg : Edges)
342 dbgs() << LS << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);
343 dbgs() << "\n" << "Instructions:";
344 for (MachineInstr *MI : Instrs) {
345 dbgs() << "\n ";
346 MI->print(dbgs());
347 }
348 dbgs() << "\n";
349 }
350
351 unsigned getID() const {
352 return ID;
353 }
354
355};
356
357class X86DomainReassignment : public MachineFunctionPass {
358 const X86Subtarget *STI = nullptr;
359 MachineRegisterInfo *MRI = nullptr;
360 const X86InstrInfo *TII = nullptr;
361
362 /// All edges that are included in some closure
363 DenseMap<Register, unsigned> EnclosedEdges;
364
365 /// All instructions that are included in some closure.
366 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
367
368public:
369 static char ID;
370
371 X86DomainReassignment() : MachineFunctionPass(ID) { }
372
373 bool runOnMachineFunction(MachineFunction &MF) override;
374
375 void getAnalysisUsage(AnalysisUsage &AU) const override {
376 AU.setPreservesCFG();
378 }
379
380 StringRef getPassName() const override {
381 return "X86 Domain Reassignment Pass";
382 }
383
384private:
385 /// A map of available Instruction Converters.
386 InstrConverterBaseMap Converters;
387
388 /// Initialize Converters map.
389 void initConverters();
390
391 /// Starting from \Reg, expand the closure as much as possible.
392 void buildClosure(Closure &, Register Reg);
393
394 /// Enqueue \p Reg to be considered for addition to the closure.
395 /// Return false if the closure becomes invalid.
396 bool visitRegister(Closure &, Register Reg, RegDomain &Domain,
397 SmallVectorImpl<Register> &Worklist);
398
399 /// Reassign the closure to \p Domain.
400 void reassign(const Closure &C, RegDomain Domain) const;
401
402 /// Add \p MI to the closure.
403 /// Return false if the closure becomes invalid.
404 bool encloseInstr(Closure &C, MachineInstr *MI);
405
406 /// /returns true if it is profitable to reassign the closure to \p Domain.
407 bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
408
409 /// Calculate the total cost of reassigning the closure to \p Domain.
410 double calculateCost(const Closure &C, RegDomain Domain) const;
411};
412
413char X86DomainReassignment::ID = 0;
414
415} // End anonymous namespace.
416
417bool X86DomainReassignment::visitRegister(Closure &C, Register Reg,
418 RegDomain &Domain,
419 SmallVectorImpl<Register> &Worklist) {
420 if (!Reg.isVirtual())
421 return true;
422
423 auto I = EnclosedEdges.find(Reg);
424 if (I != EnclosedEdges.end()) {
425 if (I->second != C.getID()) {
426 C.setAllIllegal();
427 return false;
428 }
429 return true;
430 }
431
432 if (!MRI->hasOneDef(Reg))
433 return true;
434
435 RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
436 // First edge in closure sets the domain.
437 if (Domain == NoDomain)
438 Domain = RD;
439
440 if (Domain != RD)
441 return true;
442
443 Worklist.push_back(Reg);
444 return true;
445}
446
447bool X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
448 auto [I, Inserted] = EnclosedInstrs.try_emplace(MI, C.getID());
449 if (!Inserted) {
450 if (I->second != C.getID()) {
451 // Instruction already belongs to another closure, avoid conflicts between
452 // closure and mark this closure as illegal.
453 C.setAllIllegal();
454 return false;
455 }
456 return true;
457 }
458
459 C.addInstruction(MI);
460
461 // Mark closure as illegal for reassignment to domains, if there is no
462 // converter for the instruction or if the converter cannot convert the
463 // instruction.
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);
469 }
470 }
471 return C.hasLegalDstDomain();
472}
473
474double X86DomainReassignment::calculateCost(const Closure &C,
475 RegDomain DstDomain) const {
476 assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
477
478 double Cost = 0.0;
479 for (auto *MI : C.instructions())
480 Cost += Converters.find({DstDomain, MI->getOpcode()})
481 ->second->getExtraCost(MI, MRI);
482 return Cost;
483}
484
485bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
486 RegDomain Domain) const {
487 return calculateCost(C, Domain) < 0.0;
488}
489
490void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
491 assert(C.isLegal(Domain) && "Cannot convert illegal closure");
492
493 // Iterate all instructions in the closure, convert each one using the
494 // appropriate converter.
495 SmallVector<MachineInstr *, 8> ToErase;
496 for (auto *MI : C.instructions())
497 if (Converters.find({Domain, MI->getOpcode()})
498 ->second->convertInstr(MI, TII, MRI))
499 ToErase.push_back(MI);
500
501 // Iterate all registers in the closure, replace them with registers in the
502 // destination domain.
503 for (Register Reg : C.edges()) {
504 MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
505 for (auto &MO : MRI->use_operands(Reg)) {
506 if (MO.isReg())
507 // Remove all subregister references as they are not valid in the
508 // destination domain.
509 MO.setSubReg(0);
510 }
511 }
512
513 for (auto *MI : ToErase)
514 MI->eraseFromParent();
515}
516
517/// \returns true when \p Reg is used as part of an address calculation in \p
518/// MI.
520 const TargetInstrInfo *TII) {
521 if (!MI.mayLoadOrStore())
522 return false;
523
524 const MCInstrDesc &Desc = TII->get(MI.getOpcode());
525 int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
526 if (MemOpStart == -1)
527 return false;
528
529 MemOpStart += X86II::getOperandBias(Desc);
530 for (unsigned MemOpIdx = MemOpStart,
531 MemOpEnd = MemOpStart + X86::AddrNumOperands;
532 MemOpIdx < MemOpEnd; ++MemOpIdx) {
533 const MachineOperand &Op = MI.getOperand(MemOpIdx);
534 if (Op.isReg() && Op.getReg() == Reg)
535 return true;
536 }
537 return false;
538}
539
540void X86DomainReassignment::buildClosure(Closure &C, Register Reg) {
542 RegDomain Domain = NoDomain;
543 visitRegister(C, Reg, Domain, Worklist);
544 while (!Worklist.empty()) {
545 Register CurReg = Worklist.pop_back_val();
546
547 // Register already in this closure.
548 if (!C.insertEdge(CurReg))
549 continue;
550 EnclosedEdges[Reg] = C.getID();
551
552 MachineInstr *DefMI = MRI->getVRegDef(CurReg);
553 if (!encloseInstr(C, DefMI))
554 return;
555
556 // Add register used by the defining MI to the worklist.
557 // Do not add registers which are used in address calculation, they will be
558 // added to a different closure.
559 int OpEnd = DefMI->getNumOperands();
560 const MCInstrDesc &Desc = DefMI->getDesc();
561 int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
562 if (MemOp != -1)
563 MemOp += X86II::getOperandBias(Desc);
564 for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
565 if (OpIdx == MemOp) {
566 // skip address calculation.
568 continue;
569 }
570 auto &Op = DefMI->getOperand(OpIdx);
571 if (!Op.isReg() || !Op.isUse())
572 continue;
573 if (!visitRegister(C, Op.getReg(), Domain, Worklist))
574 return;
575 }
576
577 // Expand closure through register uses.
578 for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
579 // We would like to avoid converting closures which calculare addresses,
580 // as this should remain in GPRs.
581 if (usedAsAddr(UseMI, CurReg, TII)) {
582 C.setAllIllegal();
583 return;
584 }
585 if (!encloseInstr(C, &UseMI))
586 return;
587
588 for (auto &DefOp : UseMI.defs()) {
589 if (!DefOp.isReg())
590 continue;
591
592 Register DefReg = DefOp.getReg();
593 if (!DefReg.isVirtual()) {
594 C.setAllIllegal();
595 return;
596 }
597 if (!visitRegister(C, DefReg, Domain, Worklist))
598 return;
599 }
600 }
601 }
602}
603
604void X86DomainReassignment::initConverters() {
605 Converters[{MaskDomain, TargetOpcode::PHI}] =
606 std::make_unique<InstrIgnore>(TargetOpcode::PHI);
607
608 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
609 std::make_unique<InstrIgnore>(TargetOpcode::IMPLICIT_DEF);
610
611 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
612 std::make_unique<InstrReplaceWithCopy>(TargetOpcode::INSERT_SUBREG, 2);
613
614 Converters[{MaskDomain, TargetOpcode::COPY}] =
615 std::make_unique<InstrCOPYReplacer>(TargetOpcode::COPY, MaskDomain,
616 TargetOpcode::COPY);
617
618 auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
619 Converters[{MaskDomain, From}] =
620 std::make_unique<InstrReplacerDstCOPY>(From, To);
621 };
622
623#define GET_EGPR_IF_ENABLED(OPC) STI->hasEGPR() ? OPC##_EVEX : OPC
624 createReplacerDstCOPY(X86::MOVZX32rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
625 createReplacerDstCOPY(X86::MOVZX64rm16, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
626
627 createReplacerDstCOPY(X86::MOVZX32rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
628 createReplacerDstCOPY(X86::MOVZX64rr16, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
629
630 if (STI->hasDQI()) {
631 createReplacerDstCOPY(X86::MOVZX16rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
632 createReplacerDstCOPY(X86::MOVZX32rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
633 createReplacerDstCOPY(X86::MOVZX64rm8, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
634
635 createReplacerDstCOPY(X86::MOVZX16rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
636 createReplacerDstCOPY(X86::MOVZX32rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
637 createReplacerDstCOPY(X86::MOVZX64rr8, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
638 }
639
640 auto createReplacer = [&](unsigned From, unsigned To) {
641 Converters[{MaskDomain, From}] = std::make_unique<InstrReplacer>(From, To);
642 };
643
644 createReplacer(X86::MOV16rm, GET_EGPR_IF_ENABLED(X86::KMOVWkm));
645 createReplacer(X86::MOV16mr, GET_EGPR_IF_ENABLED(X86::KMOVWmk));
646 createReplacer(X86::MOV16rr, GET_EGPR_IF_ENABLED(X86::KMOVWkk));
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);
653
654 bool HasNDD = STI->hasNDD();
655 if (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);
662 }
663
664 if (STI->hasBWI()) {
665 createReplacer(X86::MOV32rm, GET_EGPR_IF_ENABLED(X86::KMOVDkm));
666 createReplacer(X86::MOV64rm, GET_EGPR_IF_ENABLED(X86::KMOVQkm));
667
668 createReplacer(X86::MOV32mr, GET_EGPR_IF_ENABLED(X86::KMOVDmk));
669 createReplacer(X86::MOV64mr, GET_EGPR_IF_ENABLED(X86::KMOVQmk));
670
671 createReplacer(X86::MOV32rr, GET_EGPR_IF_ENABLED(X86::KMOVDkk));
672 createReplacer(X86::MOV64rr, GET_EGPR_IF_ENABLED(X86::KMOVQkk));
673
674 createReplacer(X86::SHR32ri, X86::KSHIFTRDki);
675 createReplacer(X86::SHR64ri, X86::KSHIFTRQki);
676
677 createReplacer(X86::SHL32ri, X86::KSHIFTLDki);
678 createReplacer(X86::SHL64ri, X86::KSHIFTLQki);
679
680 createReplacer(X86::ADD32rr, X86::KADDDkk);
681 createReplacer(X86::ADD64rr, X86::KADDQkk);
682
683 createReplacer(X86::NOT32r, X86::KNOTDkk);
684 createReplacer(X86::NOT64r, X86::KNOTQkk);
685
686 createReplacer(X86::OR32rr, X86::KORDkk);
687 createReplacer(X86::OR64rr, X86::KORQkk);
688
689 createReplacer(X86::AND32rr, X86::KANDDkk);
690 createReplacer(X86::AND64rr, X86::KANDQkk);
691
692 createReplacer(X86::ANDN32rr, X86::KANDNDkk);
693 createReplacer(X86::ANDN64rr, X86::KANDNQkk);
694
695 createReplacer(X86::XOR32rr, X86::KXORDkk);
696 createReplacer(X86::XOR64rr, X86::KXORQkk);
697
698 if (HasNDD) {
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);
713 }
714
715 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
716 // to prove only Z flag is used.
717 // createReplacer(X86::TEST32rr, X86::KTESTDkk);
718 // createReplacer(X86::TEST64rr, X86::KTESTQkk);
719 }
720
721 if (STI->hasDQI()) {
722 createReplacer(X86::ADD8rr, X86::KADDBkk);
723 createReplacer(X86::ADD16rr, X86::KADDWkk);
724
725 createReplacer(X86::AND8rr, X86::KANDBkk);
726
727 createReplacer(X86::MOV8rm, GET_EGPR_IF_ENABLED(X86::KMOVBkm));
728 createReplacer(X86::MOV8mr, GET_EGPR_IF_ENABLED(X86::KMOVBmk));
729 createReplacer(X86::MOV8rr, GET_EGPR_IF_ENABLED(X86::KMOVBkk));
730
731 createReplacer(X86::NOT8r, X86::KNOTBkk);
732
733 createReplacer(X86::OR8rr, X86::KORBkk);
734
735 createReplacer(X86::SHR8ri, X86::KSHIFTRBki);
736 createReplacer(X86::SHL8ri, X86::KSHIFTLBki);
737
738 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
739 // to prove only Z flag is used.
740 // createReplacer(X86::TEST8rr, X86::KTESTBkk);
741 // createReplacer(X86::TEST16rr, X86::KTESTWkk);
742
743 createReplacer(X86::XOR8rr, X86::KXORBkk);
744
745 if (HasNDD) {
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);
754 }
755 }
756#undef GET_EGPR_IF_ENABLED
757}
758
759bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
760 if (skipFunction(MF.getFunction()))
761 return false;
763 return false;
764
766 dbgs() << "***** Machine Function before Domain Reassignment *****\n");
767 LLVM_DEBUG(MF.print(dbgs()));
768
769 STI = &MF.getSubtarget<X86Subtarget>();
770 // GPR->K is the only transformation currently supported, bail out early if no
771 // AVX512.
772 // TODO: We're also bailing of AVX512BW isn't supported since we use VK32 and
773 // VK64 for GR32/GR64, but those aren't legal classes on KNL. If the register
774 // coalescer doesn't clean it up and we generate a spill we will crash.
775 if (!STI->hasAVX512() || !STI->hasBWI())
776 return false;
777
778 MRI = &MF.getRegInfo();
779 assert(MRI->isSSA() && "Expected MIR to be in SSA form");
780
781 TII = STI->getInstrInfo();
782 initConverters();
783 bool Changed = false;
784
785 EnclosedEdges.clear();
786 EnclosedInstrs.clear();
787
788 std::vector<Closure> Closures;
789
790 // Go over all virtual registers and calculate a closure.
791 unsigned ClosureID = 0;
792 for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
793 Register Reg = Register::index2VirtReg(Idx);
794
795 // Skip unused VRegs.
796 if (MRI->reg_nodbg_empty(Reg))
797 continue;
798
799 // GPR only current source domain supported.
800 if (!MRI->getTargetRegisterInfo()->isGeneralPurposeRegisterClass(
801 MRI->getRegClass(Reg)))
802 continue;
803
804 // Register already in closure.
805 if (EnclosedEdges.contains(Reg))
806 continue;
807
808 // Calculate closure starting with Reg.
809 Closure C(ClosureID++, {MaskDomain});
810 buildClosure(C, Reg);
811
812 // Collect all closures that can potentially be converted.
813 if (!C.empty() && C.isLegal(MaskDomain))
814 Closures.push_back(std::move(C));
815 }
816
817 for (Closure &C : Closures) {
818 LLVM_DEBUG(C.dump(MRI));
819 if (isReassignmentProfitable(C, MaskDomain)) {
820 reassign(C, MaskDomain);
821 ++NumClosuresConverted;
822 Changed = true;
823 }
824 }
825
827 dbgs() << "***** Machine Function after Domain Reassignment *****\n");
828 LLVM_DEBUG(MF.print(dbgs()));
829
830 return Changed;
831}
832
833INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
834 "X86 Domain Reassignment Pass", false, false)
835
836/// Returns an instance of the Domain Reassignment pass.
838 return new X86DomainReassignment();
839}
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:57
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
This file contains some functions that are useful when dealing with strings.
#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:256
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:20
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
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:316
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 > >
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.