LLVM: lib/Target/Hexagon/HexagonNewValueJump.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
49#include
50#include
51#include
52
53using namespace llvm;
54
55#define DEBUG_TYPE "hexagon-nvj"
56
57STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created");
58
60 cl::desc("Maximum number of predicated jumps to be converted to "
61 "New Value Jump"));
62
64 cl::desc("Disable New Value Jumps"));
65
66namespace {
67
69 static char ID;
70
72
73 void getAnalysisUsage(AnalysisUsage &AU) const override {
74 AU.addRequired();
76 }
77
78 StringRef getPassName() const override { return "Hexagon NewValueJump"; }
79
80 bool runOnMachineFunction(MachineFunction &Fn) override;
81
82 MachineFunctionProperties getRequiredProperties() const override {
83 return MachineFunctionProperties().setNoVRegs();
84 }
85
86 private:
87 const HexagonInstrInfo *QII;
88 const HexagonRegisterInfo *QRI;
89
90
91 const MachineBranchProbabilityInfo *MBPI;
92
93 bool isNewValueJumpCandidate(const MachineInstr &MI) const;
94 };
95
96}
97
98char HexagonNewValueJump::ID = 0;
99
101 "Hexagon NewValueJump", false, false)
105
106
107
114
115 if (QII->isPredicated(*II))
116 return false;
117
118
119
120
121
122
123
124
125
126
127
128 if (II->getOpcode() == TargetOpcode::KILL)
129 return false;
130
132 return false;
133
135 return false;
136
138 return false;
139
140
141 [[maybe_unused]] bool HadDef = false;
143 if (!Op.isReg() || !Op.isDef())
144 continue;
145 if (HadDef)
146 return false;
147 HadDef = true;
148 if (!Hexagon::IntRegsRegClass.contains(Op.getReg()))
149 return false;
150 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 for (unsigned i = 0; i < II->getNumOperands(); ++i) {
168 if (II->getOperand(i).isReg() &&
169 (II->getOperand(i).isUse() || II->getOperand(i).isDef())) {
171 ++localII;
174 ++localBegin) {
175 if (localBegin == skip)
176 continue;
177
178 if (localBegin->modifiesRegister(Reg, TRI) ||
179 localBegin->readsRegister(Reg, TRI))
180 return false;
181 }
182 }
183 }
184 return true;
185}
186
187
188
189
190
193
194 if (MII->mayStore())
195 return false;
196
197
198 if (MII->isCall())
199 return false;
200
201
202 if (!afterRA) {
203
204
205
206
207
208
209
210
211
212 if (MII->getOpcode() == TargetOpcode::KILL ||
213 MII->getOpcode() == TargetOpcode::PHI ||
214 MII->getOpcode() == TargetOpcode::COPY)
215 return false;
216
217
218
219
220
221 if (MII->getOpcode() == Hexagon::LDriw_pred ||
222 MII->getOpcode() == Hexagon::STriw_pred)
223 return false;
224 }
225
226 return true;
227}
228
232 unsigned pReg,
233 bool secondReg,
234 bool optLocation,
238
239
240
241 if (!secondReg) {
243 if (!Op2.isImm())
244 return false;
245
246 int64_t v = Op2.getImm();
247 bool Valid = false;
248
249 switch (MI.getOpcode()) {
250 case Hexagon::C2_cmpeqi:
251 case Hexagon::C4_cmpneqi:
252 case Hexagon::C2_cmpgti:
253 case Hexagon::C4_cmpltei:
254 Valid = (isUInt<5>(v) || v == -1);
255 break;
256 case Hexagon::C2_cmpgtui:
257 case Hexagon::C4_cmplteui:
259 break;
260 case Hexagon::S2_tstbit_i:
261 case Hexagon::S4_ntstbit_i:
262 Valid = (v == 0);
263 break;
264 }
265
266 if (!Valid)
267 return false;
268 }
269
270 unsigned cmpReg1, cmpOp2 = 0;
271 cmpReg1 = MI.getOperand(1).getReg();
272
273 if (secondReg) {
274 cmpOp2 = MI.getOperand(2).getReg();
275
276
277
278 if (cmpReg1 == cmpOp2)
279 return false;
280
281
282
283
287 if (def->getOpcode() == TargetOpcode::COPY)
288 return false;
289 }
290 }
291
292
293
294 ++II;
296 if (localII->isDebugInstr())
297 continue;
298
299
300
302 return false;
303
304
305
306 if (localII->modifiesRegister(pReg, TRI) ||
307 localII->readsRegister(pReg, TRI))
308 return false;
309
310
311
312
313
314
315
316
317 if (localII->modifiesRegister(cmpReg1, TRI) ||
318 (secondReg && localII->modifiesRegister(cmpOp2, TRI)))
319 return false;
320 }
321 return true;
322}
323
324
325
327 bool secondRegNewified,
330 *MBPI) {
331 bool taken = false;
335
337 taken = true;
338
339 switch (MI->getOpcode()) {
340 case Hexagon::C2_cmpeq:
341 return taken ? Hexagon::J4_cmpeq_t_jumpnv_t
342 : Hexagon::J4_cmpeq_t_jumpnv_nt;
343
344 case Hexagon::C2_cmpeqi:
345 if (reg >= 0)
346 return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t
347 : Hexagon::J4_cmpeqi_t_jumpnv_nt;
348 return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t
349 : Hexagon::J4_cmpeqn1_t_jumpnv_nt;
350
351 case Hexagon::C4_cmpneqi:
352 if (reg >= 0)
353 return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t
354 : Hexagon::J4_cmpeqi_f_jumpnv_nt;
355 return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t :
356 Hexagon::J4_cmpeqn1_f_jumpnv_nt;
357
358 case Hexagon::C2_cmpgt:
359 if (secondRegNewified)
360 return taken ? Hexagon::J4_cmplt_t_jumpnv_t
361 : Hexagon::J4_cmplt_t_jumpnv_nt;
362 return taken ? Hexagon::J4_cmpgt_t_jumpnv_t
363 : Hexagon::J4_cmpgt_t_jumpnv_nt;
364
365 case Hexagon::C2_cmpgti:
366 if (reg >= 0)
367 return taken ? Hexagon::J4_cmpgti_t_jumpnv_t
368 : Hexagon::J4_cmpgti_t_jumpnv_nt;
369 return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t
370 : Hexagon::J4_cmpgtn1_t_jumpnv_nt;
371
372 case Hexagon::C2_cmpgtu:
373 if (secondRegNewified)
374 return taken ? Hexagon::J4_cmpltu_t_jumpnv_t
375 : Hexagon::J4_cmpltu_t_jumpnv_nt;
376 return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t
377 : Hexagon::J4_cmpgtu_t_jumpnv_nt;
378
379 case Hexagon::C2_cmpgtui:
380 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t
381 : Hexagon::J4_cmpgtui_t_jumpnv_nt;
382
383 case Hexagon::C4_cmpneq:
384 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t
385 : Hexagon::J4_cmpeq_f_jumpnv_nt;
386
387 case Hexagon::C4_cmplte:
388 if (secondRegNewified)
389 return taken ? Hexagon::J4_cmplt_f_jumpnv_t
390 : Hexagon::J4_cmplt_f_jumpnv_nt;
391 return taken ? Hexagon::J4_cmpgt_f_jumpnv_t
392 : Hexagon::J4_cmpgt_f_jumpnv_nt;
393
394 case Hexagon::C4_cmplteu:
395 if (secondRegNewified)
396 return taken ? Hexagon::J4_cmpltu_f_jumpnv_t
397 : Hexagon::J4_cmpltu_f_jumpnv_nt;
398 return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t
399 : Hexagon::J4_cmpgtu_f_jumpnv_nt;
400
401 case Hexagon::C4_cmpltei:
402 if (reg >= 0)
403 return taken ? Hexagon::J4_cmpgti_f_jumpnv_t
404 : Hexagon::J4_cmpgti_f_jumpnv_nt;
405 return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t
406 : Hexagon::J4_cmpgtn1_f_jumpnv_nt;
407
408 case Hexagon::C4_cmplteui:
409 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t
410 : Hexagon::J4_cmpgtui_f_jumpnv_nt;
411
412 default:
413 llvm_unreachable("Could not find matching New Value Jump instruction.");
414 }
415
416 return 0;
417}
418
419bool HexagonNewValueJump::isNewValueJumpCandidate(
421 switch (MI.getOpcode()) {
422 case Hexagon::C2_cmpeq:
423 case Hexagon::C2_cmpeqi:
424 case Hexagon::C2_cmpgt:
425 case Hexagon::C2_cmpgti:
426 case Hexagon::C2_cmpgtu:
427 case Hexagon::C2_cmpgtui:
428 case Hexagon::C4_cmpneq:
429 case Hexagon::C4_cmpneqi:
430 case Hexagon::C4_cmplte:
431 case Hexagon::C4_cmplteu:
432 case Hexagon::C4_cmpltei:
433 case Hexagon::C4_cmplteui:
434 return true;
435
436 default:
437 return false;
438 }
439}
440
441bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
442 LLVM_DEBUG(dbgs() << "********** Hexagon New Value Jump **********\n"
443 << "********** Function: " << MF.getName() << "\n");
444
446 return false;
447
448
449
450
451 QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
452 QRI = static_cast<const HexagonRegisterInfo *>(
454 MBPI = &getAnalysis().getMBPI();
455
457 !MF.getSubtarget().useNewValueJumps())
458 return false;
459
461 int nvjGenerated = 0;
462
463
465 MBBb != MBBe; ++MBBb) {
466 MachineBasicBlock *MBB = &*MBBb;
467
471 << "********** dumping instr bottom up **********\n");
472 bool foundJump = false;
473 bool foundCompare = false;
474 bool invertPredicate = false;
475 unsigned predReg = 0;
476 unsigned cmpReg1 = 0;
477 int cmpOp2 = 0;
480 MachineInstr *cmpInstr = nullptr, *jmpInstr = nullptr;
481 MachineBasicBlock *jmpTarget = nullptr;
482 bool afterRA = false;
483 bool isSecondOpReg = false;
484 bool isSecondOpNewified = false;
485
487 MII != E;) {
488 MachineInstr &MI = *--MII;
489 if (MI.isDebugInstr()) {
490 continue;
491 }
492
493 if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))
494 break;
495
497
498 if (!foundJump && (MI.getOpcode() == Hexagon::J2_jumpt ||
499 MI.getOpcode() == Hexagon::J2_jumptpt ||
500 MI.getOpcode() == Hexagon::J2_jumpf ||
501 MI.getOpcode() == Hexagon::J2_jumpfpt ||
502 MI.getOpcode() == Hexagon::J2_jumptnewpt ||
503 MI.getOpcode() == Hexagon::J2_jumptnew ||
504 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
505 MI.getOpcode() == Hexagon::J2_jumpfnew)) {
506
507
508 jmpPos = MII;
509 jmpInstr = &MI;
510 predReg = MI.getOperand(0).getReg();
511 afterRA = Register::isPhysicalRegister(predReg);
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528 bool predLive = false;
529 for (const MachineBasicBlock *SuccMBB : MBB->successors())
530 if (SuccMBB->isLiveIn(predReg))
531 predLive = true;
532 if (predLive)
533 break;
534
535 if (.getOperand(1).isMBB())
536 continue;
537 jmpTarget = MI.getOperand(1).getMBB();
538 foundJump = true;
539 if (MI.getOpcode() == Hexagon::J2_jumpf ||
540 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
541 MI.getOpcode() == Hexagon::J2_jumpfnew) {
542 invertPredicate = true;
543 }
544 continue;
545 }
546
547
548
549
550 if (foundJump && MI.getNumOperands() == 0)
551 break;
552
553 if (foundJump && !foundCompare && MI.getOperand(0).isReg() &&
554 MI.getOperand(0).getReg() == predReg) {
555
556 if (isNewValueJumpCandidate(MI)) {
558 (MI.getDesc().isCompare()) &&
559 "Only compare instruction can be collapsed into New Value Jump");
560 isSecondOpReg = MI.getOperand(2).isReg();
561
563 afterRA, jmpPos, MF))
564 break;
565
566 cmpInstr = &MI;
567 cmpPos = MII;
568 foundCompare = true;
569
570
571
572 cmpReg1 = MI.getOperand(1).getReg();
573
574 if (isSecondOpReg)
575 cmpOp2 = MI.getOperand(2).getReg();
576 else
577 cmpOp2 = MI.getOperand(2).getImm();
578 continue;
579 }
580 }
581
582 if (foundCompare && foundJump) {
583
585 break;
586
587 bool foundFeeder = false;
589 if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef() &&
590 (MI.getOperand(0).getReg() == cmpReg1 ||
591 (isSecondOpReg &&
592 MI.getOperand(0).getReg() == (unsigned)cmpOp2))) {
593
594 Register feederReg = MI.getOperand(0).getReg();
595
596
597
598
599
600
601
602 if (feederReg == cmpReg1) {
604 if (!isSecondOpReg)
605 break;
606 else
607 continue;
608 } else
609 foundFeeder = true;
610 }
611
612 if (!foundFeeder && isSecondOpReg && feederReg == (unsigned)cmpOp2)
614 break;
615
616 if (isSecondOpReg) {
617
618
619 unsigned COp = cmpInstr->getOpcode();
620 if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) &&
621 (feederReg == (unsigned)cmpOp2)) {
622 unsigned tmp = cmpReg1;
623 cmpReg1 = cmpOp2;
624 cmpOp2 = tmp;
625 }
626
627
628
629
630 if (feederReg == (unsigned)cmpOp2)
631 isSecondOpNewified = true;
632 }
633
634
635
636
637
638 auto TransferKills = [jmpPos,cmpPos] (MachineInstr &MI) {
639 for (MachineOperand &MO : MI.operands()) {
640 if (!MO.isReg() || !MO.isUse())
641 continue;
643 for (auto I = std::next(MI.getIterator()); I != jmpPos; ++I) {
644 if (I == cmpPos)
645 continue;
646 for (MachineOperand &Op : I->operands()) {
647 if (.isReg() ||
.isUse() ||
.isKill())
648 continue;
649 if (Op.getReg() != UseR)
650 continue;
651
652
653 Op.setIsKill(false);
654 MO.setIsKill(true);
655 return;
656 }
657 }
658 }
659 };
660
661 TransferKills(*feederPos);
662 TransferKills(*cmpPos);
663 bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI);
664 bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI);
665
667 MBB->splice(jmpPos, MI.getParent(), cmpInstr);
669 MachineInstr *NewMI;
670
671 assert((isNewValueJumpCandidate(*cmpInstr)) &&
672 "This compare is not a New Value Jump candidate.");
674 isSecondOpNewified,
675 jmpTarget, MBPI);
676 if (invertPredicate)
678
679 if (isSecondOpReg)
680 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))
684
685 else
686 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))
690
691 assert(NewMI && "New Value Jump Instruction Not created!");
692 (void)NewMI;
700 jmpInstr->eraseFromParent();
701 ++nvjGenerated;
702 ++NumNVJGenerated;
703 break;
704 }
705 }
706 }
707 }
708
709 return true;
710}
711
713 return new HexagonNewValueJump();
714}
unsigned const MachineRegisterInfo * MRI
for(const MachineOperand &MO :llvm::drop_begin(OldMI.operands(), Desc.getNumOperands()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< bool > DisableNewValueJumps("disable-nvjump", cl::Hidden, cl::desc("Disable New Value Jumps"))
static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII, const TargetRegisterInfo *TRI, MachineBasicBlock::iterator II, unsigned pReg, bool secondReg, bool optLocation, MachineBasicBlock::iterator end, MachineFunction &MF)
Definition HexagonNewValueJump.cpp:229
static bool commonChecksToProhibitNewValueJump(bool afterRA, MachineBasicBlock::iterator MII)
Definition HexagonNewValueJump.cpp:191
hexagon Hexagon static false bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII, const TargetRegisterInfo *TRI, MachineBasicBlock::iterator II, MachineBasicBlock::iterator end, MachineBasicBlock::iterator skip, MachineFunction &MF)
Definition HexagonNewValueJump.cpp:108
static cl::opt< int > DbgNVJCount("nvj-count", cl::init(-1), cl::Hidden, cl::desc("Maximum number of predicated jumps to be converted to " "New Value Jump"))
static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, bool secondRegNewified, MachineBasicBlock *jmpTarget, const MachineBranchProbabilityInfo *MBPI)
Definition HexagonNewValueJump.cpp:326
static bool skip(DataExtractor &Data, uint64_t &Offset, bool SkippedRanges)
Skip an InlineInfo object in the specified data at the specified offset.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
AnalysisUsage & addRequired()
FunctionPass class - This class is used to implement most global optimizations.
unsigned getInvertedPredicatedOpcode(const int Opc) const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
LLVM_ABI void dump() const
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) 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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
static constexpr bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#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.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createHexagonNewValueJump()
Definition HexagonNewValueJump.cpp:712
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
unsigned getKillRegState(bool B)
DWARFExpression::Operation Op