From 73a75d092e58d0f697b62455c6c2f0c52c4fa1ca Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Mon, 15 Aug 2016 08:22:42 +0000 Subject: [PATCH] MachineLoop: add methods findLoopControlBlock and findLoopPreheader This adds two new utility functions findLoopControlBlock and findLoopPreheader to MachineLoop and MachineLoopInfo. These functions are refactored and taken from the Hexagon target as they are target independent; thus this is intendend to be a non-functional change. Differential Revision: https://reviews.llvm.org/D22959 llvm-svn: 278661 --- include/llvm/CodeGen/MachineLoopInfo.h | 14 ++++ lib/CodeGen/MachineLoopInfo.cpp | 45 +++++++++++++ lib/Target/Hexagon/HexagonHardwareLoops.cpp | 73 ++++----------------- 3 files changed, 70 insertions(+), 62 deletions(-) diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index 45697522e79..308fc942a8c 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -54,6 +54,12 @@ public: /// that contains the header. MachineBasicBlock *getBottomBlock(); + /// \brief Find the block that contains the loop control variable and the + /// loop test. This will return the latch block if it's one of the exiting + /// blocks. Otherwise, return the exiting block. Return 'null' when + /// multiple exiting blocks are present. + MachineBasicBlock *findLoopControlBlock(); + void dump() const; private: @@ -81,6 +87,14 @@ public: LoopInfoBase& getBase() { return LI; } + /// \brief Find the block that either is the loop preheader, or could + /// speculatively be used as the preheader. This is e.g. useful to place + /// loop setup code. Code that cannot be speculated should not be placed + /// here. SpeculativePreheader is controlling whether it also tries to + /// find the speculative preheader if the regular preheader is not present. + MachineBasicBlock *findLoopPreheader(MachineLoop *L, + bool SpeculativePreheader = false) const; + /// The iterator interface to the top-level loops in the current function. typedef LoopInfoBase::iterator iterator; inline iterator begin() const { return LI.begin(); } diff --git a/lib/CodeGen/MachineLoopInfo.cpp b/lib/CodeGen/MachineLoopInfo.cpp index 376f78fda1c..fdeaf7b7116 100644 --- a/lib/CodeGen/MachineLoopInfo.cpp +++ b/lib/CodeGen/MachineLoopInfo.cpp @@ -77,6 +77,51 @@ MachineBasicBlock *MachineLoop::getBottomBlock() { return BotMBB; } +MachineBasicBlock *MachineLoop::findLoopControlBlock() { + if (MachineBasicBlock *Latch = getLoopLatch()) { + if (isLoopExiting(Latch)) + return Latch; + else + return getExitingBlock(); + } + return nullptr; +} + +MachineBasicBlock * +MachineLoopInfo::findLoopPreheader(MachineLoop *L, + bool SpeculativePreheader) const { + if (MachineBasicBlock *PB = L->getLoopPreheader()) + return PB; + + if (!SpeculativePreheader) + return nullptr; + + MachineBasicBlock *HB = L->getHeader(), *LB = L->getLoopLatch(); + if (HB->pred_size() != 2 || HB->hasAddressTaken()) + return nullptr; + // Find the predecessor of the header that is not the latch block. + MachineBasicBlock *Preheader = nullptr; + for (MachineBasicBlock *P : HB->predecessors()) { + if (P == LB) + continue; + // Sanity. + if (Preheader) + return nullptr; + Preheader = P; + } + + // Check if the preheader candidate is a successor of any other loop + // headers. We want to avoid having two loop setups in the same block. + for (MachineBasicBlock *S : Preheader->successors()) { + if (S == HB) + continue; + MachineLoop *T = getLoopFor(S); + if (T && T->getHeader() == S) + return nullptr; + } + return Preheader; +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MachineLoop::dump() const { print(dbgs()); diff --git a/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/lib/Target/Hexagon/HexagonHardwareLoops.cpp index e4d7da1f385..930747faa0d 100644 --- a/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -277,10 +277,6 @@ namespace { /// cannot be adjusted to reflect the post-bump value. bool fixupInductionVariable(MachineLoop *L); - /// \brief Find the block that either is the loop preheader, or could - /// speculatively be used as the preheader. - MachineBasicBlock *findLoopPreheader(MachineLoop *L) const; - /// \brief Given a loop, if it does not have a preheader, create one. /// Return the block that is the preheader. MachineBasicBlock *createPreheaderForLoop(MachineLoop *L); @@ -377,28 +373,15 @@ bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) { return Changed; } -/// \brief Return the latch block if it's one of the exiting blocks. Otherwise, -/// return the exiting block. Return 'null' when multiple exiting blocks are -/// present. -static MachineBasicBlock* getExitingBlock(MachineLoop *L) { - if (MachineBasicBlock *Latch = L->getLoopLatch()) { - if (L->isLoopExiting(Latch)) - return Latch; - else - return L->getExitingBlock(); - } - return nullptr; -} - bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L, unsigned &Reg, int64_t &IVBump, MachineInstr *&IVOp ) const { MachineBasicBlock *Header = L->getHeader(); - MachineBasicBlock *Preheader = findLoopPreheader(L); + MachineBasicBlock *Preheader = MLI->findLoopPreheader(L, SpecPreheader); MachineBasicBlock *Latch = L->getLoopLatch(); - MachineBasicBlock *ExitingBlock = getExitingBlock(L); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); if (!Header || !Preheader || !Latch || !ExitingBlock) return false; @@ -566,7 +549,7 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, // Look for the cmp instruction to determine if we can get a useful trip // count. The trip count can be either a register or an immediate. The // location of the value depends upon the type (reg or imm). - MachineBasicBlock *ExitingBlock = getExitingBlock(L); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); if (!ExitingBlock) return nullptr; @@ -577,7 +560,7 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, if (!FoundIV) return nullptr; - MachineBasicBlock *Preheader = findLoopPreheader(L); + MachineBasicBlock *Preheader = MLI->findLoopPreheader(L, SpecPreheader); MachineOperand *InitialValue = nullptr; MachineInstr *IV_Phi = MRI->getVRegDef(IVReg); @@ -798,7 +781,7 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, if (!isPowerOf2_64(std::abs(IVBump))) return nullptr; - MachineBasicBlock *PH = findLoopPreheader(Loop); + MachineBasicBlock *PH = MLI->findLoopPreheader(Loop, SpecPreheader); assert (PH && "Should have a preheader by now"); MachineBasicBlock::iterator InsertPos = PH->getFirstTerminator(); DebugLoc DL; @@ -1149,7 +1132,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L, if (containsInvalidInstruction(L, IsInnerHWLoop)) return false; - MachineBasicBlock *LastMBB = getExitingBlock(L); + MachineBasicBlock *LastMBB = L->findLoopControlBlock(); // Don't generate hw loop if the loop has more than one exit. if (!LastMBB) return false; @@ -1164,7 +1147,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L, // Ensure the loop has a preheader: the loop instruction will be // placed there. - MachineBasicBlock *Preheader = findLoopPreheader(L); + MachineBasicBlock *Preheader = MLI->findLoopPreheader(L, SpecPreheader); if (!Preheader) { Preheader = createPreheaderForLoop(L); if (!Preheader) @@ -1191,7 +1174,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L, // Determine the loop start. MachineBasicBlock *TopBlock = L->getTopBlock(); - MachineBasicBlock *ExitingBlock = getExitingBlock(L); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); MachineBasicBlock *LoopStart = 0; if (ExitingBlock != L->getLoopLatch()) { MachineBasicBlock *TB = 0, *FB = 0; @@ -1580,7 +1563,7 @@ static bool isImmValidForOpcode(unsigned CmpOpc, int64_t Imm) { bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) { MachineBasicBlock *Header = L->getHeader(); MachineBasicBlock *Latch = L->getLoopLatch(); - MachineBasicBlock *ExitingBlock = getExitingBlock(L); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); if (!(Header && Latch && ExitingBlock)) return false; @@ -1818,51 +1801,17 @@ bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) { return false; } -/// Find a preaheader of the given loop. -MachineBasicBlock *HexagonHardwareLoops::findLoopPreheader(MachineLoop *L) - const { - if (MachineBasicBlock *PB = L->getLoopPreheader()) - return PB; - if (!SpecPreheader) - return nullptr; - MachineBasicBlock *HB = L->getHeader(), *LB = L->getLoopLatch(); - if (HB->pred_size() != 2 || HB->hasAddressTaken()) - return nullptr; - // Find the predecessor of the header that is not the latch block. - MachineBasicBlock *Preheader = nullptr; - for (MachineBasicBlock *P : HB->predecessors()) { - if (P == LB) - continue; - // Sanity. - if (Preheader) - return nullptr; - Preheader = P; - } - - // Check if the preheader candidate is a successor of any other loop - // headers. We want to avoid having two loop setups in the same block. - for (MachineBasicBlock *S : Preheader->successors()) { - if (S == HB) - continue; - MachineLoop *T = MLI->getLoopFor(S); - if (T && T->getHeader() == S) - return nullptr; - } - return Preheader; -} - - /// createPreheaderForLoop - Create a preheader for a given loop. MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop( MachineLoop *L) { - if (MachineBasicBlock *TmpPH = findLoopPreheader(L)) + if (MachineBasicBlock *TmpPH = MLI->findLoopPreheader(L, SpecPreheader)) return TmpPH; if (!HWCreatePreheader) return nullptr; MachineBasicBlock *Header = L->getHeader(); MachineBasicBlock *Latch = L->getLoopLatch(); - MachineBasicBlock *ExitingBlock = getExitingBlock(L); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); MachineFunction *MF = Header->getParent(); DebugLoc DL;