[llvm-commits] [llvm] r81221 - in /llvm/trunk: include/llvm/Analysis/LoopInfo.h include/llvm/Transforms/Utils/BasicBlockUtils.h lib/Analysis/LoopInfo.cpp lib/Transforms/Scalar/LICM.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp lib/Transforms/Scalar/LoopUnswitch.cpp lib/Transforms/Utils/BasicBlockUtils.cpp lib/Transforms/Utils/BreakCriticalEdges.cpp lib/Transforms/Utils/LCSSA.cpp lib/Transforms/Utils/LoopSimplify.cpp test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll test/Transforms/LoopUnswitch/preserve-analyses.ll

Dan Gohman gohman at apple.com
Tue Sep 8 08:45:01 PDT 2009


Author: djg
Date: Tue Sep  8 10:45:00 2009
New Revision: 81221

URL: http://llvm.org/viewvc/llvm-project?rev=81221&view=rev
Log:
Re-apply r80926, with fixes: keep the domtree informed of new blocks
that get created during loop unswitching, and fix SplitBlockPredecessors'
LCSSA updating code to create new PHIs instead of trying to just move
existing ones.

Also, optimize Loop::verifyLoop, since it gets called a lot. Use
searches on a sorted list of blocks instead of calling the "contains"
function, as is done in other places in the Loop class, since "contains"
does a linear search. Also, don't call verifyLoop from LoopSimplify or
LCSSA, as the PassManager is already calling verifyLoop as part of
LoopInfo's verifyAnalysis.

Added:
    llvm/trunk/test/Transforms/LoopUnswitch/preserve-analyses.ll
Removed:
    llvm/trunk/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll
Modified:
    llvm/trunk/include/llvm/Analysis/LoopInfo.h
    llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
    llvm/trunk/lib/Analysis/LoopInfo.cpp
    llvm/trunk/lib/Transforms/Scalar/LICM.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp
    llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp
    llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
    llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp
    llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
    llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp

Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
+++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Tue Sep  8 10:45:00 2009
@@ -376,14 +376,85 @@
   /// verifyLoop - Verify loop structure
   void verifyLoop() const {
 #ifndef NDEBUG
-    assert (getHeader() && "Loop header is missing");
-    assert (getLoopPreheader() && "Loop preheader is missing");
-    assert (getLoopLatch() && "Loop latch is missing");
-    for (iterator I = SubLoops.begin(), E = SubLoops.end(); I != E; ++I)
-      (*I)->verifyLoop();
+    assert(!Blocks.empty() && "Loop header is missing");
+    assert(getHeader() && "Loop header is missing");
+
+    // Sort the blocks vector so that we can use binary search to do quick
+    // lookups.
+    SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end());
+    std::sort(LoopBBs.begin(), LoopBBs.end());
+
+    // Check the individual blocks.
+    for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) {
+      BlockT *BB = *I;
+      bool HasInsideLoopSuccs = false;
+      bool HasInsideLoopPreds = false;
+      SmallVector<BlockT *, 2> OutsideLoopPreds;
+
+      typedef GraphTraits<BlockT*> BlockTraits;
+      for (typename BlockTraits::ChildIteratorType SI =
+           BlockTraits::child_begin(BB), SE = BlockTraits::child_end(BB);
+           SI != SE; ++SI)
+        if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *SI)) {
+          HasInsideLoopSuccs = true;
+          break;
+        }
+      typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
+      for (typename InvBlockTraits::ChildIteratorType PI =
+           InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
+           PI != PE; ++PI) {
+        if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *PI))
+          HasInsideLoopPreds = true;
+        else
+          OutsideLoopPreds.push_back(*PI);
+      }
+
+      if (BB == getHeader()) {
+        assert(!OutsideLoopPreds.empty() && "Loop is unreachable!");
+      } else if (!OutsideLoopPreds.empty()) {
+        // A non-header loop shouldn't be reachable from outside the loop,
+        // though it is permitted if the predecessor is not itself actually
+        // reachable.
+        BlockT *EntryBB = BB->getParent()->begin();
+        for (df_iterator<BlockT *> NI = df_begin(EntryBB),
+             NE = df_end(EntryBB); NI != NE; ++NI)
+          for (unsigned i = 0, e = OutsideLoopPreds.size(); i != e; ++i)
+            assert(*NI != OutsideLoopPreds[i] &&
+                   "Loop has multiple entry points!");
+      }
+      assert(HasInsideLoopPreds && "Loop block has no in-loop predecessors!");
+      assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!");
+      assert(BB != getHeader()->getParent()->begin() &&
+             "Loop contains function entry block!");
+    }
+
+    // Check the subloops.
+    for (iterator I = begin(), E = end(); I != E; ++I)
+      // Each block in each subloop should be contained within this loop.
+      for (block_iterator BI = (*I)->block_begin(), BE = (*I)->block_end();
+           BI != BE; ++BI) {
+        assert(std::binary_search(LoopBBs.begin(), LoopBBs.end(), *BI) &&
+               "Loop does not contain all the blocks of a subloop!");
+      }
+
+    // Check the parent loop pointer.
+    if (ParentLoop) {
+      assert(std::find(ParentLoop->begin(), ParentLoop->end(), this) !=
+               ParentLoop->end() &&
+             "Loop is not a subloop of its parent!");
+    }
 #endif
   }
 
+  /// verifyLoop - Verify loop structure of this loop and all nested loops.
+  void verifyLoopNest() const {
+    // Verify this loop.
+    verifyLoop();
+    // Verify the subloops.
+    for (iterator I = begin(), E = end(); I != E; ++I)
+      (*I)->verifyLoopNest();
+  }
+
   void print(raw_ostream &OS, unsigned Depth = 0) const {
     OS.indent(Depth*2) << "Loop at depth " << getLoopDepth()
        << " containing: ";
@@ -873,6 +944,8 @@
   ///
   virtual bool runOnFunction(Function &F);
 
+  virtual void verifyAnalysis() const;
+
   virtual void releaseMemory() { LI.releaseMemory(); }
 
   virtual void print(raw_ostream &O, const Module* M = 0) const;

Modified: llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/BasicBlockUtils.h Tue Sep  8 10:45:00 2009
@@ -126,10 +126,10 @@
 /// dest go to one block instead of each going to a different block, but isn't 
 /// the standard definition of a "critical edge".
 ///
-bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0,
-                       bool MergeIdenticalEdges = false);
+BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
+                              Pass *P = 0, bool MergeIdenticalEdges = false);
 
-inline bool SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) {
+inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) {
   return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P);
 }
 
@@ -143,7 +143,7 @@
   TerminatorInst *TI = (*PI)->getTerminator();
   for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
     if (TI->getSuccessor(i) == Succ)
-      MadeChange |= SplitCriticalEdge(TI, i, P);
+      MadeChange |= !!SplitCriticalEdge(TI, i, P);
   return MadeChange;
 }
 
@@ -151,8 +151,9 @@
 /// and return true, otherwise return false.  This method requires that there be
 /// an edge between the two blocks.  If P is specified, it updates the analyses
 /// described above.
-inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0,
-                              bool MergeIdenticalEdges = false) {
+inline BasicBlock *SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst,
+                                     Pass *P = 0,
+                                     bool MergeIdenticalEdges = false) {
   TerminatorInst *TI = Src->getTerminator();
   unsigned i = 0;
   while (1) {
@@ -180,8 +181,12 @@
 /// Preds array, which has NumPreds elements in it.  The new block is given a
 /// suffix of 'Suffix'.  This function returns the new block.
 ///
-/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree and
-/// DominanceFrontier, but no other analyses.
+/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
+/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses.
+/// In particular, it does not preserve LoopSimplify (because it's
+/// complicated to handle the case where one of the edges being split
+/// is an exit of a loop with other exits).
+///
 BasicBlock *SplitBlockPredecessors(BasicBlock *BB, BasicBlock *const *Preds,
                                    unsigned NumPreds, const char *Suffix,
                                    Pass *P = 0);

Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LoopInfo.cpp Tue Sep  8 10:45:00 2009
@@ -300,6 +300,9 @@
 ///
 void
 Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
+  assert(isLoopSimplifyForm() &&
+         "getUniqueExitBlocks assumes the loop is in canonical form!");
+
   // Sort the blocks vector so that we can use binary search to do quick
   // lookups.
   SmallVector<BasicBlock *, 128> LoopBBs(block_begin(), block_end());
@@ -371,6 +374,13 @@
   return false;
 }
 
+void LoopInfo::verifyAnalysis() const {
+  for (iterator I = begin(), E = end(); I != E; ++I) {
+    assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
+    (*I)->verifyLoopNest();
+  }
+}
+
 void LoopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesAll();
   AU.addRequired<DominatorTree>();

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Tue Sep  8 10:45:00 2009
@@ -91,6 +91,7 @@
       AU.addRequired<AliasAnalysis>();
       AU.addPreserved<ScalarEvolution>();
       AU.addPreserved<DominanceFrontier>();
+      AU.addPreservedID(LoopSimplifyID);
     }
 
     bool doFinalization() {

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Sep  8 10:45:00 2009
@@ -484,36 +484,37 @@
       // loop because multiple copies sometimes do useful sinking of code in
       // that case(?).
       Instruction *OldLoc = dyn_cast<Instruction>(OperandValToReplace);
+      BasicBlock *PHIPred = PN->getIncomingBlock(i);
       if (L->contains(OldLoc->getParent())) {
         // If this is a critical edge, split the edge so that we do not insert
         // the code on all predecessor/successor paths.  We do this unless this
         // is the canonical backedge for this loop, as this can make some
         // inserted code be in an illegal position.
-        BasicBlock *PHIPred = PN->getIncomingBlock(i);
         if (e != 1 && PHIPred->getTerminator()->getNumSuccessors() > 1 &&
             (PN->getParent() != L->getHeader() || !L->contains(PHIPred))) {
 
           // First step, split the critical edge.
-          SplitCriticalEdge(PHIPred, PN->getParent(), P, false);
+          BasicBlock *NewBB = SplitCriticalEdge(PHIPred, PN->getParent(),
+                                                P, false);
 
           // Next step: move the basic block.  In particular, if the PHI node
           // is outside of the loop, and PredTI is in the loop, we want to
           // move the block to be immediately before the PHI block, not
           // immediately after PredTI.
-          if (L->contains(PHIPred) && !L->contains(PN->getParent())) {
-            BasicBlock *NewBB = PN->getIncomingBlock(i);
+          if (L->contains(PHIPred) && !L->contains(PN->getParent()))
             NewBB->moveBefore(PN->getParent());
-          }
 
           // Splitting the edge can reduce the number of PHI entries we have.
           e = PN->getNumIncomingValues();
+          PHIPred = NewBB;
+          i = PN->getBasicBlockIndex(PHIPred);
         }
       }
-      Value *&Code = InsertedCode[PN->getIncomingBlock(i)];
+      Value *&Code = InsertedCode[PHIPred];
       if (!Code) {
         // Insert the code into the end of the predecessor block.
         Instruction *InsertPt = (L->contains(OldLoc->getParent())) ?
-                                PN->getIncomingBlock(i)->getTerminator() :
+                                PHIPred->getTerminator() :
                                 OldLoc->getParent()->getTerminator();
         Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(),
                                            Rewriter, InsertPt, L, LI);

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

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LoopUnswitch.cpp Tue Sep  8 10:45:00 2009
@@ -112,6 +112,10 @@
 
   private:
 
+    virtual void releaseMemory() {
+      UnswitchedVals.clear();
+    }
+
     /// RemoveLoopFromWorklist - If the specified loop is on the loop worklist,
     /// remove it.
     void RemoveLoopFromWorklist(Loop *L) {
@@ -518,7 +522,12 @@
     std::swap(TrueDest, FalseDest);
 
   // Insert the new branch.
-  BranchInst::Create(TrueDest, FalseDest, BranchVal, InsertPt);
+  BranchInst *BI = BranchInst::Create(TrueDest, FalseDest, BranchVal, InsertPt);
+
+  // If either edge is critical, split it. This helps preserve LoopSimplify
+  // form for enclosing loops.
+  SplitCriticalEdge(BI, 0, this);
+  SplitCriticalEdge(BI, 1, this);
 }
 
 /// UnswitchTrivialCondition - Given a loop that has a trivial unswitchable
@@ -575,47 +584,11 @@
 
   for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
     BasicBlock *ExitBlock = ExitBlocks[i];
-    std::vector<BasicBlock*> Preds(pred_begin(ExitBlock), pred_end(ExitBlock));
-
-    for (unsigned j = 0, e = Preds.size(); j != e; ++j) {
-      BasicBlock* NewExitBlock = SplitEdge(Preds[j], ExitBlock, this);
-      BasicBlock* StartBlock = Preds[j];
-      BasicBlock* EndBlock;
-      if (NewExitBlock->getSinglePredecessor() == ExitBlock) {
-        EndBlock = NewExitBlock;
-        NewExitBlock = EndBlock->getSinglePredecessor();
-      } else {
-        EndBlock = ExitBlock;
-      }
-      
-      std::set<PHINode*> InsertedPHIs;
-      PHINode* OldLCSSA = 0;
-      for (BasicBlock::iterator I = EndBlock->begin();
-           (OldLCSSA = dyn_cast<PHINode>(I)); ++I) {
-        Value* OldValue = OldLCSSA->getIncomingValueForBlock(NewExitBlock);
-        PHINode* NewLCSSA = PHINode::Create(OldLCSSA->getType(),
-                                            OldLCSSA->getName() + ".us-lcssa",
-                                            NewExitBlock->getTerminator());
-        NewLCSSA->addIncoming(OldValue, StartBlock);
-        OldLCSSA->setIncomingValue(OldLCSSA->getBasicBlockIndex(NewExitBlock),
-                                   NewLCSSA);
-        InsertedPHIs.insert(NewLCSSA);
-      }
-
-      BasicBlock::iterator InsertPt = EndBlock->getFirstNonPHI();
-      for (BasicBlock::iterator I = NewExitBlock->begin();
-         (OldLCSSA = dyn_cast<PHINode>(I)) && InsertedPHIs.count(OldLCSSA) == 0;
-         ++I) {
-        PHINode *NewLCSSA = PHINode::Create(OldLCSSA->getType(),
-                                            OldLCSSA->getName() + ".us-lcssa",
-                                            InsertPt);
-        OldLCSSA->replaceAllUsesWith(NewLCSSA);
-        NewLCSSA->addIncoming(OldLCSSA, NewExitBlock);
-      }
-
-    }    
+    SmallVector<BasicBlock *, 4> Preds(pred_begin(ExitBlock),
+                                       pred_end(ExitBlock));
+    SplitBlockPredecessors(ExitBlock, Preds.data(), Preds.size(),
+                           ".us-lcssa", this);
   }
-
 }
 
 /// UnswitchNontrivialCondition - We determined that the loop is profitable 
@@ -945,27 +918,35 @@
               // FIXME: This is a hack.  We need to keep the successor around
               // and hooked up so as to preserve the loop structure, because
               // trying to update it is complicated.  So instead we preserve the
-              // loop structure and put the block on an dead code path.
-              
-              BasicBlock *SISucc = SI->getSuccessor(i);
-              BasicBlock* Old = SI->getParent();
-              BasicBlock* Split = SplitBlock(Old, SI, this);
-              
-              Instruction* OldTerm = Old->getTerminator();
-              BranchInst::Create(Split, SISucc,
-                                 ConstantInt::getTrue(Context), OldTerm);
-
-              LPM->deleteSimpleAnalysisValue(Old->getTerminator(), L);
-              Old->getTerminator()->eraseFromParent();
-              
-              PHINode *PN;
-              for (BasicBlock::iterator II = SISucc->begin();
-                   (PN = dyn_cast<PHINode>(II)); ++II) {
-                Value *InVal = PN->removeIncomingValue(Split, false);
-                PN->addIncoming(InVal, Old);
-              }
-
-              SI->removeCase(i);
+              // loop structure and put the block on a dead code path.
+              BasicBlock *Switch = SI->getParent();
+              SplitEdge(Switch, SI->getSuccessor(i), this);
+              // Compute the successors instead of relying on the return value
+              // of SplitEdge, since it may have split the switch successor
+              // after PHI nodes.
+              BasicBlock *NewSISucc = SI->getSuccessor(i);
+              BasicBlock *OldSISucc = *succ_begin(NewSISucc);
+              // Create an "unreachable" destination.
+              BasicBlock *Abort = BasicBlock::Create(Context, "us-unreachable",
+                                                     Switch->getParent(),
+                                                     OldSISucc);
+              new UnreachableInst(Context, Abort);
+              // Force the new case destination to branch to the "unreachable"
+              // block while maintaining a (dead) CFG edge to the old block.
+              NewSISucc->getTerminator()->eraseFromParent();
+              BranchInst::Create(Abort, OldSISucc,
+                                 ConstantInt::getTrue(Context), NewSISucc);
+              // Release the PHI operands for this edge.
+              for (BasicBlock::iterator II = NewSISucc->begin();
+                   PHINode *PN = dyn_cast<PHINode>(II); ++II)
+                PN->setIncomingValue(PN->getBasicBlockIndex(Switch),
+                                     UndefValue::get(PN->getType()));
+              // Tell the domtree about the new block. We don't fully update
+              // the domtree here -- instead we force it to do a full recomputation
+              // after the pass is complete -- but we do need to inform it of
+              // new blocks.
+              if (DT)
+                DT->addNewBlock(Abort, NewSISucc);
               break;
             }
           }

Modified: llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BasicBlockUtils.cpp Tue Sep  8 10:45:00 2009
@@ -24,6 +24,7 @@
 #include "llvm/Analysis/Dominators.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Transforms/Scalar.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ValueHandle.h"
 #include <algorithm>
@@ -319,7 +320,8 @@
     ++SplitIt;
   BasicBlock *New = Old->splitBasicBlock(SplitIt, Old->getName()+".split");
 
-  // The new block lives in whichever loop the old one did.
+  // The new block lives in whichever loop the old one did. This preserves
+  // LCSSA as well, because we force the split point to be after any PHI nodes.
   if (LoopInfo* LI = P->getAnalysisIfAvailable<LoopInfo>())
     if (Loop *L = LI->getLoopFor(Old))
       L->addBasicBlockToLoop(New, LI->getBase());
@@ -353,8 +355,12 @@
 /// Preds array, which has NumPreds elements in it.  The new block is given a
 /// suffix of 'Suffix'.
 ///
-/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree and
-/// DominanceFrontier, but no other analyses.
+/// This currently updates the LLVM IR, AliasAnalysis, DominatorTree,
+/// DominanceFrontier, LoopInfo, and LCCSA but no other analyses.
+/// In particular, it does not preserve LoopSimplify (because it's
+/// complicated to handle the case where one of the edges being split
+/// is an exit of a loop with other exits).
+///
 BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB, 
                                          BasicBlock *const *Preds,
                                          unsigned NumPreds, const char *Suffix,
