Index: include/llvm/CodeGen/MachineLoopInfo.h =================================================================== --- include/llvm/CodeGen/MachineLoopInfo.h +++ include/llvm/CodeGen/MachineLoopInfo.h @@ -33,6 +33,7 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" namespace llvm { @@ -78,6 +79,9 @@ void operator=(const MachineLoopInfo &) = delete; MachineLoopInfo(const MachineLoopInfo &) = delete; + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + public: static char ID; // Pass identification, replacement for typeid @@ -157,6 +161,22 @@ void removeBlock(MachineBasicBlock *BB) { LI.removeBlock(BB); } + + /// \brief Find the register that contains the loop controlling + /// induction variable. + /// If successful, it will return true and set the \p Reg, \p IVBump + /// and \p IVOp arguments. Otherwise it will return false. + /// The returned induction register is the register R that follows the + /// following induction pattern: + /// loop: + /// R = phi ..., [ R, LatchBlock ] + /// R = R + #bump + /// if (R < #N) goto loop + /// IVBump is the immediate value added to R, and IVOp is the instruction + /// "R = R + #bump". + bool findInductionRegister(MachineLoop *L, unsigned &Reg, int64_t &IVBump, + MachineInstr *&IVOp) const; + }; Index: lib/CodeGen/MachineLoopInfo.cpp =================================================================== --- lib/CodeGen/MachineLoopInfo.cpp +++ lib/CodeGen/MachineLoopInfo.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetInstrInfo.h" using namespace llvm; // Explicitly instantiate methods in LoopInfoImpl.h for MI-level Loops. @@ -35,9 +36,11 @@ char &llvm::MachineLoopInfoID = MachineLoopInfo::ID; -bool MachineLoopInfo::runOnMachineFunction(MachineFunction &) { +bool MachineLoopInfo::runOnMachineFunction(MachineFunction &MF) { releaseMemory(); LI.analyze(getAnalysis().getBase()); + MRI = &MF.getRegInfo(); + TII = MF.getSubtarget().getInstrInfo(); return false; } @@ -122,6 +125,91 @@ return Preheader; } +bool MachineLoopInfo::findInductionRegister(MachineLoop *L, + unsigned &Reg, + int64_t &IVBump, + MachineInstr *&IVOp) const { + MachineBasicBlock *Header = L->getHeader(); + MachineBasicBlock *Preheader = findLoopPreheader(L, false); + MachineBasicBlock *Latch = L->getLoopLatch(); + MachineBasicBlock *ExitingBlock = L->findLoopControlBlock(); + if (!Header || !Preheader || !Latch || !ExitingBlock) + return false; + + // This pair represents an induction register together with an immediate + // value that will be added to it in each loop iteration. + typedef std::pair RegisterBump; + + // Mapping: R.next -> (R, bump), where R, R.next and bump are derived + // from an induction operation + // R.next = R + bump + // where bump is an immediate value. + typedef std::map InductionMap; + + InductionMap IndMap; + + typedef MachineBasicBlock::instr_iterator instr_iterator; + for (instr_iterator I = Header->instr_begin(), E = Header->instr_end(); + I != E && I->isPHI(); ++I) { + MachineInstr *Phi = &*I; + + // Have a PHI instruction. Get the operand that corresponds to the + // latch block, and see if is a result of an addition of form "reg+imm", + // where the "reg" is defined by the PHI node we are looking at. + for (unsigned i = 1, n = Phi->getNumOperands(); i < n; i += 2) { + if (Phi->getOperand(i+1).getMBB() != Latch) + continue; + + unsigned PhiOpReg = Phi->getOperand(i).getReg(); + MachineInstr *DI = MRI->getVRegDef(PhiOpReg); + + if (DI->getDesc().isAdd()) { + // If the register operand to the add is the PHI we're looking at, this + // meets the induction pattern. + unsigned IndReg = DI->getOperand(1).getReg(); + MachineOperand &Opnd2 = DI->getOperand(2); + int64_t V; + if (MRI->getVRegDef(IndReg) == Phi && + TII->getInstrOperandImmValue(*DI, Opnd2, V)) { + unsigned UpdReg = DI->getOperand(0).getReg(); + IndMap.insert(std::make_pair(UpdReg, std::make_pair(IndReg, V))); + } + } + } // for (i) + } // for (instr) + + unsigned CmpReg1 = 0, CmpReg2 = 0; + int CmpMask = 0, CmpImm = 0; + if (!TII->analyzeLoopTestBlock(*ExitingBlock, CmpReg1, CmpReg2, CmpMask, CmpImm)) + return false; + + // Exactly one of the input registers to the comparison should be among + // the induction registers. + InductionMap::iterator IndMapEnd = IndMap.end(); + InductionMap::iterator F = IndMapEnd; + if (CmpReg1 != 0) { + InductionMap::iterator F1 = IndMap.find(CmpReg1); + if (F1 != IndMapEnd) + F = F1; + } + if (CmpReg2 != 0) { + InductionMap::iterator F2 = IndMap.find(CmpReg2); + if (F2 != IndMapEnd) { + if (F != IndMapEnd) + return false; + F = F2; + } + } + if (F == IndMapEnd) + return false; + + Reg = F->second.first; + IVBump = F->second.second; + IVOp = MRI->getVRegDef(F->first); + + return true; +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MachineLoop::dump() const { print(dbgs()); Index: lib/Target/Hexagon/HexagonHardwareLoops.cpp =================================================================== --- lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -552,8 +552,8 @@ unsigned IVReg = 0; int64_t IVBump = 0; MachineInstr *IVOp; - bool FoundIV = findInductionRegister(L, IVReg, IVBump, IVOp); - if (!FoundIV) + + if (!MLI->findInductionRegister(L, IVReg, IVBump, IVOp)) return nullptr; MachineBasicBlock *Preheader = MLI->findLoopPreheader(L, SpecPreheader);