[llvm-commits] [llvm] r40977 - /llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp

Devang Patel dpatel at apple.com
Thu Aug 9 17:33:50 PDT 2007


Author: dpatel
Date: Thu Aug  9 19:33:50 2007
New Revision: 40977

URL: http://llvm.org/viewvc/llvm-project?rev=40977&view=rev
Log:
ExitCondition and Induction variable are loop constraints 
not split condition constraints.

Modified:
    llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp?rev=40977&r1=40976&r2=40977&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp Thu Aug  9 19:33:50 2007
@@ -53,46 +53,32 @@
 
     class SplitInfo {
     public:
-      SplitInfo() : IndVar(NULL), SplitValue(NULL), ExitValue(NULL),
-                    SplitCondition(NULL), ExitCondition(NULL), 
-                    IndVarIncrement(NULL) {}
+      SplitInfo() : SplitValue(NULL), SplitCondition(NULL) {}
 
-      // Induction variable whose range is being split by this transformation.
-      PHINode *IndVar;
-      
       // Induction variable's range is split at this value.
       Value *SplitValue;
       
-      // Induction variable's final loop exit value.
-      Value *ExitValue;
-      
       // This compare instruction compares IndVar against SplitValue.
       ICmpInst *SplitCondition;
 
-      // Loop exit condition.
-      ICmpInst *ExitCondition;
-
-      Instruction *IndVarIncrement;
-
       // Clear split info.
       void clear() {
-        IndVar = NULL;
         SplitValue = NULL;
-        ExitValue = NULL;
         SplitCondition = NULL;
-        ExitCondition = NULL;
-        IndVarIncrement = NULL;
       }
 
-      /// Return true if V is a induction variable or induction variable's
-      /// increment for loop L.
-      bool findIndVar(Value *V, Loop *L);
     };
-
+    
   private:
     /// Find condition inside a loop that is suitable candidate for index split.
     void findSplitCondition();
 
+    /// Find loop's exit condition.
+    void findLoopConditionals();
+
+    /// Return induction variable associated with value V.
+    void findIndVar(Value *V, Loop *L);
+
     /// processOneIterationLoop - Current loop L contains compare instruction
     /// that compares induction variable, IndVar, agains loop invariant. If
     /// entire (i.e. meaningful) loop body is dominated by this compare
@@ -112,6 +98,13 @@
     unsigned findSplitCost(Loop *L, SplitInfo &SD);
     bool splitLoop(SplitInfo &SD);
 
+    void initialize() {
+      IndVar = NULL; 
+      IndVarIncrement = NULL;
+      ExitCondition = NULL;
+      StartValue = ExitValue = NULL;
+    }
+
   private:
 
     // Current Loop.
@@ -119,6 +112,19 @@
     ScalarEvolution *SE;
     DominatorTree *DT;
     SmallVector<SplitInfo, 4> SplitData;
+
+    // Induction variable whose range is being split by this transformation.
+    PHINode *IndVar;
+    Instruction *IndVarIncrement;
+      
+    // Loop exit condition.
+    ICmpInst *ExitCondition;
+
+    // Induction variable's initial value.
+    Value *StartValue;
+
+    // Induction variable's final loop exit value.
+    Value *ExitValue;
   };
 
   char LoopIndexSplit::ID = 0;
@@ -137,6 +143,13 @@
   SE = &getAnalysis<ScalarEvolution>();
   DT = &getAnalysis<DominatorTree>();
 
+  initialize();
+
+  findLoopConditionals();
+
+  if (!ExitCondition)
+    return false;
+
   findSplitCondition();
 
   if (SplitData.empty())
@@ -183,24 +196,24 @@
 
 /// Return true if V is a induction variable or induction variable's
 /// increment for loop L.
-bool LoopIndexSplit::SplitInfo::findIndVar(Value *V, Loop *L) {
+void LoopIndexSplit::findIndVar(Value *V, Loop *L) {
   
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I)
-    return false;
+    return;
 
   // Check if I is a phi node from loop header or not.
   if (PHINode *PN = dyn_cast<PHINode>(V)) {
     if (PN->getParent() == L->getHeader()) {
-            IndVar = PN;
-            return true;
+      IndVar = PN;
+      return;
     }
   }
  
   // Check if I is a add instruction whose one operand is
   // phi node from loop header and second operand is constant.
   if (I->getOpcode() != Instruction::Add)
-    return false;
+    return;
   
   Value *Op0 = I->getOperand(0);
   Value *Op1 = I->getOperand(1);
@@ -210,7 +223,7 @@
         && isa<ConstantInt>(Op1)) {
       IndVar = PN;
       IndVarIncrement = I;
-      return true;
+      return;
     }
   }
   