@@ -366,19 +372,44 @@
   // The new block unconditionally branches to the old block.
   BranchInst *BI = BranchInst::Create(BB, NewBB);
   
+  LoopInfo *LI = P ? P->getAnalysisIfAvailable<LoopInfo>() : 0;
+  Loop *L = LI ? LI->getLoopFor(BB) : 0;
+  bool PreserveLCSSA = P->mustPreserveAnalysisID(LCSSAID);
+
   // Move the edges from Preds to point to NewBB instead of BB.
-  for (unsigned i = 0; i != NumPreds; ++i)
+  // While here, if we need to preserve loop analyses, collect
+  // some information about how this split will affect loops.
+  bool HasLoopExit = false;
+  bool IsLoopEntry = !!L;
+  bool SplitMakesNewLoopHeader = false;
+  for (unsigned i = 0; i != NumPreds; ++i) {
     Preds[i]->getTerminator()->replaceUsesOfWith(BB, NewBB);
-  
+
+    if (LI) {
+      // If we need to preserve LCSSA, determine if any of
+      // the preds is a loop exit.
+      if (PreserveLCSSA)
+        if (Loop *PL = LI->getLoopFor(Preds[i]))
+          if (!PL->contains(BB))
+            HasLoopExit = true;
+      // If we need to preserve LoopInfo, note whether any of the
+      // preds crosses an interesting loop boundary.
+      if (L) {
+        if (L->contains(Preds[i]))
+          IsLoopEntry = false;
+        else
+          SplitMakesNewLoopHeader = true;
+      }
+    }
+  }
+
   // Update dominator tree and dominator frontier if available.
   DominatorTree *DT = P ? P->getAnalysisIfAvailable<DominatorTree>() : 0;
   if (DT)
     DT->splitBlock(NewBB);
   if (DominanceFrontier *DF = P ? P->getAnalysisIfAvailable<DominanceFrontier>():0)
     DF->splitBlock(NewBB);
-  AliasAnalysis *AA = P ? P->getAnalysisIfAvailable<AliasAnalysis>() : 0;
-  
-  
+
   // Insert a new PHI node into NewBB for every PHI node in BB and that new PHI
   // node becomes an incoming value for BB's phi node.  However, if the Preds
   // list is empty, we need to insert dummy entries into the PHI nodes in BB to
@@ -389,20 +420,42 @@
       cast<PHINode>(I)->addIncoming(UndefValue::get(I->getType()), NewBB);
     return NewBB;
   }
+
+  AliasAnalysis *AA = P ? P->getAnalysisIfAvailable<AliasAnalysis>() : 0;
+
+  if (L) {
+    if (IsLoopEntry) {
+      if (Loop *PredLoop = LI->getLoopFor(Preds[0])) {
+        // Add the new block to the nearest enclosing loop (and not an
+        // adjacent loop).
+        while (PredLoop && !PredLoop->contains(BB))
+          PredLoop = PredLoop->getParentLoop();
+        if (PredLoop)
+          PredLoop->addBasicBlockToLoop(NewBB, LI->getBase());
+      }
+    } else {
+      L->addBasicBlockToLoop(NewBB, LI->getBase());
+      if (SplitMakesNewLoopHeader)
+        L->moveToHeader(NewBB);
+    }
+  }
   
   // Otherwise, create a new PHI node in NewBB for each PHI node in BB.
   for (BasicBlock::iterator I = BB->begin(); isa<PHINode>(I); ) {
     PHINode *PN = cast<PHINode>(I++);
     
     // Check to see if all of the values coming in are the same.  If so, we
-    // don't need to create a new PHI node.
-    Value *InVal = PN->getIncomingValueForBlock(Preds[0]);
-    for (unsigned i = 1; i != NumPreds; ++i)
-      if (InVal != PN->getIncomingValueForBlock(Preds[i])) {
-        InVal = 0;
-        break;
-      }
-    
+    // don't need to create a new PHI node, unless it's needed for LCSSA.
+    Value *InVal = 0;
+    if (!HasLoopExit) {
+      InVal = PN->getIncomingValueForBlock(Preds[0]);
+      for (unsigned i = 1; i != NumPreds; ++i)
+        if (InVal != PN->getIncomingValueForBlock(Preds[i])) {
+          InVal = 0;
+          break;
+        }
+    }
+
     if (InVal) {
       // If all incoming values for the new PHI would be the same, just don't
       // make a new PHI.  Instead, just remove the incoming values from the old
@@ -427,13 +480,6 @@
     // Add an incoming value to the PHI node in the loop for the preheader
     // edge.
     PN->addIncoming(InVal, NewBB);
-    
-    // Check to see if we can eliminate this phi node.
-    if (Value *V = PN->hasConstantValue(DT)) {
-      PN->replaceAllUsesWith(V);
-      if (AA) AA->deleteValue(PN);
-      PN->eraseFromParent();
-    }
   }
   
   return NewBB;

Modified: llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp Tue Sep  8 10:45:00 2009
@@ -122,9 +122,9 @@
 /// false otherwise.  This ensures that all edges to that dest go to one block
 /// instead of each going to a different block.
 //
-bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
-                             bool MergeIdenticalEdges) {
-  if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return false;
+BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
+                                    Pass *P, bool MergeIdenticalEdges) {
+  if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0;
   BasicBlock *TIBB = TI->getParent();
   BasicBlock *DestBB = TI->getSuccessor(SuccNum);
 
@@ -172,7 +172,7 @@
   
 
   // If we don't have a pass object, we can't update anything...
-  if (P == 0) return true;
+  if (P == 0) return NewBB;
 
   // Now update analysis information.  Since the only predecessor of NewBB is
   // the TIBB, TIBB clearly dominates NewBB.  TIBB usually doesn't dominate
@@ -254,9 +254,9 @@
   
   // Update LoopInfo if it is around.
   if (LoopInfo *LI = P->getAnalysisIfAvailable<LoopInfo>()) {
-    // If one or the other blocks were not in a loop, the new block is not
-    // either, and thus LI doesn't need to be updated.
-    if (Loop *TIL = LI->getLoopFor(TIBB))
+    if (Loop *TIL = LI->getLoopFor(TIBB)) {
+      // If one or the other blocks were not in a loop, the new block is not
+      // either, and thus LI doesn't need to be updated.
       if (Loop *DestLoop = LI->getLoopFor(DestBB)) {
         if (TIL == DestLoop) {
           // Both in the same loop, the NewBB joins loop.
@@ -278,6 +278,65 @@
             P->addBasicBlockToLoop(NewBB, LI->getBase());
         }
       }
+      // If TIBB is in a loop and DestBB is outside of that loop, split the
+      // other exit blocks of the loop that also have predecessors outside
+      // the loop, to maintain a LoopSimplify guarantee.
+      if (!TIL->contains(DestBB) &&
+          P->mustPreserveAnalysisID(LoopSimplifyID)) {
+        // For each unique exit block...
+        SmallVector<BasicBlock *, 4> ExitBlocks;
+        TIL->getExitBlocks(ExitBlocks);
+        for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
+          // Collect all the preds that are inside the loop, and note
+          // whether there are any preds outside the loop.
+          SmallVector<BasicBlock *, 4> Preds;
+          bool AllPredsInLoop = false;
+          BasicBlock *Exit = ExitBlocks[i];
+          for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit);
+               I != E; ++I)
+            if (TIL->contains(*I))
+              Preds.push_back(*I);
+            else
+              AllPredsInLoop = true;
+          // If there are any preds not in the loop, we'll need to split
+          // the edges. The Preds.empty() check is needed because a block
+          // may appear multiple times in the list. We can't use
+          // getUniqueExitBlocks above because that depends on LoopSimplify
+          // form, which we're in the process of restoring!
+          if (Preds.empty() || !AllPredsInLoop) continue;
+          BasicBlock *NewBB = SplitBlockPredecessors(Exit,
+                                                     Preds.data(), Preds.size(),
+                                                     "split", P);
+          // Update LCSSA form by creating new PHIs in the new exit blocks
+          // as needed.
+          if (P->mustPreserveAnalysisID(LCSSAID))
+            for (BasicBlock::iterator I = Exit->begin();
+                 PHINode *PN = dyn_cast<PHINode>(I); ++I) {
+              unsigned Idx = PN->getBasicBlockIndex(NewBB);
+              Value *V = PN->getIncomingValue(Idx);
+              // If the PHI is already suitable, don't create a new one.
+              if (PHINode *VP = dyn_cast<PHINode>(V))
+                if (VP->getParent() == NewBB)
+                  continue;
+              // A new PHI is needed. Create one and populate it.
+              PHINode *NewPN =
+                PHINode::Create(PN->getType(), "split", NewBB->getTerminator());
+              for (unsigned i = 0, e = Preds.size(); i != e; ++i)
+                NewPN->addIncoming(V, Preds[i]);
+              PN->setIncomingValue(Idx, NewPN);
+            }
+        }
+      }
+      // LCSSA form was updated above for the case where LoopSimplify is
+      // available, which means that all predecessors of loop exit blocks
+      // are within the loop. Without LoopSimplify form, it would be
+      // necessary to insert a new phi.
+      assert((!P->mustPreserveAnalysisID(LCSSAID) ||
+              P->mustPreserveAnalysisID(LoopSimplifyID)) &&
+             "SplitCriticalEdge doesn't know how to update LCCSA form "
+             "without LoopSimplify!");
+    }
   }
