[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