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.cpp139
-rw-r--r--llvm/lib/Target/PowerPC/PPCInstrInfo.h28
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;
};
}
OpenPOWER on IntegriCloud