-  return true;
+
+  return NewBB;
 }

Modified: llvm/trunk/lib/Transforms/Utils/LCSSA.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LCSSA.cpp?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LCSSA.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LCSSA.cpp Tue Sep  8 10:45:00 2009
@@ -58,6 +58,7 @@
     DominatorTree *DT;
     std::vector<BasicBlock*> LoopBlocks;
     PredIteratorCache PredCache;
+    Loop *L;
     
     virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
 
@@ -72,9 +73,9 @@
       AU.setPreservesCFG();
       AU.addRequiredID(LoopSimplifyID);
       AU.addPreservedID(LoopSimplifyID);
-      AU.addRequired<LoopInfo>();
+      AU.addRequiredTransitive<LoopInfo>();
       AU.addPreserved<LoopInfo>();
-      AU.addRequired<DominatorTree>();
+      AU.addRequiredTransitive<DominatorTree>();
       AU.addPreserved<ScalarEvolution>();
       AU.addPreserved<DominatorTree>();
 
@@ -86,6 +87,15 @@
       AU.addPreserved<DominanceFrontier>();
     }
   private:
+
+    /// verifyAnalysis() - Verify loop nest.
+    virtual void verifyAnalysis() const {
+#ifndef NDEBUG
+      // Check the special guarantees that LCSSA makes.
+      assert(L->isLCSSAForm());
+#endif
+    }
+
     void getLoopValuesUsedOutsideLoop(Loop *L,
                                       SetVector<Instruction*> &AffectedValues,
                                  const SmallVector<BasicBlock*, 8>& exitBlocks);
@@ -107,7 +117,8 @@
 const PassInfo *const llvm::LCSSAID = &X;
 
 /// runOnFunction - Process all loops in the function, inner-most out.
-bool LCSSA::runOnLoop(Loop *L, LPPassManager &LPM) {
+bool LCSSA::runOnLoop(Loop *l, LPPassManager &LPM) {
+  L = l;
   PredCache.clear();
   
   LI = &LPM.getAnalysis<LoopInfo>();

Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=81221&r1=81220&r2=81221&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Tue Sep  8 10:45:00 2009
@@ -69,8 +69,8 @@
 
     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
       // We need loop information to identify the loops...
-      AU.addRequired<LoopInfo>();
-      AU.addRequired<DominatorTree>();
+      AU.addRequiredTransitive<LoopInfo>();
+      AU.addRequiredTransitive<DominatorTree>();
 
       AU.addPreserved<LoopInfo>();
       AU.addPreserved<DominatorTree>();
@@ -83,9 +83,11 @@
     void verifyAnalysis() const {
 #ifndef NDEBUG
       LoopInfo *NLI = &getAnalysis<LoopInfo>();
-      for (LoopInfo::iterator I = NLI->begin(), E = NLI->end(); I != E; ++I) 
-        (*I)->verifyLoop();
-#endif  
+      for (LoopInfo::iterator I = NLI->begin(), E = NLI->end(); I != E; ++I) {
+        // Check the special guarantees that LoopSimplify makes.
+        assert((*I)->isLoopSimplifyForm());
+      }
+#endif
     }
 
   private:
@@ -346,15 +348,6 @@
   BasicBlock *NewBB =
     SplitBlockPredecessors(Header, &OutsideBlocks[0], OutsideBlocks.size(),
                            ".preheader", this);
-  
-
-  //===--------------------------------------------------------------------===//
-  //  Update analysis results now that we have performed the transformation
-  //
-
-  // We know that we have loop information to update... update it now.
-  if (Loop *Parent = L->getParentLoop())
-    Parent->addBasicBlockToLoop(NewBB, LI->getBase());
 
   // Make sure that NewBB is put someplace intelligent, which doesn't mess up
   // code layout too horribly.
@@ -377,17 +370,6 @@
                                              LoopBlocks.size(), ".loopexit",
                                              this);
 
-  // Update Loop Information - we know that the new block will be in whichever
-  // loop the Exit block is in.  Note that it may not be in that immediate loop,
-  // if the successor is some other loop header.  In that case, we continue 
-  // walking up the loop tree to find a loop that contains both the successor
-  // block and the predecessor block.
-  Loop *SuccLoop = LI->getLoopFor(Exit);
-  while (SuccLoop && !SuccLoop->contains(L->getHeader()))
-    SuccLoop = SuccLoop->getParentLoop();
-  if (SuccLoop)
-    SuccLoop->addBasicBlockToLoop(NewBB, LI->getBase());
-
   return NewBB;
 }
 
@@ -521,10 +503,6 @@
   else
     LI->changeTopLevelLoop(L, NewOuter);
 
-  // This block is going to be our new header block: add it to this loop and all
-  // parent loops.
-  NewOuter->addBasicBlockToLoop(NewBB, LI->getBase());
-
   // L is now a subloop of our outer loop.
   NewOuter->addChildLoop(L);
 
@@ -532,6 +510,10 @@
        I != E; ++I)
     NewOuter->addBlockEntry(*I);
 
+  // Now reset the header in L, which had been moved by
+  // SplitBlockPredecessors for the outer loop.
+  L->moveToHeader(Header);
+
   // Determine which blocks should stay in L and which should be moved out to
   // the Outer loop now.
   std::set<BasicBlock*> BlocksInL;

