Remove redundant checks added by loop unrolling

Benjamin Poulain benjamin at webkit.org
Sat Nov 29 12:59:23 PST 2014


Hi,

I noticed the optimized code generated for loops often include redundant 
checks that the size is not zero.

For example, code like this:
   unsigned total = 0;
   for (unsigned i = 0; i < size; ++i) { ...

when optimized, generate the following prologue:
   entry:
     %cmp4 = icmp eq i32 %size, 0
     br i1 %cmp4, label %for.end, label %for.body.lr.ph

   for.body.lr.ph:                                   ; preds = %entry
    %0 = add i32 %size, -1
     %xtraiter = and i32 %size, 3
     %lcmp.mod = icmp ne i32 %xtraiter, 0
     %lcmp.overflow = icmp eq i32 %size, 0
     %lcmp.or = or i1 %lcmp.overflow, %lcmp.mod
     br i1 %lcmp.or, label %for.body.prol, label %for.body.lr.ph.split

Notice the redundant test for "icmp eq i32 %size, 0". When compiled to 
target, we have one redundant check per loop that can never be true.

The extra check for size==0 comes from LoopUnroll. It is never optimized 
out because LoopUnrollPass is run after the passes that could eliminate 
redundant conditions.

I have attached a patch that fixes the problem. For every pass of 
LoopUnroll, I added a GVN pass to remove every redundant conditions and 
branches. My patch is without test, I need guidance on how to properly 
test this.

Benjamin
-------------- next part --------------
diff --git lib/Transforms/IPO/PassManagerBuilder.cpp lib/Transforms/IPO/PassManagerBuilder.cpp
index 0414caa..cd9a3e7 100644
--- lib/Transforms/IPO/PassManagerBuilder.cpp
+++ lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -275,8 +275,10 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
         MPM.add(createEarlyCSEPass());      // Catch trivial redundancies
 
       // BBVectorize may have significantly shortened a loop body; unroll again.
-      if (!DisableUnrollLoops)
-        MPM.add(createLoopUnrollPass());
+      if (!DisableUnrollLoops) {
+          MPM.add(createLoopUnrollPass());           // Unroll small loops
+          MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies
+      }
     }
   }
 
@@ -340,8 +342,10 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
         MPM.add(createEarlyCSEPass());      // Catch trivial redundancies
 
       // BBVectorize may have significantly shortened a loop body; unroll again.
-      if (!DisableUnrollLoops)
-        MPM.add(createLoopUnrollPass());
+      if (!DisableUnrollLoops) {
+        MPM.add(createLoopUnrollPass());           // Unroll small loops
+        MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies
+      }
     }
   }
 
@@ -349,8 +353,10 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
   MPM.add(createCFGSimplificationPass());
   MPM.add(createInstructionCombiningPass());
 
-  if (!DisableUnrollLoops)
-    MPM.add(createLoopUnrollPass());    // Unroll small loops
+  if (!DisableUnrollLoops) {
+    MPM.add(createLoopUnrollPass());           // Unroll small loops
+    MPM.add(createGVNPass(DisableGVNLoadPRE)); // Remove redundancies
+  }
 
   // After vectorization and unrolling, assume intrinsics may tell us more
   // about pointer alignments.


More information about the llvm-commits mailing list