diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonInstrInfo.cpp')
-rw-r--r-- | lib/Target/Hexagon/HexagonInstrInfo.cpp | 225 |
1 files changed, 157 insertions, 68 deletions
diff --git a/lib/Target/Hexagon/HexagonInstrInfo.cpp b/lib/Target/Hexagon/HexagonInstrInfo.cpp index 0a7dc6b49d00..b265a883da5c 100644 --- a/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -152,10 +152,11 @@ static unsigned nonDbgMICount(MachineBasicBlock::const_instr_iterator MIB, /// On Hexagon, we have two instructions used to set-up the hardware loop /// (LOOP0, LOOP1) with corresponding endloop (ENDLOOP0, ENDLOOP1) instructions /// to indicate the end of a loop. -static MachineInstr *findLoopInstr(MachineBasicBlock *BB, int EndLoopOp, +static MachineInstr *findLoopInstr(MachineBasicBlock *BB, unsigned EndLoopOp, + MachineBasicBlock *TargetBB, SmallPtrSet<MachineBasicBlock *, 8> &Visited) { - int LOOPi; - int LOOPr; + unsigned LOOPi; + unsigned LOOPr; if (EndLoopOp == Hexagon::ENDLOOP0) { LOOPi = Hexagon::J2_loop0i; LOOPr = Hexagon::J2_loop0r; @@ -165,26 +166,24 @@ static MachineInstr *findLoopInstr(MachineBasicBlock *BB, int EndLoopOp, } // The loop set-up instruction will be in a predecessor block - for (MachineBasicBlock::pred_iterator PB = BB->pred_begin(), - PE = BB->pred_end(); PB != PE; ++PB) { + for (MachineBasicBlock *PB : BB->predecessors()) { // If this has been visited, already skip it. - if (!Visited.insert(*PB).second) + if (!Visited.insert(PB).second) continue; - if (*PB == BB) + if (PB == BB) continue; - for (MachineBasicBlock::reverse_instr_iterator I = (*PB)->instr_rbegin(), - E = (*PB)->instr_rend(); I != E; ++I) { - int Opc = I->getOpcode(); + for (auto I = PB->instr_rbegin(), E = PB->instr_rend(); I != E; ++I) { + unsigned Opc = I->getOpcode(); if (Opc == LOOPi || Opc == LOOPr) return &*I; - // We've reached a different loop, which means the loop0 has been removed. - if (Opc == EndLoopOp) + // We've reached a different loop, which means the loop01 has been + // removed. + if (Opc == EndLoopOp && I->getOperand(0).getMBB() != TargetBB) return nullptr; } // Check the predecessors for the LOOP instruction. - MachineInstr *loop = findLoopInstr(*PB, EndLoopOp, Visited); - if (loop) - return loop; + if (MachineInstr *Loop = findLoopInstr(PB, EndLoopOp, TargetBB, Visited)) + return Loop; } return nullptr; } @@ -597,7 +596,8 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB, // Since we're adding an ENDLOOP, there better be a LOOP instruction. // Check for it, and change the BB target if needed. SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; - MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, VisitedBBs); + MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), + VisitedBBs); assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP"); Loop->getOperand(0).setMBB(TBB); // Add the ENDLOOP after the finding the LOOP0. @@ -637,7 +637,8 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB, // Since we're adding an ENDLOOP, there better be a LOOP instruction. // Check for it, and change the BB target if needed. SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; - MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, VisitedBBs); + MachineInstr *Loop = findLoopInstr(TBB, EndLoopOp, Cond[1].getMBB(), + VisitedBBs); assert(Loop != 0 && "Inserting an ENDLOOP without a LOOP"); Loop->getOperand(0).setMBB(TBB); // Add the ENDLOOP after the finding the LOOP0. @@ -687,7 +688,8 @@ unsigned HexagonInstrInfo::reduceLoopCount(MachineBasicBlock &MBB, MachineFunction *MF = MBB.getParent(); DebugLoc DL = Cmp.getDebugLoc(); SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs; - MachineInstr *Loop = findLoopInstr(&MBB, Cmp.getOpcode(), VisitedBBs); + MachineInstr *Loop = findLoopInstr(&MBB, Cmp.getOpcode(), + Cmp.getOperand(0).getMBB(), VisitedBBs); if (!Loop) return 0; // If the loop trip count is a compile-time value, then just change the @@ -1074,13 +1076,13 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6; MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc)) - .addOperand(MI.getOperand(0)) + .add(MI.getOperand(0)) .addImm(MI.getOperand(1).getImm()) .addReg(SrcSubLo) .setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); MI1New->getOperand(0).setIsKill(false); BuildMI(MBB, MI, DL, get(NewOpc)) - .addOperand(MI.getOperand(0)) + .add(MI.getOperand(0)) // The Vectors are indexed in multiples of vector size. .addImm(MI.getOperand(1).getImm() + Offset) .addReg(SrcSubHi) @@ -1106,15 +1108,13 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { unsigned DstReg = MI.getOperand(0).getReg(); unsigned Offset = Is128B ? VecOffset << 7 : VecOffset << 6; - MachineInstr *MI1New = - BuildMI(MBB, MI, DL, get(NewOpc), - HRI.getSubReg(DstReg, Hexagon::vsub_lo)) - .addOperand(MI.getOperand(1)) - .addImm(MI.getOperand(2).getImm()); + MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc), + HRI.getSubReg(DstReg, Hexagon::vsub_lo)) + .add(MI.getOperand(1)) + .addImm(MI.getOperand(2).getImm()); MI1New->getOperand(1).setIsKill(false); - BuildMI(MBB, MI, DL, get(NewOpc), - HRI.getSubReg(DstReg, Hexagon::vsub_hi)) - .addOperand(MI.getOperand(1)) + BuildMI(MBB, MI, DL, get(NewOpc), HRI.getSubReg(DstReg, Hexagon::vsub_hi)) + .add(MI.getOperand(1)) // The Vectors are indexed in multiples of vector size. .addImm(MI.getOperand(2).getImm() + Offset) .setMemRefs(MI.memoperands_begin(), MI.memoperands_end()); @@ -1227,18 +1227,18 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { bool IsDestLive = !LiveAtMI.available(MRI, Op0.getReg()); if (Op0.getReg() != Op2.getReg()) { auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vcmov)) - .addOperand(Op0) - .addOperand(Op1) - .addOperand(Op2); + .add(Op0) + .add(Op1) + .add(Op2); if (IsDestLive) T.addReg(Op0.getReg(), RegState::Implicit); IsDestLive = true; } if (Op0.getReg() != Op3.getReg()) { auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vncmov)) - .addOperand(Op0) - .addOperand(Op1) - .addOperand(Op3); + .add(Op0) + .add(Op1) + .add(Op3); if (IsDestLive) T.addReg(Op0.getReg(), RegState::Implicit); } @@ -1259,10 +1259,10 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { unsigned SrcLo = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_lo); unsigned SrcHi = HRI.getSubReg(Op2.getReg(), Hexagon::vsub_hi); auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vccombine)) - .addOperand(Op0) - .addOperand(Op1) - .addReg(SrcHi) - .addReg(SrcLo); + .add(Op0) + .add(Op1) + .addReg(SrcHi) + .addReg(SrcLo); if (IsDestLive) T.addReg(Op0.getReg(), RegState::Implicit); IsDestLive = true; @@ -1271,10 +1271,10 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { unsigned SrcLo = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_lo); unsigned SrcHi = HRI.getSubReg(Op3.getReg(), Hexagon::vsub_hi); auto T = BuildMI(MBB, MI, DL, get(Hexagon::V6_vnccombine)) - .addOperand(Op0) - .addOperand(Op1) - .addReg(SrcHi) - .addReg(SrcLo); + .add(Op0) + .add(Op1) + .addReg(SrcHi) + .addReg(SrcLo); if (IsDestLive) T.addReg(Op0.getReg(), RegState::Implicit); } @@ -1376,7 +1376,7 @@ bool HexagonInstrInfo::PredicateInstruction( MachineOperand &Op = MI.getOperand(NOp); if (!Op.isReg() || !Op.isDef() || Op.isImplicit()) break; - T.addOperand(Op); + T.add(Op); NOp++; } @@ -1386,7 +1386,7 @@ bool HexagonInstrInfo::PredicateInstruction( assert(GotPredReg); T.addReg(PredReg, PredRegFlags); while (NOp < NumOps) - T.addOperand(MI.getOperand(NOp++)); + T.add(MI.getOperand(NOp++)); MI.setDesc(get(PredOpc)); while (unsigned n = MI.getNumOperands()) @@ -1413,18 +1413,28 @@ bool HexagonInstrInfo::DefinesPredicate( auto &HRI = getRegisterInfo(); for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) { MachineOperand MO = MI.getOperand(oper); - if (MO.isReg() && MO.isDef()) { + if (MO.isReg()) { + if (!MO.isDef()) + continue; const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg()); if (RC == &Hexagon::PredRegsRegClass) { Pred.push_back(MO); return true; } + continue; + } else if (MO.isRegMask()) { + for (unsigned PR : Hexagon::PredRegsRegClass) { + if (!MI.modifiesRegister(PR, &HRI)) + continue; + Pred.push_back(MO); + return true; + } } } return false; } -bool HexagonInstrInfo::isPredicable(MachineInstr &MI) const { +bool HexagonInstrInfo::isPredicable(const MachineInstr &MI) const { return MI.getDesc().isPredicable(); } @@ -1715,7 +1725,7 @@ bool HexagonInstrInfo::isComplex(const MachineInstr &MI) const { // Return true if the instruction is a compund branch instruction. bool HexagonInstrInfo::isCompoundBranchInstr(const MachineInstr &MI) const { - return (getType(MI) == HexagonII::TypeCOMPOUND && MI.isBranch()); + return getType(MI) == HexagonII::TypeCJ && MI.isBranch(); } bool HexagonInstrInfo::isCondInst(const MachineInstr &MI) const { @@ -3009,10 +3019,12 @@ bool HexagonInstrInfo::producesStall(const MachineInstr &MI, bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI, unsigned PredReg) const { - for (unsigned opNum = 0; opNum < MI.getNumOperands(); opNum++) { - const MachineOperand &MO = MI.getOperand(opNum); + for (const MachineOperand &MO : MI.operands()) { + // Predicate register must be explicitly defined. + if (MO.isRegMask() && MO.clobbersPhysReg(PredReg)) + return false; if (MO.isReg() && MO.isDef() && MO.isImplicit() && (MO.getReg() == PredReg)) - return false; // Predicate register must be explicitly defined. + return false; } // Hexagon Programmer's Reference says that decbin, memw_locked, and @@ -3415,7 +3427,9 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const { return NVOpcode; switch (MI.getOpcode()) { - default: llvm_unreachable("Unknown .new type"); + default: + llvm::report_fatal_error(std::string("Unknown .new type: ") + + std::to_string(MI.getOpcode()).c_str()); case Hexagon::S4_storerb_ur: return Hexagon::S4_storerbnew_ur; @@ -3456,20 +3470,75 @@ int HexagonInstrInfo::getDotNewOp(const MachineInstr &MI) const { int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, const MachineBranchProbabilityInfo *MBPI) const { // We assume that block can have at most two successors. - bool taken = false; const MachineBasicBlock *Src = MI.getParent(); const MachineOperand &BrTarget = MI.getOperand(1); - const MachineBasicBlock *Dst = BrTarget.getMBB(); + bool Taken = false; + const BranchProbability OneHalf(1, 2); - const BranchProbability Prediction = MBPI->getEdgeProbability(Src, Dst); - if (Prediction >= BranchProbability(1,2)) - taken = true; + if (BrTarget.isMBB()) { + const MachineBasicBlock *Dst = BrTarget.getMBB(); + Taken = MBPI->getEdgeProbability(Src, Dst) >= OneHalf; + } else { + // The branch target is not a basic block (most likely a function). + // Since BPI only gives probabilities for targets that are basic blocks, + // try to identify another target of this branch (potentially a fall- + // -through) and check the probability of that target. + // + // The only handled branch combinations are: + // - one conditional branch, + // - one conditional branch followed by one unconditional branch. + // Otherwise, assume not-taken. + assert(MI.isConditionalBranch()); + const MachineBasicBlock &B = *MI.getParent(); + bool SawCond = false, Bad = false; + for (const MachineInstr &I : B) { + if (!I.isBranch()) + continue; + if (I.isConditionalBranch()) { + SawCond = true; + if (&I != &MI) { + Bad = true; + break; + } + } + if (I.isUnconditionalBranch() && !SawCond) { + Bad = true; + break; + } + } + if (!Bad) { + MachineBasicBlock::const_instr_iterator It(MI); + MachineBasicBlock::const_instr_iterator NextIt = std::next(It); + if (NextIt == B.instr_end()) { + // If this branch is the last, look for the fall-through block. + for (const MachineBasicBlock *SB : B.successors()) { + if (!B.isLayoutSuccessor(SB)) + continue; + Taken = MBPI->getEdgeProbability(Src, SB) < OneHalf; + break; + } + } else { + assert(NextIt->isUnconditionalBranch()); + // Find the first MBB operand and assume it's the target. + const MachineBasicBlock *BT = nullptr; + for (const MachineOperand &Op : NextIt->operands()) { + if (!Op.isMBB()) + continue; + BT = Op.getMBB(); + break; + } + Taken = BT && MBPI->getEdgeProbability(Src, BT) < OneHalf; + } + } // if (!Bad) + } + + // The Taken flag should be set to something reasonable by this point. switch (MI.getOpcode()) { case Hexagon::J2_jumpt: - return taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; + return Taken ? Hexagon::J2_jumptnewpt : Hexagon::J2_jumptnew; case Hexagon::J2_jumpf: - return taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; + return Taken ? Hexagon::J2_jumpfnewpt : Hexagon::J2_jumpfnew; default: llvm_unreachable("Unexpected jump instruction."); @@ -3479,26 +3548,46 @@ int HexagonInstrInfo::getDotNewPredJumpOp(const MachineInstr &MI, // Return .new predicate version for an instruction. int HexagonInstrInfo::getDotNewPredOp(const MachineInstr &MI, const MachineBranchProbabilityInfo *MBPI) const { - int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); - if (NewOpcode >= 0) // Valid predicate new instruction - return NewOpcode; - switch (MI.getOpcode()) { // Condtional Jumps case Hexagon::J2_jumpt: case Hexagon::J2_jumpf: return getDotNewPredJumpOp(MI, MBPI); - - default: - assert(0 && "Unknown .new type"); } - return 0; + + int NewOpcode = Hexagon::getPredNewOpcode(MI.getOpcode()); + if (NewOpcode >= 0) + return NewOpcode; + + dbgs() << "Cannot convert to .new: " << getName(MI.getOpcode()) << '\n'; + llvm_unreachable(nullptr); } -int HexagonInstrInfo::getDotOldOp(const int opc) const { - int NewOp = opc; +int HexagonInstrInfo::getDotOldOp(const MachineInstr &MI) const { + int NewOp = MI.getOpcode(); if (isPredicated(NewOp) && isPredicatedNew(NewOp)) { // Get predicate old form NewOp = Hexagon::getPredOldOpcode(NewOp); + const MachineFunction &MF = *MI.getParent()->getParent(); + const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>(); + // All Hexagon architectures have prediction bits on dot-new branches, + // but only Hexagon V60+ has prediction bits on dot-old ones. Make sure + // to pick the right opcode when converting back to dot-old. + if (!HST.getFeatureBits()[Hexagon::ArchV60]) { + switch (NewOp) { + case Hexagon::J2_jumptpt: + NewOp = Hexagon::J2_jumpt; + break; + case Hexagon::J2_jumpfpt: + NewOp = Hexagon::J2_jumpf; + break; + case Hexagon::J2_jumprtpt: + NewOp = Hexagon::J2_jumprt; + break; + case Hexagon::J2_jumprfpt: + NewOp = Hexagon::J2_jumprf; + break; + } + } assert(NewOp >= 0 && "Couldn't change predicate new instruction to its old form."); } |