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 llvm {
67
70
71}
72
73namespace {
74
76 static char ID;
77
79
83 }
84
86
88
91 MachineFunctionProperties::Property::NoVRegs);
92 }
93
94 private:
97
98
100
101 bool isNewValueJumpCandidate(const MachineInstr &MI) const;
102 };
103
104}
105
106char HexagonNewValueJump::ID = 0;
107
109 "Hexagon NewValueJump", false, false)
113
114
115
122
123 if (QII->isPredicated(*II))
124 return false;
125
126
127
128
129
130
131
132
133
134
135
136 if (II->getOpcode() == TargetOpcode::KILL)
137 return false;
138
139 if (II->isImplicitDef())
140 return false;
141
142 if (QII->isSolo(*II))
143 return false;
144
145 if (QII->isFloat(*II))
146 return false;
147
148
149 bool HadDef = false;
151 if (.isReg() ||
.isDef())
152 continue;
153 if (HadDef)
154 return false;
155 HadDef = true;
156 if (!Hexagon::IntRegsRegClass.contains(Op.getReg()))
157 return false;
158 }
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175 for (unsigned i = 0; i < II->getNumOperands(); ++i) {
176 if (II->getOperand(i).isReg() &&
177 (II->getOperand(i).isUse() || II->getOperand(i).isDef())) {
179 ++localII;
180 Register Reg = II->getOperand(i).getReg();
182 ++localBegin) {
183 if (localBegin == skip)
184 continue;
185
186 if (localBegin->modifiesRegister(Reg, TRI) ||
187 localBegin->readsRegister(Reg, TRI))
188 return false;
189 }
190 }
191 }
192 return true;
193}
194
195
196
197
198
201
202 if (MII->mayStore())
203 return false;
204
205
206 if (MII->isCall())
207 return false;
208
209
210 if (!afterRA) {
211
212
213
214
215
216
217
218
219
220 if (MII->getOpcode() == TargetOpcode::KILL ||
221 MII->getOpcode() == TargetOpcode::PHI ||
222 MII->getOpcode() == TargetOpcode::COPY)
223 return false;
224
225
226
227
228
229 if (MII->getOpcode() == Hexagon::LDriw_pred ||
230 MII->getOpcode() == Hexagon::STriw_pred)
231 return false;
232 }
233
234 return true;
235}
236
240 unsigned pReg,
241 bool secondReg,
242 bool optLocation,
246
247
248
249 if (!secondReg) {
251 if (!Op2.isImm())
252 return false;
253
254 int64_t v = Op2.getImm();
255 bool Valid = false;
256
257 switch (MI.getOpcode()) {
258 case Hexagon::C2_cmpeqi:
259 case Hexagon::C4_cmpneqi:
260 case Hexagon::C2_cmpgti:
261 case Hexagon::C4_cmpltei:
262 Valid = (isUInt<5>(v) || v == -1);
263 break;
264 case Hexagon::C2_cmpgtui:
265 case Hexagon::C4_cmplteui:
266 Valid = isUInt<5>(v);
267 break;
268 case Hexagon::S2_tstbit_i:
269 case Hexagon::S4_ntstbit_i:
270 Valid = (v == 0);
271 break;
272 }
273
274 if (!Valid)
275 return false;
276 }
277
278 unsigned cmpReg1, cmpOp2 = 0;
279 cmpReg1 = MI.getOperand(1).getReg();
280
281 if (secondReg) {
282 cmpOp2 = MI.getOperand(2).getReg();
283
284
285
286 if (cmpReg1 == cmpOp2)
287 return false;
288
289
290
291
295 if (def->getOpcode() == TargetOpcode::COPY)
296 return false;
297 }
298 }
299
300
301
302 ++II;
304 if (localII->isDebugInstr())
305 continue;
306
307
308
310 return false;
311
312
313
314 if (localII->modifiesRegister(pReg, TRI) ||
315 localII->readsRegister(pReg, TRI))
316 return false;
317
318
319
320
321
322
323
324
325 if (localII->modifiesRegister(cmpReg1, TRI) ||
326 (secondReg && localII->modifiesRegister(cmpOp2, TRI)))
327 return false;
328 }
329 return true;
330}
331
332
333
335 bool secondRegNewified,
338 *MBPI) {
339 bool taken = false;
343
345 taken = true;
346
347 switch (MI->getOpcode()) {
348 case Hexagon::C2_cmpeq:
349 return taken ? Hexagon::J4_cmpeq_t_jumpnv_t
350 : Hexagon::J4_cmpeq_t_jumpnv_nt;
351
352 case Hexagon::C2_cmpeqi:
353 if (reg >= 0)
354 return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t
355 : Hexagon::J4_cmpeqi_t_jumpnv_nt;
356 return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t
357 : Hexagon::J4_cmpeqn1_t_jumpnv_nt;
358
359 case Hexagon::C4_cmpneqi:
360 if (reg >= 0)
361 return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t
362 : Hexagon::J4_cmpeqi_f_jumpnv_nt;
363 return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t :
364 Hexagon::J4_cmpeqn1_f_jumpnv_nt;
365
366 case Hexagon::C2_cmpgt:
367 if (secondRegNewified)
368 return taken ? Hexagon::J4_cmplt_t_jumpnv_t
369 : Hexagon::J4_cmplt_t_jumpnv_nt;
370 return taken ? Hexagon::J4_cmpgt_t_jumpnv_t
371 : Hexagon::J4_cmpgt_t_jumpnv_nt;
372
373 case Hexagon::C2_cmpgti:
374 if (reg >= 0)
375 return taken ? Hexagon::J4_cmpgti_t_jumpnv_t
376 : Hexagon::J4_cmpgti_t_jumpnv_nt;
377 return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t
378 : Hexagon::J4_cmpgtn1_t_jumpnv_nt;
379
380 case Hexagon::C2_cmpgtu:
381 if (secondRegNewified)
382 return taken ? Hexagon::J4_cmpltu_t_jumpnv_t
383 : Hexagon::J4_cmpltu_t_jumpnv_nt;
384 return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t
385 : Hexagon::J4_cmpgtu_t_jumpnv_nt;
386
387 case Hexagon::C2_cmpgtui:
388 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t
389 : Hexagon::J4_cmpgtui_t_jumpnv_nt;
390
391 case Hexagon::C4_cmpneq:
392 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t
393 : Hexagon::J4_cmpeq_f_jumpnv_nt;
394
395 case Hexagon::C4_cmplte:
396 if (secondRegNewified)
397 return taken ? Hexagon::J4_cmplt_f_jumpnv_t
398 : Hexagon::J4_cmplt_f_jumpnv_nt;
399 return taken ? Hexagon::J4_cmpgt_f_jumpnv_t
400 : Hexagon::J4_cmpgt_f_jumpnv_nt;
401
402 case Hexagon::C4_cmplteu:
403 if (secondRegNewified)
404 return taken ? Hexagon::J4_cmpltu_f_jumpnv_t
405 : Hexagon::J4_cmpltu_f_jumpnv_nt;
406 return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t
407 : Hexagon::J4_cmpgtu_f_jumpnv_nt;
408
409 case Hexagon::C4_cmpltei:
410 if (reg >= 0)
411 return taken ? Hexagon::J4_cmpgti_f_jumpnv_t
412 : Hexagon::J4_cmpgti_f_jumpnv_nt;
413 return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t
414 : Hexagon::J4_cmpgtn1_f_jumpnv_nt;
415
416 case Hexagon::C4_cmplteui:
417 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t
418 : Hexagon::J4_cmpgtui_f_jumpnv_nt;
419
420 default:
421 llvm_unreachable("Could not find matching New Value Jump instruction.");
422 }
423
424 return 0;
425}
426
427bool HexagonNewValueJump::isNewValueJumpCandidate(
429 switch (MI.getOpcode()) {
430 case Hexagon::C2_cmpeq:
431 case Hexagon::C2_cmpeqi:
432 case Hexagon::C2_cmpgt:
433 case Hexagon::C2_cmpgti:
434 case Hexagon::C2_cmpgtu:
435 case Hexagon::C2_cmpgtui:
436 case Hexagon::C4_cmpneq:
437 case Hexagon::C4_cmpneqi:
438 case Hexagon::C4_cmplte:
439 case Hexagon::C4_cmplteu:
440 case Hexagon::C4_cmpltei:
441 case Hexagon::C4_cmplteui:
442 return true;
443
444 default:
445 return false;
446 }
447}
448
449bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
450 LLVM_DEBUG(dbgs() << "********** Hexagon New Value Jump **********\n"
451 << "********** Function: " << MF.getName() << "\n");
452
454 return false;
455
456
457
458
462 MBPI = &getAnalysis().getMBPI();
463
466 return false;
467
469 int nvjGenerated = 0;
470
471
473 MBBb != MBBe; ++MBBb) {
475
479 << "********** dumping instr bottom up **********\n");
480 bool foundJump = false;
481 bool foundCompare = false;
482 bool invertPredicate = false;
483 unsigned predReg = 0;
484 unsigned cmpReg1 = 0;
485 int cmpOp2 = 0;
488 MachineInstr *cmpInstr = nullptr, *jmpInstr = nullptr;
490 bool afterRA = false;
491 bool isSecondOpReg = false;
492 bool isSecondOpNewified = false;
493
495 MII != E;) {
497 if (MI.isDebugInstr()) {
498 continue;
499 }
500
501 if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))
502 break;
503
505
506 if (!foundJump && (MI.getOpcode() == Hexagon::J2_jumpt ||
507 MI.getOpcode() == Hexagon::J2_jumptpt ||
508 MI.getOpcode() == Hexagon::J2_jumpf ||
509 MI.getOpcode() == Hexagon::J2_jumpfpt ||
510 MI.getOpcode() == Hexagon::J2_jumptnewpt ||
511 MI.getOpcode() == Hexagon::J2_jumptnew ||
512 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
513 MI.getOpcode() == Hexagon::J2_jumpfnew)) {
514
515
516 jmpPos = MII;
517 jmpInstr = &MI;
518 predReg = MI.getOperand(0).getReg();
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536 bool predLive = false;
538 if (SuccMBB->isLiveIn(predReg))
539 predLive = true;
540 if (predLive)
541 break;
542
543 if (.getOperand(1).isMBB())
544 continue;
545 jmpTarget = MI.getOperand(1).getMBB();
546 foundJump = true;
547 if (MI.getOpcode() == Hexagon::J2_jumpf ||
548 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
549 MI.getOpcode() == Hexagon::J2_jumpfnew) {
550 invertPredicate = true;
551 }
552 continue;
553 }
554
555
556
557
558 if (foundJump && MI.getNumOperands() == 0)
559 break;
560
561 if (foundJump && !foundCompare && MI.getOperand(0).isReg() &&
562 MI.getOperand(0).getReg() == predReg) {
563
564 if (isNewValueJumpCandidate(MI)) {
566 (MI.getDesc().isCompare()) &&
567 "Only compare instruction can be collapsed into New Value Jump");
568 isSecondOpReg = MI.getOperand(2).isReg();
569
571 afterRA, jmpPos, MF))
572 break;
573
574 cmpInstr = &MI;
575 cmpPos = MII;
576 foundCompare = true;
577
578
579
580 cmpReg1 = MI.getOperand(1).getReg();
581
582 if (isSecondOpReg)
583 cmpOp2 = MI.getOperand(2).getReg();
584 else
585 cmpOp2 = MI.getOperand(2).getImm();
586 continue;
587 }
588 }
589
590 if (foundCompare && foundJump) {
591
593 break;
594
595 bool foundFeeder = false;
597 if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef() &&
598 (MI.getOperand(0).getReg() == cmpReg1 ||
599 (isSecondOpReg &&
600 MI.getOperand(0).getReg() == (unsigned)cmpOp2))) {
601
602 Register feederReg = MI.getOperand(0).getReg();
603
604
605
606
607
608
609
610 if (feederReg == cmpReg1) {
612 if (!isSecondOpReg)
613 break;
614 else
615 continue;
616 } else
617 foundFeeder = true;
618 }
619
620 if (!foundFeeder && isSecondOpReg && feederReg == (unsigned)cmpOp2)
622 break;
623
624 if (isSecondOpReg) {
625
626
627 unsigned COp = cmpInstr->getOpcode();
628 if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) &&
629 (feederReg == (unsigned)cmpOp2)) {
630 unsigned tmp = cmpReg1;
631 cmpReg1 = cmpOp2;
632 cmpOp2 = tmp;
633 }
634
635
636
637
638 if (feederReg == (unsigned)cmpOp2)
639 isSecondOpNewified = true;
640 }
641
642
643
644
645
646 auto TransferKills = [jmpPos,cmpPos] (MachineInstr &MI) {
648 if (!MO.isReg() || !MO.isUse())
649 continue;
651 for (auto I = std::next(MI.getIterator()); I != jmpPos; ++I) {
652 if (I == cmpPos)
653 continue;
655 if (.isReg() ||
.isUse() ||
.isKill())
656 continue;
657 if (Op.getReg() != UseR)
658 continue;
659
660
661 Op.setIsKill(false);
662 MO.setIsKill(true);
663 return;
664 }
665 }
666 }
667 };
668
669 TransferKills(*feederPos);
670 TransferKills(*cmpPos);
671 bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI);
672 bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI);
673
675 MBB->splice(jmpPos, MI.getParent(), cmpInstr);
678
679 assert((isNewValueJumpCandidate(*cmpInstr)) &&
680 "This compare is not a New Value Jump candidate.");
682 isSecondOpNewified,
683 jmpTarget, MBPI);
684 if (invertPredicate)
685 opc = QII->getInvertedPredicatedOpcode(opc);
686
687 if (isSecondOpReg)
688 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))
692
693 else
694 NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc))
698
699 assert(NewMI && "New Value Jump Instruction Not created!");
700 (void)NewMI;
708 jmpInstr->eraseFromParent();
709 ++nvjGenerated;
710 ++NumNVJGenerated;
711 break;
712 }
713 }
714 }
715 }
716
717 return true;
718}
719
721 return new HexagonNewValueJump();
722}
unsigned const MachineRegisterInfo * MRI
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)
static bool commonChecksToProhibitNewValueJump(bool afterRA, MachineBasicBlock::iterator MII)
hexagon Hexagon static false bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII, const TargetRegisterInfo *TRI, MachineBasicBlock::iterator II, MachineBasicBlock::iterator end, MachineBasicBlock::iterator skip, MachineFunction &MF)
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"))
hexagon Hexagon NewValueJump
static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, bool secondRegNewified, MachineBasicBlock *jmpTarget, const MachineBranchProbabilityInfo *MBPI)
static bool skip(DataExtractor &Data, uint64_t &Offset, bool SkippedRanges)
Skip an InlineInfo object in the specified data at the specified offset.
unsigned const TargetRegisterInfo * TRI
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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
bool useNewValueJumps() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
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 '...
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.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
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.
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.
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,...
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
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.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
virtual const TargetInstrInfo * getInstrInfo() const
#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.
void initializeHexagonNewValueJumpPass(PassRegistry &)
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createHexagonNewValueJump()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned getKillRegState(bool B)