diff options
| author | Brendon Cahoon <bcahoon@codeaurora.org> | 2016-07-29 16:44:44 +0000 |
|---|---|---|
| committer | Brendon Cahoon <bcahoon@codeaurora.org> | 2016-07-29 16:44:44 +0000 |
| commit | 254f889dc54672f6765791078a5c22a71e2b7cb3 (patch) | |
| tree | f1e9c5895906c2bf954cbd915ebd061396abb1c2 /llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | |
| parent | 0bd55a7608098ebacd4f8bd4a83a15bc1b3e7206 (diff) | |
| download | bcm5719-llvm-254f889dc54672f6765791078a5c22a71e2b7cb3.tar.gz bcm5719-llvm-254f889dc54672f6765791078a5c22a71e2b7cb3.zip | |
MachinePipeliner pass that implements Swing Modulo Scheduling
Software pipelining is an optimization for improving ILP by
overlapping loop iterations. Swing Modulo Scheduling (SMS) is
an implementation of software pipelining that attempts to
reduce register pressure and generate efficient pipelines with
a low compile-time cost.
This implementaion of SMS is a target-independent back-end pass.
When enabled, the pass should run just prior to the register
allocation pass, while the machine IR is in SSA form. If the pass
is successful, then the original loop is replaced by the optimized
loop. The optimized loop contains one or more prolog blocks, the
pipelined kernel, and one or more epilog blocks.
This pass is enabled for Hexagon only. To enable for other targets,
a couple of target specific hooks must be implemented, and the
pass needs to be called from the target's TargetMachine
implementation.
Differential Review: http://reviews.llvm.org/D16829
llvm-svn: 277169
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp | 107 |
1 files changed, 107 insertions, 0 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 { |

