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"));
75 void getAnalysisUsage(AnalysisUsage &AU)
const override {
76 AU.
addRequired<MachineBranchProbabilityInfoWrapperPass>();
80 StringRef getPassName()
const override {
return "Hexagon NewValueJump"; }
82 bool runOnMachineFunction(MachineFunction &Fn)
override;
84 MachineFunctionProperties getRequiredProperties()
const override {
85 return MachineFunctionProperties().setNoVRegs();
89 const HexagonInstrInfo *QII;
90 const HexagonRegisterInfo *QRI;
93 const MachineBranchProbabilityInfo *MBPI;
95 bool isNewValueJumpCandidate(
const MachineInstr &
MI)
const;
100char HexagonNewValueJump::ID = 0;
103 "Hexagon NewValueJump",
false,
false)
117 if (QII->isPredicated(*
II))
130 if (
II->getOpcode() == TargetOpcode::KILL)
133 if (
II->isImplicitDef())
136 if (QII->isSolo(*
II))
139 if (QII->isFloat(*
II))
145 if (!Op.isReg() || !Op.isDef())
150 if (!Hexagon::IntRegsRegClass.contains(Op.getReg()))
169 for (
unsigned i = 0; i <
II->getNumOperands(); ++i) {
170 if (
II->getOperand(i).isReg() &&
171 (
II->getOperand(i).isUse() ||
II->getOperand(i).isDef())) {
177 if (localBegin ==
skip)
180 if (localBegin->modifiesRegister(
Reg,
TRI) ||
181 localBegin->readsRegister(
Reg,
TRI))
214 if (MII->getOpcode() == TargetOpcode::KILL ||
215 MII->getOpcode() == TargetOpcode::PHI ||
216 MII->getOpcode() == TargetOpcode::COPY)
223 if (MII->getOpcode() == Hexagon::LDriw_pred ||
224 MII->getOpcode() == Hexagon::STriw_pred)
251 switch (
MI.getOpcode()) {
252 case Hexagon::C2_cmpeqi:
253 case Hexagon::C4_cmpneqi:
254 case Hexagon::C2_cmpgti:
255 case Hexagon::C4_cmpltei:
258 case Hexagon::C2_cmpgtui:
259 case Hexagon::C4_cmplteui:
262 case Hexagon::S2_tstbit_i:
263 case Hexagon::S4_ntstbit_i:
272 unsigned cmpReg1, cmpOp2 = 0;
273 cmpReg1 =
MI.getOperand(1).getReg();
276 cmpOp2 =
MI.getOperand(2).getReg();
280 if (cmpReg1 == cmpOp2)
289 if (def->
getOpcode() == TargetOpcode::COPY)
298 if (localII->isDebugInstr())
308 if (localII->modifiesRegister(pReg,
TRI) ||
309 localII->readsRegister(pReg,
TRI))
319 if (localII->modifiesRegister(cmpReg1,
TRI) ||
320 (secondReg && localII->modifiesRegister(cmpOp2,
TRI)))
329 bool secondRegNewified,
341 switch (
MI->getOpcode()) {
342 case Hexagon::C2_cmpeq:
343 return taken ? Hexagon::J4_cmpeq_t_jumpnv_t
344 : Hexagon::J4_cmpeq_t_jumpnv_nt;
346 case Hexagon::C2_cmpeqi:
348 return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t
349 : Hexagon::J4_cmpeqi_t_jumpnv_nt;
350 return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t
351 : Hexagon::J4_cmpeqn1_t_jumpnv_nt;
353 case Hexagon::C4_cmpneqi:
355 return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t
356 : Hexagon::J4_cmpeqi_f_jumpnv_nt;
357 return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t :
358 Hexagon::J4_cmpeqn1_f_jumpnv_nt;
360 case Hexagon::C2_cmpgt:
361 if (secondRegNewified)
362 return taken ? Hexagon::J4_cmplt_t_jumpnv_t
363 : Hexagon::J4_cmplt_t_jumpnv_nt;
364 return taken ? Hexagon::J4_cmpgt_t_jumpnv_t
365 : Hexagon::J4_cmpgt_t_jumpnv_nt;
367 case Hexagon::C2_cmpgti:
369 return taken ? Hexagon::J4_cmpgti_t_jumpnv_t
370 : Hexagon::J4_cmpgti_t_jumpnv_nt;
371 return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t
372 : Hexagon::J4_cmpgtn1_t_jumpnv_nt;
374 case Hexagon::C2_cmpgtu:
375 if (secondRegNewified)
376 return taken ? Hexagon::J4_cmpltu_t_jumpnv_t
377 : Hexagon::J4_cmpltu_t_jumpnv_nt;
378 return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t
379 : Hexagon::J4_cmpgtu_t_jumpnv_nt;
381 case Hexagon::C2_cmpgtui:
382 return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t
383 : Hexagon::J4_cmpgtui_t_jumpnv_nt;
385 case Hexagon::C4_cmpneq:
386 return taken ? Hexagon::J4_cmpeq_f_jumpnv_t
387 : Hexagon::J4_cmpeq_f_jumpnv_nt;
389 case Hexagon::C4_cmplte:
390 if (secondRegNewified)
391 return taken ? Hexagon::J4_cmplt_f_jumpnv_t
392 : Hexagon::J4_cmplt_f_jumpnv_nt;
393 return taken ? Hexagon::J4_cmpgt_f_jumpnv_t
394 : Hexagon::J4_cmpgt_f_jumpnv_nt;
396 case Hexagon::C4_cmplteu:
397 if (secondRegNewified)
398 return taken ? Hexagon::J4_cmpltu_f_jumpnv_t
399 : Hexagon::J4_cmpltu_f_jumpnv_nt;
400 return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t
401 : Hexagon::J4_cmpgtu_f_jumpnv_nt;
403 case Hexagon::C4_cmpltei:
405 return taken ? Hexagon::J4_cmpgti_f_jumpnv_t
406 : Hexagon::J4_cmpgti_f_jumpnv_nt;
407 return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t
408 : Hexagon::J4_cmpgtn1_f_jumpnv_nt;
410 case Hexagon::C4_cmplteui:
411 return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t
412 : Hexagon::J4_cmpgtui_f_jumpnv_nt;
421bool HexagonNewValueJump::isNewValueJumpCandidate(
423 switch (
MI.getOpcode()) {
424 case Hexagon::C2_cmpeq:
425 case Hexagon::C2_cmpeqi:
426 case Hexagon::C2_cmpgt:
427 case Hexagon::C2_cmpgti:
428 case Hexagon::C2_cmpgtu:
429 case Hexagon::C2_cmpgtui:
430 case Hexagon::C4_cmpneq:
431 case Hexagon::C4_cmpneqi:
432 case Hexagon::C4_cmplte:
433 case Hexagon::C4_cmplteu:
434 case Hexagon::C4_cmpltei:
435 case Hexagon::C4_cmplteui:
443bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) {
444 LLVM_DEBUG(
dbgs() <<
"********** Hexagon New Value Jump **********\n"
445 <<
"********** Function: " << MF.
getName() <<
"\n");
453 QII =
static_cast<const HexagonInstrInfo *
>(MF.
getSubtarget().getInstrInfo());
454 QRI =
static_cast<const HexagonRegisterInfo *
>(
456 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
461 !MF.
getSubtarget<HexagonSubtarget>().useNewValueJumps())
465 int nvjGenerated = 0;
469 MBBb != MBBe; ++MBBb) {
470 MachineBasicBlock *
MBB = &*MBBb;
475 <<
"********** dumping instr bottom up **********\n");
476 bool foundJump =
false;
477 bool foundCompare =
false;
478 bool invertPredicate =
false;
479 unsigned predReg = 0;
480 unsigned cmpReg1 = 0;
484 MachineInstr *cmpInstr =
nullptr, *jmpInstr =
nullptr;
485 MachineBasicBlock *jmpTarget =
nullptr;
486 bool afterRA =
false;
487 bool isSecondOpReg =
false;
488 bool isSecondOpNewified =
false;
492 MachineInstr &
MI = *--MII;
493 if (
MI.isDebugInstr()) {
497 if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated))
502 if (!foundJump && (
MI.getOpcode() == Hexagon::J2_jumpt ||
503 MI.getOpcode() == Hexagon::J2_jumptpt ||
504 MI.getOpcode() == Hexagon::J2_jumpf ||
505 MI.getOpcode() == Hexagon::J2_jumpfpt ||
506 MI.getOpcode() == Hexagon::J2_jumptnewpt ||
507 MI.getOpcode() == Hexagon::J2_jumptnew ||
508 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
509 MI.getOpcode() == Hexagon::J2_jumpfnew)) {
514 predReg =
MI.getOperand(0).getReg();
515 afterRA = Register::isPhysicalRegister(predReg);
532 bool predLive =
false;
534 if (SuccMBB->isLiveIn(predReg))
539 if (!
MI.getOperand(1).isMBB())
541 jmpTarget =
MI.getOperand(1).getMBB();
543 if (
MI.getOpcode() == Hexagon::J2_jumpf ||
544 MI.getOpcode() == Hexagon::J2_jumpfnewpt ||
545 MI.getOpcode() == Hexagon::J2_jumpfnew) {
546 invertPredicate =
true;
554 if (foundJump &&
MI.getNumOperands() == 0)
557 if (foundJump && !foundCompare &&
MI.getOperand(0).isReg() &&
558 MI.getOperand(0).getReg() == predReg) {
560 if (isNewValueJumpCandidate(
MI)) {
562 (
MI.getDesc().isCompare()) &&
563 "Only compare instruction can be collapsed into New Value Jump");
564 isSecondOpReg =
MI.getOperand(2).isReg();
567 afterRA, jmpPos, MF))
576 cmpReg1 =
MI.getOperand(1).getReg();
579 cmpOp2 =
MI.getOperand(2).getReg();
581 cmpOp2 =
MI.getOperand(2).getImm();
586 if (foundCompare && foundJump) {
591 bool foundFeeder =
false;
593 if (
MI.getOperand(0).isReg() &&
MI.getOperand(0).isDef() &&
594 (
MI.getOperand(0).getReg() == cmpReg1 ||
596 MI.getOperand(0).getReg() == (
unsigned)cmpOp2))) {
598 Register feederReg =
MI.getOperand(0).getReg();
606 if (feederReg == cmpReg1) {
616 if (!foundFeeder && isSecondOpReg && feederReg == (
unsigned)cmpOp2)
624 if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) &&
625 (feederReg == (
unsigned)cmpOp2)) {
626 unsigned tmp = cmpReg1;
634 if (feederReg == (
unsigned)cmpOp2)
635 isSecondOpNewified =
true;
642 auto TransferKills = [jmpPos,cmpPos] (MachineInstr &
MI) {
643 for (MachineOperand &MO :
MI.operands()) {
644 if (!MO.isReg() || !MO.isUse())
647 for (
auto I = std::next(
MI.getIterator());
I != jmpPos; ++
I) {
650 for (MachineOperand &
Op :
I->operands()) {
651 if (!
Op.isReg() || !
Op.isUse() || !
Op.isKill())
653 if (
Op.getReg() != UseR)
665 TransferKills(*feederPos);
666 TransferKills(*cmpPos);
667 bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI);
668 bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI);
675 assert((isNewValueJumpCandidate(*cmpInstr)) &&
676 "This compare is not a New Value Jump candidate.");
684 NewMI =
BuildMI(*
MBB, jmpPos, dl, QII->get(opc))
690 NewMI =
BuildMI(*
MBB, jmpPos, dl, QII->get(opc))
695 assert(NewMI &&
"New Value Jump Instruction Not created!");
704 jmpInstr->eraseFromParent();
717 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)
cl::opt< bool > DisablePacketizer
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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate 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.
constexpr RegState getKillRegState(bool B)
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.
DWARFExpression::Operation Op