[llvm-commits] [llvm] r40883 - in /llvm/trunk: include/llvm/LinkAllPasses.h include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/LoopIndexSplit.cpp

Devang Patel dpatel at apple.com
Mon Aug 6 17:25:58 PDT 2007


Author: dpatel
Date: Mon Aug  6 19:25:56 2007
New Revision: 40883

URL: http://llvm.org/viewvc/llvm-project?rev=40883&view=rev
Log:
Begin loop index split pass.

Added:
    llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
Modified:
    llvm/trunk/include/llvm/LinkAllPasses.h
    llvm/trunk/include/llvm/Transforms/Scalar.h

Modified: llvm/trunk/include/llvm/LinkAllPasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=40883&r1=40882&r2=40883&view=diff

==============================================================================
--- llvm/trunk/include/llvm/LinkAllPasses.h (original)
+++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Aug  6 19:25:56 2007
@@ -83,6 +83,7 @@
       (void) llvm::createLoopUnrollPass();
       (void) llvm::createLoopUnswitchPass();
       (void) llvm::createLoopRotatePass();
+      (void) llvm::createLoopIndexSplitPass();
       (void) llvm::createLowerAllocationsPass();
       (void) llvm::createLowerGCPass();
       (void) llvm::createLowerInvokePass();

Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=40883&r1=40882&r2=40883&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
+++ llvm/trunk/include/llvm/Transforms/Scalar.h Mon Aug  6 19:25:56 2007
@@ -141,6 +141,12 @@
 //
 LoopPass *createLoopRotatePass();
 
+//===----------------------------------------------------------------------===//
+//
+// LoopIndexSplit - This pass splits loop
+//
+LoopPass *createLoopIndexSplitPass();
+
 
 //===----------------------------------------------------------------------===//
 //