Removed: llvm/trunk/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll?rev=81220&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll (original)
+++ llvm/trunk/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll (removed)
@@ -1,52 +0,0 @@
-; RUN: llvm-as < %s | opt -loop-unswitch -disable-output 
-; rdar://7197574
-
-target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32"
-target triple = "thumbv7-apple-darwin9"
-	%struct.frame = type { i16*, i16*, i16* }
-
-declare arm_apcscc i32 @ercCollect8PredBlocks(i32* nocapture, i32, i32, i32* nocapture, i32, i32, i32, i8 zeroext) nounwind
-
-define arm_apcscc void @concealBlocks(i32 %lastColumn, i32 %lastRow, i32 %comp, %struct.frame* nocapture %recfr, i32 %picSizeX, i32* nocapture %condition) nounwind {
-entry:
-	br i1 undef, label %bb.nph12, label %return
-
-bb28:		; preds = %bb.nph12
-	unreachable
-
-bb42:		; preds = %bb.nph12
-	br label %bb43
-
-bb43:		; preds = %bb61, %bb42
-	%0 = call arm_apcscc  i32 @ercCollect8PredBlocks(i32* undef, i32 undef, i32 0, i32* %condition, i32 %lastRow, i32 %lastColumn, i32 undef, i8 zeroext 1) nounwind		; <i32> [#uses=0]
-	switch i32 %comp, label %bb58 [
-		i32 0, label %bb52
-		i32 1, label %bb54
-		i32 2, label %bb56
-	]
-
-bb52:		; preds = %bb43
-	br label %bb58
-
-bb54:		; preds = %bb43
-	br label %bb58
-
-bb56:		; preds = %bb43
-	unreachable
-
-bb58:		; preds = %bb54, %bb52, %bb43
-	br i1 %1, label %bb59, label %bb61
-
-bb59:		; preds = %bb58
-	br label %bb61
-
-bb61:		; preds = %bb59, %bb58
-	br label %bb43
-
-bb.nph12:		; preds = %entry
-	%1 = icmp eq i32 %comp, 0		; <i1> [#uses=1]
-	br i1 undef, label %bb28, label %bb42
-
-return:		; preds = %entry
-	ret void
-}

Added: llvm/trunk/test/Transforms/LoopUnswitch/preserve-analyses.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnswitch/preserve-analyses.ll?rev=81221&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/LoopUnswitch/preserve-analyses.ll (added)
+++ llvm/trunk/test/Transforms/LoopUnswitch/preserve-analyses.ll Tue Sep  8 10:45:00 2009
@@ -0,0 +1,645 @@
+; RUN: opt -loop-unswitch %s -disable-output
+
+; Loop unswitch should be able to unswitch these loops and
+; preserve LCSSA and LoopSimplify forms.
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:64"
+target triple = "armv6-apple-darwin9"
+
+%struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
+%struct._RuneCharClass = type { [14 x i8], i32 }
+%struct._RuneEntry = type { i32, i32, i32, i32* }
+%struct._RuneLocale = type { [8 x i8], [32 x i8], i32 (i8*, i32, i8**)*, i32 (i32, i8*, i32, i8**)*, i32, [256 x i32], [256 x i32], [256 x i32], %struct._RuneRange, %struct._RuneRange, %struct._RuneRange, i8*, i32, i32, %struct._RuneCharClass* }
+%struct._RuneRange = type { i32, %struct._RuneEntry* }
+%struct.__sFILEX = type opaque
+%struct.__sbuf = type { i8*, i32 }
+%struct.colstr = type { i8*, i8* }
+%struct.optstr = type { i8*, i32* }
+
+ at expflg = external global i32                     ; <i32*> [#uses=0]
+ at ctrflg = external global i32                     ; <i32*> [#uses=0]
+ at boxflg = external global i32                     ; <i32*> [#uses=0]
+ at dboxflg = external global i32                    ; <i32*> [#uses=0]
+ at tab = external global i32                        ; <i32*> [#uses=0]
+ at F1 = external global i32                         ; <i32*> [#uses=0]
+ at F2 = external global i32                         ; <i32*> [#uses=0]
+ at allflg = external global i32                     ; <i32*> [#uses=0]
+ at leftover = external global i32                   ; <i32*> [#uses=0]
+ at textflg = external global i32                    ; <i32*> [#uses=0]
+ at left1flg = external global i32                   ; <i32*> [#uses=0]
+ at rightl = external global i32                     ; <i32*> [#uses=0]
+ at iline = external global i32                      ; <i32*> [#uses=0]
+ at ifile = external global i8*                      ; <i8**> [#uses=0]
+ at .str = external constant [6 x i8], align 1       ; <[6 x i8]*> [#uses=0]
+ at texname = external global i32                    ; <i32*> [#uses=0]
+ at texct = external global i32                      ; <i32*> [#uses=0]
+ at texstr = external global [63 x i8], align 4      ; <[63 x i8]*> [#uses=0]
+ at nlin = external global i32                       ; <i32*> [#uses=0]
+ at ncol = external global i32                       ; <i32*> [#uses=0]
+ at nclin = external global i32                      ; <i32*> [#uses=0]
+ at nslin = external global i32                      ; <i32*> [#uses=0]
+ at style = external global [100 x [20 x i32]]       ; <[100 x [20 x i32]]*> [#uses=0]
+ at ctop = external global [100 x [20 x i32]]        ; <[100 x [20 x i32]]*> [#uses=0]
+ at font = external global [100 x [20 x [2 x i8]]]   ; <[100 x [20 x [2 x i8]]]*> [#uses=0]
+ at csize = external global [100 x [20 x [4 x i8]]]  ; <[100 x [20 x [4 x i8]]]*> [#uses=0]
+ at vsize = external global [100 x [20 x [4 x i8]]]  ; <[100 x [20 x [4 x i8]]]*> [#uses=0]
+ at cll = external global [20 x [10 x i8]]           ; <[20 x [10 x i8]]*> [#uses=0]
+ at stynum = external global [201 x i32]             ; <[201 x i32]*> [#uses=0]
+ at lefline = external global [100 x [20 x i32]]     ; <[100 x [20 x i32]]*> [#uses=0]
+ at fullbot = external global [200 x i32]            ; <[200 x i32]*> [#uses=0]
+ at instead = external global [200 x i8*]            ; <[200 x i8*]*> [#uses=0]
+ at evenflg = external global i32                    ; <i32*> [#uses=0]
+ at evenup = external global [20 x i32]              ; <[20 x i32]*> [#uses=0]
+ at linsize = external global i32                    ; <i32*> [#uses=0]
+ at pr1403 = external global i32                     ; <i32*> [#uses=0]
+ at delim1 = external global i32                     ; <i32*> [#uses=1]
+ at delim2 = external global i32                     ; <i32*> [#uses=1]
+ at table = external global [200 x %struct.colstr*]  ; <[200 x %struct.colstr*]*> [#uses=0]
+ at cspace = external global i8*                     ; <i8**> [#uses=0]
+ at cstore = external global i8*                     ; <i8**> [#uses=0]
+ at exstore = external global i8*                    ; <i8**> [#uses=0]
+ at exlim = external global i8*                      ; <i8**> [#uses=0]
+ at sep = external global [20 x i32]                 ; <[20 x i32]*> [#uses=0]
+ at used = external global [20 x i32]                ; <[20 x i32]*> [#uses=0]
+ at lused = external global [20 x i32]               ; <[20 x i32]*> [#uses=0]
+ at rused = external global [20 x i32]               ; <[20 x i32]*> [#uses=0]
+ at linestop = external global [200 x i32]           ; <[200 x i32]*> [#uses=0]
+ at last = external global i8*                       ; <i8**> [#uses=0]
+ at linstart = external global i32                   ; <i32*> [#uses=0]
+ at tabin = external global %struct.FILE*            ; <%struct.FILE**> [#uses=0]
+ at tabout = external global %struct.FILE*           ; <%struct.FILE**> [#uses=0]
+ at sargc = external global i32                      ; <i32*> [#uses=0]
+ at sargv = external global i8**                     ; <i8***> [#uses=0]
+ at .str1 = external constant [4 x i8], align 1      ; <[4 x i8]*> [#uses=0]
+ at .str12 = external constant [16 x i8], align 1    ; <[16 x i8]*> [#uses=0]
+ at .str2 = external constant [4 x i8], align 1      ; <[4 x i8]*> [#uses=0]
+ at .str3 = external constant [16 x i8], align 1     ; <[16 x i8]*> [#uses=0]
+ at .str4 = external constant [4 x i8], align 1      ; <[4 x i8]*> [#uses=0]
+ at .str5 = external constant [2 x i8], align 1      ; <[2 x i8]*> [#uses=0]
+ at .str6 = external constant [16 x i8], align 1     ; <[16 x i8]*> [#uses=0]
+ at __stdinp = external global %struct.FILE*         ; <%struct.FILE**> [#uses=0]
+ at __stdoutp = external global %struct.FILE*        ; <%struct.FILE**> [#uses=0]
+ at .str7 = external constant [4 x i8], align 1      ; <[4 x i8]*> [#uses=0]
+ at .str8 = external constant [4 x i8], align 1      ; <[4 x i8]*> [#uses=0]
+ at options = external global [21 x %struct.optstr]  ; <[21 x %struct.optstr]*> [#uses=0]
+ at .str9 = external constant [7 x i8], align 1      ; <[7 x i8]*> [#uses=0]
+ at .str110 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str211 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str312 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str413 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str514 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str615 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str716 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str817 = external constant [10 x i8], align 1   ; <[10 x i8]*> [#uses=0]
+ at .str918 = external constant [10 x i8], align 1   ; <[10 x i8]*> [#uses=0]
+ at .str10 = external constant [6 x i8], align 1     ; <[6 x i8]*> [#uses=0]
+ at .str11 = external constant [6 x i8], align 1     ; <[6 x i8]*> [#uses=0]
+ at .str1219 = external constant [12 x i8], align 1  ; <[12 x i8]*> [#uses=0]
+ at .str13 = external constant [12 x i8], align 1    ; <[12 x i8]*> [#uses=0]
+ at .str14 = external constant [4 x i8], align 1     ; <[4 x i8]*> [#uses=0]
+ at .str15 = external constant [4 x i8], align 1     ; <[4 x i8]*> [#uses=0]
+ at .str16 = external constant [9 x i8], align 1     ; <[9 x i8]*> [#uses=0]
+ at .str17 = external constant [9 x i8], align 1     ; <[9 x i8]*> [#uses=0]
+ at .str18 = external constant [6 x i8], align 1     ; <[6 x i8]*> [#uses=0]
+ at .str19 = external constant [6 x i8], align 1     ; <[6 x i8]*> [#uses=0]
+ at .str20 = external constant [14 x i8], align 1    ; <[14 x i8]*> [#uses=0]
+ at .str21 = external constant [25 x i8], align 1    ; <[25 x i8]*> [#uses=0]
+ at .str22 = external constant [11 x i8], align 1    ; <[11 x i8]*> [#uses=0]
+ at .str23 = external constant [15 x i8], align 1    ; <[15 x i8]*> [#uses=0]
+ at .str24 = external constant [34 x i8], align 1    ; <[34 x i8]*> [#uses=0]
+ at .str125 = external constant [32 x i8], align 1   ; <[32 x i8]*> [#uses=0]
+ at .str226 = external constant [17 x i8], align 1   ; <[17 x i8]*> [#uses=0]
+ at .str327 = external constant [38 x i8], align 1   ; <[38 x i8]*> [#uses=0]
+ at oncol = external global i32                      ; <i32*> [#uses=0]
+ at .str428 = external constant [40 x i8], align 1   ; <[40 x i8]*> [#uses=0]
+ at .str529 = external constant [31 x i8], align 1   ; <[31 x i8]*> [#uses=0]
+ at .str630 = external constant [51 x i8], align 1   ; <[51 x i8]*> [#uses=0]
+ at .str731 = external constant [51 x i8], align 1   ; <[51 x i8]*> [#uses=0]
+ at .str832 = external constant [40 x i8], align 1   ; <[40 x i8]*> [#uses=0]
+ at .str933 = external constant [26 x i8], align 1   ; <[26 x i8]*> [#uses=0]
+ at .str1034 = external constant [24 x i8], align 1  ; <[24 x i8]*> [#uses=0]
+ at .str1135 = external constant [21 x i8], align 1  ; <[21 x i8]*> [#uses=0]
+ at .str1236 = external constant [24 x i8], align 1  ; <[24 x i8]*> [#uses=0]
+ at .str1337 = external constant [33 x i8], align 1  ; <[33 x i8]*> [#uses=0]
+ at .str1438 = external constant [22 x i8], align 1  ; <[22 x i8]*> [#uses=0]
+ at .str1539 = external constant [32 x i8], align 1  ; <[32 x i8]*> [#uses=0]
+ at .str1640 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str1741 = external constant [6 x i8], align 1   ; <[6 x i8]*> [#uses=0]
+ at _DefaultRuneLocale = external global %struct._RuneLocale ; <%struct._RuneLocale*> [#uses=0]
+ at .str43 = external constant [3 x i8], align 1     ; <[3 x i8]*> [#uses=0]
+ at .str144 = external constant [43 x i8], align 1   ; <[43 x i8]*> [#uses=0]
+ at .str245 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str346 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str447 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str548 = external constant [3 x i8], align 1    ; <[3 x i8]*> [#uses=0]
+ at .str649 = external constant [1 x i8], align 1    ; <[1 x i8]*> [#uses=0]
+ at .str51 = external constant [5 x i8], align 1     ; <[5 x i8]*> [#uses=0]
+ at .str152 = external constant [2 x i8], align 1    ; <[2 x i8]*> [#uses=0]
+ at .str253 = external constant [2 x i8], align 1    ; <[2 x i8]*> [#uses=0]
+ at .str354 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str455 = external constant [10 x i8], align 1   ; <[10 x i8]*> [#uses=0]
+ at .str556 = external constant [16 x i8], align 1   ; <[16 x i8]*> [#uses=0]
+ at .str657 = external constant [19 x i8], align 1   ; <[19 x i8]*> [#uses=0]
+ at .str758 = external constant [32 x i8], align 1   ; <[32 x i8]*> [#uses=0]
+ at .str859 = external constant [8 x i8], align 1    ; <[8 x i8]*> [#uses=0]
+ at .str960 = external constant [30 x i8], align 1   ; <[30 x i8]*> [#uses=0]
+ at .str1061 = external constant [17 x i8], align 1  ; <[17 x i8]*> [#uses=0]
+ at .str1162 = external constant [35 x i8], align 1  ; <[35 x i8]*> [#uses=0]
+ at .str1263 = external constant [14 x i8], align 1  ; <[14 x i8]*> [#uses=0]
+ at .str1364 = external constant [20 x i8], align 1  ; <[20 x i8]*> [#uses=0]
+ at .str1465 = external constant [30 x i8], align 1  ; <[30 x i8]*> [#uses=0]
+ at .str1566 = external constant [41 x i8], align 1  ; <[41 x i8]*> [#uses=0]
+ at .str1667 = external constant [12 x i8], align 1  ; <[12 x i8]*> [#uses=0]
+ at .str1768 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str1869 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str1970 = external constant [29 x i8], align 1  ; <[29 x i8]*> [#uses=0]
+ at .str2071 = external constant [22 x i8], align 1  ; <[22 x i8]*> [#uses=0]
+ at .str2172 = external constant [17 x i8], align 1  ; <[17 x i8]*> [#uses=0]
+ at .str2273 = external constant [15 x i8], align 1  ; <[15 x i8]*> [#uses=0]
+ at .str2374 = external constant [36 x i8], align 1  ; <[36 x i8]*> [#uses=0]
+ at .str2475 = external constant [9 x i8], align 1   ; <[9 x i8]*> [#uses=0]
+ at .str25 = external constant [7 x i8], align 1     ; <[7 x i8]*> [#uses=0]
+ at .str26 = external constant [20 x i8], align 1    ; <[20 x i8]*> [#uses=0]
+ at .str27 = external constant [17 x i8], align 1    ; <[17 x i8]*> [#uses=0]
+ at .str28 = external constant [11 x i8], align 1    ; <[11 x i8]*> [#uses=0]
+ at .str29 = external constant [25 x i8], align 1    ; <[25 x i8]*> [#uses=0]
+ at .str30 = external constant [24 x i8], align 1    ; <[24 x i8]*> [#uses=0]
+ at .str31 = external constant [14 x i8], align 1    ; <[14 x i8]*> [#uses=0]
+ at .str32 = external constant [18 x i8], align 1    ; <[18 x i8]*> [#uses=0]
+ at .str33 = external constant [79 x i8], align 1    ; <[79 x i8]*> [#uses=0]
+ at .str77 = external constant [13 x i8], align 1    ; <[13 x i8]*> [#uses=0]
+ at .str178 = external constant [13 x i8], align 1   ; <[13 x i8]*> [#uses=0]
+ at .str279 = external constant [12 x i8], align 1   ; <[12 x i8]*> [#uses=0]
+ at .str380 = external constant [5 x i8], align 1    ; <[5 x i8]*> [#uses=0]
+ at .str481 = external constant [8 x i8], align 1    ; <[8 x i8]*> [#uses=0]
+ at .str582 = external constant [11 x i8], align 1   ; <[11 x i8]*> [#uses=0]
+ at .str683 = external constant [33 x i8], align 1   ; <[33 x i8]*> [#uses=0]
+ at .str784 = external constant [8 x i8], align 1    ; <[8 x i8]*> [#uses=0]
+ at .str885 = external constant [12 x i8], align 1   ; <[12 x i8]*> [#uses=0]
+ at .str986 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str1087 = external constant [28 x i8], align 1  ; <[28 x i8]*> [#uses=0]
+ at .str1188 = external constant [29 x i8], align 1  ; <[29 x i8]*> [#uses=0]
+ at .str1289 = external constant [11 x i8], align 1  ; <[11 x i8]*> [#uses=0]
+ at .str1390 = external constant [16 x i8], align 1  ; <[16 x i8]*> [#uses=0]
+ at .str1491 = external constant [22 x i8], align 1  ; <[22 x i8]*> [#uses=0]
+ at .str1592 = external constant [15 x i8], align 1  ; <[15 x i8]*> [#uses=0]
+ at .str1693 = external constant [13 x i8], align 1  ; <[13 x i8]*> [#uses=0]
+ at .str1794 = external constant [21 x i8], align 1  ; <[21 x i8]*> [#uses=0]
+ at .str1895 = external constant [25 x i8], align 1  ; <[25 x i8]*> [#uses=0]
+ at .str1996 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str2097 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str2198 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str2299 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str23100 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str24101 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str25102 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+ at .str26103 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+ at .str27104 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str28105 = external constant [5 x i8], align 1  ; <[5 x i8]*> [#uses=0]
+ at .str29106 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+ at .str30107 = external constant [7 x i8], align 1  ; <[7 x i8]*> [#uses=0]
+ at .str31108 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str111 = external constant [5 x i8], align 1    ; <[5 x i8]*> [#uses=0]
+ at .str1112 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str2113 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str3114 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str4115 = external constant [14 x i8], align 1  ; <[14 x i8]*> [#uses=0]
+ at .str5116 = external constant [16 x i8], align 1  ; <[16 x i8]*> [#uses=0]
+ at .str6117 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str7118 = external constant [28 x i8], align 1  ; <[28 x i8]*> [#uses=0]
+ at .str8119 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str9120 = external constant [16 x i8], align 1  ; <[16 x i8]*> [#uses=0]
+ at .str10121 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+ at .str11122 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str12123 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+ at .str13124 = external constant [27 x i8], align 1 ; <[27 x i8]*> [#uses=0]
+ at .str14125 = external constant [6 x i8], align 1  ; <[6 x i8]*> [#uses=0]
+ at .str15126 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+ at .str16127 = external constant [2 x i8], align 1  ; <[2 x i8]*> [#uses=0]
+ at .str17128 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str18129 = external constant [30 x i8], align 1 ; <[30 x i8]*> [#uses=0]
+ at .str19130 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+ at .str20131 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str21132 = external constant [9 x i8], align 1  ; <[9 x i8]*> [#uses=0]
+ at .str22133 = external constant [2 x i8], align 1  ; <[2 x i8]*> [#uses=0]
+ at watchout = external global i32                   ; <i32*> [#uses=0]
+ at once = external global i32                       ; <i32*> [#uses=0]
+ at .str23134 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+ at .str24135 = external constant [9 x i8], align 1  ; <[9 x i8]*> [#uses=0]
+ at .str25136 = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0]
+ at .str26137 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str27138 = external constant [63 x i8], align 1 ; <[63 x i8]*> [#uses=0]
+ at .str28139 = external constant [61 x i8], align 1 ; <[61 x i8]*> [#uses=0]
+ at .str29140 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str30141 = external constant [19 x i8], align 1 ; <[19 x i8]*> [#uses=0]
+ at .str31142 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str32143 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+ at .str33144 = external constant [3 x i8], align 1  ; <[3 x i8]*> [#uses=0]
+ at .str34 = external constant [12 x i8], align 1    ; <[12 x i8]*> [#uses=0]
+ at .str35 = external constant [23 x i8], align 1    ; <[23 x i8]*> [#uses=0]
+ at .str36 = external constant [23 x i8], align 1    ; <[23 x i8]*> [#uses=0]
+ at .str37 = external constant [5 x i8], align 1     ; <[5 x i8]*> [#uses=0]
+ at __stderrp = external global %struct.FILE*        ; <%struct.FILE**> [#uses=0]
+ at .str38 = external constant [44 x i8], align 1    ; <[44 x i8]*> [#uses=0]
+ at .str39 = external constant [16 x i8], align 1    ; <[16 x i8]*> [#uses=0]
+ at topat = external global [20 x i32]               ; <[20 x i32]*> [#uses=0]
+ at .str40 = external constant [22 x i8], align 1    ; <[22 x i8]*> [#uses=0]
+ at .str41 = external constant [10 x i8], align 1    ; <[10 x i8]*> [#uses=0]
+ at .str42 = external constant [12 x i8], align 1    ; <[12 x i8]*> [#uses=0]
+ at .str43145 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+ at .str149 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at useln = external global i32                      ; <i32*> [#uses=0]
+ at .str1150 = external constant [1 x i8], align 1   ; <[1 x i8]*> [#uses=0]
+ at .str2151 = external constant [26 x i8], align 1  ; <[26 x i8]*> [#uses=0]
+ at .str3152 = external constant [32 x i8], align 1  ; <[32 x i8]*> [#uses=0]
+ at spcount = external global i32                    ; <i32*> [#uses=0]
+ at tpcount = external global i32                    ; <i32*> [#uses=0]
+ at thisvec = external global i8*                    ; <i8**> [#uses=0]
+ at tpvecs = external global [50 x i8*]              ; <[50 x i8*]*> [#uses=0]
+ at .str156 = external constant [21 x i8], align 1   ; <[21 x i8]*> [#uses=0]
+ at spvecs = external global [20 x i8*]              ; <[20 x i8*]*> [#uses=0]
+ at .str1157 = external constant [29 x i8], align 1  ; <[29 x i8]*> [#uses=0]
+ at .str2158 = external constant [24 x i8], align 1  ; <[24 x i8]*> [#uses=0]
+ at .str164 = external constant [71 x i8], align 1   ; <[71 x i8]*> [#uses=0]
+ at .str1165 = external constant [71 x i8], align 1  ; <[71 x i8]*> [#uses=0]
+ at .str2166 = external constant [47 x i8], align 1  ; <[47 x i8]*> [#uses=0]
+ at .str169 = external constant [18 x i8], align 1   ; <[18 x i8]*> [#uses=0]
+ at backp = external global i8*                      ; <i8**> [#uses=0]
+ at backup = external global [500 x i8]              ; <[500 x i8]*> [#uses=0]
+ at .str1170 = external constant [15 x i8], align 1  ; <[15 x i8]*> [#uses=0]
+ at .str2171 = external constant [16 x i8], align 1  ; <[16 x i8]*> [#uses=0]
+ at .str176 = external constant [5 x i8], align 1    ; <[5 x i8]*> [#uses=0]
+ at .str1177 = external constant [35 x i8], align 1  ; <[35 x i8]*> [#uses=0]
+ at .str2178 = external constant [11 x i8], align 1  ; <[11 x i8]*> [#uses=0]
+ at .str3179 = external constant [33 x i8], align 1  ; <[33 x i8]*> [#uses=0]
+ at .str4180 = external constant [36 x i8], align 1  ; <[36 x i8]*> [#uses=0]
+ at .str5181 = external constant [11 x i8], align 1  ; <[11 x i8]*> [#uses=0]
+ at .str6182 = external constant [9 x i8], align 1   ; <[9 x i8]*> [#uses=0]
+ at .str7183 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str8184 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str9185 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str10186 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+ at .str11187 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str12188 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str13189 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str14190 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str15191 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+ at .str16192 = external constant [4 x i8], align 1  ; <[4 x i8]*> [#uses=0]
+ at .str17193 = external constant [5 x i8], align 1  ; <[5 x i8]*> [#uses=0]
+ at .str18194 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+ at .str19195 = external constant [19 x i8], align 1 ; <[19 x i8]*> [#uses=0]
+ at .str203 = external constant [5 x i8], align 1    ; <[5 x i8]*> [#uses=0]
+ at .str1204 = external constant [12 x i8], align 1  ; <[12 x i8]*> [#uses=0]
+ at .str2205 = external constant [31 x i8], align 1  ; <[31 x i8]*> [#uses=0]
+ at .str3206 = external constant [15 x i8], align 1  ; <[15 x i8]*> [#uses=0]
+ at .str4207 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str5208 = external constant [10 x i8], align 1  ; <[10 x i8]*> [#uses=0]
+ at .str6209 = external constant [5 x i8], align 1   ; <[5 x i8]*> [#uses=0]
+ at .str7210 = external constant [9 x i8], align 1   ; <[9 x i8]*> [#uses=0]
+ at .str8211 = external constant [21 x i8], align 1  ; <[21 x i8]*> [#uses=0]
+ at .str9212 = external constant [11 x i8], align 1  ; <[11 x i8]*> [#uses=0]
+ at .str10213 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str11214 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str12215 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str13216 = external constant [8 x i8], align 1  ; <[8 x i8]*> [#uses=0]
+ at .str14217 = external constant [37 x i8], align 1 ; <[37 x i8]*> [#uses=0]
+ at .str15218 = external constant [9 x i8], align 1  ; <[9 x i8]*> [#uses=0]
+ at .str16219 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+ at .str17220 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+ at .str18221 = external constant [9 x i8], align 1  ; <[9 x i8]*> [#uses=0]
+ at .str19222 = external constant [7 x i8], align 1  ; <[7 x i8]*> [#uses=0]
+ at .str20223 = external constant [3 x i8], align 1  ; <[3 x i8]*> [#uses=0]
+ at .str21224 = external constant [4 x i8], align 1  ; <[4 x i8]*> [#uses=0]
+ at .str22225 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+ at .str23226 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+ at .str24227 = external constant [5 x i8], align 1  ; <[5 x i8]*> [#uses=0]
+ at .str25228 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str26229 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str27230 = external constant [4 x i8], align 1  ; <[4 x i8]*> [#uses=0]
+ at .str28231 = external constant [7 x i8], align 1  ; <[7 x i8]*> [#uses=0]
+ at .str242 = external constant [7 x i8], align 1    ; <[7 x i8]*> [#uses=0]
+ at .str1243 = external constant [25 x i8], align 1  ; <[25 x i8]*> [#uses=0]
+ at .str252 = external constant [4 x i8], align 1    ; <[4 x i8]*> [#uses=0]
+ at .str1253 = external constant [1 x i8], align 1   ; <[1 x i8]*> [#uses=0]
+ at .str2254 = external constant [9 x i8], align 1   ; <[9 x i8]*> [#uses=0]
+ at .str3255 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str4256 = external constant [3 x i8], align 1   ; <[3 x i8]*> [#uses=0]
+ at .str5257 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str6258 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str7259 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str8260 = external constant [12 x i8], align 1  ; <[12 x i8]*> [#uses=0]
+ at .str9261 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str10262 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str11263 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str12264 = external constant [5 x i8], align 1  ; <[5 x i8]*> [#uses=0]
+ at .str13265 = external constant [2 x i8], align 1  ; <[2 x i8]*> [#uses=0]
+ at .str14266 = external constant [5 x i8], align 1  ; <[5 x i8]*> [#uses=0]
+ at .str15267 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+ at .str16268 = external constant [29 x i8], align 1 ; <[29 x i8]*> [#uses=0]
+ at .str17269 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+ at .str18270 = external constant [4 x i8], align 1  ; <[4 x i8]*> [#uses=0]
+ at .str19271 = external constant [9 x i8], align 1  ; <[9 x i8]*> [#uses=0]
+ at .str20272 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+ at .str21273 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+ at .str282 = external constant [8 x i8], align 1    ; <[8 x i8]*> [#uses=0]
+ at .str1283 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str2284 = external constant [4 x i8], align 1   ; <[4 x i8]*> [#uses=0]
+ at .str3285 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str4286 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str5287 = external constant [8 x i8], align 1   ; <[8 x i8]*> [#uses=0]
+ at .str6288 = external constant [15 x i8], align 1  ; <[15 x i8]*> [#uses=0]
+ at .str7289 = external constant [12 x i8], align 1  ; <[12 x i8]*> [#uses=0]
+ at .str8290 = external constant [3 x i8], align 1   ; <[3 x i8]*> [#uses=0]
+ at .str9291 = external constant [7 x i8], align 1   ; <[7 x i8]*> [#uses=0]
+ at .str10292 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+ at .str11293 = external constant [6 x i8], align 1  ; <[6 x i8]*> [#uses=0]
+ at .str12294 = external constant [2 x i8], align 1  ; <[2 x i8]*> [#uses=0]
+ at .str13295 = external constant [1 x i8], align 1  ; <[1 x i8]*> [#uses=0]
+ at .str14296 = external constant [6 x i8], align 1  ; <[6 x i8]*> [#uses=0]
+ at .str15297 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+ at .str16298 = external constant [4 x i8], align 1  ; <[4 x i8]*> [#uses=0]
+ at .str17299 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+
+declare arm_apcscc void @main(i32, i8**) noreturn nounwind
+
+declare arm_apcscc i32 @swapin() nounwind
+
+declare arm_apcscc %struct.FILE* @"\01_fopen"(i8*, i8*)
+
+declare arm_apcscc void @setinp(i32, i8**) nounwind
+
+declare arm_apcscc i32 @tbl(i32, i8**) nounwind
+
+declare arm_apcscc i32 @fprintf(%struct.FILE* nocapture, i8* nocapture, ...) nounwind
+
+declare arm_apcscc i32 @fclose(%struct.FILE* nocapture) nounwind
+
+declare arm_apcscc void @exit(i32) noreturn nounwind
+
+declare arm_apcscc void @tableput() nounwind
+
+declare arm_apcscc void @init_options() nounwind
+
+declare arm_apcscc void @backrest(i8*) nounwind
+
+declare arm_apcscc void @getcomm() nounwind
+
+declare arm_apcscc i32 @printf(i8* nocapture, ...) nounwind
+
+declare arm_apcscc i8* @strchr(i8*, i32) nounwind readonly
+
+declare arm_apcscc i32 @strlen(i8* nocapture) nounwind readonly
+
+declare arm_apcscc void @getspec() nounwind
+
+declare arm_apcscc void @readspec() nounwind
+
+declare arm_apcscc i32 @"\01_fwrite"(i8*, i32, i32, i8*)
+
+declare arm_apcscc i32 @atoi(i8* nocapture) nounwind readonly
+
+declare arm_apcscc i32 @fputc(i32, i8* nocapture) nounwind
+
+declare arm_apcscc void @gettbl() nounwind
+
+declare arm_apcscc i32 @vspen(i8*) nounwind readonly
+
+declare arm_apcscc i32 @vspand(i32, i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @oneh(i32) nounwind readonly
+
+declare arm_apcscc i32 @nodata(i32) nounwind readonly
+
+declare arm_apcscc i32 @permute() nounwind
+
+declare arm_apcscc void @maktab() nounwind
+
+declare arm_apcscc i32 @filler(i8*) nounwind readonly
+
+declare arm_apcscc void @wide(i8*, i8*, i8*) nounwind
+
+declare arm_apcscc i32 @"\01_fputs"(i8*, i8*)
+
+declare arm_apcscc void @runout() nounwind
+
+declare arm_apcscc void @need() nounwind
+
+declare arm_apcscc void @deftail() nounwind
+
+declare arm_apcscc i32 @ifline(i8*) nounwind readonly
+
+declare arm_apcscc void @runtabs(i32, i32) nounwind
+
+declare arm_apcscc void @putline(i32, i32) nounwind
+
+declare arm_apcscc void @putsize(i8*) nounwind
+
+declare arm_apcscc void @putfont(i8*) nounwind
+
+declare arm_apcscc i32 @__maskrune(i32, i32)
+
+declare arm_apcscc void @funnies(i32, i32) nounwind
+
+declare arm_apcscc void @puttext(i8*, i8*, i8*) nounwind
+
+declare arm_apcscc i32 @puts(i8* nocapture) nounwind
+
+declare arm_apcscc void @yetmore() nounwind
+
+declare arm_apcscc i32 @domore(i8*) nounwind
+
+declare arm_apcscc void @checkuse() nounwind
+
+declare arm_apcscc void @release() nounwind
+
+declare arm_apcscc i32* @alocv(i32) nounwind
+
+declare arm_apcscc i8* @calloc(...)
+
+declare arm_apcscc i8* @chspace() nounwind
+
+declare arm_apcscc i32 @real(i8*) nounwind readonly
+
+declare arm_apcscc void @choochar() nounwind
+
+declare arm_apcscc i32 @point(i32) nounwind readnone
+
+declare arm_apcscc void @error(i8*) nounwind
+
+declare arm_apcscc i8* @gets1(i8*) nounwind
+
+declare arm_apcscc i8* @fgets(i8*, i32, %struct.FILE* nocapture) nounwind
+
+declare arm_apcscc i32 @get1char() nounwind
+
+declare arm_apcscc i32 @getc(%struct.FILE* nocapture) nounwind
+
+declare arm_apcscc void @un1getc(i32) nounwind
+
+declare arm_apcscc void @savefill() nounwind
+
+declare arm_apcscc void @cleanfc() nounwind
+
+declare arm_apcscc void @saveline() nounwind
+
+declare arm_apcscc void @ifdivert() nounwind
+
+declare arm_apcscc void @restline() nounwind
+
+declare arm_apcscc void @endoff() nounwind
+
+declare arm_apcscc void @rstofill() nounwind
+
+declare arm_apcscc i32 @gettext(i8* nocapture, i32, i32, i8*, i8*) nounwind
+
+declare arm_apcscc void @untext() nounwind
+
+declare arm_apcscc i32 @interv(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @up1(i32) nounwind readonly
+
+declare arm_apcscc i32 @interh(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @maknew(i8*) nounwind
+
+define arm_apcscc i32 @ineqn(i8* %s, i8* %p) nounwind readonly {
+entry:
+  %0 = load i32* @delim1, align 4                 ; <i32> [#uses=1]
+  %1 = load i32* @delim2, align 4                 ; <i32> [#uses=1]
+  br label %bb8.outer
+
+bb:                                               ; preds = %bb8
+  %2 = icmp eq i8* %p_addr.0, %s                  ; <i1> [#uses=1]
+  br i1 %2, label %bb10, label %bb2
+
+bb2:                                              ; preds = %bb
+  %3 = getelementptr inbounds i8* %p_addr.0, i32 1 ; <i8*> [#uses=3]
+  switch i32 %ineq.0.ph, label %bb8.backedge [
+    i32 0, label %bb3
+    i32 1, label %bb6
+  ]
+
+bb8.backedge:                                     ; preds = %bb6, %bb5, %bb2
+  br label %bb8
+
+bb3:                                              ; preds = %bb2
+  %4 = icmp eq i32 %8, %0                         ; <i1> [#uses=1]
+  br i1 %4, label %bb8.outer.loopexit, label %bb5
+
+bb5:                                              ; preds = %bb3
+  br i1 %6, label %bb6, label %bb8.backedge
+
+bb6:                                              ; preds = %bb5, %bb2
+  %5 = icmp eq i32 %8, %1                         ; <i1> [#uses=1]
+  br i1 %5, label %bb7, label %bb8.backedge
+
+bb7:                                              ; preds = %bb6
+  %.lcssa1 = phi i8* [ %3, %bb6 ]                 ; <i8*> [#uses=1]
+  br label %bb8.outer.backedge
+
+bb8.outer.backedge:                               ; preds = %bb8.outer.loopexit, %bb7
+  %.lcssa2 = phi i8* [ %.lcssa1, %bb7 ], [ %.lcssa, %bb8.outer.loopexit ] ; <i8*> [#uses=1]
+  %ineq.0.ph.be = phi i32 [ 0, %bb7 ], [ 1, %bb8.outer.loopexit ] ; <i32> [#uses=1]
+  br label %bb8.outer
+
+bb8.outer.loopexit:                               ; preds = %bb3
+  %.lcssa = phi i8* [ %3, %bb3 ]                  ; <i8*> [#uses=1]
+  br label %bb8.outer.backedge
+
+bb8.outer:                                        ; preds = %bb8.outer.backedge, %entry
+  %ineq.0.ph = phi i32 [ 0, %entry ], [ %ineq.0.ph.be, %bb8.outer.backedge ] ; <i32> [#uses=3]
+  %p_addr.0.ph = phi i8* [ %p, %entry ], [ %.lcssa2, %bb8.outer.backedge ] ; <i8*> [#uses=1]
+  %6 = icmp eq i32 %ineq.0.ph, 1                  ; <i1> [#uses=1]
+  br label %bb8
+
+bb8:                                              ; preds = %bb8.outer, %bb8.backedge
+  %p_addr.0 = phi i8* [ %p_addr.0.ph, %bb8.outer ], [ %3, %bb8.backedge ] ; <i8*> [#uses=3]
+  %7 = load i8* %p_addr.0, align 1                ; <i8> [#uses=2]
+  %8 = sext i8 %7 to i32                          ; <i32> [#uses=2]
+  %9 = icmp eq i8 %7, 0                           ; <i1> [#uses=1]
+  br i1 %9, label %bb10, label %bb
+
+bb10:                                             ; preds = %bb8, %bb
+  %.0 = phi i32 [ %ineq.0.ph, %bb ], [ 0, %bb8 ]  ; <i32> [#uses=1]
+  ret i32 %.0
+}
+
+declare arm_apcscc i32 @match(i8* nocapture, i8* nocapture) nounwind readonly
+
+declare arm_apcscc i32 @prefix(i8* nocapture, i8* nocapture) nounwind readonly
+
+declare arm_apcscc i32 @letter(i32) nounwind readnone
+
+declare arm_apcscc i32 @numb(i8* nocapture) nounwind readonly
+
+declare arm_apcscc i32 @digit(i32) nounwind readnone
+
+declare arm_apcscc i32 @max(i32, i32) nounwind readnone
+
+declare arm_apcscc void @tcopy(i8* nocapture, i8* nocapture) nounwind
+
+declare arm_apcscc i32 @ctype(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @min(i32, i32) nounwind readnone
+
+declare arm_apcscc i32 @fspan(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @lspan(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @ctspan(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @thish(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @allh(i32) nounwind readonly
+
+declare arm_apcscc void @tohcol(i32) nounwind
+
+declare arm_apcscc void @makeline(i32, i32, i32) nounwind
+
+declare arm_apcscc i32 @next(i32) nounwind readonly
+
+declare arm_apcscc i32 @prev(i32) nounwind readonly
+
+declare arm_apcscc i32 @lefdata(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @left(i32, i32, i32* nocapture) nounwind
+
+declare arm_apcscc i32 @strcmp(i8* nocapture, i8* nocapture) nounwind readonly
+
+declare arm_apcscc void @getstop() nounwind
+
+declare arm_apcscc void @drawline(i32, i32, i32, i32, i32, i32) nounwind
+
+declare arm_apcscc void @fullwide(i32, i32) nounwind
+
+declare arm_apcscc void @drawvert(i32, i32, i32, i32) nounwind
+
+declare arm_apcscc i32 @barent(i8*) nounwind readonly
+
+declare arm_apcscc i32 @midbcol(i32, i32) nounwind readonly
+
+declare arm_apcscc i32 @midbar(i32, i32) nounwind readonly
+
+
+; This is a simplified form of ineqn from above. It triggers some
+; different cases in the loop-unswitch code.
+
+define void @simplified_ineqn() nounwind readonly {
+entry:
+  br label %bb8.outer
+
+bb8.outer:                                        ; preds = %bb6, %bb2, %entry
+  %x = phi i32 [ 0, %entry ], [ 0, %bb6 ], [ 1, %bb2 ] ; <i32> [#uses=1]
+  br i1 undef, label %return, label %bb2
+
+bb2:                                              ; preds = %bb
+  switch i32 %x, label %bb6 [
+    i32 0, label %bb8.outer
+  ]
+
+bb6:                                              ; preds = %bb2
+  br i1 undef, label %bb8.outer, label %bb2
+
+return:                                             ; preds = %bb8, %bb
+  ret void
+}





More information about the llvm-commits mailing list