summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/PowerPC')
-rw-r--r--llvm/lib/Target/PowerPC/PPCInstrInfo.cpp144
-rw-r--r--llvm/lib/Target/PowerPC/PPCInstrInfo.h28
2 files changed, 96 insertions, 76 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index e4540d6520e..c33f0b36867 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -3930,21 +3930,97 @@ bool PPCInstrInfo::isBDNZ(unsigned Opcode) const {
return (Opcode == (Subtarget.isPPC64() ? PPC::BDNZ8 : PPC::BDNZ));
}
-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;
+class PPCPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
+ MachineInstr *Loop, *EndLoop, *LoopCount;
+ MachineFunction *MF;
+ const TargetInstrInfo *TII;
+ int64_t TripCount;
+
+public:
+ PPCPipelinerLoopInfo(MachineInstr *Loop, MachineInstr *EndLoop,
+ MachineInstr *LoopCount)
+ : Loop(Loop), EndLoop(EndLoop), LoopCount(LoopCount),
+ MF(Loop->getParent()->getParent()),
+ TII(MF->getSubtarget().getInstrInfo()) {
+ // Inspect the Loop instruction up-front, as it may be deleted when we call
+ // createTripCountGreaterCondition.
+ if (LoopCount->getOpcode() == PPC::LI8 || LoopCount->getOpcode() == PPC::LI)
+ TripCount = LoopCount->getOperand(1).getImm();
+ else
+ TripCount = -1;
}
- return true;
+
+ 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 {
+ if (TripCount == -1) {
+ // 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 {};
+ }
+
+ 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);
+ }
+ }
+ return nullptr;
}
-MachineInstr *
-PPCInstrInfo::findLoopInstr(MachineBasicBlock &PreHeader) const {
+MachineInstr *PPCInstrInfo::findLoopInstr(
+ MachineBasicBlock &PreHeader,
+ SmallPtrSet<MachineBasicBlock *, 8> &Visited) const {
unsigned LOOPi = (Subtarget.isPPC64() ? PPC::MTCTR8loop : PPC::MTCTRloop);
@@ -3955,50 +4031,6 @@ PPCInstrInfo::findLoopInstr(MachineBasicBlock &PreHeader) const {
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 5150650439b..13eecdff558 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -486,26 +486,14 @@ 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) 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;
+ 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;
};
}
OpenPOWER on IntegriCloud