summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Hexagon')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp162
-rw-r--r--llvm/lib/Target/Hexagon/HexagonInstrInfo.h19
2 files changed, 89 insertions, 92 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
index 97318a8057b..ea43db0f413 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
@@ -674,86 +674,94 @@ unsigned HexagonInstrInfo::insertBranch(MachineBasicBlock &MBB,
return 2;
}
-/// 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.
-bool HexagonInstrInfo::analyzeLoop(MachineLoop &L,
- MachineInstr *&IndVarInst,
- MachineInstr *&CmpInst) const {
-
- MachineBasicBlock *LoopEnd = L.getBottomBlock();
- MachineBasicBlock::iterator I = LoopEnd->getFirstTerminator();
- // We really "analyze" only hardware loops right now.
- if (I != LoopEnd->end() && isEndLoopN(I->getOpcode())) {
- IndVarInst = nullptr;
- CmpInst = &*I;
- return false;
+class HexagonPipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
+ MachineInstr *Loop, *EndLoop;
+ MachineFunction *MF;
+ const HexagonInstrInfo *TII;
+ int64_t TripCount;
+ Register LoopCount;
+ DebugLoc DL;
+
+public:
+ HexagonPipelinerLoopInfo(MachineInstr *Loop, MachineInstr *EndLoop)
+ : Loop(Loop), EndLoop(EndLoop), MF(Loop->getParent()->getParent()),
+ TII(MF->getSubtarget<HexagonSubtarget>().getInstrInfo()),
+ DL(Loop->getDebugLoc()) {
+ // Inspect the Loop instruction up-front, as it may be deleted when we call
+ // createTripCountGreaterCondition.
+ TripCount = Loop->getOpcode() == Hexagon::J2_loop0r
+ ? -1
+ : Loop->getOperand(1).getImm();
+ if (TripCount == -1)
+ LoopCount = Loop->getOperand(1).getReg();
}
- return true;
-}
-/// 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. this function
-/// assumes the nth iteration is peeled first.
-unsigned HexagonInstrInfo::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) && isEndLoopN(Cmp.getOpcode())
- && "Expecting a hardware loop");
- MachineFunction *MF = MBB.getParent();
- DebugLoc DL = Cmp.getDebugLoc();
- SmallPtrSet<MachineBasicBlock *, 8> 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
- // value.
- if (Loop->getOpcode() == Hexagon::J2_loop0i ||
- Loop->getOpcode() == Hexagon::J2_loop1i) {
- int64_t Offset = Loop->getOperand(1).getImm();
- if (Offset <= 1)
- Loop->eraseFromParent();
- else
- Loop->getOperand(1).setImm(Offset - 1);
- return Offset - 1;
+ bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
+ // Only ignore the terminator.
+ return MI == EndLoop;
}
- // The loop trip count is a run-time value. We generate code to subtract
- // one from the trip count, and update the loop instruction.
- assert(Loop->getOpcode() == Hexagon::J2_loop0r && "Unexpected instruction");
- Register LoopCount = Loop->getOperand(1).getReg();
- // Check if we're done with the loop.
- unsigned LoopEnd = createVR(MF, MVT::i1);
- MachineInstr *NewCmp = BuildMI(&MBB, DL, get(Hexagon::C2_cmpgtui), LoopEnd).
- addReg(LoopCount).addImm(1);
- unsigned NewLoopCount = createVR(MF, MVT::i32);
- MachineInstr *NewAdd = BuildMI(&MBB, DL, get(Hexagon::A2_addi), NewLoopCount).
- addReg(LoopCount).addImm(-1);
- const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
- // Update the previously generated instructions with the new loop counter.
- for (SmallVectorImpl<MachineInstr *>::iterator I = PrevInsts.begin(),
- E = PrevInsts.end(); I != E; ++I)
- (*I)->substituteRegister(LoopCount, NewLoopCount, 0, HRI);
- PrevInsts.clear();
- PrevInsts.push_back(NewCmp);
- PrevInsts.push_back(NewAdd);
- // Insert the new loop instruction if this is the last time the loop is
- // decremented.
- if (Iter == MaxIter)
- BuildMI(&MBB, DL, get(Hexagon::J2_loop0r)).
- addMBB(Loop->getOperand(0).getMBB()).addReg(NewLoopCount);
- // Delete the old loop instruction.
- if (Iter == 0)
- Loop->eraseFromParent();
- Cond.push_back(MachineOperand::CreateImm(Hexagon::J2_jumpf));
- Cond.push_back(NewCmp->getOperand(0));
- return NewLoopCount;
+
+ Optional<bool>
+ createTripCountGreaterCondition(int TC, MachineBasicBlock &MBB,
+ SmallVectorImpl<MachineOperand> &Cond) override {
+ if (TripCount == -1) {
+ // Check if we're done with the loop.
+ unsigned Done = TII->createVR(MF, MVT::i1);
+ MachineInstr *NewCmp = BuildMI(&MBB, DL,
+ TII->get(Hexagon::C2_cmpgtui), Done)
+ .addReg(LoopCount)
+ .addImm(TC);
+ Cond.push_back(MachineOperand::CreateImm(Hexagon::J2_jumpf));
+ Cond.push_back(NewCmp->getOperand(0));
+ return {};
+ }
+
+ return TripCount > TC;
+ }
+
+ void setPreheader(MachineBasicBlock *NewPreheader) override {
+ NewPreheader->splice(NewPreheader->getFirstTerminator(), Loop->getParent(),
+ Loop);
+ }
+
+ void adjustTripCount(int TripCountAdjust) override {
+ // If the loop trip count is a compile-time value, then just change the
+ // value.
+ if (Loop->getOpcode() == Hexagon::J2_loop0i ||
+ Loop->getOpcode() == Hexagon::J2_loop1i) {
+ int64_t TripCount = Loop->getOperand(1).getImm() + TripCountAdjust;
+ assert(TripCount > 0 && "Can't create an empty or negative loop!");
+ Loop->getOperand(1).setImm(TripCount);
+ return;
+ }
+
+ // The loop trip count is a run-time value. We generate code to subtract
+ // one from the trip count, and update the loop instruction.
+ Register LoopCount = Loop->getOperand(1).getReg();
+ Register NewLoopCount = TII->createVR(MF, MVT::i32);
+ BuildMI(*Loop->getParent(), Loop, Loop->getDebugLoc(),
+ TII->get(Hexagon::A2_addi), NewLoopCount)
+ .addReg(LoopCount)
+ .addImm(TripCountAdjust);
+ Loop->getOperand(1).setReg(NewLoopCount);
+ }
+
+ void disposed() override { Loop->eraseFromParent(); }
+};
+
+std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
+HexagonInstrInfo::analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const {
+ // We really "analyze" only hardware loops right now.
+ MachineBasicBlock::iterator I = LoopBB->getFirstTerminator();
+
+ if (I != LoopBB->end() && isEndLoopN(I->getOpcode())) {
+ SmallPtrSet<MachineBasicBlock *, 8> VisitedBBs;
+ MachineInstr *LoopInst = findLoopInstr(
+ LoopBB, I->getOpcode(), I->getOperand(0).getMBB(), VisitedBBs);
+ if (LoopInst)
+ return std::make_unique<HexagonPipelinerLoopInfo>(LoopInst, &*I);
+ }
+ return nullptr;
}
bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
index e0a999d0f4c..e863400480b 100644
--- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h
@@ -129,21 +129,10 @@ public:
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
- /// Analyze the loop code, return true if it cannot be understood. Upon
- /// success, this function returns false and returns information about the
- /// induction variable and compare instruction used at the end.
- 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 nth 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;
+ /// 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<PipelinerLoopInfo>
+ analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
/// Return true if it's profitable to predicate
/// instructions with accumulated instruction latency of "NumCycles"
OpenPOWER on IntegriCloud