diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp | 726 |
1 files changed, 726 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp b/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp new file mode 100644 index 000000000000..db44901ca706 --- /dev/null +++ b/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonNewValueJump.cpp @@ -0,0 +1,726 @@ +//===- HexagonNewValueJump.cpp - Hexagon Backend New Value Jump -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This implements NewValueJump pass in Hexagon. +// Ideally, we should merge this as a Peephole pass prior to register +// allocation, but because we have a spill in between the feeder and new value +// jump instructions, we are forced to write after register allocation. +// Having said that, we should re-attempt to pull this earlier at some point +// in future. + +// The basic approach looks for sequence of predicated jump, compare instruciton +// that genereates the predicate and, the feeder to the predicate. Once it finds +// all, it collapses compare and jump instruction into a new value jump +// intstructions. +// +//===----------------------------------------------------------------------===// + +#include "Hexagon.h" +#include "HexagonInstrInfo.h" +#include "HexagonRegisterInfo.h" +#include "HexagonSubtarget.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/Pass.h" +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> +#include <iterator> + +using namespace llvm; + +#define DEBUG_TYPE "hexagon-nvj" + +STATISTIC(NumNVJGenerated, "Number of New Value Jump Instructions created"); + +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 cl::opt<bool> DisableNewValueJumps("disable-nvjump", cl::Hidden, + cl::ZeroOrMore, cl::init(false), + cl::desc("Disable New Value Jumps")); + +namespace llvm { + +FunctionPass *createHexagonNewValueJump(); +void initializeHexagonNewValueJumpPass(PassRegistry&); + +} // end namespace llvm + +namespace { + + struct HexagonNewValueJump : public MachineFunctionPass { + static char ID; + + HexagonNewValueJump() : MachineFunctionPass(ID) {} + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired<MachineBranchProbabilityInfo>(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + StringRef getPassName() const override { return "Hexagon NewValueJump"; } + + bool runOnMachineFunction(MachineFunction &Fn) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + private: + const HexagonInstrInfo *QII; + const HexagonRegisterInfo *QRI; + + /// A handle to the branch probability pass. + const MachineBranchProbabilityInfo *MBPI; + + bool isNewValueJumpCandidate(const MachineInstr &MI) const; + }; + +} // end anonymous namespace + +char HexagonNewValueJump::ID = 0; + +INITIALIZE_PASS_BEGIN(HexagonNewValueJump, "hexagon-nvj", + "Hexagon NewValueJump", false, false) +INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) +INITIALIZE_PASS_END(HexagonNewValueJump, "hexagon-nvj", + "Hexagon NewValueJump", false, false) + +// We have identified this II could be feeder to NVJ, +// verify that it can be. +static bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII, + const TargetRegisterInfo *TRI, + MachineBasicBlock::iterator II, + MachineBasicBlock::iterator end, + MachineBasicBlock::iterator skip, + MachineFunction &MF) { + // Predicated instruction can not be feeder to NVJ. + if (QII->isPredicated(*II)) + return false; + + // Bail out if feederReg is a paired register (double regs in + // our case). One would think that we can check to see if a given + // register cmpReg1 or cmpReg2 is a sub register of feederReg + // using -- if (QRI->isSubRegister(feederReg, cmpReg1) logic + // before the callsite of this function + // But we can not as it comes in the following fashion. + // %d0 = Hexagon_S2_lsr_r_p killed %d0, killed %r2 + // %r0 = KILL %r0, implicit killed %d0 + // %p0 = CMPEQri killed %r0, 0 + // Hence, we need to check if it's a KILL instruction. + if (II->getOpcode() == TargetOpcode::KILL) + return false; + + if (II->isImplicitDef()) + return false; + + if (QII->isSolo(*II)) + return false; + + if (QII->isFloat(*II)) + return false; + + // Make sure that the (unique) def operand is a register from IntRegs. + bool HadDef = false; + for (const MachineOperand &Op : II->operands()) { + if (!Op.isReg() || !Op.isDef()) + continue; + if (HadDef) + return false; + HadDef = true; + if (!Hexagon::IntRegsRegClass.contains(Op.getReg())) + return false; + } + assert(HadDef); + + // Make sure there is no 'def' or 'use' of any of the uses of + // feeder insn between its definition, this MI and jump, jmpInst + // skipping compare, cmpInst. + // Here's the example. + // r21=memub(r22+r24<<#0) + // p0 = cmp.eq(r21, #0) + // r4=memub(r3+r21<<#0) + // if (p0.new) jump:t .LBB29_45 + // Without this check, it will be converted into + // r4=memub(r3+r21<<#0) + // r21=memub(r22+r24<<#0) + // p0 = cmp.eq(r21, #0) + // if (p0.new) jump:t .LBB29_45 + // and result WAR hazards if converted to New Value Jump. + for (unsigned i = 0; i < II->getNumOperands(); ++i) { + if (II->getOperand(i).isReg() && + (II->getOperand(i).isUse() || II->getOperand(i).isDef())) { + MachineBasicBlock::iterator localII = II; + ++localII; + unsigned Reg = II->getOperand(i).getReg(); + for (MachineBasicBlock::iterator localBegin = localII; localBegin != end; + ++localBegin) { + if (localBegin == skip) + continue; + // Check for Subregisters too. + if (localBegin->modifiesRegister(Reg, TRI) || + localBegin->readsRegister(Reg, TRI)) + return false; + } + } + } + return true; +} + +// These are the common checks that need to performed +// to determine if +// 1. compare instruction can be moved before jump. +// 2. feeder to the compare instruction can be moved before jump. +static bool commonChecksToProhibitNewValueJump(bool afterRA, + MachineBasicBlock::iterator MII) { + // If store in path, bail out. + if (MII->mayStore()) + return false; + + // if call in path, bail out. + if (MII->isCall()) + return false; + + // if NVJ is running prior to RA, do the following checks. + if (!afterRA) { + // The following Target Opcode instructions are spurious + // to new value jump. If they are in the path, bail out. + // KILL sets kill flag on the opcode. It also sets up a + // single register, out of pair. + // %d0 = S2_lsr_r_p killed %d0, killed %r2 + // %r0 = KILL %r0, implicit killed %d0 + // %p0 = C2_cmpeqi killed %r0, 0 + // PHI can be anything after RA. + // COPY can remateriaze things in between feeder, compare and nvj. + if (MII->getOpcode() == TargetOpcode::KILL || + MII->getOpcode() == TargetOpcode::PHI || + MII->getOpcode() == TargetOpcode::COPY) + return false; + + // The following pseudo Hexagon instructions sets "use" and "def" + // of registers by individual passes in the backend. At this time, + // we don't know the scope of usage and definitions of these + // instructions. + if (MII->getOpcode() == Hexagon::LDriw_pred || + MII->getOpcode() == Hexagon::STriw_pred) + return false; + } + + return true; +} + +static bool canCompareBeNewValueJump(const HexagonInstrInfo *QII, + const TargetRegisterInfo *TRI, + MachineBasicBlock::iterator II, + unsigned pReg, + bool secondReg, + bool optLocation, + MachineBasicBlock::iterator end, + MachineFunction &MF) { + MachineInstr &MI = *II; + + // If the second operand of the compare is an imm, make sure it's in the + // range specified by the arch. + if (!secondReg) { + const MachineOperand &Op2 = MI.getOperand(2); + if (!Op2.isImm()) + return false; + + int64_t v = Op2.getImm(); + bool Valid = false; + + switch (MI.getOpcode()) { + case Hexagon::C2_cmpeqi: + case Hexagon::C4_cmpneqi: + case Hexagon::C2_cmpgti: + case Hexagon::C4_cmpltei: + Valid = (isUInt<5>(v) || v == -1); + break; + case Hexagon::C2_cmpgtui: + case Hexagon::C4_cmplteui: + Valid = isUInt<5>(v); + break; + case Hexagon::S2_tstbit_i: + case Hexagon::S4_ntstbit_i: + Valid = (v == 0); + break; + } + + if (!Valid) + return false; + } + + unsigned cmpReg1, cmpOp2 = 0; // cmpOp2 assignment silences compiler warning. + cmpReg1 = MI.getOperand(1).getReg(); + + if (secondReg) { + cmpOp2 = MI.getOperand(2).getReg(); + + // If the same register appears as both operands, we cannot generate a new + // value compare. Only one operand may use the .new suffix. + if (cmpReg1 == cmpOp2) + return false; + + // Make sure that the second register is not from COPY + // at machine code level, we don't need this, but if we decide + // to move new value jump prior to RA, we would be needing this. + MachineRegisterInfo &MRI = MF.getRegInfo(); + if (secondReg && !TargetRegisterInfo::isPhysicalRegister(cmpOp2)) { + MachineInstr *def = MRI.getVRegDef(cmpOp2); + if (def->getOpcode() == TargetOpcode::COPY) + return false; + } + } + + // Walk the instructions after the compare (predicate def) to the jump, + // and satisfy the following conditions. + ++II; + for (MachineBasicBlock::iterator localII = II; localII != end; ++localII) { + if (localII->isDebugInstr()) + continue; + + // Check 1. + // If "common" checks fail, bail out. + if (!commonChecksToProhibitNewValueJump(optLocation, localII)) + return false; + + // Check 2. + // If there is a def or use of predicate (result of compare), bail out. + if (localII->modifiesRegister(pReg, TRI) || + localII->readsRegister(pReg, TRI)) + return false; + + // Check 3. + // If there is a def of any of the use of the compare (operands of compare), + // bail out. + // Eg. + // p0 = cmp.eq(r2, r0) + // r2 = r4 + // if (p0.new) jump:t .LBB28_3 + if (localII->modifiesRegister(cmpReg1, TRI) || + (secondReg && localII->modifiesRegister(cmpOp2, TRI))) + return false; + } + return true; +} + +// Given a compare operator, return a matching New Value Jump compare operator. +// Make sure that MI here is included in isNewValueJumpCandidate. +static unsigned getNewValueJumpOpcode(MachineInstr *MI, int reg, + bool secondRegNewified, + MachineBasicBlock *jmpTarget, + const MachineBranchProbabilityInfo + *MBPI) { + bool taken = false; + MachineBasicBlock *Src = MI->getParent(); + const BranchProbability Prediction = + MBPI->getEdgeProbability(Src, jmpTarget); + + if (Prediction >= BranchProbability(1,2)) + taken = true; + + switch (MI->getOpcode()) { + case Hexagon::C2_cmpeq: + return taken ? Hexagon::J4_cmpeq_t_jumpnv_t + : Hexagon::J4_cmpeq_t_jumpnv_nt; + + case Hexagon::C2_cmpeqi: + if (reg >= 0) + return taken ? Hexagon::J4_cmpeqi_t_jumpnv_t + : Hexagon::J4_cmpeqi_t_jumpnv_nt; + return taken ? Hexagon::J4_cmpeqn1_t_jumpnv_t + : Hexagon::J4_cmpeqn1_t_jumpnv_nt; + + case Hexagon::C4_cmpneqi: + if (reg >= 0) + return taken ? Hexagon::J4_cmpeqi_f_jumpnv_t + : Hexagon::J4_cmpeqi_f_jumpnv_nt; + return taken ? Hexagon::J4_cmpeqn1_f_jumpnv_t : + Hexagon::J4_cmpeqn1_f_jumpnv_nt; + + case Hexagon::C2_cmpgt: + if (secondRegNewified) + return taken ? Hexagon::J4_cmplt_t_jumpnv_t + : Hexagon::J4_cmplt_t_jumpnv_nt; + return taken ? Hexagon::J4_cmpgt_t_jumpnv_t + : Hexagon::J4_cmpgt_t_jumpnv_nt; + + case Hexagon::C2_cmpgti: + if (reg >= 0) + return taken ? Hexagon::J4_cmpgti_t_jumpnv_t + : Hexagon::J4_cmpgti_t_jumpnv_nt; + return taken ? Hexagon::J4_cmpgtn1_t_jumpnv_t + : Hexagon::J4_cmpgtn1_t_jumpnv_nt; + + case Hexagon::C2_cmpgtu: + if (secondRegNewified) + return taken ? Hexagon::J4_cmpltu_t_jumpnv_t + : Hexagon::J4_cmpltu_t_jumpnv_nt; + return taken ? Hexagon::J4_cmpgtu_t_jumpnv_t + : Hexagon::J4_cmpgtu_t_jumpnv_nt; + + case Hexagon::C2_cmpgtui: + return taken ? Hexagon::J4_cmpgtui_t_jumpnv_t + : Hexagon::J4_cmpgtui_t_jumpnv_nt; + + case Hexagon::C4_cmpneq: + return taken ? Hexagon::J4_cmpeq_f_jumpnv_t + : Hexagon::J4_cmpeq_f_jumpnv_nt; + + case Hexagon::C4_cmplte: + if (secondRegNewified) + return taken ? Hexagon::J4_cmplt_f_jumpnv_t + : Hexagon::J4_cmplt_f_jumpnv_nt; + return taken ? Hexagon::J4_cmpgt_f_jumpnv_t + : Hexagon::J4_cmpgt_f_jumpnv_nt; + + case Hexagon::C4_cmplteu: + if (secondRegNewified) + return taken ? Hexagon::J4_cmpltu_f_jumpnv_t + : Hexagon::J4_cmpltu_f_jumpnv_nt; + return taken ? Hexagon::J4_cmpgtu_f_jumpnv_t + : Hexagon::J4_cmpgtu_f_jumpnv_nt; + + case Hexagon::C4_cmpltei: + if (reg >= 0) + return taken ? Hexagon::J4_cmpgti_f_jumpnv_t + : Hexagon::J4_cmpgti_f_jumpnv_nt; + return taken ? Hexagon::J4_cmpgtn1_f_jumpnv_t + : Hexagon::J4_cmpgtn1_f_jumpnv_nt; + + case Hexagon::C4_cmplteui: + return taken ? Hexagon::J4_cmpgtui_f_jumpnv_t + : Hexagon::J4_cmpgtui_f_jumpnv_nt; + + default: + llvm_unreachable("Could not find matching New Value Jump instruction."); + } + // return *some value* to avoid compiler warning + return 0; +} + +bool HexagonNewValueJump::isNewValueJumpCandidate( + const MachineInstr &MI) const { + switch (MI.getOpcode()) { + case Hexagon::C2_cmpeq: + case Hexagon::C2_cmpeqi: + case Hexagon::C2_cmpgt: + case Hexagon::C2_cmpgti: + case Hexagon::C2_cmpgtu: + case Hexagon::C2_cmpgtui: + case Hexagon::C4_cmpneq: + case Hexagon::C4_cmpneqi: + case Hexagon::C4_cmplte: + case Hexagon::C4_cmplteu: + case Hexagon::C4_cmpltei: + case Hexagon::C4_cmplteui: + return true; + + default: + return false; + } +} + +bool HexagonNewValueJump::runOnMachineFunction(MachineFunction &MF) { + LLVM_DEBUG(dbgs() << "********** Hexagon New Value Jump **********\n" + << "********** Function: " << MF.getName() << "\n"); + + if (skipFunction(MF.getFunction())) + return false; + + // If we move NewValueJump before register allocation we'll need live variable + // analysis here too. + + QII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); + QRI = static_cast<const HexagonRegisterInfo *>( + MF.getSubtarget().getRegisterInfo()); + MBPI = &getAnalysis<MachineBranchProbabilityInfo>(); + + if (DisableNewValueJumps || + !MF.getSubtarget<HexagonSubtarget>().useNewValueJumps()) + return false; + + int nvjCount = DbgNVJCount; + int nvjGenerated = 0; + + // Loop through all the bb's of the function + for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock *MBB = &*MBBb; + + LLVM_DEBUG(dbgs() << "** dumping bb ** " << MBB->getNumber() << "\n"); + LLVM_DEBUG(MBB->dump()); + LLVM_DEBUG(dbgs() << "\n" + << "********** dumping instr bottom up **********\n"); + bool foundJump = false; + bool foundCompare = false; + bool invertPredicate = false; + unsigned predReg = 0; // predicate reg of the jump. + unsigned cmpReg1 = 0; + int cmpOp2 = 0; + MachineBasicBlock::iterator jmpPos; + MachineBasicBlock::iterator cmpPos; + MachineInstr *cmpInstr = nullptr, *jmpInstr = nullptr; + MachineBasicBlock *jmpTarget = nullptr; + bool afterRA = false; + bool isSecondOpReg = false; + bool isSecondOpNewified = false; + // Traverse the basic block - bottom up + for (MachineBasicBlock::iterator MII = MBB->end(), E = MBB->begin(); + MII != E;) { + MachineInstr &MI = *--MII; + if (MI.isDebugInstr()) { + continue; + } + + if ((nvjCount == 0) || (nvjCount > -1 && nvjCount <= nvjGenerated)) + break; + + LLVM_DEBUG(dbgs() << "Instr: "; MI.dump(); dbgs() << "\n"); + + if (!foundJump && (MI.getOpcode() == Hexagon::J2_jumpt || + MI.getOpcode() == Hexagon::J2_jumptpt || + MI.getOpcode() == Hexagon::J2_jumpf || + MI.getOpcode() == Hexagon::J2_jumpfpt || + MI.getOpcode() == Hexagon::J2_jumptnewpt || + MI.getOpcode() == Hexagon::J2_jumptnew || + MI.getOpcode() == Hexagon::J2_jumpfnewpt || + MI.getOpcode() == Hexagon::J2_jumpfnew)) { + // This is where you would insert your compare and + // instr that feeds compare + jmpPos = MII; + jmpInstr = &MI; + predReg = MI.getOperand(0).getReg(); + afterRA = TargetRegisterInfo::isPhysicalRegister(predReg); + + // If ifconverter had not messed up with the kill flags of the + // operands, the following check on the kill flag would suffice. + // if(!jmpInstr->getOperand(0).isKill()) break; + + // This predicate register is live out of BB + // this would only work if we can actually use Live + // variable analysis on phy regs - but LLVM does not + // provide LV analysis on phys regs. + //if(LVs.isLiveOut(predReg, *MBB)) break; + + // Get all the successors of this block - which will always + // be 2. Check if the predicate register is live-in in those + // successor. If yes, we can not delete the predicate - + // I am doing this only because LLVM does not provide LiveOut + // at the BB level. + bool predLive = false; + for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(), + SIE = MBB->succ_end(); + SI != SIE; ++SI) { + MachineBasicBlock *succMBB = *SI; + if (succMBB->isLiveIn(predReg)) + predLive = true; + } + if (predLive) + break; + + if (!MI.getOperand(1).isMBB()) + continue; + jmpTarget = MI.getOperand(1).getMBB(); + foundJump = true; + if (MI.getOpcode() == Hexagon::J2_jumpf || + MI.getOpcode() == Hexagon::J2_jumpfnewpt || + MI.getOpcode() == Hexagon::J2_jumpfnew) { + invertPredicate = true; + } + continue; + } + + // No new value jump if there is a barrier. A barrier has to be in its + // own packet. A barrier has zero operands. We conservatively bail out + // here if we see any instruction with zero operands. + if (foundJump && MI.getNumOperands() == 0) + break; + + if (foundJump && !foundCompare && MI.getOperand(0).isReg() && + MI.getOperand(0).getReg() == predReg) { + // Not all compares can be new value compare. Arch Spec: 7.6.1.1 + if (isNewValueJumpCandidate(MI)) { + assert( + (MI.getDesc().isCompare()) && + "Only compare instruction can be collapsed into New Value Jump"); + isSecondOpReg = MI.getOperand(2).isReg(); + + if (!canCompareBeNewValueJump(QII, QRI, MII, predReg, isSecondOpReg, + afterRA, jmpPos, MF)) + break; + + cmpInstr = &MI; + cmpPos = MII; + foundCompare = true; + + // We need cmpReg1 and cmpOp2(imm or reg) while building + // new value jump instruction. + cmpReg1 = MI.getOperand(1).getReg(); + + if (isSecondOpReg) + cmpOp2 = MI.getOperand(2).getReg(); + else + cmpOp2 = MI.getOperand(2).getImm(); + continue; + } + } + + if (foundCompare && foundJump) { + // If "common" checks fail, bail out on this BB. + if (!commonChecksToProhibitNewValueJump(afterRA, MII)) + break; + + bool foundFeeder = false; + MachineBasicBlock::iterator feederPos = MII; + if (MI.getOperand(0).isReg() && MI.getOperand(0).isDef() && + (MI.getOperand(0).getReg() == cmpReg1 || + (isSecondOpReg && + MI.getOperand(0).getReg() == (unsigned)cmpOp2))) { + + unsigned feederReg = MI.getOperand(0).getReg(); + + // First try to see if we can get the feeder from the first operand + // of the compare. If we can not, and if secondOpReg is true + // (second operand of the compare is also register), try that one. + // TODO: Try to come up with some heuristic to figure out which + // feeder would benefit. + + if (feederReg == cmpReg1) { + if (!canBeFeederToNewValueJump(QII, QRI, MII, jmpPos, cmpPos, MF)) { + if (!isSecondOpReg) + break; + else + continue; + } else + foundFeeder = true; + } + + if (!foundFeeder && isSecondOpReg && feederReg == (unsigned)cmpOp2) + if (!canBeFeederToNewValueJump(QII, QRI, MII, jmpPos, cmpPos, MF)) + break; + + if (isSecondOpReg) { + // In case of CMPLT, or CMPLTU, or EQ with the second register + // to newify, swap the operands. + unsigned COp = cmpInstr->getOpcode(); + if ((COp == Hexagon::C2_cmpeq || COp == Hexagon::C4_cmpneq) && + (feederReg == (unsigned)cmpOp2)) { + unsigned tmp = cmpReg1; + cmpReg1 = cmpOp2; + cmpOp2 = tmp; + } + + // Now we have swapped the operands, all we need to check is, + // if the second operand (after swap) is the feeder. + // And if it is, make a note. + if (feederReg == (unsigned)cmpOp2) + isSecondOpNewified = true; + } + + // Now that we are moving feeder close the jump, + // make sure we are respecting the kill values of + // the operands of the feeder. + + auto TransferKills = [jmpPos,cmpPos] (MachineInstr &MI) { + for (MachineOperand &MO : MI.operands()) { + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned UseR = MO.getReg(); + for (auto I = std::next(MI.getIterator()); I != jmpPos; ++I) { + if (I == cmpPos) + continue; + for (MachineOperand &Op : I->operands()) { + if (!Op.isReg() || !Op.isUse() || !Op.isKill()) + continue; + if (Op.getReg() != UseR) + continue; + // We found that there is kill of a use register + // Set up a kill flag on the register + Op.setIsKill(false); + MO.setIsKill(true); + return; + } + } + } + }; + + TransferKills(*feederPos); + TransferKills(*cmpPos); + bool MO1IsKill = cmpPos->killsRegister(cmpReg1, QRI); + bool MO2IsKill = isSecondOpReg && cmpPos->killsRegister(cmpOp2, QRI); + + MBB->splice(jmpPos, MI.getParent(), MI); + MBB->splice(jmpPos, MI.getParent(), cmpInstr); + DebugLoc dl = MI.getDebugLoc(); + MachineInstr *NewMI; + + assert((isNewValueJumpCandidate(*cmpInstr)) && + "This compare is not a New Value Jump candidate."); + unsigned opc = getNewValueJumpOpcode(cmpInstr, cmpOp2, + isSecondOpNewified, + jmpTarget, MBPI); + if (invertPredicate) + opc = QII->getInvertedPredicatedOpcode(opc); + + if (isSecondOpReg) + NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc)) + .addReg(cmpReg1, getKillRegState(MO1IsKill)) + .addReg(cmpOp2, getKillRegState(MO2IsKill)) + .addMBB(jmpTarget); + + else + NewMI = BuildMI(*MBB, jmpPos, dl, QII->get(opc)) + .addReg(cmpReg1, getKillRegState(MO1IsKill)) + .addImm(cmpOp2) + .addMBB(jmpTarget); + + assert(NewMI && "New Value Jump Instruction Not created!"); + (void)NewMI; + if (cmpInstr->getOperand(0).isReg() && + cmpInstr->getOperand(0).isKill()) + cmpInstr->getOperand(0).setIsKill(false); + if (cmpInstr->getOperand(1).isReg() && + cmpInstr->getOperand(1).isKill()) + cmpInstr->getOperand(1).setIsKill(false); + cmpInstr->eraseFromParent(); + jmpInstr->eraseFromParent(); + ++nvjGenerated; + ++NumNVJGenerated; + break; + } + } + } + } + + return true; +} + +FunctionPass *llvm::createHexagonNewValueJump() { + return new HexagonNewValueJump(); +} |
