LLVM: lib/CodeGen/DetectDeadLanes.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
36
37using namespace llvm;
38
39#define DEBUG_TYPE "detect-dead-lanes"
40
44 unsigned NumVirtRegs = MRI->getNumVirtRegs();
45 VRegInfos = std::unique_ptr<VRegInfo[]>(new VRegInfo[NumVirtRegs]);
46 WorklistMembers.resize(NumVirtRegs);
47 DefinedByCopy.resize(NumVirtRegs);
48}
49
50
51
53
54
55
56 switch (MI.getOpcode()) {
57 case TargetOpcode::COPY:
58 case TargetOpcode::PHI:
59 case TargetOpcode::INSERT_SUBREG:
60 case TargetOpcode::REG_SEQUENCE:
61 case TargetOpcode::EXTRACT_SUBREG:
62 return true;
63 }
64 return false;
65}
66
74 if (DstRC == SrcRC)
75 return false;
76
77 unsigned SrcSubIdx = MO.getSubReg();
78
80 unsigned DstSubIdx = 0;
81 switch (MI.getOpcode()) {
82 case TargetOpcode::INSERT_SUBREG:
84 DstSubIdx = MI.getOperand(3).getImm();
85 break;
86 case TargetOpcode::REG_SEQUENCE: {
88 DstSubIdx = MI.getOperand(OpNum+1).getImm();
89 break;
90 }
91 case TargetOpcode::EXTRACT_SUBREG: {
92 unsigned SubReg = MI.getOperand(2).getImm();
93 SrcSubIdx = TRI.composeSubRegIndices(SubReg, SrcSubIdx);
94 }
95 }
96
97 unsigned PreA, PreB;
98 if (SrcSubIdx && DstSubIdx)
99 return .getCommonSuperRegClass(SrcRC, SrcSubIdx, DstRC, DstSubIdx, PreA,
100 PreB);
101 if (SrcSubIdx)
102 return .getMatchingSuperRegClass(SrcRC, DstRC, SrcSubIdx);
103 if (DstSubIdx)
104 return .getMatchingSuperRegClass(DstRC, SrcRC, DstSubIdx);
105 return .getCommonSubClass(SrcRC, DstRC);
106}
107
108void DeadLaneDetector::addUsedLanesOnOperand(const MachineOperand &MO,
111 return;
114 return;
115
116 unsigned MOSubReg = MO.getSubReg();
117 if (MOSubReg != 0)
120
124
125 if ((UsedLanes & ~PrevUsedLanes).none())
126 return;
127
128
129 MORegInfo.UsedLanes = PrevUsedLanes | UsedLanes;
130 if (DefinedByCopy.test(MORegIdx))
131 PutInWorklist(MORegIdx);
132}
133
134void DeadLaneDetector::transferUsedLanesStep(const MachineInstr &MI,
138 continue;
140 addUsedLanesOnOperand(MO, UsedOnMO);
141 }
142}
143
151
152 switch (MI.getOpcode()) {
153 case TargetOpcode::COPY:
154 case TargetOpcode::PHI:
155 return UsedLanes;
156 case TargetOpcode::REG_SEQUENCE: {
157 assert(OpNum % 2 == 1);
158 unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
160 }
161 case TargetOpcode::INSERT_SUBREG: {
162 unsigned SubIdx = MI.getOperand(3).getImm();
165 if (OpNum == 2)
166 return MO2UsedLanes;
167
169 Register DefReg = Def.getReg();
173 MO1UsedLanes = UsedLanes & ~TRI->getSubRegIndexLaneMask(SubIdx);
174 else
176
178 return MO1UsedLanes;
179 }
180 case TargetOpcode::EXTRACT_SUBREG: {
182 unsigned SubIdx = MI.getOperand(2).getImm();
184 }
185 default:
186 llvm_unreachable("function must be called with COPY-like instruction");
187 }
188}
189
190void DeadLaneDetector::transferDefinedLanesStep(const MachineOperand &Use,
192 if (.readsReg())
193 return;
194
195
197 if (MI.getDesc().getNumDefs() != 1)
198 return;
199
200
201 if (MI.getOpcode() == TargetOpcode::PATCHPOINT)
202 return;
204 Register DefReg = Def.getReg();
206 return;
208 if (!DefinedByCopy.test(DefRegIdx))
209 return;
210
212 DefinedLanes =
215
216 VRegInfo &RegInfo = VRegInfos[DefRegIdx];
217 LaneBitmask PrevDefinedLanes = RegInfo.DefinedLanes;
218
219 if ((DefinedLanes & ~PrevDefinedLanes).none())
220 return;
221
222 RegInfo.DefinedLanes = PrevDefinedLanes | DefinedLanes;
223 PutInWorklist(DefRegIdx);
224}
225
229
230 switch (MI.getOpcode()) {
231 case TargetOpcode::REG_SEQUENCE: {
232 unsigned SubIdx = MI.getOperand(OpNum + 1).getImm();
235 break;
236 }
237 case TargetOpcode::INSERT_SUBREG: {
238 unsigned SubIdx = MI.getOperand(3).getImm();
239 if (OpNum == 2) {
242 } else {
243 assert(OpNum == 1 && "INSERT_SUBREG must have two operands");
244
245 DefinedLanes &= ~TRI->getSubRegIndexLaneMask(SubIdx);
246 }
247 break;
248 }
249 case TargetOpcode::EXTRACT_SUBREG: {
250 unsigned SubIdx = MI.getOperand(2).getImm();
251 assert(OpNum == 1 && "EXTRACT_SUBREG must have one register operand only");
253 break;
254 }
255 case TargetOpcode::COPY:
256 case TargetOpcode::PHI:
257 break;
258 default:
259 llvm_unreachable("function must be called with COPY-like instruction");
260 }
261
262 assert(Def.getSubReg() == 0 &&
263 "Should not have subregister defs in machine SSA phase");
265 return DefinedLanes;
266}
267
268LaneBitmask DeadLaneDetector::determineInitialDefinedLanes(unsigned Reg) {
269
270
273
277
278
280 DefinedByCopy.set(RegIdx);
281 PutInWorklist(RegIdx);
282
283 if (Def.isDead())
285
286
287
288
290
291
295 continue;
297 if (!MOReg)
298 continue;
299
305 } else {
310
312 continue;
313 }
314 unsigned MOSubReg = MO.getSubReg();
317 MOSubReg, MODefinedLanes);
318 }
319
322 }
323 return DefinedLanes;
324 }
325 if (DefMI.isImplicitDef() || Def.isDead())
327
329 "Should not have subregister defs in machine SSA phase");
331}
332
333LaneBitmask DeadLaneDetector::determineInitialUsedLanes(unsigned Reg) {
337 continue;
338
340 if (UseMI.isKill())
341 continue;
342
345 assert(UseMI.getDesc().getNumDefs() == 1);
348
349
351
352 bool CrossCopy = false;
356 if (CrossCopy)
358 }
359
360 if (!CrossCopy)
361 continue;
362 }
363 }
364
365
368
370 }
371 return UsedLanes;
372}
373
374namespace {
375
377public:
379
380 static char ID;
382
383 StringRef getPassName() const override { return "Detect Dead Lanes"; }
384
385 void getAnalysisUsage(AnalysisUsage &AU) const override {
388 }
389
390private:
391
392
393
394
395
396 std::pair<bool, bool>
399
402
404 bool *CrossCopy) const;
405
408};
409
410}
411
412char DetectDeadLanes::ID = 0;
414
416
417bool DetectDeadLanes::isUndefRegAtInput(
419 unsigned SubReg = MO.getSubReg();
421 return (RegInfo.DefinedLanes & RegInfo.UsedLanes & Mask).none();
422}
423
424bool DetectDeadLanes::isUndefInput(const DeadLaneDetector &DLD,
426 bool *CrossCopy) const {
428 return false;
431 return false;
433 Register DefReg = Def.getReg();
435 return false;
438 return false;
439
442 if (UsedLanes.any())
443 return false;
444
449 }
450 return true;
451}
452
454
456 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
458
459
461 Info.DefinedLanes = determineInitialDefinedLanes(Reg);
462 Info.UsedLanes = determineInitialUsedLanes(Reg);
463 }
464
465
466 while (!Worklist.empty()) {
467 unsigned RegIdx = Worklist.front();
468 Worklist.pop_front();
469 WorklistMembers.reset(RegIdx);
472
473
476 transferUsedLanesStep(MI, Info.UsedLanes);
477
479 transferDefinedLanesStep(MO, Info.DefinedLanes);
480 }
481
483 dbgs() << "Defined/Used lanes:\n";
484 for (unsigned RegIdx = 0; RegIdx < NumVirtRegs; ++RegIdx) {
490 }
491 dbgs() << "\n";
492 });
493}
494
495std::pair<bool, bool>
496DetectDeadLanes::modifySubRegisterOperandStatus(const DeadLaneDetector &DLD,
498 bool Changed = false;
499 bool Again = false;
500
505 continue;
507 if (!Reg.isVirtual())
508 continue;
513 << "Marking operand '" << MO << "' as dead in " << MI);
515 Changed = true;
516 }
518 bool CrossCopy = false;
519 if (isUndefRegAtInput(MO, RegInfo)) {
521 << "Marking operand '" << MO << "' as undef in " << MI);
523 Changed = true;
524 } else if (isUndefInput(DLD, MO, &CrossCopy)) {
526 << "Marking operand '" << MO << "' as undef in " << MI);
528 Changed = true;
529 if (CrossCopy)
530 Again = true;
531 }
532 }
533 }
534 }
535 }
536
537 return std::make_pair(Changed, Again);
538}
539
540bool DetectDeadLanes::runOnMachineFunction(MachineFunction &MF) {
541
542
543
544
545
547 if (->subRegLivenessEnabled()) {
548 LLVM_DEBUG(dbgs() << "Skipping Detect dead lanes pass\n");
549 return false;
550 }
551
552 TRI = MRI->getTargetRegisterInfo();
553
555
556 bool Changed = false;
557 bool Again;
558 do {
560 bool LocalChanged;
561 std::tie(LocalChanged, Again) = modifySubRegisterOperandStatus(DLD, MF);
562 Changed |= LocalChanged;
563 } while (Again);
564
565 return Changed;
566}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
Analysis containing CSE Info
static bool isCrossCopy(const MachineRegisterInfo &MRI, const MachineInstr &MI, const TargetRegisterClass *DstRC, const MachineOperand &MO)
static bool lowersToCopies(const MachineInstr &MI)
Returns true if MI will get lowered to a series of COPY instructions.
Analysis that tracks defined/used subregister lanes across COPY instructions and instructions that ge...
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Represent the analysis usage information of a pass.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
bool test(unsigned Idx) const
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
LaneBitmask transferUsedLanes(const MachineInstr &MI, LaneBitmask UsedLanes, const MachineOperand &MO) const
Given a mask UsedLanes used from the output of instruction MI determine which lanes are used from ope...
void computeSubRegisterLaneBitInfo()
Update the DefinedLanes and the UsedLanes for all virtual registers.
DeadLaneDetector(const MachineRegisterInfo *MRI, const TargetRegisterInfo *TRI)
bool isDefinedByCopy(unsigned RegIdx) const
LaneBitmask transferDefinedLanes(const MachineOperand &Def, unsigned OpNum, LaneBitmask DefinedLanes) const
Given a mask DefinedLanes of lanes defined at operand OpNum of COPY-like instruction,...
const VRegInfo & getVRegInfo(unsigned RegIdx) const
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
bool isImplicitDef() const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
unsigned getOperandNo() const
Returns the index of this operand in the instruction that it belongs to.
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setIsDead(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
def_iterator def_begin(Register RegNo) const
bool hasOneDef(Register RegNo) const
Return true if there is exactly one operand defining the specified register.
LaneBitmask getMaxLaneMaskForVReg(Register Reg) const
Returns a mask covering all bits that can appear in lane masks of subregisters of the virtual registe...
unsigned getNumVirtRegs() const
getNumVirtRegs - Return the number of virtual registers created.
Wrapper class representing virtual and physical registers.
static Register index2VirtReg(unsigned Index)
Convert a 0-based index to a virtual register number.
static unsigned virtReg2Index(Register Reg)
Convert a virtual register number to a 0-based index.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
StringRef - Represent a constant reference to a string, i.e.
const LaneBitmask LaneMask
const bool CoveredBySubRegs
Whether a combination of subregisters can cover every register in the class.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
LaneBitmask reverseComposeSubRegIndexLaneMask(unsigned IdxA, LaneBitmask LaneMask) const
Transform a lanemask given for a virtual register to the corresponding lanemask before using subregis...
LaneBitmask getSubRegIndexLaneMask(unsigned SubIdx) const
Return a bitmask representing the parts of a register that are covered by SubIdx.
LaneBitmask composeSubRegIndexLaneMask(unsigned IdxA, LaneBitmask Mask) const
Transforms a LaneMask computed for one subregister to the lanemask that would have been computed when...
A Use represents the edge between a Value definition and its users.
unsigned getOperandNo() const
Return the operand # of this use in its User.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
Printable PrintLaneMask(LaneBitmask LaneMask)
Create Printable object to print LaneBitmasks on a raw_ostream.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
char & DetectDeadLanesID
This pass adds dead/undef flags after analyzing subregister lanes.
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.
Contains a bitmask of which lanes of a given virtual register are defined and which ones are actually...
static constexpr LaneBitmask getAll()
constexpr bool none() const
constexpr bool any() const
static constexpr LaneBitmask getNone()