From: Dan Gohman Date: Tue, 8 Sep 2009 15:45:00 +0000 (+0000) Subject: Re-apply r80926, with fixes: keep the domtree informed of new blocks X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5c89b5240c90eb8171f999e5f06f815502d0321c;p=oota-llvm.git 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81221 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index b803176d889..003930ee45f 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 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 OutsideLoopPreds; + + typedef GraphTraits 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 > 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 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 95ffa460696..e766d729e1b 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 b2405792d63..665e53df6dc 100644 --- a/lib/Analysis/LoopInfo.cpp +++ b/lib/Analysis/LoopInfo.cpp @@ -300,6 +300,9 @@ bool Loop::isLoopSimplifyForm() const { /// void Loop::getUniqueExitBlocks(SmallVectorImpl &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 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(); diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index 15bb9c70dfe..1c298785da8 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -91,6 +91,7 @@ namespace { AU.addRequired(); AU.addPreserved(); AU.addPreserved(); + AU.addPreservedID(LoopSimplifyID); } bool doFinalization() { diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index 0bf62ec9064..82eb14fb2ae 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(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 8e7c91a3f28..1662bdbaef5 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 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 InsertedPHIs; - PHINode* OldLCSSA = 0; - for (BasicBlock::iterator I = EndBlock->begin(); - (OldLCSSA = dyn_cast(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(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 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(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(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 c165e04fb8a..736d26e75fb 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 @@ -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()) 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() : 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() : 0; if (DT) DT->splitBlock(NewBB); if (DominanceFrontier *DF = P ? P->getAnalysisIfAvailable():0) DF->splitBlock(NewBB); - AliasAnalysis *AA = P ? P->getAnalysisIfAvailable() : 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(I)->addIncoming(UndefValue::get(I->getType()), NewBB); return NewBB; } + + AliasAnalysis *AA = P ? P->getAnalysisIfAvailable() : 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(I); ) { PHINode *PN = cast(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 632aa2b723b..59350a71a73 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()) { - // 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 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 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(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(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 84fcc643bfb..b510262c05c 100644 --- a/lib/Transforms/Utils/LCSSA.cpp +++ b/lib/Transforms/Utils/LCSSA.cpp @@ -58,6 +58,7 @@ namespace { DominatorTree *DT; std::vector 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(); + AU.addRequiredTransitive(); AU.addPreserved(); - AU.addRequired(); + AU.addRequiredTransitive(); AU.addPreserved(); AU.addPreserved(); @@ -86,6 +87,15 @@ namespace { AU.addPreserved(); } 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 &AffectedValues, const SmallVector& 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(); diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 56e5a46cb78..2ff9f8be4bb 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(); - AU.addRequired(); + AU.addRequiredTransitive(); + AU.addRequiredTransitive(); AU.addPreserved(); AU.addPreserved(); @@ -83,9 +83,11 @@ namespace { void verifyAnalysis() const { #ifndef NDEBUG LoopInfo *NLI = &getAnalysis(); - 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 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 02580851ec6..00000000000 --- 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 ; [#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 ; [#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 00000000000..6145bf50b0b --- /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 ; [#uses=0] +@ctrflg = external global i32 ; [#uses=0] +@boxflg = external global i32 ; [#uses=0] +@dboxflg = external global i32 ; [#uses=0] +@tab = external global i32 ; [#uses=0] +@F1 = external global i32 ; [#uses=0] +@F2 = external global i32 ; [#uses=0] +@allflg = external global i32 ; [#uses=0] +@leftover = external global i32 ; [#uses=0] +@textflg = external global i32 ; [#uses=0] +@left1flg = external global i32 ; [#uses=0] +@rightl = external global i32 ; [#uses=0] +@iline = external global i32 ; [#uses=0] +@ifile = external global i8* ; [#uses=0] +@.str = external constant [6 x i8], align 1 ; <[6 x i8]*> [#uses=0] +@texname = external global i32 ; [#uses=0] +@texct = external global i32 ; [#uses=0] +@texstr = external global [63 x i8], align 4 ; <[63 x i8]*> [#uses=0] +@nlin = external global i32 ; [#uses=0] +@ncol = external global i32 ; [#uses=0] +@nclin = external global i32 ; [#uses=0] +@nslin = external global 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 ; [#uses=0] +@evenup = external global [20 x i32] ; <[20 x i32]*> [#uses=0] +@linsize = external global i32 ; [#uses=0] +@pr1403 = external global i32 ; [#uses=0] +@delim1 = external global i32 ; [#uses=1] +@delim2 = external global i32 ; [#uses=1] +@table = external global [200 x %struct.colstr*] ; <[200 x %struct.colstr*]*> [#uses=0] +@cspace = external global i8* ; [#uses=0] +@cstore = external global i8* ; [#uses=0] +@exstore = external global i8* ; [#uses=0] +@exlim = external global 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* ; [#uses=0] +@linstart = external global 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 ; [#uses=0] +@sargv = external global 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 ; [#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 ; [#uses=0] +@once = external global 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 ; [#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 ; [#uses=0] +@tpcount = external global i32 ; [#uses=0] +@thisvec = external global 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* ; [#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 ; [#uses=1] + %1 = load i32* @delim2, align 4 ; [#uses=1] + br label %bb8.outer + +bb: ; preds = %bb8 + %2 = icmp eq i8* %p_addr.0, %s ; [#uses=1] + br i1 %2, label %bb10, label %bb2 + +bb2: ; preds = %bb + %3 = getelementptr inbounds i8* %p_addr.0, i32 1 ; [#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 ; [#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 ; [#uses=1] + br i1 %5, label %bb7, label %bb8.backedge + +bb7: ; preds = %bb6 + %.lcssa1 = phi i8* [ %3, %bb6 ] ; [#uses=1] + br label %bb8.outer.backedge + +bb8.outer.backedge: ; preds = %bb8.outer.loopexit, %bb7 + %.lcssa2 = phi i8* [ %.lcssa1, %bb7 ], [ %.lcssa, %bb8.outer.loopexit ] ; [#uses=1] + %ineq.0.ph.be = phi i32 [ 0, %bb7 ], [ 1, %bb8.outer.loopexit ] ; [#uses=1] + br label %bb8.outer + +bb8.outer.loopexit: ; preds = %bb3 + %.lcssa = phi i8* [ %3, %bb3 ] ; [#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 ] ; [#uses=3] + %p_addr.0.ph = phi i8* [ %p, %entry ], [ %.lcssa2, %bb8.outer.backedge ] ; [#uses=1] + %6 = icmp eq i32 %ineq.0.ph, 1 ; [#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 ] ; [#uses=3] + %7 = load i8* %p_addr.0, align 1 ; [#uses=2] + %8 = sext i8 %7 to i32 ; [#uses=2] + %9 = icmp eq i8 %7, 0 ; [#uses=1] + br i1 %9, label %bb10, label %bb + +bb10: ; preds = %bb8, %bb + %.0 = phi i32 [ %ineq.0.ph, %bb ], [ 0, %bb8 ] ; [#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 ] ; [#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 +}