[llvm] r276919 - [Hexagon] Find speculative loop preheader in hardware loop generation
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 27 14:20:54 PDT 2016
Author: kparzysz
Date: Wed Jul 27 16:20:54 2016
New Revision: 276919
URL: http://llvm.org/viewvc/llvm-project?rev=276919&view=rev
Log:
[Hexagon] Find speculative loop preheader in hardware loop generation
Before adding a new preheader block, check if there is a candidate block
where the loop setup could be placed speculatively. This will be off by
default.
Added:
llvm/trunk/test/CodeGen/Hexagon/hwloop-preh.ll
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonHardwareLoops.cpp
Modified: llvm/trunk/lib/Target/Hexagon/HexagonHardwareLoops.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonHardwareLoops.cpp?rev=276919&r1=276918&r2=276919&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonHardwareLoops.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonHardwareLoops.cpp Wed Jul 27 16:20:54 2016
@@ -60,6 +60,13 @@ static cl::opt<bool> HWCreatePreheader("
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::findInduction
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::getLoo
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::comput
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::convertToHard
// 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::fixupInductio
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:
// 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;
Added: llvm/trunk/test/CodeGen/Hexagon/hwloop-preh.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/hwloop-preh.ll?rev=276919&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/hwloop-preh.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/hwloop-preh.ll Wed Jul 27 16:20:54 2016
@@ -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" }
More information about the llvm-commits
mailing list