@@ -219,11 +232,66 @@
         && isa<ConstantInt>(Op0)) {
       IndVar = PN;
       IndVarIncrement = I;
-      return true;
+      return;
     }
   }
   
-  return false;
+  return;
+}
+
+// Find loop's exit condition and associated induction variable.
+void LoopIndexSplit::findLoopConditionals() {
+
+  BasicBlock *ExitBlock = NULL;
+
+  for (Loop::block_iterator I = L->block_begin(), E = L->block_end();
+       I != E; ++I) {
+    BasicBlock *BB = *I;
+    if (!L->isLoopExit(BB))
+      continue;
+    if (ExitBlock)
+      return;
+    ExitBlock = BB;
+  }
+
+  if (!ExitBlock)
+    return;
+  
+  // If exit block's terminator is conditional branch inst then we have found
+  // exit condition.
+  BranchInst *BR = dyn_cast<BranchInst>(ExitBlock->getTerminator());
+  if (!BR || BR->isUnconditional())
+    return;
+  
+  ICmpInst *CI = dyn_cast<ICmpInst>(BR->getCondition());
+  if (!CI)
+    return;
+  
+  ExitCondition = CI;
+
+  // Exit condition's one operand is loop invariant exit value and second 
+  // operand is SCEVAddRecExpr based on induction variable.
+  Value *V0 = CI->getOperand(0);
+  Value *V1 = CI->getOperand(1);
+  
+  SCEVHandle SH0 = SE->getSCEV(V0);
+  SCEVHandle SH1 = SE->getSCEV(V1);
+  
+  if (SH0->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH1)) {
+    ExitValue = V0;
+    findIndVar(V1, L);
+  }
+  else if (SH1->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH0)) {
+    ExitValue =  V1;
+    findIndVar(V0, L);
+  }
+
+  if (!ExitValue || !IndVar)
+    ExitCondition = NULL;
+  else if (IndVar) {
+    BasicBlock *Preheader = L->getLoopPreheader();
+    StartValue = IndVar->getIncomingValueForBlock(Preheader);
+  }
 }
 
 /// Find condition inside a loop that is suitable candidate for index split.
@@ -246,7 +314,7 @@
       continue;
 
     ICmpInst *CI = dyn_cast<ICmpInst>(BR->getCondition());
-    if (!CI)
+    if (!CI || CI == ExitCondition)
       return;
 
     // If one operand is loop invariant and second operand is SCEVAddRecExpr
@@ -260,14 +328,26 @@
     if (SH0->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH1)) {
       SD.SplitValue = V0;
       SD.SplitCondition = CI;
-      if (SD.findIndVar(V1, L))
-        SplitData.push_back(SD);
+      if (PHINode *PN = dyn_cast<PHINode>(V1)) {
+        if (PN == IndVar)
+          SplitData.push_back(SD);
+      }
+      else  if (Instruction *Insn = dyn_cast<Instruction>(V1)) {
+        if (IndVarIncrement && IndVarIncrement == Insn)
+          SplitData.push_back(SD);
+      }
     }
     else if (SH1->isLoopInvariant(L) && isa<SCEVAddRecExpr>(SH0)) {
       SD.SplitValue =  V1;
       SD.SplitCondition = CI;
-      if (SD.findIndVar(V0, L))
-        SplitData.push_back(SD);
+      if (PHINode *PN = dyn_cast<PHINode>(V0)) {
+        if (PN == IndVar)
+          SplitData.push_back(SD);
+      }
+      else  if (Instruction *Insn = dyn_cast<Instruction>(V0)) {
+        if (IndVarIncrement && IndVarIncrement == Insn)
+          SplitData.push_back(SD);
+      }
     }
   }
 }
@@ -340,7 +420,7 @@
 
   BasicBlock *Preheader = L->getLoopPreheader();
   Instruction *Terminator = Header->getTerminator();
-  Value *StartValue = SD.IndVar->getIncomingValueForBlock(Preheader);
+  StartValue = IndVar->getIncomingValueForBlock(Preheader);
 
   // Replace split condition in header.
   // Transform 
@@ -349,14 +429,14 @@
   //      c1 = icmp uge i32 SplitValue, StartValue
   //      c2 = icmp ult i32 vSplitValue, ExitValue
   //      and i32 c1, c2 
