summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Analysis/LoopInfo.h83
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h21
-rw-r--r--lib/Analysis/LoopInfo.cpp10
-rw-r--r--lib/Transforms/Scalar/LICM.cpp1
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp15
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp105
-rw-r--r--lib/Transforms/Utils/BasicBlockUtils.cpp92
-rw-r--r--lib/Transforms/Utils/BreakCriticalEdges.cpp75
-rw-r--r--lib/Transforms/Utils/LCSSA.cpp17
-rw-r--r--lib/Transforms/Utils/LoopSimplify.cpp40
-rw-r--r--test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll52
-rw-r--r--test/Transforms/LoopUnswitch/preserve-analyses.ll645
12 files changed, 959 insertions, 197 deletions
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h
index b803176..003930e 100644
--- a/include/llvm/Analysis/LoopInfo.h
+++ b/include/llvm/Analysis/LoopInfo.h
@@ -376,14 +376,85 @@ public:
/// 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 @@ public:
///
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;
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 95ffa46..e766d72 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -126,10 +126,10 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
/// 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 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) {
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 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) {
/// 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 @@ BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P);
/// 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);
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index b240579..665e53d 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -300,6 +300,9 @@ bool Loop::isLoopSimplifyForm() const {
///
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 @@ bool LoopInfo::runOnFunction(Function &) {
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>();
diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp
index 15bb9c7..1c29878 100644
--- a/lib/Transforms/Scalar/LICM.cpp
+++ b/lib/Transforms/Scalar/LICM.cpp
@@ -91,6 +91,7 @@ namespace {
AU.addRequired<AliasAnalysis>();
AU.addPreserved<ScalarEvolution>();
AU.addPreserved<DominanceFrontier>();
+ AU.addPreservedID(LoopSimplifyID);
}
bool doFinalization() {
diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 0bf62ec..82eb14f 100644
--- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -484,36 +484,37 @@ void BasedUser::RewriteInstructionToUseNewBase(const SCEV *const &NewBase,
// 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);
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp
index 8e7c91a..1662bdb 100644
--- a/lib/Transforms/Scalar/LoopUnswitch.cpp
+++ b/lib/Transforms/Scalar/LoopUnswitch.cpp
@@ -112,6 +112,10 @@ namespace {
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 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
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 @@ void LoopUnswitch::SplitExitEdges(Loop *L,
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 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC,
// 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;
}
}
diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp
index c165e04..736d26e 100644
--- a/lib/Transforms/Utils/BasicBlockUtils.cpp
+++ b/lib/Transforms/Utils/BasicBlockUtils.cpp
@@ -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 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) {
++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 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P) {
/// 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 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
// 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 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
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 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
// 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;
diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp
index 632aa2b..59350a7 100644
--- a/lib/Transforms/Utils/BreakCriticalEdges.cpp
+++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp
@@ -122,9 +122,9 @@ bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
/// 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 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
// 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 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
// 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 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
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;
}
diff --git a/lib/Transforms/Utils/LCSSA.cpp b/lib/Transforms/Utils/LCSSA.cpp
index 84fcc64..b510262 100644
--- a/lib/Transforms/Utils/LCSSA.cpp
+++ b/lib/Transforms/Utils/LCSSA.cpp
@@ -58,6 +58,7 @@ namespace {
DominatorTree *DT;
std::vector<BasicBlock*> LoopBlocks;
PredIteratorCache PredCache;
+ Loop *L;
virtual bool runOnLoop(Loop *L, LPPassManager &LPM);
@@ -72,9 +73,9 @@ namespace {
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 @@ namespace {
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 @@ Pass *llvm::createLCSSAPass() { return new LCSSA(); }
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>();
diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp
index 56e5a46..2ff9f8b 100644
--- a/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/lib/Transforms/Utils/LoopSimplify.cpp
@@ -69,8 +69,8 @@ namespace {
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 @@ namespace {
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 *LoopSimplify::InsertPreheaderForLoop(Loop *L) {
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 @@ BasicBlock *LoopSimplify::RewriteLoopExitBlock(Loop *L, BasicBlock *Exit) {
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 @@ Loop *LoopSimplify::SeparateNestedLoop(Loop *L) {
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 @@ Loop *LoopSimplify::SeparateNestedLoop(Loop *L) {
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;
diff --git a/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll b/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll
deleted file mode 100644
index 0258085..0000000
--- a/test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll
+++ /dev/null
@@ -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
-}
diff --git a/test/Transforms/LoopUnswitch/preserve-analyses.ll b/test/Transforms/LoopUnswitch/preserve-analyses.ll
new file mode 100644
index 0000000..6145bf5
--- /dev/null
+++ b/test/Transforms/LoopUnswitch/preserve-analyses.ll
@@ -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* }
+
+@expflg = external global i32 ; <i32*> [#uses=0]
+@ctrflg = external global i32 ; <i32*> [#uses=0]
+@boxflg = external global i32 ; <i32*> [#uses=0]
+@dboxflg = external global i32 ; <i32*> [#uses=0]
+@tab = external global i32 ; <i32*> [#uses=0]
+@F1 = external global i32 ; <i32*> [#uses=0]
+@F2 = external global i32 ; <i32*> [#uses=0]
+@allflg = external global i32 ; <i32*> [#uses=0]
+@leftover = external global i32 ; <i32*> [#uses=0]
+@textflg = external global i32 ; <i32*> [#uses=0]
+@left1flg = external global i32 ; <i32*> [#uses=0]
+@rightl = external global i32 ; <i32*> [#uses=0]
+@iline = external global i32 ; <i32*> [#uses=0]
+@ifile = external global i8* ; <i8**> [#uses=0]
+@.str = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@texname = external global i32 ; <i32*> [#uses=0]
+@texct = external global i32 ; <i32*> [#uses=0]
+@texstr = external global [63 x i8], align 4 ; <[63 x i8]*> [#uses=0]
+@nlin = external global i32 ; <i32*> [#uses=0]
+@ncol = external global i32 ; <i32*> [#uses=0]
+@nclin = external global i32 ; <i32*> [#uses=0]
+@nslin = external global i32 ; <i32*> [#uses=0]
+@style = external global [100 x [20 x i32]] ; <[100 x [20 x i32]]*> [#uses=0]
+@ctop = external global [100 x [20 x i32]] ; <[100 x [20 x i32]]*> [#uses=0]
+@font = external global [100 x [20 x [2 x i8]]] ; <[100 x [20 x [2 x i8]]]*> [#uses=0]
+@csize = external global [100 x [20 x [4 x i8]]] ; <[100 x [20 x [4 x i8]]]*> [#uses=0]
+@vsize = external global [100 x [20 x [4 x i8]]] ; <[100 x [20 x [4 x i8]]]*> [#uses=0]
+@cll = external global [20 x [10 x i8]] ; <[20 x [10 x i8]]*> [#uses=0]
+@stynum = external global [201 x i32] ; <[201 x i32]*> [#uses=0]
+@lefline = external global [100 x [20 x i32]] ; <[100 x [20 x i32]]*> [#uses=0]
+@fullbot = external global [200 x i32] ; <[200 x i32]*> [#uses=0]
+@instead = external global [200 x i8*] ; <[200 x i8*]*> [#uses=0]
+@evenflg = external global i32 ; <i32*> [#uses=0]
+@evenup = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@linsize = external global i32 ; <i32*> [#uses=0]
+@pr1403 = external global i32 ; <i32*> [#uses=0]
+@delim1 = external global i32 ; <i32*> [#uses=1]
+@delim2 = external global i32 ; <i32*> [#uses=1]
+@table = external global [200 x %struct.colstr*] ; <[200 x %struct.colstr*]*> [#uses=0]
+@cspace = external global i8* ; <i8**> [#uses=0]
+@cstore = external global i8* ; <i8**> [#uses=0]
+@exstore = external global i8* ; <i8**> [#uses=0]
+@exlim = external global i8* ; <i8**> [#uses=0]
+@sep = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@used = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@lused = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@rused = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@linestop = external global [200 x i32] ; <[200 x i32]*> [#uses=0]
+@last = external global i8* ; <i8**> [#uses=0]
+@linstart = external global i32 ; <i32*> [#uses=0]
+@tabin = external global %struct.FILE* ; <%struct.FILE**> [#uses=0]
+@tabout = external global %struct.FILE* ; <%struct.FILE**> [#uses=0]
+@sargc = external global i32 ; <i32*> [#uses=0]
+@sargv = external global i8** ; <i8***> [#uses=0]
+@.str1 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str12 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str2 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str3 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str4 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str5 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str6 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@__stdinp = external global %struct.FILE* ; <%struct.FILE**> [#uses=0]
+@__stdoutp = external global %struct.FILE* ; <%struct.FILE**> [#uses=0]
+@.str7 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str8 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@options = external global [21 x %struct.optstr] ; <[21 x %struct.optstr]*> [#uses=0]
+@.str9 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str110 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str211 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str312 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str413 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str514 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str615 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str716 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str817 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str918 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str10 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str11 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str1219 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str13 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str14 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str15 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str16 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str17 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str18 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str19 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str20 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str21 = external constant [25 x i8], align 1 ; <[25 x i8]*> [#uses=0]
+@.str22 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str23 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str24 = external constant [34 x i8], align 1 ; <[34 x i8]*> [#uses=0]
+@.str125 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str226 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+@.str327 = external constant [38 x i8], align 1 ; <[38 x i8]*> [#uses=0]
+@oncol = external global i32 ; <i32*> [#uses=0]
+@.str428 = external constant [40 x i8], align 1 ; <[40 x i8]*> [#uses=0]
+@.str529 = external constant [31 x i8], align 1 ; <[31 x i8]*> [#uses=0]
+@.str630 = external constant [51 x i8], align 1 ; <[51 x i8]*> [#uses=0]
+@.str731 = external constant [51 x i8], align 1 ; <[51 x i8]*> [#uses=0]
+@.str832 = external constant [40 x i8], align 1 ; <[40 x i8]*> [#uses=0]
+@.str933 = external constant [26 x i8], align 1 ; <[26 x i8]*> [#uses=0]
+@.str1034 = external constant [24 x i8], align 1 ; <[24 x i8]*> [#uses=0]
+@.str1135 = external constant [21 x i8], align 1 ; <[21 x i8]*> [#uses=0]
+@.str1236 = external constant [24 x i8], align 1 ; <[24 x i8]*> [#uses=0]
+@.str1337 = external constant [33 x i8], align 1 ; <[33 x i8]*> [#uses=0]
+@.str1438 = external constant [22 x i8], align 1 ; <[22 x i8]*> [#uses=0]
+@.str1539 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str1640 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str1741 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@_DefaultRuneLocale = external global %struct._RuneLocale ; <%struct._RuneLocale*> [#uses=0]
+@.str43 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str144 = external constant [43 x i8], align 1 ; <[43 x i8]*> [#uses=0]
+@.str245 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str346 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str447 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str548 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str649 = external constant [1 x i8], align 1 ; <[1 x i8]*> [#uses=0]
+@.str51 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str152 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str253 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str354 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str455 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str556 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str657 = external constant [19 x i8], align 1 ; <[19 x i8]*> [#uses=0]
+@.str758 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str859 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str960 = external constant [30 x i8], align 1 ; <[30 x i8]*> [#uses=0]
+@.str1061 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+@.str1162 = external constant [35 x i8], align 1 ; <[35 x i8]*> [#uses=0]
+@.str1263 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str1364 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+@.str1465 = external constant [30 x i8], align 1 ; <[30 x i8]*> [#uses=0]
+@.str1566 = external constant [41 x i8], align 1 ; <[41 x i8]*> [#uses=0]
+@.str1667 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str1768 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str1869 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str1970 = external constant [29 x i8], align 1 ; <[29 x i8]*> [#uses=0]
+@.str2071 = external constant [22 x i8], align 1 ; <[22 x i8]*> [#uses=0]
+@.str2172 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+@.str2273 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str2374 = external constant [36 x i8], align 1 ; <[36 x i8]*> [#uses=0]
+@.str2475 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str25 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str26 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+@.str27 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+@.str28 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str29 = external constant [25 x i8], align 1 ; <[25 x i8]*> [#uses=0]
+@.str30 = external constant [24 x i8], align 1 ; <[24 x i8]*> [#uses=0]
+@.str31 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str32 = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0]
+@.str33 = external constant [79 x i8], align 1 ; <[79 x i8]*> [#uses=0]
+@.str77 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str178 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str279 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str380 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str481 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str582 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str683 = external constant [33 x i8], align 1 ; <[33 x i8]*> [#uses=0]
+@.str784 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str885 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str986 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str1087 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+@.str1188 = external constant [29 x i8], align 1 ; <[29 x i8]*> [#uses=0]
+@.str1289 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str1390 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str1491 = external constant [22 x i8], align 1 ; <[22 x i8]*> [#uses=0]
+@.str1592 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str1693 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str1794 = external constant [21 x i8], align 1 ; <[21 x i8]*> [#uses=0]
+@.str1895 = external constant [25 x i8], align 1 ; <[25 x i8]*> [#uses=0]
+@.str1996 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str2097 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str2198 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str2299 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str23100 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str24101 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str25102 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str26103 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str27104 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str28105 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str29106 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str30107 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str31108 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str111 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str1112 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str2113 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str3114 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str4115 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str5116 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str6117 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str7118 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+@.str8119 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str9120 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str10121 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str11122 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str12123 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str13124 = external constant [27 x i8], align 1 ; <[27 x i8]*> [#uses=0]
+@.str14125 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str15126 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str16127 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str17128 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str18129 = external constant [30 x i8], align 1 ; <[30 x i8]*> [#uses=0]
+@.str19130 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str20131 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str21132 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str22133 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@watchout = external global i32 ; <i32*> [#uses=0]
+@once = external global i32 ; <i32*> [#uses=0]
+@.str23134 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+@.str24135 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str25136 = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0]
+@.str26137 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str27138 = external constant [63 x i8], align 1 ; <[63 x i8]*> [#uses=0]
+@.str28139 = external constant [61 x i8], align 1 ; <[61 x i8]*> [#uses=0]
+@.str29140 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str30141 = external constant [19 x i8], align 1 ; <[19 x i8]*> [#uses=0]
+@.str31142 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str32143 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str33144 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str34 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str35 = external constant [23 x i8], align 1 ; <[23 x i8]*> [#uses=0]
+@.str36 = external constant [23 x i8], align 1 ; <[23 x i8]*> [#uses=0]
+@.str37 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@__stderrp = external global %struct.FILE* ; <%struct.FILE**> [#uses=0]
+@.str38 = external constant [44 x i8], align 1 ; <[44 x i8]*> [#uses=0]
+@.str39 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@topat = external global [20 x i32] ; <[20 x i32]*> [#uses=0]
+@.str40 = external constant [22 x i8], align 1 ; <[22 x i8]*> [#uses=0]
+@.str41 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str42 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str43145 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str149 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@useln = external global i32 ; <i32*> [#uses=0]
+@.str1150 = external constant [1 x i8], align 1 ; <[1 x i8]*> [#uses=0]
+@.str2151 = external constant [26 x i8], align 1 ; <[26 x i8]*> [#uses=0]
+@.str3152 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@spcount = external global i32 ; <i32*> [#uses=0]
+@tpcount = external global i32 ; <i32*> [#uses=0]
+@thisvec = external global i8* ; <i8**> [#uses=0]
+@tpvecs = external global [50 x i8*] ; <[50 x i8*]*> [#uses=0]
+@.str156 = external constant [21 x i8], align 1 ; <[21 x i8]*> [#uses=0]
+@spvecs = external global [20 x i8*] ; <[20 x i8*]*> [#uses=0]
+@.str1157 = external constant [29 x i8], align 1 ; <[29 x i8]*> [#uses=0]
+@.str2158 = external constant [24 x i8], align 1 ; <[24 x i8]*> [#uses=0]
+@.str164 = external constant [71 x i8], align 1 ; <[71 x i8]*> [#uses=0]
+@.str1165 = external constant [71 x i8], align 1 ; <[71 x i8]*> [#uses=0]
+@.str2166 = external constant [47 x i8], align 1 ; <[47 x i8]*> [#uses=0]
+@.str169 = external constant [18 x i8], align 1 ; <[18 x i8]*> [#uses=0]
+@backp = external global i8* ; <i8**> [#uses=0]
+@backup = external global [500 x i8] ; <[500 x i8]*> [#uses=0]
+@.str1170 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str2171 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str176 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str1177 = external constant [35 x i8], align 1 ; <[35 x i8]*> [#uses=0]
+@.str2178 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str3179 = external constant [33 x i8], align 1 ; <[33 x i8]*> [#uses=0]
+@.str4180 = external constant [36 x i8], align 1 ; <[36 x i8]*> [#uses=0]
+@.str5181 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str6182 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str7183 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str8184 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str9185 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str10186 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str11187 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str12188 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str13189 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str14190 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str15191 = external constant [17 x i8], align 1 ; <[17 x i8]*> [#uses=0]
+@.str16192 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str17193 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str18194 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str19195 = external constant [19 x i8], align 1 ; <[19 x i8]*> [#uses=0]
+@.str203 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str1204 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str2205 = external constant [31 x i8], align 1 ; <[31 x i8]*> [#uses=0]
+@.str3206 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str4207 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str5208 = external constant [10 x i8], align 1 ; <[10 x i8]*> [#uses=0]
+@.str6209 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str7210 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str8211 = external constant [21 x i8], align 1 ; <[21 x i8]*> [#uses=0]
+@.str9212 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str10213 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str11214 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str12215 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str13216 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str14217 = external constant [37 x i8], align 1 ; <[37 x i8]*> [#uses=0]
+@.str15218 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str16219 = external constant [20 x i8], align 1 ; <[20 x i8]*> [#uses=0]
+@.str17220 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+@.str18221 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str19222 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str20223 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str21224 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str22225 = external constant [11 x i8], align 1 ; <[11 x i8]*> [#uses=0]
+@.str23226 = external constant [13 x i8], align 1 ; <[13 x i8]*> [#uses=0]
+@.str24227 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str25228 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str26229 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str27230 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str28231 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str242 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str1243 = external constant [25 x i8], align 1 ; <[25 x i8]*> [#uses=0]
+@.str252 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str1253 = external constant [1 x i8], align 1 ; <[1 x i8]*> [#uses=0]
+@.str2254 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str3255 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str4256 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str5257 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str6258 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str7259 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str8260 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str9261 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str10262 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str11263 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str12264 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str13265 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str14266 = external constant [5 x i8], align 1 ; <[5 x i8]*> [#uses=0]
+@.str15267 = external constant [16 x i8], align 1 ; <[16 x i8]*> [#uses=0]
+@.str16268 = external constant [29 x i8], align 1 ; <[29 x i8]*> [#uses=0]
+@.str17269 = external constant [14 x i8], align 1 ; <[14 x i8]*> [#uses=0]
+@.str18270 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str19271 = external constant [9 x i8], align 1 ; <[9 x i8]*> [#uses=0]
+@.str20272 = external constant [32 x i8], align 1 ; <[32 x i8]*> [#uses=0]
+@.str21273 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str282 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str1283 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str2284 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.str3285 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str4286 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str5287 = external constant [8 x i8], align 1 ; <[8 x i8]*> [#uses=0]
+@.str6288 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str7289 = external constant [12 x i8], align 1 ; <[12 x i8]*> [#uses=0]
+@.str8290 = external constant [3 x i8], align 1 ; <[3 x i8]*> [#uses=0]
+@.str9291 = external constant [7 x i8], align 1 ; <[7 x i8]*> [#uses=0]
+@.str10292 = external constant [15 x i8], align 1 ; <[15 x i8]*> [#uses=0]
+@.str11293 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str12294 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=0]
+@.str13295 = external constant [1 x i8], align 1 ; <[1 x i8]*> [#uses=0]
+@.str14296 = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0]
+@.str15297 = external constant [28 x i8], align 1 ; <[28 x i8]*> [#uses=0]
+@.str16298 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=0]
+@.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
+}