[PATCH] [Request, 45 lines] D25075: [JumpThreading] Allow threading over loop headers when creating single block loops

James Molloy via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 30 00:19:44 PDT 2016


jmolloy created this revision.
jmolloy added a reviewer: reames.
jmolloy added a subscriber: llvm-commits.
jmolloy set the repository for this revision to rL LLVM.

We have a very broad-brush bailout in JumpThreading - we never thread over a
loop header. This is so we don't create irreducible control flow.

However, as mentioned in the existing comments there are situations where we'd
want to thread over a loop header and it can create significant improvements in
some cases.

As it's hard to know if irreducible control flow would be created, handle
specially the case where we thread from predecessor to itself - essentially
generating a single block loop.  Single block loops aren't irreducible by
definition and are easy to check.


Repository:
  rL LLVM

https://reviews.llvm.org/D25075

Files:
  include/llvm/Transforms/Scalar/JumpThreading.h
  lib/Transforms/Scalar/JumpThreading.cpp
  test/Transforms/JumpThreading/singleblock-loop.ll


Index: test/Transforms/JumpThreading/singleblock-loop.ll
===================================================================
--- /dev/null
+++ test/Transforms/JumpThreading/singleblock-loop.ll
@@ -0,0 +1,28 @@
+; RUN: opt < %s -S -jump-threading | FileCheck %s
+
+; %i.0 can only take the value 2. If it gets incremented to 3, the loop will exit.
+; Jump threading must thread the %entry and backedge arcs directly to %while.body.
+
+; CHECK-LABEL: @f
+; CHECK: while.body: ; preds = %while.cond.thread, %while.cond
+define void @f() {
+entry:
+  br label %while.cond
+
+while.cond:                                       ; preds = %while.body, %entry
+  %i.0 = phi i32 [ 2, %entry ], [ %add.i.0, %while.body ]
+  %cmp = icmp slt i32 %i.0, 3
+  br i1 %cmp, label %while.body, label %return
+
+while.body:                                       ; preds = %while.cond
+  %add = add nsw i32 %i.0, 1
+  %call = call i32 @g()
+  %cmp3 = icmp eq i32 %call, 0
+  %add.i.0 = select i1 %cmp3, i32 %add, i32 %i.0
+  br label %while.cond
+
+return:
+  ret void
+}
+
+declare i32 @g()
Index: lib/Transforms/Scalar/JumpThreading.cpp
===================================================================
--- lib/Transforms/Scalar/JumpThreading.cpp
+++ lib/Transforms/Scalar/JumpThreading.cpp
@@ -168,6 +168,7 @@
   DEBUG(dbgs() << "Jump threading on function '" << F.getName() << "'\n");
   TLI = TLI_;
   LVI = LVI_;
+  Fn = &F;
   BFI.reset();
   BPI.reset();
   // When profile data is available, we need to update edge weights after
@@ -1182,11 +1183,6 @@
 bool JumpThreadingPass::ProcessThreadableEdges(Value *Cond, BasicBlock *BB,
                                                ConstantPreference Preference,
                                                Instruction *CxtI) {
-  // If threading this would thread across a loop header, don't even try to
-  // thread the edge.
-  if (LoopHeaders.count(BB))
-    return false;
-
   PredValueInfoTy PredValues;
   if (!ComputeValueKnownInPredecessors(Cond, BB, PredValues, Preference, CxtI))
     return false;
@@ -1457,7 +1453,11 @@
 
   // If threading this would thread across a loop header, don't thread the edge.
   // See the comments above FindLoopHeaders for justifications and caveats.
-  if (LoopHeaders.count(BB)) {
+  //
+  // However, if we're threading a block to *itself*, we know we're creating
+  // a one block loop that must by definition by valid. Proceed in this case.
+  if (LoopHeaders.count(BB) &&
+      std::find(PredBBs.begin(), PredBBs.end(), SuccBB) == PredBBs.end()) {
     DEBUG(dbgs() << "  Not threading across loop header BB '" << BB->getName()
           << "' to dest BB '" << SuccBB->getName()
           << "' - it might create an irreducible loop!\n");
@@ -1593,6 +1593,10 @@
   // Update the edge weight from BB to SuccBB, which should be less than before.
   UpdateBlockFreqAndEdgeWeight(PredBB, BB, NewBB, SuccBB);
 
+  if (LoopHeaders.count(BB))
+    // We threaded over a loop header. Recalculate loop headers now.
+    FindLoopHeaders(*Fn);
+  
   // Threaded an edge!
   ++NumThreads;
   return true;
Index: include/llvm/Transforms/Scalar/JumpThreading.h
===================================================================
--- include/llvm/Transforms/Scalar/JumpThreading.h
+++ include/llvm/Transforms/Scalar/JumpThreading.h
@@ -62,6 +62,7 @@
   std::unique_ptr<BlockFrequencyInfo> BFI;
   std::unique_ptr<BranchProbabilityInfo> BPI;
   bool HasProfileData = false;
+  Function *Fn;
 #ifdef NDEBUG
   SmallPtrSet<const BasicBlock *, 16> LoopHeaders;
 #else


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D25075.72992.patch
Type: text/x-patch
Size: 3541 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160930/01f9ebe0/attachment.bin>


More information about the llvm-commits mailing list