-  bool SignedPredicate = SD.ExitCondition->isSignedPredicate();
+  bool SignedPredicate = ExitCondition->isSignedPredicate();
   Instruction *C1 = new ICmpInst(SignedPredicate ? 
                                  ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE,
                                  SD.SplitValue, StartValue, "lisplit", 
                                  Terminator);
   Instruction *C2 = new ICmpInst(SignedPredicate ? 
                                  ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
-                                 SD.SplitValue, SD.ExitValue, "lisplit", 
+                                 SD.SplitValue, ExitValue, "lisplit", 
                                  Terminator);
   Instruction *NSplitCond = BinaryOperator::createAnd(C1, C2, "lisplit", 
                                                       Terminator);
@@ -413,11 +493,11 @@
       continue;
 
     // Induction variable is OK.
-    if (I == SD.IndVar)
+    if (I == IndVar)
       continue;
 
     // Induction variable increment is OK.
-    if (I == SD.IndVarIncrement)
+    if (I == IndVarIncrement)
       continue;
 
     // Terminator is also harmless.
@@ -444,11 +524,11 @@
       continue;
 
     // Induction variable increment is OK.
-    if (SD.IndVarIncrement && SD.IndVarIncrement == I)
+    if (IndVarIncrement && IndVarIncrement == I)
       continue;
 
     // Check if I is induction variable increment instruction.
-    if (!SD.IndVarIncrement && I->getOpcode() == Instruction::Add) {
+    if (!IndVarIncrement && I->getOpcode() == Instruction::Add) {
 
       Value *Op0 = I->getOperand(0);
       Value *Op1 = I->getOperand(1);
@@ -457,14 +537,14 @@
 
       if ((PN = dyn_cast<PHINode>(Op0))) {
         if ((CI = dyn_cast<ConstantInt>(Op1)))
-          SD.IndVarIncrement = I;
+          IndVarIncrement = I;
       } else 
         if ((PN = dyn_cast<PHINode>(Op1))) {
           if ((CI = dyn_cast<ConstantInt>(Op0)))
-            SD.IndVarIncrement = I;
+            IndVarIncrement = I;
       }
           
-      if (SD.IndVarIncrement && PN == SD.IndVar && CI->isOne())
+      if (IndVarIncrement && PN == IndVar && CI->isOne())
         continue;
     }
 
@@ -472,38 +552,17 @@
     // Exit condition is OK if it compares loop invariant exit value,
     // which is checked below.
     else if (ICmpInst *EC = dyn_cast<ICmpInst>(I)) {
-      ++BI;
-      Instruction *N = BI;
-      if (N == ExitBlock->getTerminator()) {
-        SD.ExitCondition = EC;
+      if (EC == ExitCondition)
         continue;
-      }
     }
 
+    if (I == ExitBlock->getTerminator())
+      continue;
+
     // Otherwise we have instruction that may not be safe.
     return false;
   }
 
-  // Check if Exit condition is comparing induction variable against 
-  // loop invariant value. If one operand is induction variable and 
-  // the other operand is loop invaraint then Exit condition is safe.
-  if (SD.ExitCondition) {
-    Value *Op0 = SD.ExitCondition->getOperand(0);
-    Value *Op1 = SD.ExitCondition->getOperand(1);
-
-    Instruction *Insn0 = dyn_cast<Instruction>(Op0);
-    Instruction *Insn1 = dyn_cast<Instruction>(Op1);
-    
-    if (Insn0 && Insn0 == SD.IndVarIncrement)
-      SD.ExitValue = Op1;
-    else if (Insn1 && Insn1 == SD.IndVarIncrement)
-      SD.ExitValue = Op0;
-
-    SCEVHandle ValueSCEV = SE->getSCEV(SD.ExitValue);
-    if (!ValueSCEV->isLoopInvariant(L))
-      return false;
-  }
-
   // We could not find any reason to consider ExitBlock unsafe.
   return true;
 }
@@ -528,6 +587,21 @@
 }
 
 bool LoopIndexSplit::splitLoop(SplitInfo &SD) {
-  // FIXME :)
+  // True loop is original loop. False loop is cloned loop.
+  //[*] Calculate True loop's new Exit Value in loop preheader.
+  //      NewExitValue = min(SplitValue, ExitValue)
+  //[*] Calculate False loop's new Start Value in loop preheader.
+  //      NewStartValue = min(SplitValue, TrueLoop.StartValue)
+  //[*] Split Exit Edge.
+  //[*] Clone loop. Avoid true destination of split condition and 
+  //    the blocks dominated by true destination. 
+  //[*] True loops exit edge enters False loop.
+  //[*] Eliminate split condition's false branch from True loop.
+  //    Update true loop dom info.
+  //[*] Update True loop's exit value using NewExitValue.
+  //[*] Update False loop's start value using NewStartValue.
+  //[*] Fix lack of true branch in False loop CFG.
+  //    Update false loop dom info.
+  //[*] Update dom info in general.
   return false;
 }





More information about the llvm-commits mailing list