55#define DEBUG_TYPE "hexagon-nvj"
57STATISTIC(NumNVJGenerated,
"Number of New Value Jump Instructions created");
60 cl::desc(
"Maximum number of predicated jumps to be converted to "
64 cl::desc(
"Disable New Value Jumps"));
73 void getAnalysisUsage(AnalysisUsage &AU)
const override {
74 AU.
addRequired<MachineBranchProbabilityInfoWrapperPass>();
78 StringRef getPassName()
const override {
return "Hexagon NewValueJump"; }
80 bool runOnMachineFunction(MachineFunction &Fn)
override;
82 MachineFunctionProperties getRequiredProperties()
const override {
83 return MachineFunctionProperties().setNoVRegs();
87 const HexagonInstrInfo *QII;
88 const HexagonRegisterInfo *QRI;
91 const MachineBranchProbabilityInfo *MBPI;
93 bool isNewValueJumpCandidate(
const MachineInstr &
MI)
const;
98char HexagonNewValueJump::ID = 0;
101 "Hexagon NewValueJump",
false,
false)
115 if (QII->isPredicated(*
II))
128 if (
II->getOpcode() == TargetOpcode::KILL)
131 if (
II->isImplicitDef())
134 if (QII->isSolo(*
II))
137 if (QII->isFloat(*
II))
143 if (!Op.isReg() || !Op.isDef())
148 if (!Hexagon::IntRegsRegClass.contains(Op.getReg()))
167 for (
unsigned i = 0; i <
II->getNumOperands(); ++i) {
168 if (
II->getOperand(i).isReg() &&
169 (
II->getOperand(i).isUse() ||
II->getOperand(i).isDef())) {
175 if (localBegin ==
skip)
178 if (localBegin->modifiesRegister(
Reg,
TRI) ||
179 localBegin->readsRegister(
Reg,
TRI))
212 if (MII->getOpcode() == TargetOpcode::KILL ||
213 MII->getOpcode() == TargetOpcode::PHI ||
214 MII->getOpcode() == TargetOpcode::COPY)
221 if (MII->getOpcode() == Hexagon::LDriw_pred ||
222 MII->getOpcode() == Hexagon::STriw_pred)
249 switch (
MI.getOpcode()) {
250 case Hexagon::C2_cmpeqi:
251 case Hexagon::C4_cmpneqi:
252 case Hexagon::C2_cmpgti:
253 case Hexagon::C4_cmpltei:
256 case Hexagon::C2_cmpgtui:
257 case Hexagon::C4_cmplteui:
260 case Hexagon::S2_tstbit_i:
261 case Hexagon::S4_ntstbit_i:
270 unsigned cmpReg1, cmpOp2 = 0;
271 cmpReg1 =
MI.getOperand(1).getReg();
274 cmpOp2 =
MI.getOperand(2).getReg();
278 if (cmpReg1 == cmpOp2)
287 if (def->
getOpcode() == TargetOpcode::COPY)
296 if (localII->isDebugInstr())
306 if (localII->modifiesRegister(pReg,
TRI) ||
307 localII->readsRegister(pReg,
TRI))
317 if (localII->modifiesRegister(cmpReg1,
TRI) ||
318 (secondReg && localII->modifiesRegister(cmpOp2,
TRI)))
327 bool secondRegNewified,
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;
344 case Hexagon::C2_cmpeqi:
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;
351 case Hexagon::C4_cmpneqi:
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;
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;
365 case Hexagon::C2_cmpgti:
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;
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;
379 case Hexagon::C2_cmpgtui:
380 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t
381 : Hexagon::J4_cmpgtui_t_jumpnv_nt;
383 case Hexagon::C4_cmpneq:
384 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t
385 : Hexagon::J4_cmpeq_f_jumpnv_nt;
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;
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;
401 case Hexagon::C4_cmpltei:
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;
408 case Hexagon::C4_cmplteui:
409 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t
410 : Hexagon::J4_cmpgtui_f_jumpnv_nt;
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:
441bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
442 LLVM_DEBUG(
dbgs() <<
"********** Hexagon New Value Jump **********\n"
443 <<
"********** Function: " << MF.
getName() <<
"\n");
451 QII =
static_cast<const HexagonInstrInfo *
>(MF.
getSubtarget().getInstrInfo());
452 QRI =
static_cast<const HexagonRegisterInfo *
>(
454 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
457 !MF.
getSubtarget<HexagonSubtarget>().useNewValueJumps())
461 int nvjGenerated = 0;
465 MBBb != MBBe; ++MBBb) {
466 MachineBasicBlock *
MBB = &*MBBb;
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;
480 MachineInstr *cmpInstr =
nullptr, *jmpInstr =
nullptr;
481 MachineBasicBlock *jmpTarget =
nullptr;
482 bool afterRA =
false;
483 bool isSecondOpReg =
false;
484 bool isSecondOpNewified =
false;
488 MachineInstr &
MI = *--MII;
489 if (
MI.isDebugInstr()) {
493 if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))
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)) {
510 predReg =
MI.getOperand(0).getReg();
511 afterRA = Register::isPhysicalRegister(predReg);
528 bool predLive =
false;
530 if (SuccMBB->isLiveIn(predReg))
535 if (!
MI.getOperand(1).isMBB())
537 jmpTarget =
MI.getOperand(1).getMBB();
539 if (
MI.getOpcode() == Hexagon::J2_jumpf ||
540 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
541 MI.getOpcode() == Hexagon::J2_jumpfnew) {
542 invertPredicate =
true;
550 if (foundJump &&
MI.getNumOperands() == 0)
553 if (foundJump && !foundCompare &&
MI.getOperand(0).isReg() &&
554 MI.getOperand(0).getReg() == predReg) {
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();
563 afterRA, jmpPos, MF))
572 cmpReg1 =
MI.getOperand(1).getReg();
575 cmpOp2 =
MI.getOperand(2).getReg();
577 cmpOp2 =
MI.getOperand(2).getImm();
582 if (foundCompare && foundJump) {
587 bool foundFeeder =
false;
589 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isDef() &&
590 (
MI.getOperand(0).getReg() == cmpReg1 ||
592 MI.getOperand(0).getReg() == (
unsigned)cmpOp2))) {
594 Register feederReg =
MI.getOperand(0).getReg();
602 if (feederReg == cmpReg1) {
612 if (!foundFeeder && isSecondOpReg && feederReg == (
unsigned)cmpOp2)
620 if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) &&
621 (feederReg == (
unsigned)cmpOp2)) {
622 unsigned tmp = cmpReg1;
630 if (feederReg == (
unsigned)cmpOp2)
631 isSecondOpNewified =
true;
638 auto TransferKills = [jmpPos,cmpPos] (MachineInstr &
MI) {
639 for (MachineOperand &MO :
MI.operands()) {
640 if (!MO.isReg() || !MO.isUse())
643 for (
auto I = std::next(
MI.getIterator());
I != jmpPos; ++
I) {
646 for (MachineOperand &
Op :
I->operands()) {
647 if (!
Op.isReg() || !
Op.isUse() || !
Op.isKill())
649 if (
Op.getReg() != UseR)
661 TransferKills(*feederPos);
662 TransferKills(*cmpPos);
663 bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI);
664 bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI);
671 assert((isNewValueJumpCandidate(*cmpInstr)) &&
672 "This compare is not a New Value Jump candidate.");
680 NewMI =
BuildMI(*
MBB, jmpPos, dl, QII->get(opc))
686 NewMI =
BuildMI(*
MBB, jmpPos, dl, QII->get(opc))
691 assert(NewMI &&
"New Value Jump Instruction Not created!");
700 jmpInstr->eraseFromParent();
713 return new HexagonNewValueJump();
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)
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"))
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.
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()
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