blob: ba7280c29cc941163dc53cd761e83493473049f3 [file] [log] [blame]
Guy Blank92d5ce32017-10-22 11:43:08 +00001//===--- 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"
Guy Blank92d5ce32017-10-22 11:43:08 +000022#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"
David Blaikieb3bde2e2017-11-17 01:07:10 +000027#include "llvm/CodeGen/TargetRegisterInfo.h"
Guy Blank92d5ce32017-10-22 11:43:08 +000028#include "llvm/Support/Debug.h"
Craig Topper59925352017-12-17 03:16:23 +000029#include <bitset>
Guy Blank92d5ce32017-10-22 11:43:08 +000030
31using namespace llvm;
32
33namespace llvm {
34void initializeX86DomainReassignmentPass(PassRegistry &);
35}
36
37#define DEBUG_TYPE "x86-domain-reassignment"
38
39STATISTIC(NumClosuresConverted, "Number of closures converted by the pass");
40
41static cl::opt<bool> DisableX86DomainReassignment(
42 "disable-x86-domain-reassignment", cl::Hidden,
43 cl::desc("X86: Disable Virtual Register Reassignment."), cl::init(false));
44
45namespace {
Craig Topper59925352017-12-17 03:16:23 +000046enum RegDomain { NoDomain = -1, GPRDomain, MaskDomain, OtherDomain, NumDomains };
Guy Blank92d5ce32017-10-22 11:43:08 +000047
48static bool isGPR(const TargetRegisterClass *RC) {
49 return X86::GR64RegClass.hasSubClassEq(RC) ||
50 X86::GR32RegClass.hasSubClassEq(RC) ||
51 X86::GR16RegClass.hasSubClassEq(RC) ||
52 X86::GR8RegClass.hasSubClassEq(RC);
53}
54
55static bool isMask(const TargetRegisterClass *RC,
56 const TargetRegisterInfo *TRI) {
57 return X86::VK16RegClass.hasSubClassEq(RC);
58}
59
60static RegDomain getDomain(const TargetRegisterClass *RC,
61 const TargetRegisterInfo *TRI) {
62 if (isGPR(RC))
63 return GPRDomain;
64 if (isMask(RC, TRI))
65 return MaskDomain;
66 return OtherDomain;
67}
68
69/// Return a register class equivalent to \p SrcRC, in \p Domain.
70static const TargetRegisterClass *getDstRC(const TargetRegisterClass *SrcRC,
71 RegDomain Domain) {
72 assert(Domain == MaskDomain && "add domain");
Guy Blankf3cefdd2017-12-05 09:08:24 +000073 if (X86::GR8RegClass.hasSubClassEq(SrcRC))
Guy Blank92d5ce32017-10-22 11:43:08 +000074 return &X86::VK8RegClass;
Guy Blankf3cefdd2017-12-05 09:08:24 +000075 if (X86::GR16RegClass.hasSubClassEq(SrcRC))
Guy Blank92d5ce32017-10-22 11:43:08 +000076 return &X86::VK16RegClass;
Guy Blankf3cefdd2017-12-05 09:08:24 +000077 if (X86::GR32RegClass.hasSubClassEq(SrcRC))
Guy Blank92d5ce32017-10-22 11:43:08 +000078 return &X86::VK32RegClass;
Guy Blankf3cefdd2017-12-05 09:08:24 +000079 if (X86::GR64RegClass.hasSubClassEq(SrcRC))
Guy Blank92d5ce32017-10-22 11:43:08 +000080 return &X86::VK64RegClass;
81 llvm_unreachable("add register class");
82 return nullptr;
83}
84
85/// Abstract Instruction Converter class.
86class InstrConverterBase {
87protected:
88 unsigned SrcOpcode;
89
90public:
91 InstrConverterBase(unsigned SrcOpcode) : SrcOpcode(SrcOpcode) {}
92
93 virtual ~InstrConverterBase() {}
94
95 /// \returns true if \p MI is legal to convert.
96 virtual bool isLegal(const MachineInstr *MI,
97 const TargetInstrInfo *TII) const {
98 assert(MI->getOpcode() == SrcOpcode &&
99 "Wrong instruction passed to converter");
100 return true;
101 }
102
103 /// Applies conversion to \p MI.
104 ///
105 /// \returns true if \p MI is no longer need, and can be deleted.
106 virtual bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
107 MachineRegisterInfo *MRI) const = 0;
108
109 /// \returns the cost increment incurred by converting \p MI.
110 virtual double getExtraCost(const MachineInstr *MI,
111 MachineRegisterInfo *MRI) const = 0;
112};
113
114/// An Instruction Converter which ignores the given instruction.
115/// For example, PHI instructions can be safely ignored since only the registers
116/// need to change.
117class InstrIgnore : public InstrConverterBase {
118public:
119 InstrIgnore(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
120
121 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
122 MachineRegisterInfo *MRI) const override {
123 assert(isLegal(MI, TII) && "Cannot convert instruction");
124 return false;
125 }
126
127 double getExtraCost(const MachineInstr *MI,
128 MachineRegisterInfo *MRI) const override {
129 return 0;
130 }
131};
132
133/// An Instruction Converter which replaces an instruction with another.
134class InstrReplacer : public InstrConverterBase {
135public:
136 /// Opcode of the destination instruction.
137 unsigned DstOpcode;
138
139 InstrReplacer(unsigned SrcOpcode, unsigned DstOpcode)
140 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
141
142 bool isLegal(const MachineInstr *MI,
143 const TargetInstrInfo *TII) const override {
144 if (!InstrConverterBase::isLegal(MI, TII))
145 return false;
146 // It's illegal to replace an instruction that implicitly defines a register
147 // with an instruction that doesn't, unless that register dead.
148 for (auto &MO : MI->implicit_operands())
149 if (MO.isReg() && MO.isDef() && !MO.isDead() &&
150 !TII->get(DstOpcode).hasImplicitDefOfPhysReg(MO.getReg()))
151 return false;
152 return true;
153 }
154
155 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
156 MachineRegisterInfo *MRI) const override {
157 assert(isLegal(MI, TII) && "Cannot convert instruction");
158 MachineInstrBuilder Bld =
159 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(DstOpcode));
160 // Transfer explicit operands from original instruction. Implicit operands
161 // are handled by BuildMI.
162 for (auto &Op : MI->explicit_operands())
163 Bld.add(Op);
164 return true;
165 }
166
167 double getExtraCost(const MachineInstr *MI,
168 MachineRegisterInfo *MRI) const override {
169 // Assuming instructions have the same cost.
170 return 0;
171 }
172};
173
174/// An Instruction Converter which replaces an instruction with another, and
175/// adds a COPY from the new instruction's destination to the old one's.
176class InstrReplacerDstCOPY : public InstrConverterBase {
177public:
178 unsigned DstOpcode;
179
180 InstrReplacerDstCOPY(unsigned SrcOpcode, unsigned DstOpcode)
181 : InstrConverterBase(SrcOpcode), DstOpcode(DstOpcode) {}
182
183 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
184 MachineRegisterInfo *MRI) const override {
185 assert(isLegal(MI, TII) && "Cannot convert instruction");
186 MachineBasicBlock *MBB = MI->getParent();
187 auto &DL = MI->getDebugLoc();
188
189 unsigned Reg = MRI->createVirtualRegister(
190 TII->getRegClass(TII->get(DstOpcode), 0, MRI->getTargetRegisterInfo(),
191 *MBB->getParent()));
192 MachineInstrBuilder Bld = BuildMI(*MBB, MI, DL, TII->get(DstOpcode), Reg);
193 for (unsigned Idx = 1, End = MI->getNumOperands(); Idx < End; ++Idx)
194 Bld.add(MI->getOperand(Idx));
195
196 BuildMI(*MBB, MI, DL, TII->get(TargetOpcode::COPY))
197 .add(MI->getOperand(0))
198 .addReg(Reg);
199
200 return true;
201 }
202
203 double getExtraCost(const MachineInstr *MI,
204 MachineRegisterInfo *MRI) const override {
205 // Assuming instructions have the same cost, and that COPY is in the same
206 // domain so it will be eliminated.
207 return 0;
208 }
209};
210
211/// An Instruction Converter for replacing COPY instructions.
212class InstrCOPYReplacer : public InstrReplacer {
213public:
214 RegDomain DstDomain;
215
216 InstrCOPYReplacer(unsigned SrcOpcode, RegDomain DstDomain, unsigned DstOpcode)
217 : InstrReplacer(SrcOpcode, DstOpcode), DstDomain(DstDomain) {}
218
219 double getExtraCost(const MachineInstr *MI,
220 MachineRegisterInfo *MRI) const override {
221 assert(MI->getOpcode() == TargetOpcode::COPY && "Expected a COPY");
222
223 for (auto &MO : MI->operands()) {
224 // Physical registers will not be converted. Assume that converting the
225 // COPY to the destination domain will eventually result in a actual
226 // instruction.
227 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
228 return 1;
229
230 RegDomain OpDomain = getDomain(MRI->getRegClass(MO.getReg()),
231 MRI->getTargetRegisterInfo());
232 // Converting a cross domain COPY to a same domain COPY should eliminate
233 // an insturction
234 if (OpDomain == DstDomain)
235 return -1;
236 }
237 return 0;
238 }
239};
240
241/// An Instruction Converter which replaces an instruction with a COPY.
242class InstrReplaceWithCopy : public InstrConverterBase {
243public:
244 // Source instruction operand Index, to be used as the COPY source.
245 unsigned SrcOpIdx;
246
247 InstrReplaceWithCopy(unsigned SrcOpcode, unsigned SrcOpIdx)
248 : InstrConverterBase(SrcOpcode), SrcOpIdx(SrcOpIdx) {}
249
250 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
251 MachineRegisterInfo *MRI) const override {
252 assert(isLegal(MI, TII) && "Cannot convert instruction");
253 BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
254 TII->get(TargetOpcode::COPY))
255 .add({MI->getOperand(0), MI->getOperand(SrcOpIdx)});
256 return true;
257 }
258
259 double getExtraCost(const MachineInstr *MI,
260 MachineRegisterInfo *MRI) const override {
261 return 0;
262 }
263};
264
265/// An Instruction Converter which completely deletes an instruction.
266/// For example, IMPLICIT_DEF instructions can be deleted when converting from
267/// GPR to mask.
268class InstrDeleter : public InstrConverterBase {
269public:
270 InstrDeleter(unsigned SrcOpcode) : InstrConverterBase(SrcOpcode) {}
271
272 bool convertInstr(MachineInstr *MI, const TargetInstrInfo *TII,
273 MachineRegisterInfo *MRI) const override {
274 assert(isLegal(MI, TII) && "Cannot convert instruction");
275 return true;
276 }
277
278 double getExtraCost(const MachineInstr *MI,
279 MachineRegisterInfo *MRI) const override {
280 return 0;
281 }
282};
283
284// Key type to be used by the Instruction Converters map.
285// A converter is identified by <destination domain, source opcode>
286typedef std::pair<int, unsigned> InstrConverterBaseKeyTy;
287
288typedef DenseMap<InstrConverterBaseKeyTy, InstrConverterBase *>
289 InstrConverterBaseMap;
290
291/// A closure is a set of virtual register representing all of the edges in
292/// the closure, as well as all of the instructions connected by those edges.
293///
294/// A closure may encompass virtual registers in the same register bank that
295/// have different widths. For example, it may contain 32-bit GPRs as well as
296/// 64-bit GPRs.
297///
298/// A closure that computes an address (i.e. defines a virtual register that is
299/// used in a memory operand) excludes the instructions that contain memory
300/// operands using the address. Such an instruction will be included in a
301/// different closure that manipulates the loaded or stored value.
302class Closure {
303private:
Guy Blank92d5ce32017-10-22 11:43:08 +0000304 /// Virtual registers in the closure.
305 DenseSet<unsigned> Edges;
306
307 /// Instructions in the closure.
308 SmallVector<MachineInstr *, 8> Instrs;
309
Guy Blank92d5ce32017-10-22 11:43:08 +0000310 /// Domains which this closure can legally be reassigned to.
Craig Topper59925352017-12-17 03:16:23 +0000311 std::bitset<NumDomains> LegalDstDomains;
Guy Blank92d5ce32017-10-22 11:43:08 +0000312
Guy Blank92d5ce32017-10-22 11:43:08 +0000313public:
Craig Topper8ec56322017-12-20 19:36:43 +0000314 Closure(std::initializer_list<RegDomain> LegalDstDomainList) {
Craig Topper59925352017-12-17 03:16:23 +0000315 for (RegDomain D : LegalDstDomainList)
316 LegalDstDomains.set(D);
317 }
Guy Blank92d5ce32017-10-22 11:43:08 +0000318
Guy Blank92d5ce32017-10-22 11:43:08 +0000319 /// Mark this closure as illegal for reassignment to all domains.
Craig Topper59925352017-12-17 03:16:23 +0000320 void setAllIllegal() { LegalDstDomains.reset(); }
Guy Blank92d5ce32017-10-22 11:43:08 +0000321
322 /// \returns true if this closure has domains which are legal to reassign to.
Craig Topper59925352017-12-17 03:16:23 +0000323 bool hasLegalDstDomain() const { return LegalDstDomains.any(); }
Guy Blank92d5ce32017-10-22 11:43:08 +0000324
325 /// \returns true if is legal to reassign this closure to domain \p RD.
Craig Topper59925352017-12-17 03:16:23 +0000326 bool isLegal(RegDomain RD) const { return LegalDstDomains[RD]; }
Guy Blank92d5ce32017-10-22 11:43:08 +0000327
Craig Topper8ec56322017-12-20 19:36:43 +0000328 /// Mark this closure as illegal for reassignment to domain \p RD.
329 void setIllegal(RegDomain RD) { LegalDstDomains[RD] = false; }
330
Guy Blank92d5ce32017-10-22 11:43:08 +0000331 bool empty() const { return Edges.empty(); }
Craig Topper8ec56322017-12-20 19:36:43 +0000332
333 bool insertEdge(unsigned Reg) {
334 return Edges.insert(Reg).second;
335 }
336
337 using const_edge_iterator = DenseSet<unsigned>::const_iterator;
338 iterator_range<const_edge_iterator> edges() const {
339 return iterator_range<const_edge_iterator>(Edges.begin(), Edges.end());
340 }
341
342 void addInstruction(MachineInstr *I) {
343 Instrs.push_back(I);
344 }
345
346 ArrayRef<MachineInstr *> instructions() const {
347 return Instrs;
348 }
349
Guy Blank92d5ce32017-10-22 11:43:08 +0000350};
351
352class X86DomainReassignment : public MachineFunctionPass {
Craig Topper8ec56322017-12-20 19:36:43 +0000353 const X86Subtarget *STI;
354 MachineRegisterInfo *MRI;
355 const X86InstrInfo *TII;
356
357 /// All edges that are included in some closure
358 DenseSet<unsigned> EnclosedEdges;
359
360 /// All instructions that are included in some closure.
361 DenseMap<MachineInstr *, Closure *> EnclosedInstrs;
362
Guy Blank92d5ce32017-10-22 11:43:08 +0000363public:
364 static char ID;
365
366 X86DomainReassignment() : MachineFunctionPass(ID) {
367 initializeX86DomainReassignmentPass(*PassRegistry::getPassRegistry());
368 }
369
370 bool runOnMachineFunction(MachineFunction &MF) override;
371
372 void getAnalysisUsage(AnalysisUsage &AU) const override {
373 AU.setPreservesCFG();
374 MachineFunctionPass::getAnalysisUsage(AU);
375 }
376
377 StringRef getPassName() const override {
378 return "X86 Domain Reassignment Pass";
379 }
380
381private:
Guy Blank92d5ce32017-10-22 11:43:08 +0000382 /// A map of available Instruction Converters.
383 InstrConverterBaseMap Converters;
384
385 /// Initialize Converters map.
386 void initConverters();
Craig Topper8ec56322017-12-20 19:36:43 +0000387
388 /// Starting from \Reg, expand the closure as much as possible.
389 void buildClosure(Closure &, unsigned Reg);
390
391 /// Enqueue \p Reg to be considered for addition to the closure.
392 void visitRegister(Closure &, unsigned Reg, RegDomain &Domain,
393 SmallVectorImpl<unsigned> &Worklist);
394
395 /// Reassign the closure to \p Domain.
396 void reassign(const Closure &C, RegDomain Domain) const;
397
398 /// Add \p MI to the closure.
399 void encloseInstr(Closure &C, MachineInstr *MI);
400
401 /// /returns true if it is profitable to reassign the closure to \p Domain.
402 bool isReassignmentProfitable(const Closure &C, RegDomain Domain) const;
403
404 /// Calculate the total cost of reassigning the closure to \p Domain.
405 double calculateCost(const Closure &C, RegDomain Domain) const;
Guy Blank92d5ce32017-10-22 11:43:08 +0000406};
407
408char X86DomainReassignment::ID = 0;
409
410} // End anonymous namespace.
411
Craig Topper8ec56322017-12-20 19:36:43 +0000412void X86DomainReassignment::visitRegister(Closure &C, unsigned Reg,
413 RegDomain &Domain,
414 SmallVectorImpl<unsigned> &Worklist) {
Guy Blank92d5ce32017-10-22 11:43:08 +0000415 if (EnclosedEdges.count(Reg))
416 return;
417
418 if (!TargetRegisterInfo::isVirtualRegister(Reg))
419 return;
420
421 if (!MRI->hasOneDef(Reg))
422 return;
423
424 RegDomain RD = getDomain(MRI->getRegClass(Reg), MRI->getTargetRegisterInfo());
425 // First edge in closure sets the domain.
426 if (Domain == NoDomain)
427 Domain = RD;
428
429 if (Domain != RD)
430 return;
431
432 Worklist.push_back(Reg);
433}
434
Craig Topper8ec56322017-12-20 19:36:43 +0000435void X86DomainReassignment::encloseInstr(Closure &C, MachineInstr *MI) {
Guy Blank92d5ce32017-10-22 11:43:08 +0000436 auto I = EnclosedInstrs.find(MI);
437 if (I != EnclosedInstrs.end()) {
Craig Topper8ec56322017-12-20 19:36:43 +0000438 if (I->second != &C)
Guy Blank92d5ce32017-10-22 11:43:08 +0000439 // Instruction already belongs to another closure, avoid conflicts between
440 // closure and mark this closure as illegal.
Craig Topper8ec56322017-12-20 19:36:43 +0000441 C.setAllIllegal();
Guy Blank92d5ce32017-10-22 11:43:08 +0000442 return;
443 }
444
Craig Topper8ec56322017-12-20 19:36:43 +0000445 EnclosedInstrs[MI] = &C;
446 C.addInstruction(MI);
Guy Blank92d5ce32017-10-22 11:43:08 +0000447
448 // Mark closure as illegal for reassignment to domains, if there is no
449 // converter for the instruction or if the converter cannot convert the
450 // instruction.
Craig Topper8ec56322017-12-20 19:36:43 +0000451 for (int i = 0; i != NumDomains; ++i) {
452 if (C.isLegal((RegDomain)i)) {
Craig Topper59925352017-12-17 03:16:23 +0000453 InstrConverterBase *IC = Converters.lookup({i, MI->getOpcode()});
454 if (!IC || !IC->isLegal(MI, TII))
Craig Topper8ec56322017-12-20 19:36:43 +0000455 C.setIllegal((RegDomain)i);
Craig Topper59925352017-12-17 03:16:23 +0000456 }
457 }
Guy Blank92d5ce32017-10-22 11:43:08 +0000458}
459
Craig Topper8ec56322017-12-20 19:36:43 +0000460double X86DomainReassignment::calculateCost(const Closure &C,
461 RegDomain DstDomain) const {
462 assert(C.isLegal(DstDomain) && "Cannot calculate cost for illegal closure");
Guy Blank92d5ce32017-10-22 11:43:08 +0000463
464 double Cost = 0.0;
Craig Topper8ec56322017-12-20 19:36:43 +0000465 for (auto *MI : C.instructions())
Guy Blank92d5ce32017-10-22 11:43:08 +0000466 Cost +=
467 Converters.lookup({DstDomain, MI->getOpcode()})->getExtraCost(MI, MRI);
468 return Cost;
469}
470
Craig Topper8ec56322017-12-20 19:36:43 +0000471bool X86DomainReassignment::isReassignmentProfitable(const Closure &C,
472 RegDomain Domain) const {
473 return calculateCost(C, Domain) < 0.0;
Guy Blank92d5ce32017-10-22 11:43:08 +0000474}
475
Craig Topper8ec56322017-12-20 19:36:43 +0000476void X86DomainReassignment::reassign(const Closure &C, RegDomain Domain) const {
477 assert(C.isLegal(Domain) && "Cannot convert illegal closure");
Guy Blank92d5ce32017-10-22 11:43:08 +0000478
479 // Iterate all instructions in the closure, convert each one using the
480 // appropriate converter.
481 SmallVector<MachineInstr *, 8> ToErase;
Craig Topper8ec56322017-12-20 19:36:43 +0000482 for (auto *MI : C.instructions())
Guy Blank92d5ce32017-10-22 11:43:08 +0000483 if (Converters.lookup({Domain, MI->getOpcode()})
484 ->convertInstr(MI, TII, MRI))
485 ToErase.push_back(MI);
486
487 // Iterate all registers in the closure, replace them with registers in the
488 // destination domain.
Craig Topper8ec56322017-12-20 19:36:43 +0000489 for (unsigned Reg : C.edges()) {
Guy Blank92d5ce32017-10-22 11:43:08 +0000490 MRI->setRegClass(Reg, getDstRC(MRI->getRegClass(Reg), Domain));
491 for (auto &MO : MRI->use_operands(Reg)) {
492 if (MO.isReg())
493 // Remove all subregister references as they are not valid in the
494 // destination domain.
495 MO.setSubReg(0);
496 }
497 }
498
499 for (auto MI : ToErase)
500 MI->eraseFromParent();
501}
502
503/// \returns true when \p Reg is used as part of an address calculation in \p
504/// MI.
505static bool usedAsAddr(const MachineInstr &MI, unsigned Reg,
506 const TargetInstrInfo *TII) {
507 if (!MI.mayLoadOrStore())
508 return false;
509
510 const MCInstrDesc &Desc = TII->get(MI.getOpcode());
511 int MemOpStart = X86II::getMemoryOperandNo(Desc.TSFlags);
512 if (MemOpStart == -1)
513 return false;
514
515 MemOpStart += X86II::getOperandBias(Desc);
516 for (unsigned MemOpIdx = MemOpStart,
517 MemOpEnd = MemOpStart + X86::AddrNumOperands;
518 MemOpIdx < MemOpEnd; ++MemOpIdx) {
519 auto &Op = MI.getOperand(MemOpIdx);
520 if (Op.isReg() && Op.getReg() == Reg)
521 return true;
522 }
523 return false;
524}
525
Craig Topper8ec56322017-12-20 19:36:43 +0000526void X86DomainReassignment::buildClosure(Closure &C, unsigned Reg) {
Guy Blank92d5ce32017-10-22 11:43:08 +0000527 SmallVector<unsigned, 4> Worklist;
Craig Topper8ec56322017-12-20 19:36:43 +0000528 RegDomain Domain = NoDomain;
529 visitRegister(C, Reg, Domain, Worklist);
Guy Blank92d5ce32017-10-22 11:43:08 +0000530 while (!Worklist.empty()) {
531 unsigned CurReg = Worklist.pop_back_val();
532
533 // Register already in this closure.
Craig Topper8ec56322017-12-20 19:36:43 +0000534 if (!C.insertEdge(CurReg))
Guy Blank92d5ce32017-10-22 11:43:08 +0000535 continue;
536
537 MachineInstr *DefMI = MRI->getVRegDef(CurReg);
Craig Topper8ec56322017-12-20 19:36:43 +0000538 encloseInstr(C, DefMI);
Guy Blank92d5ce32017-10-22 11:43:08 +0000539
540 // Add register used by the defining MI to the worklist.
541 // Do not add registers which are used in address calculation, they will be
542 // added to a different closure.
543 int OpEnd = DefMI->getNumOperands();
544 const MCInstrDesc &Desc = DefMI->getDesc();
545 int MemOp = X86II::getMemoryOperandNo(Desc.TSFlags);
546 if (MemOp != -1)
547 MemOp += X86II::getOperandBias(Desc);
548 for (int OpIdx = 0; OpIdx < OpEnd; ++OpIdx) {
549 if (OpIdx == MemOp) {
550 // skip address calculation.
551 OpIdx += (X86::AddrNumOperands - 1);
552 continue;
553 }
554 auto &Op = DefMI->getOperand(OpIdx);
555 if (!Op.isReg() || !Op.isUse())
556 continue;
Craig Topper8ec56322017-12-20 19:36:43 +0000557 visitRegister(C, Op.getReg(), Domain, Worklist);
Guy Blank92d5ce32017-10-22 11:43:08 +0000558 }
559
560 // Expand closure through register uses.
561 for (auto &UseMI : MRI->use_nodbg_instructions(CurReg)) {
562 // We would like to avoid converting closures which calculare addresses,
563 // as this should remain in GPRs.
564 if (usedAsAddr(UseMI, CurReg, TII)) {
Craig Topper8ec56322017-12-20 19:36:43 +0000565 C.setAllIllegal();
Guy Blank92d5ce32017-10-22 11:43:08 +0000566 continue;
567 }
Craig Topper8ec56322017-12-20 19:36:43 +0000568 encloseInstr(C, &UseMI);
Guy Blank92d5ce32017-10-22 11:43:08 +0000569
570 for (auto &DefOp : UseMI.defs()) {
571 if (!DefOp.isReg())
572 continue;
573
574 unsigned DefReg = DefOp.getReg();
575 if (!TargetRegisterInfo::isVirtualRegister(DefReg)) {
Craig Topper8ec56322017-12-20 19:36:43 +0000576 C.setAllIllegal();
Guy Blank92d5ce32017-10-22 11:43:08 +0000577 continue;
578 }
Craig Topper8ec56322017-12-20 19:36:43 +0000579 visitRegister(C, DefReg, Domain, Worklist);
Guy Blank92d5ce32017-10-22 11:43:08 +0000580 }
581 }
582 }
583}
584
585void X86DomainReassignment::initConverters() {
586 Converters[{MaskDomain, TargetOpcode::PHI}] =
587 new InstrIgnore(TargetOpcode::PHI);
588
589 Converters[{MaskDomain, TargetOpcode::IMPLICIT_DEF}] =
590 new InstrDeleter(TargetOpcode::IMPLICIT_DEF);
591
592 Converters[{MaskDomain, TargetOpcode::INSERT_SUBREG}] =
593 new InstrReplaceWithCopy(TargetOpcode::INSERT_SUBREG, 2);
594
595 Converters[{MaskDomain, TargetOpcode::COPY}] =
596 new InstrCOPYReplacer(TargetOpcode::COPY, MaskDomain, TargetOpcode::COPY);
597
598 auto createReplacerDstCOPY = [&](unsigned From, unsigned To) {
599 Converters[{MaskDomain, From}] = new InstrReplacerDstCOPY(From, To);
600 };
601
602 createReplacerDstCOPY(X86::MOVZX32rm16, X86::KMOVWkm);
603 createReplacerDstCOPY(X86::MOVZX64rm16, X86::KMOVWkm);
604
605 createReplacerDstCOPY(X86::MOVZX32rr16, X86::KMOVWkk);
606 createReplacerDstCOPY(X86::MOVZX64rr16, X86::KMOVWkk);
607
608 if (STI->hasDQI()) {
609 createReplacerDstCOPY(X86::MOVZX16rm8, X86::KMOVBkm);
610 createReplacerDstCOPY(X86::MOVZX32rm8, X86::KMOVBkm);
611 createReplacerDstCOPY(X86::MOVZX64rm8, X86::KMOVBkm);
612
613 createReplacerDstCOPY(X86::MOVZX16rr8, X86::KMOVBkk);
614 createReplacerDstCOPY(X86::MOVZX32rr8, X86::KMOVBkk);
615 createReplacerDstCOPY(X86::MOVZX64rr8, X86::KMOVBkk);
616 }
617
618 auto createReplacer = [&](unsigned From, unsigned To) {
619 Converters[{MaskDomain, From}] = new InstrReplacer(From, To);
620 };
621
622 createReplacer(X86::MOV16rm, X86::KMOVWkm);
623 createReplacer(X86::MOV16mr, X86::KMOVWmk);
624 createReplacer(X86::MOV16rr, X86::KMOVWkk);
625 createReplacer(X86::SHR16ri, X86::KSHIFTRWri);
626 createReplacer(X86::SHL16ri, X86::KSHIFTLWri);
627 createReplacer(X86::NOT16r, X86::KNOTWrr);
628 createReplacer(X86::OR16rr, X86::KORWrr);
629 createReplacer(X86::AND16rr, X86::KANDWrr);
630 createReplacer(X86::XOR16rr, X86::KXORWrr);
631
632 if (STI->hasBWI()) {
633 createReplacer(X86::MOV32rm, X86::KMOVDkm);
634 createReplacer(X86::MOV64rm, X86::KMOVQkm);
635
636 createReplacer(X86::MOV32mr, X86::KMOVDmk);
637 createReplacer(X86::MOV64mr, X86::KMOVQmk);
638
639 createReplacer(X86::MOV32rr, X86::KMOVDkk);
640 createReplacer(X86::MOV64rr, X86::KMOVQkk);
641
642 createReplacer(X86::SHR32ri, X86::KSHIFTRDri);
643 createReplacer(X86::SHR64ri, X86::KSHIFTRQri);
644
645 createReplacer(X86::SHL32ri, X86::KSHIFTLDri);
646 createReplacer(X86::SHL64ri, X86::KSHIFTLQri);
647
648 createReplacer(X86::ADD32rr, X86::KADDDrr);
649 createReplacer(X86::ADD64rr, X86::KADDQrr);
650
651 createReplacer(X86::NOT32r, X86::KNOTDrr);
652 createReplacer(X86::NOT64r, X86::KNOTQrr);
653
654 createReplacer(X86::OR32rr, X86::KORDrr);
655 createReplacer(X86::OR64rr, X86::KORQrr);
656
657 createReplacer(X86::AND32rr, X86::KANDDrr);
658 createReplacer(X86::AND64rr, X86::KANDQrr);
659
660 createReplacer(X86::ANDN32rr, X86::KANDNDrr);
661 createReplacer(X86::ANDN64rr, X86::KANDNQrr);
662
663 createReplacer(X86::XOR32rr, X86::KXORDrr);
664 createReplacer(X86::XOR64rr, X86::KXORQrr);
665
666 createReplacer(X86::TEST32rr, X86::KTESTDrr);
667 createReplacer(X86::TEST64rr, X86::KTESTQrr);
668 }
669
670 if (STI->hasDQI()) {
671 createReplacer(X86::ADD8rr, X86::KADDBrr);
672 createReplacer(X86::ADD16rr, X86::KADDWrr);
673
674 createReplacer(X86::AND8rr, X86::KANDBrr);
675
676 createReplacer(X86::MOV8rm, X86::KMOVBkm);
677 createReplacer(X86::MOV8mr, X86::KMOVBmk);
678 createReplacer(X86::MOV8rr, X86::KMOVBkk);
679
680 createReplacer(X86::NOT8r, X86::KNOTBrr);
681
682 createReplacer(X86::OR8rr, X86::KORBrr);
683
684 createReplacer(X86::SHR8ri, X86::KSHIFTRBri);
685 createReplacer(X86::SHL8ri, X86::KSHIFTLBri);
686
687 createReplacer(X86::TEST8rr, X86::KTESTBrr);
688 createReplacer(X86::TEST16rr, X86::KTESTWrr);
689
690 createReplacer(X86::XOR8rr, X86::KXORBrr);
691 }
692}
693
694bool X86DomainReassignment::runOnMachineFunction(MachineFunction &MF) {
Matthias Braunf1caa282017-12-15 22:22:58 +0000695 if (skipFunction(MF.getFunction()))
Guy Blank92d5ce32017-10-22 11:43:08 +0000696 return false;
697 if (DisableX86DomainReassignment)
698 return false;
699
700 DEBUG(dbgs() << "***** Machine Function before Domain Reassignment *****\n");
701 DEBUG(MF.print(dbgs()));
702
703 STI = &MF.getSubtarget<X86Subtarget>();
704 // GPR->K is the only transformation currently supported, bail out early if no
705 // AVX512.
706 if (!STI->hasAVX512())
707 return false;
708
709 MRI = &MF.getRegInfo();
710 assert(MRI->isSSA() && "Expected MIR to be in SSA form");
711
712 TII = STI->getInstrInfo();
713 initConverters();
714 bool Changed = false;
715
Craig Topper8ec56322017-12-20 19:36:43 +0000716 EnclosedEdges.clear();
717 EnclosedInstrs.clear();
Guy Blank92d5ce32017-10-22 11:43:08 +0000718
719 std::vector<Closure> Closures;
720
721 // Go over all virtual registers and calculate a closure.
722 for (unsigned Idx = 0; Idx < MRI->getNumVirtRegs(); ++Idx) {
723 unsigned Reg = TargetRegisterInfo::index2VirtReg(Idx);
724
725 // GPR only current source domain supported.
726 if (!isGPR(MRI->getRegClass(Reg)))
727 continue;
728
729 // Register already in closure.
730 if (EnclosedEdges.count(Reg))
731 continue;
732
733 // Calculate closure starting with Reg.
Craig Topper8ec56322017-12-20 19:36:43 +0000734 Closure C({MaskDomain});
735 buildClosure(C, Reg);
Guy Blank92d5ce32017-10-22 11:43:08 +0000736
737 // Collect all closures that can potentially be converted.
738 if (!C.empty() && C.isLegal(MaskDomain))
739 Closures.push_back(std::move(C));
740 }
741
742 for (Closure &C : Closures)
Craig Topper8ec56322017-12-20 19:36:43 +0000743 if (isReassignmentProfitable(C, MaskDomain)) {
744 reassign(C, MaskDomain);
Guy Blank92d5ce32017-10-22 11:43:08 +0000745 ++NumClosuresConverted;
746 Changed = true;
747 }
748
749 for (auto I : Converters)
750 delete I.second;
751
752 DEBUG(dbgs() << "***** Machine Function after Domain Reassignment *****\n");
753 DEBUG(MF.print(dbgs()));
754
755 return Changed;
756}
757
758INITIALIZE_PASS(X86DomainReassignment, "x86-domain-reassignment",
Haojian Wu1afddd42017-10-23 09:02:59 +0000759 "X86 Domain Reassignment Pass", false, false)
Guy Blank92d5ce32017-10-22 11:43:08 +0000760
761/// Returns an instance of the Domain Reassignment pass.
762FunctionPass *llvm::createX86DomainReassignmentPass() {
763 return new X86DomainReassignment();
764}