1 //===--- X86DomainReassignment.cpp - Selectively switch register classes---===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass attempts to find instruction chains (closures) in one domain,
11 // and convert them to equivalent instructions in a different domain,
12 // if profitable.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "X86.h"
17 #include "X86InstrInfo.h"
18 #include "X86Subtarget.h"
19 #include "llvm/ADT/DenseMap.h"
20 #include "llvm/ADT/DenseMapInfo.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/TargetRegisterInfo.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/Printable.h"
30 #include <bitset>
31
32 using namespace llvm;
33
34 namespace llvm {
35 void initializeX86DomainReassignmentPass(PassRegistry &);
36 }
37
38 #define DEBUG_TYPE "x86-domain-reassignment"
39
40 STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
41
42 static cl::opt<bool> DisableX86DomainReassignment(
43 "disable-x86-domain-reassignment", cl::Hidden,
44 cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
45
46 namespace {
47 enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
48
isGPR(const TargetRegisterClass * RC)49 static bool isGPR(const TargetRegisterClass *RC) {
50 return X86::GR64RegClass.hasSubClassEq(RC) ||
51 X86::GR32RegClass.hasSubClassEq(RC) ||
52 X86::GR16RegClass.hasSubClassEq(RC) ||
53 X86::GR8RegClass.hasSubClassEq(RC);
54 }
55
isMask(const TargetRegisterClass * RC,const TargetRegisterInfo * TRI)56 static bool isMask(const TargetRegisterClass *RC,
57 const TargetRegisterInfo *TRI) {
58 return X86::VK16RegClass.hasSubClassEq(RC);
59 }
60
getDomain(const TargetRegisterClass * RC,const TargetRegisterInfo * TRI)61 static RegDomain getDomain(const TargetRegisterClass *RC,
62 const TargetRegisterInfo *TRI) {
63 if (isGPR(RC))
64 return GPRDomain;
65 if (isMask(RC, TRI))
66 return MaskDomain;
67 return OtherDomain;
68 }
69
70 /// Return a register class equivalent to \p SrcRC, in \p Domain.
getDstRC(const TargetRegisterClass * SrcRC,RegDomain Domain)71 static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,
72 RegDomain Domain) {
73 assert(Domain == MaskDomain && "add domain");
74 if (X86::GR8RegClass.hasSubClassEq(SrcRC))
75 return &X86::VK8RegClass;
76 if (X86::GR16RegClass.hasSubClassEq(SrcRC))
77 return &X86::VK16RegClass;
78 if (X86::GR32RegClass.hasSubClassEq(SrcRC))
79 return &X86::VK32RegClass;
80 if (X86::GR64RegClass.hasSubClassEq(SrcRC))
81 return &X86::VK64RegClass;
82 llvm_unreachable("add register class");
83 return nullptr;
84 }
85
86 /// Abstract Instruction Converter class.
87 class InstrConverterBase {
88 protected:
89 unsigned SrcOpcode;
90
91 public:
InstrConverterBase(unsigned SrcOpcode)92 InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
93
~InstrConverterBase()94 virtual ~InstrConverterBase() {}
95
96 /// \returns true if \p MI is legal to convert.
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const97 virtual bool isLegal(const MachineInstr *MI,
98 const TargetInstrInfo *TII) const {
99 assert(MI->getOpcode() == SrcOpcode &&
100 "Wrong instruction passed to converter");
101 return true;
102 }
103
104 /// Applies conversion to \p MI.
105 ///
106 /// \returns true if \p MI is no longer need, and can be deleted.
107 virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
108 MachineRegisterInfo *MRI) const = 0;
109
110 /// \returns the cost increment incurred by converting \p MI.
111 virtual double getExtraCost(const MachineInstr *MI,
112 MachineRegisterInfo *MRI) const = 0;
113 };
114
115 /// An Instruction Converter which ignores the given instruction.
116 /// For example, PHI instructions can be safely ignored since only the registers
117 /// need to change.
118 class InstrIgnore : public InstrConverterBase {
119 public:
InstrIgnore(unsigned SrcOpcode)120 InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
121
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const122 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
123 MachineRegisterInfo *MRI) const override {
124 assert(isLegal(MI, TII) && "Cannot convert instruction");
125 return false;
126 }
127
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const128 double getExtraCost(const MachineInstr *MI,
129 MachineRegisterInfo *MRI) const override {
130 return 0;
131 }
132 };
133
134 /// An Instruction Converter which replaces an instruction with another.
135 class InstrReplacer : public InstrConverterBase {
136 public:
137 /// Opcode of the destination instruction.
138 unsigned DstOpcode;
139
InstrReplacer(unsigned SrcOpcode,unsigned DstOpcode)140 InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)
141 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
142
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const143 bool isLegal(const MachineInstr *MI,
144 const TargetInstrInfo *TII) const override {
145 if (!InstrConverterBase::isLegal(MI, TII))
146 return false;
147 // It's illegal to replace an instruction that implicitly defines a register
148 // with an instruction that doesn't, unless that register dead.
149 for (auto &MO : MI->implicit_operands())
150 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
151 !TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
152 return false;
153 return true;
154 }
155
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const156 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
157 MachineRegisterInfo *MRI) const override {
158 assert(isLegal(MI, TII) && "Cannot convert instruction");
159 MachineInstrBuilder Bld =
160 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));
161 // Transfer explicit operands from original instruction. Implicit operands
162 // are handled by BuildMI.
163 for (auto &Op : MI->explicit_operands())
164 Bld.add(Op);
165 return true;
166 }
167
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const168 double getExtraCost(const MachineInstr *MI,
169 MachineRegisterInfo *MRI) const override {
170 // Assuming instructions have the same cost.
171 return 0;
172 }
173 };
174
175 /// An Instruction Converter which replaces an instruction with another, and
176 /// adds a COPY from the new instruction's destination to the old one's.
177 class InstrReplacerDstCOPY : public InstrConverterBase {
178 public:
179 unsigned DstOpcode;
180
InstrReplacerDstCOPY(unsigned SrcOpcode,unsigned DstOpcode)181 InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)
182 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
183
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const184 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
185 MachineRegisterInfo *MRI) const override {
186 assert(isLegal(MI, TII) && "Cannot convert instruction");
187 MachineBasicBlock *MBB = MI->getParent();
188 auto &DL = MI->getDebugLoc();
189
190 unsigned Reg = MRI->createVirtualRegister(
191 TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo(),
192 *MBB->getParent()));
193 MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
194 for (unsigned Idx = 1, End = MI->getNumOperands(); Idx < End; ++Idx)
195 Bld.add(MI->getOperand(Idx));
196
197 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
198 .add(MI->getOperand(0))
199 .addReg(Reg);
200
201 return true;
202 }
203
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const204 double getExtraCost(const MachineInstr *MI,
205 MachineRegisterInfo *MRI) const override {
206 // Assuming instructions have the same cost, and that COPY is in the same
207 // domain so it will be eliminated.
208 return 0;
209 }
210 };
211
212 /// An Instruction Converter for replacing COPY instructions.
213 class InstrCOPYReplacer : public InstrReplacer {
214 public:
215 RegDomain DstDomain;
216
InstrCOPYReplacer(unsigned SrcOpcode,RegDomain DstDomain,unsigned DstOpcode)217 InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
218 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
219
isLegal(const MachineInstr * MI,const TargetInstrInfo * TII) const220 bool isLegal(const MachineInstr *MI,
221 const TargetInstrInfo *TII) const override {
222 if (!InstrConverterBase::isLegal(MI, TII))
223 return false;
224
225 // Don't allow copies to/flow GR8/GR16 physical registers.
226 // FIXME: Is there some better way to support this?
227 unsigned DstReg = MI->getOperand(0).getReg();
228 if (TargetRegisterInfo::isPhysicalRegister(DstReg) &&
229 (X86::GR8RegClass.contains(DstReg) ||
230 X86::GR16RegClass.contains(DstReg)))
231 return false;
232 unsigned SrcReg = MI->getOperand(1).getReg();
233 if (TargetRegisterInfo::isPhysicalRegister(SrcReg) &&
234 (X86::GR8RegClass.contains(SrcReg) ||
235 X86::GR16RegClass.contains(SrcReg)))
236 return false;
237
238 return true;
239 }
240
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const241 double getExtraCost(const MachineInstr *MI,
242 MachineRegisterInfo *MRI) const override {
243 assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
244
245 for (auto &MO : MI->operands()) {
246 // Physical registers will not be converted. Assume that converting the
247 // COPY to the destination domain will eventually result in a actual
248 // instruction.
249 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
250 return 1;
251
252 RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
253 MRI->getTargetRegisterInfo());
254 // Converting a cross domain COPY to a same domain COPY should eliminate
255 // an insturction
256 if (OpDomain == DstDomain)
257 return -1;
258 }
259 return 0;
260 }
261 };
262
263 /// An Instruction Converter which replaces an instruction with a COPY.
264 class InstrReplaceWithCopy : public InstrConverterBase {
265 public:
266 // Source instruction operand Index, to be used as the COPY source.
267 unsigned SrcOpIdx;
268
InstrReplaceWithCopy(unsigned SrcOpcode,unsigned SrcOpIdx)269 InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
270 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
271
convertInstr(MachineInstr * MI,const TargetInstrInfo * TII,MachineRegisterInfo * MRI) const272 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
273 MachineRegisterInfo *MRI) const override {
274 assert(isLegal(MI, TII) && "Cannot convert instruction");
275 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
276 TII->get(TargetOpcode::COPY))
277 .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
278 return true;
279 }
280
getExtraCost(const MachineInstr * MI,MachineRegisterInfo * MRI) const281 double getExtraCost(const MachineInstr *MI,
282 MachineRegisterInfo *MRI) const override {
283 return 0;
284 }
285 };
286
287 // Key type to be used by the Instruction Converters map.
288 // A converter is identified by <destination domain, source opcode>
289 typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
290
291 typedef DenseMap<InstrConverterBaseKeyTy, InstrConverterBase *>
292 InstrConverterBaseMap;
293
294 /// A closure is a set of virtual register representing all of the edges in
295 /// the closure, as well as all of the instructions connected by those edges.
296 ///
297 /// A closure may encompass virtual registers in the same register bank that
298 /// have different widths. For example, it may contain 32-bit GPRs as well as
299 /// 64-bit GPRs.
300 ///
301 /// A closure that computes an address (i.e. defines a virtual register that is
302 /// used in a memory operand) excludes the instructions that contain memory
303 /// operands using the address. Such an instruction will be included in a
304 /// different closure that manipulates the loaded or stored value.
305 class Closure {
306 private:
307 /// Virtual registers in the closure.
308 DenseSet<unsigned> Edges;
309
310 /// Instructions in the closure.
311 SmallVector<MachineInstr *, 8> Instrs;
312
313 /// Domains which this closure can legally be reassigned to.
314 std::bitset<NumDomains> LegalDstDomains;
315
316 /// An ID to uniquely identify this closure, even when it gets
317 /// moved around
318 unsigned ID;
319
320 public:
Closure(unsigned ID,std::initializer_list<RegDomain> LegalDstDomainList)321 Closure(unsigned ID, std::initializer_list<RegDomain> LegalDstDomainList) : ID(ID) {
322 for (RegDomain D : LegalDstDomainList)
323 LegalDstDomains.set(D);
324 }
325
326 /// Mark this closure as illegal for reassignment to all domains.
setAllIllegal()327 void setAllIllegal() { LegalDstDomains.reset(); }
328
329 /// \returns true if this closure has domains which are legal to reassign to.
hasLegalDstDomain() const330 bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
331
332 /// \returns true if is legal to reassign this closure to domain \p RD.
isLegal(RegDomain RD) const333 bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
334
335 /// Mark this closure as illegal for reassignment to domain \p RD.
setIllegal(RegDomain RD)336 void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
337
empty() const338 bool empty() const { return Edges.empty(); }
339
insertEdge(unsigned Reg)340 bool insertEdge(unsigned Reg) {
341 return Edges.insert(Reg).second;
342 }
343
344 using const_edge_iterator = DenseSet<unsigned>::const_iterator;
edges() const345 iterator_range<const_edge_iterator> edges() const {
346 return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());
347 }
348
addInstruction(MachineInstr * I)349 void addInstruction(MachineInstr *I) {
350 Instrs.push_back(I);
351 }
352
instructions() const353 ArrayRef<MachineInstr *> instructions() const {
354 return Instrs;
355 }
356
dump(const MachineRegisterInfo * MRI) const357 LLVM_DUMP_METHOD void dump(const MachineRegisterInfo *MRI) const {
358 dbgs() << "Registers: ";
359 bool First = true;
360 for (unsigned Reg : Edges) {
361 if (!First)
362 dbgs() << ", ";
363 First = false;
364 dbgs() << printReg(Reg, MRI->getTargetRegisterInfo(), 0, MRI);
365 }
366 dbgs() << "\n" << "Instructions:";
367 for (MachineInstr *MI : Instrs) {
368 dbgs() << "\n ";
369 MI->print(dbgs());
370 }
371 dbgs() << "\n";
372 }
373
getID() const374 unsigned getID() const {
375 return ID;
376 }
377
378 };
379
380 class X86DomainReassignment : public MachineFunctionPass {
381 const X86Subtarget *STI;
382 MachineRegisterInfo *MRI;
383 const X86InstrInfo *TII;
384
385 /// All edges that are included in some closure
386 DenseSet<unsigned> EnclosedEdges;
387
388 /// All instructions that are included in some closure.
389 DenseMap<MachineInstr *, unsigned> EnclosedInstrs;
390
391 public:
392 static char ID;
393
X86DomainReassignment()394 X86DomainReassignment() : MachineFunctionPass(ID) {
395 initializeX86DomainReassignmentPass(*PassRegistry::getPassRegistry());
396 }
397
398 bool runOnMachineFunction(MachineFunction &MF) override;
399
getAnalysisUsage(AnalysisUsage & AU) const400 void getAnalysisUsage(AnalysisUsage &AU) const override {
401 AU.setPreservesCFG();
402 MachineFunctionPass::getAnalysisUsage(AU);
403 }
404
getPassName() const405 StringRef getPassName() const override {
406 return "X86 Domain Reassignment Pass";
407 }
408
409 private:
410 /// A map of available Instruction Converters.
411 InstrConverterBaseMap Converters;
412
413 /// Initialize Converters map.
414 void initConverters();
415
416 /// Starting from \Reg, expand the closure as much as possible.
417 void buildClosure(Closure &, unsigned Reg);
418
419 /// Enqueue \p Reg to be considered for addition to the closure.
420 void visitRegister(Closure &, unsigned Reg, RegDomain &Domain,
421 SmallVectorImpl<unsigned> &Worklist);
422
423 /// Reassign the closure to \p Domain.
424 void reassign(const Closure &C, RegDomain Domain) const;
425
426 /// Add \p MI to the closure.
427 void encloseInstr(Closure &C, MachineInstr *MI);
428
429 /// /returns true if it is profitable to reassign the closure to \p Domain.
430 bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
431
432 /// Calculate the total cost of reassigning the closure to \p Domain.
433 double calculateCost(const Closure &C, RegDomain Domain) const;
434 };
435
436 char X86DomainReassignment::ID = 0;
437
438 } // End anonymous namespace.
439
visitRegister(Closure & C,unsigned Reg,RegDomain & Domain,SmallVectorImpl<unsigned> & Worklist)440 void X86DomainReassignment::visitRegister(Closure &C, unsigned Reg,
441 RegDomain &Domain,
442 SmallVectorImpl<unsigned> &Worklist) {
443 if (EnclosedEdges.count(Reg))
444 return;
445
446 if (!TargetRegisterInfo::isVirtualRegister(Reg))
447 return;
448
449 if (!MRI->hasOneDef(Reg))
450 return;
451
452 RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
453 // First edge in closure sets the domain.
454 if (Domain == NoDomain)
455 Domain = RD;
456
457 if (Domain != RD)
458 return;
459
460 Worklist.push_back(Reg);
461 }
462
encloseInstr(Closure & C,MachineInstr * MI)463 void X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
464 auto I = EnclosedInstrs.find(MI);
465 if (I != EnclosedInstrs.end()) {
466 if (I->second != C.getID())
467 // Instruction already belongs to another closure, avoid conflicts between
468 // closure and mark this closure as illegal.
469 C.setAllIllegal();
470 return;
471 }
472
473 EnclosedInstrs[MI] = C.getID();
474 C.addInstruction(MI);
475
476 // Mark closure as illegal for reassignment to domains, if there is no
477 // converter for the instruction or if the converter cannot convert the
478 // instruction.
479 for (int i = 0; i != NumDomains; ++i) {
480 if (C.isLegal((RegDomain)i)) {
481 InstrConverterBase *IC = Converters.lookup({i, MI->getOpcode()});
482 if (!IC || !IC->isLegal(MI, TII))
483 C.setIllegal((RegDomain)i);
484 }
485 }
486 }
487
calculateCost(const Closure & C,RegDomain DstDomain) const488 double X86DomainReassignment::calculateCost(const Closure &C,
489 RegDomain DstDomain) const {
490 assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
491
492 double Cost = 0.0;
493 for (auto *MI : C.instructions())
494 Cost +=
495 Converters.lookup({DstDomain, MI->getOpcode()})->getExtraCost(MI, MRI);
496 return Cost;
497 }
498
isReassignmentProfitable(const Closure & C,RegDomain Domain) const499 bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
500 RegDomain Domain) const {
501 return calculateCost(C, Domain) < 0.0;
502 }
503
reassign(const Closure & C,RegDomain Domain) const504 void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
505 assert(C.isLegal(Domain) && "Cannot convert illegal closure");
506
507 // Iterate all instructions in the closure, convert each one using the
508 // appropriate converter.
509 SmallVector<MachineInstr *, 8> ToErase;
510 for (auto *MI : C.instructions())
511 if (Converters.lookup({Domain, MI->getOpcode()})
512 ->convertInstr(MI, TII, MRI))
513 ToErase.push_back(MI);
514
515 // Iterate all registers in the closure, replace them with registers in the
516 // destination domain.
517 for (unsigned Reg : C.edges()) {
518 MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
519 for (auto &MO : MRI->use_operands(Reg)) {
520 if (MO.isReg())
521 // Remove all subregister references as they are not valid in the
522 // destination domain.
523 MO.setSubReg(0);
524 }
525 }
526
527 for (auto MI : ToErase)
528 MI->eraseFromParent();
529 }
530
531 /// \returns true when \p Reg is used as part of an address calculation in \p
532 /// MI.
usedAsAddr(const MachineInstr & MI,unsigned Reg,const TargetInstrInfo * TII)533 static bool usedAsAddr(const MachineInstr &MI, unsigned Reg,
534 const TargetInstrInfo *TII) {
535 if (!MI.mayLoadOrStore())
536 return false;
537
538 const MCInstrDesc &Desc = TII->get(MI.getOpcode());
539 int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
540 if (MemOpStart == -1)
541 return false;
542
543 MemOpStart += X86II::getOperandBias(Desc);
544 for (unsigned MemOpIdx = MemOpStart,
545 MemOpEnd = MemOpStart + X86::AddrNumOperands;
546 MemOpIdx < MemOpEnd; ++MemOpIdx) {
547 auto &Op = MI.getOperand(MemOpIdx);
548 if (Op.isReg() && Op.getReg() == Reg)
549 return true;
550 }
551 return false;
552 }
553
buildClosure(Closure & C,unsigned Reg)554 void X86DomainReassignment::buildClosure(Closure &C, unsigned Reg) {
555 SmallVector<unsigned, 4> Worklist;
556 RegDomain Domain = NoDomain;
557 visitRegister(C, Reg, Domain, Worklist);
558 while (!Worklist.empty()) {
559 unsigned CurReg = Worklist.pop_back_val();
560
561 // Register already in this closure.
562 if (!C.insertEdge(CurReg))
563 continue;
564
565 MachineInstr *DefMI = MRI->getVRegDef(CurReg);
566 encloseInstr(C, DefMI);
567
568 // Add register used by the defining MI to the worklist.
569 // Do not add registers which are used in address calculation, they will be
570 // added to a different closure.
571 int OpEnd = DefMI->getNumOperands();
572 const MCInstrDesc &Desc = DefMI->getDesc();
573 int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
574 if (MemOp != -1)
575 MemOp += X86II::getOperandBias(Desc);
576 for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
577 if (OpIdx == MemOp) {
578 // skip address calculation.
579 OpIdx += (X86::AddrNumOperands - 1);
580 continue;
581 }
582 auto &Op = DefMI->getOperand(OpIdx);
583 if (!Op.isReg() || !Op.isUse())
584 continue;
585 visitRegister(C, Op.getReg(), Domain, Worklist);
586 }
587
588 // Expand closure through register uses.
589 for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
590 // We would like to avoid converting closures which calculare addresses,
591 // as this should remain in GPRs.
592 if (usedAsAddr(UseMI, CurReg, TII)) {
593 C.setAllIllegal();
594 continue;
595 }
596 encloseInstr(C, &UseMI);
597
598 for (auto &DefOp : UseMI.defs()) {
599 if (!DefOp.isReg())
600 continue;
601
602 unsigned DefReg = DefOp.getReg();
603 if (!TargetRegisterInfo::isVirtualRegister(DefReg)) {
604 C.setAllIllegal();
605 continue;
606 }
607 visitRegister(C, DefReg, Domain, Worklist);
608 }
609 }
610 }
611 }
612
initConverters()613 void X86DomainReassignment::initConverters() {
614 Converters[{MaskDomain, TargetOpcode::PHI}] =
615 new InstrIgnore(TargetOpcode::PHI);
616
617 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
618 new InstrIgnore(TargetOpcode::IMPLICIT_DEF);
619
620 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
621 new InstrReplaceWithCopy(TargetOpcode::INSERT_SUBREG, 2);
622
623 Converters[{MaskDomain, TargetOpcode::COPY}] =
624 new InstrCOPYReplacer(TargetOpcode::COPY, MaskDomain, TargetOpcode::COPY);
625
626 auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
627 Converters[{MaskDomain, From}] = new InstrReplacerDstCOPY(From, To);
628 };
629
630 createReplacerDstCOPY(X86::MOVZX32rm16, X86::KMOVWkm);
631 createReplacerDstCOPY(X86::MOVZX64rm16, X86::KMOVWkm);
632
633 createReplacerDstCOPY(X86::MOVZX32rr16, X86::KMOVWkk);
634 createReplacerDstCOPY(X86::MOVZX64rr16, X86::KMOVWkk);
635
636 if (STI->hasDQI()) {
637 createReplacerDstCOPY(X86::MOVZX16rm8, X86::KMOVBkm);
638 createReplacerDstCOPY(X86::MOVZX32rm8, X86::KMOVBkm);
639 createReplacerDstCOPY(X86::MOVZX64rm8, X86::KMOVBkm);
640
641 createReplacerDstCOPY(X86::MOVZX16rr8, X86::KMOVBkk);
642 createReplacerDstCOPY(X86::MOVZX32rr8, X86::KMOVBkk);
643 createReplacerDstCOPY(X86::MOVZX64rr8, X86::KMOVBkk);
644 }
645
646 auto createReplacer = [&](unsigned From, unsigned To) {
647 Converters[{MaskDomain, From}] = new InstrReplacer(From, To);
648 };
649
650 createReplacer(X86::MOV16rm, X86::KMOVWkm);
651 createReplacer(X86::MOV16mr, X86::KMOVWmk);
652 createReplacer(X86::MOV16rr, X86::KMOVWkk);
653 createReplacer(X86::SHR16ri, X86::KSHIFTRWri);
654 createReplacer(X86::SHL16ri, X86::KSHIFTLWri);
655 createReplacer(X86::NOT16r, X86::KNOTWrr);
656 createReplacer(X86::OR16rr, X86::KORWrr);
657 createReplacer(X86::AND16rr, X86::KANDWrr);
658 createReplacer(X86::XOR16rr, X86::KXORWrr);
659
660 if (STI->hasBWI()) {
661 createReplacer(X86::MOV32rm, X86::KMOVDkm);
662 createReplacer(X86::MOV64rm, X86::KMOVQkm);
663
664 createReplacer(X86::MOV32mr, X86::KMOVDmk);
665 createReplacer(X86::MOV64mr, X86::KMOVQmk);
666
667 createReplacer(X86::MOV32rr, X86::KMOVDkk);
668 createReplacer(X86::MOV64rr, X86::KMOVQkk);
669
670 createReplacer(X86::SHR32ri, X86::KSHIFTRDri);
671 createReplacer(X86::SHR64ri, X86::KSHIFTRQri);
672
673 createReplacer(X86::SHL32ri, X86::KSHIFTLDri);
674 createReplacer(X86::SHL64ri, X86::KSHIFTLQri);
675
676 createReplacer(X86::ADD32rr, X86::KADDDrr);
677 createReplacer(X86::ADD64rr, X86::KADDQrr);
678
679 createReplacer(X86::NOT32r, X86::KNOTDrr);
680 createReplacer(X86::NOT64r, X86::KNOTQrr);
681
682 createReplacer(X86::OR32rr, X86::KORDrr);
683 createReplacer(X86::OR64rr, X86::KORQrr);
684
685 createReplacer(X86::AND32rr, X86::KANDDrr);
686 createReplacer(X86::AND64rr, X86::KANDQrr);
687
688 createReplacer(X86::ANDN32rr, X86::KANDNDrr);
689 createReplacer(X86::ANDN64rr, X86::KANDNQrr);
690
691 createReplacer(X86::XOR32rr, X86::KXORDrr);
692 createReplacer(X86::XOR64rr, X86::KXORQrr);
693
694 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
695 // to prove only Z flag is used.
696 //createReplacer(X86::TEST32rr, X86::KTESTDrr);
697 //createReplacer(X86::TEST64rr, X86::KTESTQrr);
698 }
699
700 if (STI->hasDQI()) {
701 createReplacer(X86::ADD8rr, X86::KADDBrr);
702 createReplacer(X86::ADD16rr, X86::KADDWrr);
703
704 createReplacer(X86::AND8rr, X86::KANDBrr);
705
706 createReplacer(X86::MOV8rm, X86::KMOVBkm);
707 createReplacer(X86::MOV8mr, X86::KMOVBmk);
708 createReplacer(X86::MOV8rr, X86::KMOVBkk);
709
710 createReplacer(X86::NOT8r, X86::KNOTBrr);
711
712 createReplacer(X86::OR8rr, X86::KORBrr);
713
714 createReplacer(X86::SHR8ri, X86::KSHIFTRBri);
715 createReplacer(X86::SHL8ri, X86::KSHIFTLBri);
716
717 // TODO: KTEST is not a replacement for TEST due to flag differences. Need
718 // to prove only Z flag is used.
719 //createReplacer(X86::TEST8rr, X86::KTESTBrr);
720 //createReplacer(X86::TEST16rr, X86::KTESTWrr);
721
722 createReplacer(X86::XOR8rr, X86::KXORBrr);
723 }
724 }
725
runOnMachineFunction(MachineFunction & MF)726 bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
727 if (skipFunction(MF.getFunction()))
728 return false;
729 if (DisableX86DomainReassignment)
730 return false;
731
732 LLVM_DEBUG(
733 dbgs() << "***** Machine Function before Domain Reassignment *****\n");
734 LLVM_DEBUG(MF.print(dbgs()));
735
736 STI = &MF.getSubtarget<X86Subtarget>();
737 // GPR->K is the only transformation currently supported, bail out early if no
738 // AVX512.
739 if (!STI->hasAVX512())
740 return false;
741
742 MRI = &MF.getRegInfo();
743 assert(MRI->isSSA() && "Expected MIR to be in SSA form");
744
745 TII = STI->getInstrInfo();
746 initConverters();
747 bool Changed = false;
748
749 EnclosedEdges.clear();
750 EnclosedInstrs.clear();
751
752 std::vector<Closure> Closures;
753
754 // Go over all virtual registers and calculate a closure.
755 unsigned ClosureID = 0;
756 for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
757 unsigned Reg = TargetRegisterInfo::index2VirtReg(Idx);
758
759 // GPR only current source domain supported.
760 if (!isGPR(MRI->getRegClass(Reg)))
761 continue;
762
763 // Register already in closure.
764 if (EnclosedEdges.count(Reg))
765 continue;
766
767 // Calculate closure starting with Reg.
768 Closure C(ClosureID++, {MaskDomain});
769 buildClosure(C, Reg);
770
771 // Collect all closures that can potentially be converted.
772 if (!C.empty() && C.isLegal(MaskDomain))
773 Closures.push_back(std::move(C));
774 }
775
776 for (Closure &C : Closures) {
777 LLVM_DEBUG(C.dump(MRI));
778 if (isReassignmentProfitable(C, MaskDomain)) {
779 reassign(C, MaskDomain);
780 ++NumClosuresConverted;
781 Changed = true;
782 }
783 }
784
785 DeleteContainerSeconds(Converters);
786
787 LLVM_DEBUG(
788 dbgs() << "***** Machine Function after Domain Reassignment *****\n");
789 LLVM_DEBUG(MF.print(dbgs()));
790
791 return Changed;
792 }
793
794 INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
795 "X86 Domain Reassignment Pass", false, false)
796
797 /// Returns an instance of the Domain Reassignment pass.
createX86DomainReassignmentPass()798 FunctionPass *llvm::createX86DomainReassignmentPass() {
799 return new X86DomainReassignment();
800 }
801