diff options
-rw-r--r-- | include/llvm/Analysis/LoopInfo.h | 83 | ||||
-rw-r--r-- | include/llvm/Transforms/Utils/BasicBlockUtils.h | 21 | ||||
-rw-r--r-- | lib/Analysis/LoopInfo.cpp | 10 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LICM.cpp | 1 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LoopStrengthReduce.cpp | 15 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LoopUnswitch.cpp | 105 | ||||
-rw-r--r-- | lib/Transforms/Utils/BasicBlockUtils.cpp | 92 | ||||
-rw-r--r-- | lib/Transforms/Utils/BreakCriticalEdges.cpp | 75 | ||||
-rw-r--r-- | lib/Transforms/Utils/LCSSA.cpp | 17 | ||||
-rw-r--r-- | lib/Transforms/Utils/LoopSimplify.cpp | 40 | ||||
-rw-r--r-- | test/Transforms/LoopUnswitch/2009-09-05-DomAssert.ll | 52 | ||||
-rw-r--r-- | test/Transforms/LoopUnswitch/preserve-analyses.ll | 645 |
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 +} |