Added: llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp?rev=40883&view=auto

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp (added)
+++ llvm/trunk/lib/Transforms/Scalar/LoopIndexSplit.cpp Mon Aug  6 19:25:56 2007
@@ -0,0 +1,384 @@
+//===- LoopIndexSplit.cpp - Loop Index Splitting Pass ---------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Devang Patel and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements Loop Index Splitting Pass.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "loop-index-split"
+
+#include "llvm/Function.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/ADT/Statistic.h"
+
+using namespace llvm;
+
+STATISTIC(NumIndexSplit, "Number of loops index split");
+
+namespace {
+
+  class VISIBILITY_HIDDEN LoopIndexSplit : public LoopPass {
+
+  public:
+    static char ID; // Pass ID, replacement for typeid
+    LoopIndexSplit() : LoopPass((intptr_t)&ID) {}
+
+    // Index split Loop L. Return true if loop is split.
+    bool runOnLoop(Loop *L, LPPassManager &LPM);
+
+    void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired<ScalarEvolution>();
+      AU.addPreserved<ScalarEvolution>();
+      AU.addRequiredID(LCSSAID);
+      AU.addPreservedID(LCSSAID);
+      AU.addPreserved<LoopInfo>();
+      AU.addRequiredID(LoopSimplifyID);
+      AU.addPreservedID(LoopSimplifyID);
+    }
+
+  private:
+    /// Find condition inside a loop that is suitable candidate for index split.
+    void findSplitCondition();
+
+    /// 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
+    /// instruction then loop body is executed only for one iteration. In
+    /// such case eliminate loop structure surrounding this loop body. For
+    bool processOneIterationLoop(LPPassManager &LPM);
+    
+    // If loop header includes loop variant instruction operands then
+    // this loop may not be eliminated.
+    bool safeHeader(BasicBlock *BB);
+
+    // If Exit block includes loop variant instructions then this
+    // loop may not be eliminated.
+    bool safeExitBlock(BasicBlock *BB);
+
+    bool splitLoop();
+
+  private:
+
+    // Current Loop.
+    Loop *L;
+    ScalarEvolution *SE;
+
+    // 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;
+  };
+
+  char LoopIndexSplit::ID = 0;
+  RegisterPass<LoopIndexSplit> X ("loop-index-split", "Index Split Loops");
+}
+
+LoopPass *llvm::createLoopIndexSplitPass() {
+  return new LoopIndexSplit();
+}
+
+// Index split Loop L. Return true if loop is split.
+bool LoopIndexSplit::runOnLoop(Loop *IncomingLoop, LPPassManager &LPM) {
+  bool Changed = false;
+  L = IncomingLoop;
+  SplitCondition = NULL;
+  SE = &getAnalysis<ScalarEvolution>();
+
+  findSplitCondition();
+
+  if (!SplitCondition)
+    return false;
+
+  if (SplitCondition->getPredicate() == ICmpInst::ICMP_EQ) 
+    // If it is possible to eliminate loop then do so.
+    Changed = processOneIterationLoop(LPM);
+  else
+    Changed = splitLoop();
+
+  if (Changed)
+    ++NumIndexSplit;
+
+  return Changed;
+}
+
+/// Find condition inside a loop that is suitable candidate for index split.
+void LoopIndexSplit::findSplitCondition() {
+
+ BasicBlock *Header = L->getHeader();
+
+  for (BasicBlock::iterator I = Header->begin(); isa<PHINode>(I); ++I) {
+    PHINode *PN = cast<PHINode>(I);
+
+    if (!PN->getType()->isInteger())
+      continue;
+
+    SCEVHandle SCEV = SE->getSCEV(PN);
+    if (!isa<SCEVAddRecExpr>(SCEV)) 
+      continue;
+
+    // If this phi node is used in a compare instruction then it is a
+    // split condition candidate.
+    for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end(); 
+         UI != E; ++UI) {
+      if (ICmpInst *CI = dyn_cast<ICmpInst>(*UI)) {
+        SplitCondition = CI;
+        break;
+      }
+    }
+
+    // Valid SplitCondition's one operand is phi node and the other operand
+    // is loop invariant.
+    if (SplitCondition) {
+      if (SplitCondition->getOperand(0) != PN)
+        SplitValue = SplitCondition->getOperand(0);
+      else
+        SplitValue = SplitCondition->getOperand(1);
+      SCEVHandle ValueSCEV = SE->getSCEV(SplitValue);
+
+      // If SplitValue is not invariant then SplitCondition is not appropriate.
+      if (!ValueSCEV->isLoopInvariant(L))
+        SplitCondition = NULL;
+    }
+
+    // We are looking for only one split condition.
+    if (SplitCondition) {
+      IndVar = PN;
+      break;
+    }
+  }
+}
+
+/// processOneIterationLoop - Current loop L contains compare instruction
+/// that compares induction variable, IndVar, against loop invariant. If
+/// entire (i.e. meaningful) loop body is dominated by this compare
+/// instruction then loop body is executed only once. In such case eliminate 
+/// loop structure surrounding this loop body. For example,
+///     for (int i = start; i < end; ++i) {
+///         if ( i == somevalue) {
+///           loop_body
+///         }
+///     }
+/// can be transformed into
+///     if (somevalue >= start && somevalue < end) {
+///        i = somevalue;
+///        loop_body
+///     }
+bool LoopIndexSplit::processOneIterationLoop(LPPassManager &LPM) {
+
+  BasicBlock *Header = L->getHeader();
+
+  // First of all, 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 (SplitCondition->getParent() != Header)
+    return false;
+  
+  // If one of the Header block's successor is not an exit block then this
+  // loop is not a suitable candidate.
+  BasicBlock *ExitBlock = NULL;
+  for (succ_iterator SI = succ_begin(Header), E = succ_end(Header); SI != E; ++SI) {
+    if (L->isLoopExit(*SI)) {
+      ExitBlock = *SI;
+      break;
+    }
+  }
+
+  if (!ExitBlock)
+    return false;
+
+  // If loop header includes loop variant instruction operands then
+  // this loop may not be eliminated.
+  if (!safeHeader(Header)) 
+    return false;
+
+  // If Exit block includes loop variant instructions then this
+  // loop may not be eliminated.
+  if (!safeExitBlock(ExitBlock)) 
+    return false;
+
+  BasicBlock *Latch = L->getLoopLatch();
+  BasicBlock *Preheader = L->getLoopPreheader();
+  Instruction *Terminator = Header->getTerminator();
+  Value *StartValue = IndVar->getIncomingValueForBlock(Preheader);
+
+  // Update CFG.
+
+  // Replace split condition in header.
+  // Transform 
+  //      SplitCondition : icmp eq i32 IndVar, SplitValue
+  // into
+  //      c1 = icmp uge i32 SplitValue, StartValue
+  //      c2 = icmp ult i32 vSplitValue, ExitValue
+  //      and i32 c1, c2 
+  bool SignedPredicate = SplitCondition->isSignedPredicate();
+  Instruction *C1 = new ICmpInst(SignedPredicate ? 
+                                 ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE,
+                                 SplitValue, StartValue, "lisplit", Terminator);
+  Instruction *C2 = new ICmpInst(SignedPredicate ? 
+                                 ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
+                                 SplitValue, ExitValue, "lisplit", Terminator);
+  Instruction *NSplitCond = BinaryOperator::create(Instruction::And,
+                                                   C1, C2, "lisplit", Terminator);
+  SplitCondition->replaceAllUsesWith(NSplitCond);
+  SplitCondition->removeFromParent();
+  delete SplitCondition;
+
+  // As a first step to break this loop, remove Latch to Header edge.
+  BasicBlock *LatchSucc = NULL;
+  Header->removePredecessor(Latch);
+  for (succ_iterator SI = succ_begin(Latch), E = succ_end(Latch);
+       SI != E; ++SI) {
+    if (Header != *SI)
+      LatchSucc = *SI;
+  }
+  BranchInst *BR = dyn_cast<BranchInst>(Latch->getTerminator());
+  BR->setUnconditionalDest(LatchSucc);
+  
+  // Now, clear latch block. Remove instructions that are responsible
+  // to increment induction variable. 
+  Instruction *LTerminator = Latch->getTerminator();
+  for (BasicBlock::iterator LB = Latch->begin(), LE = Latch->end();
+       LB != LE; ) {
+    Instruction *I = LB;
+    ++LB;
+    if (isa<PHINode>(I) || I == LTerminator)
+      continue;
+
+    I->replaceAllUsesWith(UndefValue::get(I->getType()));
+    I->removeFromParent();
+    delete I;
+  }
+
+  LPM.deleteLoopFromQueue(L);
+  return true;
+}
+
+// If loop header includes loop variant instruction operands then
+// this loop can not be eliminated. This is used by processOneIterationLoop().
+bool LoopIndexSplit::safeHeader(BasicBlock *Header) {
+
+  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 (ICmpInst *CI = dyn_cast<ICmpInst>(I)) {
+      if (CI == SplitCondition)
+        continue;
+    }
+
+    // Terminator is also harmless.
+    if (I == Terminator)
+      continue;
+
+    // Otherwise we have a instruction that may not be safe.
+    return false;
+  }
+  
+  return true;
+}
+
+// If Exit block includes loop variant instructions then this
+// loop may not be eliminated. This is used by processOneIterationLoop().
+bool LoopIndexSplit::safeExitBlock(BasicBlock *ExitBlock) {
+
+  Instruction *ExitCondition = NULL;
+  Instruction *IndVarIncrement = NULL;
+      
+  for (BasicBlock::iterator BI = ExitBlock->begin(), BE = ExitBlock->end();
+       BI != BE; ++BI) {
+    Instruction *I = BI;
+
+    // PHI Nodes are OK.
+    if (isa<PHINode>(I))
+      continue;
+
+    // Check if I is induction variable increment instruction.
+    if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(I)) {
+      if (BOp->getOpcode() != Instruction::Add)
+        return false;
+
+      Value *Op0 = BOp->getOperand(0);
+      Value *Op1 = BOp->getOperand(1);
+      PHINode *PN = NULL;
+      ConstantInt *CI = NULL;
+
+      if ((PN = dyn_cast<PHINode>(Op0))) {
+        if ((CI = dyn_cast<ConstantInt>(Op1)))
+          IndVarIncrement = I;
+      } else 
+        if ((PN = dyn_cast<PHINode>(Op1))) {
+          if ((CI = dyn_cast<ConstantInt>(Op0)))
+            IndVarIncrement = I;
+      }
+          
+      if (IndVarIncrement && PN == IndVar && CI->isOne())
+        continue;
+    }
+    // I is an Exit condition if next instruction is block terminator.
+    // Exit condition is OK if it compares loop invariant exit value,
+    // which is checked below.
+    else if (isa<ICmpInst>(I)) {
+      ++BI;
+      Instruction *N = BI;
+      if (N == ExitBlock->getTerminator()) {
+        ExitCondition = I;
+        break;
+      }
+    }
+
+    // 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 (ExitCondition) {
+    Value *Op0 = ExitCondition->getOperand(0);
+    Value *Op1 = ExitCondition->getOperand(1);
+
+    Instruction *Insn0 = dyn_cast<Instruction>(Op0);
+    Instruction *Insn1 = dyn_cast<Instruction>(Op1);
+    
+    if (Insn0 && Insn0 == IndVarIncrement)
+      ExitValue = Op1;
+    else if (Insn1 && Insn1 == IndVarIncrement)
+      ExitValue = Op0;
+
+    SCEVHandle ValueSCEV = SE->getSCEV(ExitValue);
+    if (!ValueSCEV->isLoopInvariant(L))
+      return false;
+  }
+
+  // We could not find any reason to consider ExitBlock unsafe.
+  return true;
+}
+
+bool LoopIndexSplit::splitLoop() {
+  // FIXME :)
+  return false;
+}





More information about the llvm-commits mailing list