diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 107 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonInstrInfo.h | 33 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp | 3 |
3 files changed, 139 insertions, 4 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp index abba22273f0..4664e0c43d4 100644 --- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp @@ -660,6 +660,85 @@ 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; + } + 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, + 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(), 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; + } + // 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"); + unsigned 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); + // 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, getRegisterInfo()); + 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; +} bool HexagonInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, unsigned ExtraPredCycles, @@ -1592,6 +1671,22 @@ bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint( } +/// If the instruction is an increment of a constant value, return the amount. +bool HexagonInstrInfo::getIncrementValue(const MachineInstr *MI, + int &Value) const { + if (isPostIncrement(MI)) { + unsigned AccessSize; + return getBaseAndOffset(MI, Value, AccessSize); + } + if (MI->getOpcode() == Hexagon::A2_addi) { + Value = MI->getOperand(2).getImm(); + return true; + } + + return false; +} + + unsigned HexagonInstrInfo::createVR(MachineFunction* MF, MVT VT) const { MachineRegisterInfo &MRI = MF->getRegInfo(); const TargetRegisterClass *TRC; @@ -2878,6 +2973,18 @@ bool HexagonInstrInfo::addLatencyToSchedule(const MachineInstr *MI1, } +/// \brief Get the base register and byte offset of a load/store instr. +bool HexagonInstrInfo::getMemOpBaseRegImmOfs(MachineInstr &LdSt, + unsigned &BaseReg, int64_t &Offset, const TargetRegisterInfo *TRI) + const { + unsigned AccessSize = 0; + int OffsetVal = 0; + BaseReg = getBaseAndOffset(&LdSt, OffsetVal, AccessSize); + Offset = OffsetVal; + return BaseReg != 0; +} + + /// \brief Can these instructions execute at the same time in a bundle. bool HexagonInstrInfo::canExecuteInBundle(const MachineInstr *First, const MachineInstr *Second) const { diff --git a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h index 66b6883c955..e4b2523aba9 100644 --- a/llvm/lib/Target/Hexagon/HexagonInstrInfo.h +++ b/llvm/lib/Target/Hexagon/HexagonInstrInfo.h @@ -103,6 +103,22 @@ public: MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, const DebugLoc &DL) 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 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, + MachineInstr *IndVar, MachineInstr *Cmp, + SmallVectorImpl<MachineOperand> &Cond, + SmallVectorImpl<MachineInstr *> &PrevInsts, + unsigned Iter, unsigned MaxIter) const override; + /// Return true if it's profitable to predicate /// instructions with accumulated instruction latency of "NumCycles" /// of the specified basic block, where the probability of the instructions @@ -172,6 +188,11 @@ public: /// anything was changed. bool expandPostRAPseudo(MachineInstr &MI) const override; + /// \brief Get the base register and byte offset of a load/store instr. + bool getMemOpBaseRegImmOfs(MachineInstr &LdSt, unsigned &BaseReg, + int64_t &Offset, + const TargetRegisterInfo *TRI) const override; + /// Reverses the branch condition of the specified condition list, /// returning false on success and true if it cannot be reversed. bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) @@ -248,6 +269,14 @@ public: areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA = nullptr) const override; + /// For instructions with a base and offset, return the position of the + /// base register and offset operands. + bool getBaseAndOffsetPosition(const MachineInstr *MI, unsigned &BasePos, + unsigned &OffsetPos) const override; + + /// If the instruction is an increment of a constant value, return the amount. + bool getIncrementValue(const MachineInstr *MI, int &Value) const override; + /// HexagonInstrInfo specifics. /// @@ -297,7 +326,7 @@ public: bool isNewValueStore(const MachineInstr* MI) const; bool isNewValueStore(unsigned Opcode) const; bool isOperandExtended(const MachineInstr *MI, unsigned OperandNum) const; - bool isPostIncrement(const MachineInstr* MI) const; + bool isPostIncrement(const MachineInstr* MI) const override; bool isPredicatedNew(const MachineInstr &MI) const; bool isPredicatedNew(unsigned Opcode) const; bool isPredicatedTrue(const MachineInstr &MI) const; @@ -348,8 +377,6 @@ public: unsigned getAddrMode(const MachineInstr* MI) const; unsigned getBaseAndOffset(const MachineInstr *MI, int &Offset, unsigned &AccessSize) const; - bool getBaseAndOffsetPosition(const MachineInstr *MI, unsigned &BasePos, - unsigned &OffsetPos) const; short getBaseWithLongOffset(short Opcode) const; short getBaseWithLongOffset(const MachineInstr *MI) const; short getBaseWithRegOffset(const MachineInstr *MI) const; diff --git a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp index 80f256cd586..17396942898 100644 --- a/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp +++ b/llvm/lib/Target/Hexagon/HexagonTargetMachine.cpp @@ -27,7 +27,6 @@ using namespace llvm; - static cl::opt<bool> EnableRDFOpt("rdf-opt", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::desc("Enable RDF-based optimizations")); @@ -292,6 +291,8 @@ void HexagonPassConfig::addPreRegAlloc() { if (!DisableHardwareLoops) addPass(createHexagonHardwareLoops(), false); } + if (TM->getOptLevel() >= CodeGenOpt::Default) + addPass(&MachinePipelinerID); } void HexagonPassConfig::addPostRegAlloc() { |

