Add a new Operator class, for handling Instructions and ConstantExprs
[oota-llvm.git] / lib / Transforms / Scalar / LoopUnroll.cpp
index aa1c7e736362eeb964b66a28ce8ab2c6deb47a80..23757cdb2d29c3326bbe02fa3ebbdb7c6a34bbb3 100644 (file)
@@ -12,7 +12,6 @@
 // counts of loops easily.
 //===----------------------------------------------------------------------===//
 
-#include <climits>
 #define DEBUG_TYPE "loop-unroll"
 #include "llvm/IntrinsicInst.h"
 #include "llvm/Transforms/Scalar.h"
@@ -22,6 +21,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Transforms/Utils/UnrollLoop.h"
+#include <climits>
 
 using namespace llvm;
 
@@ -33,11 +33,16 @@ static cl::opt<unsigned>
 UnrollCount("unroll-count", cl::init(0), cl::Hidden,
   cl::desc("Use this unroll count for all loops, for testing purposes"));
 
+static cl::opt<bool>
+UnrollAllowPartial("unroll-allow-partial", cl::init(false), cl::Hidden,
+  cl::desc("Allows loops to be partially unrolled until "
+           "-unroll-threshold loop size is reached."));
+
 namespace {
   class VISIBILITY_HIDDEN LoopUnroll : public LoopPass {
   public:
     static char ID; // Pass ID, replacement for typeid
-    LoopUnroll() : LoopPass((intptr_t)&ID) {}
+    LoopUnroll() : LoopPass(&ID) {}
 
     /// A magic value for use with the Threshold parameter to indicate
     /// that the loop unroll should be performed regardless of how much
@@ -55,6 +60,12 @@ namespace {
       AU.addRequired<LoopInfo>();
       AU.addPreservedID(LCSSAID);
       AU.addPreserved<LoopInfo>();
+      // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
+      // If loop unroll does not preserve dom info then LCSSA pass on next
+      // loop will receive invalid dom info.
+      // For now, recreate dom info, if loop is unrolled.
+      AU.addPreserved<DominatorTree>();
+      AU.addPreserved<DominanceFrontier>();
     }
   };
 }
@@ -62,13 +73,14 @@ namespace {
 char LoopUnroll::ID = 0;
 static RegisterPass<LoopUnroll> X("loop-unroll", "Unroll loops");
 
-LoopPass *llvm::createLoopUnrollPass() { return new LoopUnroll(); }
+Pass *llvm::createLoopUnrollPass() { return new LoopUnroll(); }
 
 /// ApproximateLoopSize - Approximate the size of the loop.
 static unsigned ApproximateLoopSize(const Loop *L) {
   unsigned Size = 0;
-  for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) {
-    BasicBlock *BB = L->getBlocks()[i];
+  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
+       I != E; ++I) {
+    BasicBlock *BB = *I;
     Instruction *Term = BB->getTerminator();
     for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
       if (isa<PHINode>(I) && BB == L->getHeader()) {
@@ -77,6 +89,8 @@ static unsigned ApproximateLoopSize(const Loop *L) {
         // Ignore instructions only used by the loop terminator.
       } else if (isa<DbgInfoIntrinsic>(I)) {
         // Ignore debug instructions
+      } else if (isa<GetElementPtrInst>(I) && I->hasOneUse()) {
+        // Ignore GEP as they generally are subsumed into a load or store.
       } else if (isa<CallInst>(I)) {
         // Estimate size overhead introduced by call instructions which
         // is higher than other instructions. Here 3 and 10 are magic
@@ -115,7 +129,8 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
   if (Count == 0) {
     // Conservative heuristic: if we know the trip count, see if we can
     // completely unroll (subject to the threshold, checked below); otherwise
-    // don't unroll.
+    // try to find greatest modulo of the trip count which is still under 
+    // threshold value.
     if (TripCount != 0) {
       Count = TripCount;
     } else {
@@ -129,15 +144,40 @@ bool LoopUnroll::runOnLoop(Loop *L, LPPassManager &LPM) {
     DOUT << "  Loop Size = " << LoopSize << "\n";
     uint64_t Size = (uint64_t)LoopSize*Count;
     if (TripCount != 1 && Size > UnrollThreshold) {
-      DOUT << "  TOO LARGE TO UNROLL: "
-           << Size << ">" << UnrollThreshold << "\n";
-      return false;
+      DOUT << "  Too large to fully unroll with count: " << Count
+           << " because size: " << Size << ">" << UnrollThreshold << "\n";
+      if (UnrollAllowPartial) {
+        // Reduce unroll count to be modulo of TripCount for partial unrolling
+        Count = UnrollThreshold / LoopSize;        
+        while (Count != 0 && TripCount%Count != 0) {
+          Count--;
+        }        
+        if (Count < 2) {
+          DOUT << "  could not unroll partially\n";
+          return false;
+        } else {
+          DOUT << "  partially unrolling with count: " << Count << "\n";
+        }
+      } else {
+        DOUT << "  will not try to unroll partially because "
+             << "-unroll-allow-partial not given\n";
+        return false;
+      }
     }
   }
 
   // Unroll the loop.
+  Function *F = L->getHeader()->getParent();
   if (!UnrollLoop(L, Count, LI, &LPM))
     return false;
 
+  // FIXME: Reconstruct dom info, because it is not preserved properly.
+  DominatorTree *DT = getAnalysisIfAvailable<DominatorTree>();
+  if (DT) {
+    DT->runOnFunction(*F);
+    DominanceFrontier *DF = getAnalysisIfAvailable<DominanceFrontier>();
+    if (DF)
+      DF->runOnFunction(*F);
+  }
   return true;
 }