diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 139 | ||||
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrInfo.h | 28 |
2 files changed, 76 insertions, 91 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp index 455fbdfea28..e4540d6520e 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -3930,92 +3930,21 @@ bool PPCInstrInfo::isBDNZ(unsigned Opcode) const { return (Opcode == (Subtarget.isPPC64() ? PPC::BDNZ8 : PPC::BDNZ)); } -class PPCPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo { - MachineInstr *Loop, *EndLoop, *LoopCount; - MachineFunction *MF; - const TargetInstrInfo *TII; - -public: - PPCPipelinerLoopInfo(MachineInstr *Loop, MachineInstr *EndLoop, - MachineInstr *LoopCount) - : Loop(Loop), EndLoop(EndLoop), LoopCount(LoopCount), - MF(Loop->getParent()->getParent()), - TII(MF->getSubtarget().getInstrInfo()) {} - - bool shouldIgnoreForPipelining(const MachineInstr *MI) const override { - // Only ignore the terminator. - return MI == EndLoop; - } - - Optional<bool> - createTripCountGreaterCondition(int TC, MachineBasicBlock &MBB, - SmallVectorImpl<MachineOperand> &Cond) override { - bool IsConstantTripCount = - LoopCount->getOpcode() == PPC::LI8 || LoopCount->getOpcode() == PPC::LI; - if (!IsConstantTripCount) { - // Since BDZ/BDZ8 that we will insert will also decrease the ctr by 1, - // so we don't need to generate any thing here. - Cond.push_back(MachineOperand::CreateImm(0)); - Cond.push_back(MachineOperand::CreateReg( - MF->getSubtarget<PPCSubtarget>().isPPC64() ? PPC::CTR8 : PPC::CTR, - true)); - return {}; - } - - int64_t TripCount = LoopCount->getOperand(1).getImm(); - return TripCount > TC; - } - - void setPreheader(MachineBasicBlock *NewPreheader) override { - // Do nothing. We want the LOOP setup instruction to stay in the *old* - // preheader, so we can use BDZ in the prologs to adapt the loop trip count. - } - - void adjustTripCount(int TripCountAdjust) override { - // If the loop trip count is a compile-time value, then just change the - // value. - if (LoopCount->getOpcode() == PPC::LI8 || - LoopCount->getOpcode() == PPC::LI) { - int64_t TripCount = LoopCount->getOperand(1).getImm() + TripCountAdjust; - LoopCount->getOperand(1).setImm(TripCount); - return; - } - - // Since BDZ/BDZ8 that we will insert will also decrease the ctr by 1, - // so we don't need to generate any thing here. - } - - void disposed() override { - Loop->eraseFromParent(); - // Ensure the loop setup instruction is deleted too. - LoopCount->eraseFromParent(); - } -}; - -std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> -PPCInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const { - // We really "analyze" only hardware loops right now. - MachineBasicBlock::iterator I = LoopBB->getFirstTerminator(); - MachineBasicBlock *Preheader = *LoopBB->pred_begin(); - if (Preheader == LoopBB) - Preheader = *std::next(LoopBB->pred_begin()); - MachineFunction *MF = Preheader->getParent(); - - if (I != LoopBB->end() && isBDNZ(I->getOpcode())) { - SmallPtrSet<MachineBasicBlock *, 8> Visited; - if (MachineInstr *LoopInst = findLoopInstr(*Preheader, Visited)) { - Register LoopCountReg = LoopInst->getOperand(0).getReg(); - MachineRegisterInfo &MRI = MF->getRegInfo(); - MachineInstr *LoopCount = MRI.getUniqueVRegDef(LoopCountReg); - return std::make_unique<PPCPipelinerLoopInfo>(LoopInst, &*I, LoopCount); - } +bool PPCInstrInfo::analyzeLoop(MachineLoop &L, MachineInstr *&IndVarInst, + MachineInstr *&CmpInst) const { + MachineBasicBlock *LoopEnd = L.getBottomBlock(); + MachineBasicBlock::iterator I = LoopEnd->getFirstTerminator(); + // We really "analyze" only CTR loops right now. + if (I != LoopEnd->end() && isBDNZ(I->getOpcode())) { + IndVarInst = nullptr; + CmpInst = &*I; + return false; } - return nullptr; + return true; } -MachineInstr *PPCInstrInfo::findLoopInstr( - MachineBasicBlock &PreHeader, - SmallPtrSet<MachineBasicBlock *, 8> &Visited) const { +MachineInstr * +PPCInstrInfo::findLoopInstr(MachineBasicBlock &PreHeader) const { unsigned LOOPi = (Subtarget.isPPC64() ? PPC::MTCTR8loop : PPC::MTCTRloop); @@ -4026,6 +3955,50 @@ MachineInstr *PPCInstrInfo::findLoopInstr( return nullptr; } +unsigned PPCInstrInfo::reduceLoopCount( + MachineBasicBlock &MBB, MachineBasicBlock &PreHeader, MachineInstr *IndVar, + MachineInstr &Cmp, SmallVectorImpl<MachineOperand> &Cond, + SmallVectorImpl<MachineInstr *> &PrevInsts, unsigned Iter, + unsigned MaxIter) const { + // We expect a hardware loop currently. This means that IndVar is set + // to null, and the compare is the ENDLOOP instruction. + assert((!IndVar) && isBDNZ(Cmp.getOpcode()) && "Expecting a CTR loop"); + MachineFunction *MF = MBB.getParent(); + DebugLoc DL = Cmp.getDebugLoc(); + MachineInstr *Loop = findLoopInstr(PreHeader); + if (!Loop) + return 0; + Register LoopCountReg = Loop->getOperand(0).getReg(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstr *LoopCount = MRI.getUniqueVRegDef(LoopCountReg); + + if (!LoopCount) + return 0; + // If the loop trip count is a compile-time value, then just change the + // value. + if (LoopCount->getOpcode() == PPC::LI8 || LoopCount->getOpcode() == PPC::LI) { + int64_t Offset = LoopCount->getOperand(1).getImm(); + if (Offset <= 1) { + LoopCount->eraseFromParent(); + Loop->eraseFromParent(); + return 0; + } + LoopCount->getOperand(1).setImm(Offset - 1); + return Offset - 1; + } + + // The loop trip count is a run-time value. + // We need to subtract one from the trip count, + // and insert branch later to check if we're done with the loop. + + // Since BDZ/BDZ8 that we will insert will also decrease the ctr by 1, + // so we don't need to generate any thing here. + Cond.push_back(MachineOperand::CreateImm(0)); + Cond.push_back(MachineOperand::CreateReg( + Subtarget.isPPC64() ? PPC::CTR8 : PPC::CTR, true)); + return LoopCountReg; +} + // Return true if get the base operand, byte offset of an instruction and the // memory width. Width is the size of memory that is being loaded/stored. bool PPCInstrInfo::getMemOperandWithOffsetWidth( diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h index 13eecdff558..5150650439b 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -486,14 +486,26 @@ public: /// On PPC, we have two instructions used to set-up the hardware loop /// (MTCTRloop, MTCTR8loop) with corresponding endloop (BDNZ, BDNZ8) /// instructions to indicate the end of a loop. - MachineInstr * - findLoopInstr(MachineBasicBlock &PreHeader, - SmallPtrSet<MachineBasicBlock *, 8> &Visited) const; - - /// Analyze loop L, which must be a single-basic-block loop, and if the - /// conditions can be understood enough produce a PipelinerLoopInfo object. - std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo> - analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override; + MachineInstr *findLoopInstr(MachineBasicBlock &PreHeader) const; + + /// Analyze the loop code to find the loop induction variable and compare used + /// to compute the number of iterations. Currently, we analyze loop that are + /// controlled using hardware loops. In this case, the induction variable + /// instruction is null. For all other cases, this function returns true, + /// which means we're unable to analyze it. \p IndVarInst and \p CmpInst will + /// return new values when we can analyze the readonly loop \p L, otherwise, + /// nothing got changed + bool analyzeLoop(MachineLoop &L, MachineInstr *&IndVarInst, + MachineInstr *&CmpInst) const override; + /// Generate code to reduce the loop iteration by one and check if the loop + /// is finished. Return the value/register of the new loop count. We need + /// this function when peeling off one or more iterations of a loop. This + /// function assumes the last iteration is peeled first. + unsigned reduceLoopCount(MachineBasicBlock &MBB, MachineBasicBlock &PreHeader, + MachineInstr *IndVar, MachineInstr &Cmp, + SmallVectorImpl<MachineOperand> &Cond, + SmallVectorImpl<MachineInstr *> &PrevInsts, + unsigned Iter, unsigned MaxIter) const override; }; } |

