[PATCH] D46211: [LICM] Compute a must execute property for the prefix of the header as we go

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 27 14:23:33 PDT 2018


reames created this revision.
reames added reviewers: mkazantsev, anna.
Herald added subscribers: bollu, mcrosier.

Computing this property within the existing walk ensures that the cost is linear with the size of the block.  If we did this from within isGuaranteedToExecute, it would be quadratic without some very fancy caching.

This allows us to reliably catch a hoistable instruction within a header which may throw at some point *after* our hoistable instruction.  It doesn't do anything for non-header cases, but given how common single block loops are, this seems very worthwhile.

(The rest of this is not part of the commit message, just recording ideas.)

Given this, we could expand in a couple of directions:

- special case a guard which is known not to be taken on the first iteration of the loop
- support hoisting of guards themselves if we compute an extra IsPrefixReadOnly property as we go.
- I'm seriously considering keeping around the set of loop blocks with implicit control flow in LoopSafetyInfo.  Doing so would let us apply a variation of the exit logic combined with this prefix property to handle non-header cases as well.


Repository:
  rL LLVM

https://reviews.llvm.org/D46211

Files:
  lib/Transforms/Scalar/LICM.cpp
  test/Transforms/LICM/preheader-safe.ll


Index: test/Transforms/LICM/preheader-safe.ll
===================================================================
--- test/Transforms/LICM/preheader-safe.ll
+++ test/Transforms/LICM/preheader-safe.ll
@@ -55,7 +55,26 @@
   br label %loop
 }
 
+; Similiar to the above, but the hoistable instruction (%y in this case)
+; happens not to be the first instruction in the block.
+define void @throw_header_after_nonfirst(i64* %xp, i64* %yp, i1* %cond) {
+; CHECK-LABEL: throw_header_after_nonfirst
+; CHECK: %y = load i64, i64* %yp
+; CHECK-LABEL: loop
+; CHECK: %div = udiv i64 %x, %y
+; CHECK: call void @use(i64 %div)
+entry:
+  br label %loop
 
+loop:                                         ; preds = %entry, %for.inc
+  %iv = phi i64 [0, %entry], [%div, %loop]
+  %gep = getelementptr i64, i64* %xp, i64 %iv
+  %x = load i64, i64* %gep
+  %y = load i64, i64* %yp
+  %div = udiv i64 %x, %y
+  call void @use(i64 %div) readonly
+  br label %loop
+}
 
 ; Negative test
 define void @throw_header_before(i64 %x, i64 %y, i1* %cond) {
Index: lib/Transforms/Scalar/LICM.cpp
===================================================================
--- lib/Transforms/Scalar/LICM.cpp
+++ lib/Transforms/Scalar/LICM.cpp
@@ -449,6 +449,11 @@
     if (inSubLoop(BB, CurLoop, LI))
       continue;
 
+    // Keep track of whether the prefix of instructions visited so far are such
+    // that the next instruction visited is guaranteed to execute if the loop
+    // is entered.  
+    bool IsMustExecute = CurLoop->getHeader() == BB;
+
     for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
       Instruction &I = *II++;
       // Try constant folding this instruction.  If all the operands are
@@ -496,10 +501,14 @@
       //
       if (CurLoop->hasLoopInvariantOperands(&I) &&
           canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, SafetyInfo, ORE) &&
-          isSafeToExecuteUnconditionally(
-              I, DT, CurLoop, SafetyInfo, ORE,
-              CurLoop->getLoopPreheader()->getTerminator()))
+          (IsMustExecute ||
+           isSafeToExecuteUnconditionally(
+               I, DT, CurLoop, SafetyInfo, ORE,
+               CurLoop->getLoopPreheader()->getTerminator())))
         Changed |= hoist(I, DT, CurLoop, SafetyInfo, ORE);
+
+      if (IsMustExecute)
+        IsMustExecute = isGuaranteedToTransferExecutionToSuccessor(&I);
     }
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D46211.144397.patch
Type: text/x-patch
Size: 2377 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180427/b865c266/attachment.bin>


More information about the llvm-commits mailing list