diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp | 67 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Hexagon/hwloop-preh.ll | 44 |
2 files changed, 101 insertions, 10 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp b/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp index cc154c4be01..608f29184e5 100644 --- a/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp +++ b/llvm/lib/Target/Hexagon/HexagonHardwareLoops.cpp @@ -60,6 +60,13 @@ static cl::opt<bool> HWCreatePreheader("hexagon-hwloop-preheader", cl::Hidden, cl::init(true), cl::desc("Add a preheader to a hardware loop if one doesn't exist")); +// Turn it off by default. If a preheader block is not created here, the +// software pipeliner may be unable to find a block suitable to serve as +// a preheader. In that case SWP will not run. +static cl::opt<bool> SpecPreheader("hwloop-spec-preheader", cl::init(false), + cl::Hidden, cl::ZeroOrMore, cl::desc("Allow speculation of preheader " + "instructions")); + STATISTIC(NumHWLoops, "Number of loops converted to hardware loops"); namespace llvm { @@ -270,6 +277,10 @@ 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); @@ -385,7 +396,7 @@ bool HexagonHardwareLoops::findInductionRegister(MachineLoop *L, MachineInstr *&IVOp ) const { MachineBasicBlock *Header = L->getHeader(); - MachineBasicBlock *Preheader = L->getLoopPreheader(); + MachineBasicBlock *Preheader = findLoopPreheader(L); MachineBasicBlock *Latch = L->getLoopLatch(); MachineBasicBlock *ExitingBlock = getExitingBlock(L); if (!Header || !Preheader || !Latch || !ExitingBlock) @@ -566,7 +577,7 @@ CountValue *HexagonHardwareLoops::getLoopTripCount(MachineLoop *L, if (!FoundIV) return nullptr; - MachineBasicBlock *Preheader = L->getLoopPreheader(); + MachineBasicBlock *Preheader = findLoopPreheader(L); MachineOperand *InitialValue = nullptr; MachineInstr *IV_Phi = MRI->getVRegDef(IVReg); @@ -787,7 +798,7 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop, if (!isPowerOf2_64(std::abs(IVBump))) return nullptr; - MachineBasicBlock *PH = Loop->getLoopPreheader(); + MachineBasicBlock *PH = findLoopPreheader(Loop); assert (PH && "Should have a preheader by now"); MachineBasicBlock::iterator InsertPos = PH->getFirstTerminator(); DebugLoc DL; @@ -1153,7 +1164,7 @@ bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L, // Ensure the loop has a preheader: the loop instruction will be // placed there. - MachineBasicBlock *Preheader = L->getLoopPreheader(); + MachineBasicBlock *Preheader = findLoopPreheader(L); if (!Preheader) { Preheader = createPreheaderForLoop(L); if (!Preheader) @@ -1807,12 +1818,45 @@ bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) { return false; } -/// \brief Create a preheader for a given loop. +/// 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 = L->getLoopPreheader()) + if (MachineBasicBlock *TmpPH = findLoopPreheader(L)) return TmpPH; - if (!HWCreatePreheader) return nullptr; @@ -1958,9 +2002,12 @@ MachineBasicBlock *HexagonHardwareLoops::createPreheaderForLoop( // Update the dominator information with the new preheader. if (MDT) { - MachineDomTreeNode *HDom = MDT->getNode(Header); - MDT->addNewBlock(NewPH, HDom->getIDom()->getBlock()); - MDT->changeImmediateDominator(Header, NewPH); + if (MachineDomTreeNode *HN = MDT->getNode(Header)) { + if (MachineDomTreeNode *DHN = HN->getIDom()) { + MDT->addNewBlock(NewPH, DHN->getBlock()); + MDT->changeImmediateDominator(Header, NewPH); + } + } } return NewPH; diff --git a/llvm/test/CodeGen/Hexagon/hwloop-preh.ll b/llvm/test/CodeGen/Hexagon/hwloop-preh.ll new file mode 100644 index 00000000000..e92461f43da --- /dev/null +++ b/llvm/test/CodeGen/Hexagon/hwloop-preh.ll @@ -0,0 +1,44 @@ +; RUN: llc -march=hexagon -disable-machine-licm -hwloop-spec-preheader=1 < %s | FileCheck %s +; CHECK: loop0 + +target triple = "hexagon" + +define i32 @foo(i32 %x, i32 %n, i32* nocapture %A, i32* nocapture %B) #0 { +entry: + %cmp = icmp sgt i32 %x, 0 + br i1 %cmp, label %for.cond.preheader, label %return + +for.cond.preheader: ; preds = %entry + %cmp16 = icmp sgt i32 %n, 0 + br i1 %cmp16, label %for.body.preheader, label %return + +for.body.preheader: ; preds = %for.cond.preheader + br label %for.body + +for.body: ; preds = %for.body.preheader, %for.body + %arrayidx.phi = phi i32* [ %arrayidx.inc, %for.body ], [ %B, %for.body.preheader ] + %arrayidx2.phi = phi i32* [ %arrayidx2.inc, %for.body ], [ %A, %for.body.preheader ] + %i.07 = phi i32 [ %inc, %for.body ], [ 0, %for.body.preheader ] + %0 = load i32, i32* %arrayidx.phi, align 4, !tbaa !0 + %1 = load i32, i32* %arrayidx2.phi, align 4, !tbaa !0 + %add = add nsw i32 %1, %0 + store i32 %add, i32* %arrayidx2.phi, align 4, !tbaa !0 + %inc = add nsw i32 %i.07, 1 + %exitcond = icmp eq i32 %inc, %n + %arrayidx.inc = getelementptr i32, i32* %arrayidx.phi, i32 1 + %arrayidx2.inc = getelementptr i32, i32* %arrayidx2.phi, i32 1 + br i1 %exitcond, label %return.loopexit, label %for.body + +return.loopexit: ; preds = %for.body + br label %return + +return: ; preds = %return.loopexit, %for.cond.preheader, %entry + %retval.0 = phi i32 [ 2, %entry ], [ 0, %for.cond.preheader ], [ 0, %return.loopexit ] + ret i32 %retval.0 +} + +!0 = !{!"int", !1} +!1 = !{!"omnipotent char", !2} +!2 = !{!"Simple C/C++ TBAA"} + +attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="-hvx,-hvx-double" } |

