Skeleton for transformations to truncate loop's iteration space.
authorDevang Patel <dpatel@apple.com>
Mon, 17 Sep 2007 20:39:48 +0000 (20:39 +0000)
committerDevang Patel <dpatel@apple.com>
Mon, 17 Sep 2007 20:39:48 +0000 (20:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42054 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/LoopIndexSplit.cpp

index b40dd04c82dd240d42e9d084f386a9827684c565..4b510c2df5847c0178a8d8e6ee02d2e1636f63ff 100644 (file)
@@ -111,7 +111,14 @@ namespace {
     /// instruction then loop body is executed only for one iteration. In
     /// such case eliminate loop structure surrounding this loop body. For
     bool processOneIterationLoop(SplitInfo &SD);
-    
+
+    void updateLoopBounds(ICmpInst *CI);
+    /// updateLoopIterationSpace - Current loop body is covered by an AND
+    /// instruction whose operands compares induction variables with loop
+    /// invariants. If possible, hoist this check outside the loop by
+    /// updating appropriate start and end values for induction variable.
+    bool updateLoopIterationSpace(SplitInfo &SD);
+
     /// If loop header includes loop variant instruction operands then
     /// this loop may not be eliminated.
     bool safeHeader(SplitInfo &SD,  BasicBlock *BB);
@@ -229,7 +236,19 @@ bool LoopIndexSplit::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM_Ref) {
          E = SplitData.end(); SI != E;) {
     SplitInfo &SD = *SI;
     ICmpInst *CI = dyn_cast<ICmpInst>(SD.SplitCondition);
-    if (CI && CI->getPredicate() == ICmpInst::ICMP_EQ) {
+    if (SD.SplitCondition->getOpcode() == Instruction::And) {
+      Changed = updateLoopIterationSpace(SD);
+      if (Changed) {
+        ++NumIndexSplit;
+        // If is loop is eliminated then nothing else to do here.
+        return Changed;
+      } else {
+        SmallVector<SplitInfo, 4>::iterator Delete_SI = SI;
+        ++SI;
+        SplitData.erase(Delete_SI);
+      }
+    }
+    else if (CI && CI->getPredicate() == ICmpInst::ICMP_EQ) {
       Changed = processOneIterationLoop(SD);
       if (Changed) {
         ++NumIndexSplit;
@@ -391,6 +410,25 @@ void LoopIndexSplit::findSplitCondition() {
     if (BR->isUnconditional())
       continue;
 
+    if (Instruction *AndI = dyn_cast<Instruction>(BR->getCondition())) {
+      if (AndI->getOpcode() == Instruction::And) {
+        ICmpInst *Op0 = dyn_cast<ICmpInst>(AndI->getOperand(0));
+        ICmpInst *Op1 = dyn_cast<ICmpInst>(AndI->getOperand(1));
+
+        if (!Op0 || !Op1)
+          continue;
+
+        if (!safeICmpInst(Op0, SD))
+          continue;
+        SD.clear();
+        if (!safeICmpInst(Op1, SD))
+          continue;
+        SD.clear();
+        SD.SplitCondition = AndI;
+        SplitData.push_back(SD);
+        continue;
+      }
+    }
     ICmpInst *CI = dyn_cast<ICmpInst>(BR->getCondition());
     if (!CI || CI == ExitCondition)
       continue;
@@ -662,6 +700,164 @@ bool LoopIndexSplit::safeExitingBlock(SplitInfo &SD,
   return true;
 }
 
+void LoopIndexSplit::updateLoopBounds(ICmpInst *CI) {
+
+  Value *V0 = CI->getOperand(0);
+  Value *V1 = CI->getOperand(1);
+  Value *NV = NULL;
+
+  SCEVHandle SH0 = SE->getSCEV(V0);
+  
+  if (SH0->isLoopInvariant(L))
+    NV = V0;
+  else
+    NV = V1;
+
+  switch (CI->getPredicate()) {
+  case ICmpInst::ICMP_ULE:
+  case ICmpInst::ICMP_SLE:
+    // for (i = LB; i < UB; ++i)
+    //   if (i <= NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NUB = min (NV+1, UB)
+    // for (i = LB; i < NUB ; ++i)
+    //   LOOP_BODY
+    //
+
+
+
+    // for (i = LB; i <= UB; ++i)
+    //   if (i <= NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NUB = min (NV, UB)
+    // for (i = LB; i <= NUB ; ++i)
+    //   LOOP_BODY
+    //
+    break;
+  case ICmpInst::ICMP_ULT:
+  case ICmpInst::ICMP_SLT:
+    // for (i = LB; i < UB; ++i)
+    //   if (i < NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NUB = min (NV, UB)
+    // for (i = LB; i < NUB ; ++i)
+    //   LOOP_BODY
+    //
+
+
+
+    // for (i = LB; i <= UB; ++i)
+    //   if (i < NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NUB = min (NV -1 , UB)
+    // for (i = LB; i <= NUB ; ++i)
+    //   LOOP_BODY
+    //
+    break;
+  case ICmpInst::ICMP_UGE:
+  case ICmpInst::ICMP_SGE:
+    // for (i = LB; i (< or <=) UB; ++i)
+    //   if (i >= NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NLB = max (NV, LB)
+    // for (i = NLB; i (< or <=) UB ; ++i)
+    //   LOOP_BODY
+    //
+    break;
+  case ICmpInst::ICMP_UGT:
+  case ICmpInst::ICMP_SGT:
+    // for (i = LB; i (< or <=) UB; ++i)
+    //   if (i > NV && ...)
+    //      LOOP_BODY
+    // 
+    // is transformed into
+    // NLB = max (NV+1, LB)
+    // for (i = NLB; i (< or <=) UB ; ++i)
+    //   LOOP_BODY
+    //
+    break;
+  default:
+    assert ( 0 && "Unexpected split condition predicate");
+  }
+}
+/// updateLoopIterationSpace - Current loop body is covered by an AND
+/// instruction whose operands compares induction variables with loop
+/// invariants. If possible, hoist this check outside the loop by
+/// updating appropriate start and end values for induction variable.
+bool LoopIndexSplit::updateLoopIterationSpace(SplitInfo &SD) {
+  BasicBlock *Header = L->getHeader();
+  ICmpInst *Op0 = cast<ICmpInst>(SD.SplitCondition->getOperand(0));
+  ICmpInst *Op1 = cast<ICmpInst>(SD.SplitCondition->getOperand(1));
+
+  if (Op0->getPredicate() == ICmpInst::ICMP_EQ 
+      || Op0->getPredicate() == ICmpInst::ICMP_NE
+      || Op0->getPredicate() == ICmpInst::ICMP_EQ 
+      || Op0->getPredicate() == ICmpInst::ICMP_NE)
+    return false;
+
+  // Check if SplitCondition dominates entire loop body
+  // or not.
+  
+  // If SplitCondition is not in loop header then this loop is not suitable
+  // for this transformation.
+  if (SD.SplitCondition->getParent() != Header)
+    return false;
+  
+  // If loop header includes loop variant instruction operands then
+  // this loop may not be eliminated.
+  Instruction *Terminator = Header->getTerminator();
+  for(BasicBlock::iterator BI = Header->begin(), BE = Header->end(); 
+      BI != BE; ++BI) {
+    Instruction *I = BI;
+
+    // PHI Nodes are OK.
+    if (isa<PHINode>(I))
+      continue;
+
+    // SplitCondition itself is OK.
+    if (I == SD.SplitCondition)
+      continue;
+    if (I == Op0 || I == Op1)
+      continue;
+
+    // Induction variable is OK.
+    if (I == IndVar)
+      continue;
+
+    // Induction variable increment is OK.
+    if (I == IndVarIncrement)
+      continue;
+
+    // Terminator is also harmless.
+    if (I == Terminator)
+      continue;
+
+    // Otherwise we have a instruction that may not be safe.
+    return false;
+  }
+
+  // If Exiting block includes loop variant instructions then this
+  // loop may not be eliminated.
+  if (!safeExitingBlock(SD, ExitCondition->getParent())) 
+    return false;
+
+  updateLoopBounds(Op0);
+  updateLoopBounds(Op1);
+  // Update CFG
+  return true;
+}
+
+
 /// removeBlocks - Remove basic block DeadBB and all blocks dominated by DeadBB.
 /// This routine is used to remove split condition's dead branch, dominated by
 /// DeadBB. LiveBB dominates split conidition's other branch.