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
This commit is contained in:
Dan Gohman 2009-09-08 15:45:00 +00:00
parent 6ca0b9e722
commit 5c89b5240c
12 changed files with 959 additions and 197 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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>();

View File

@ -91,6 +91,7 @@ namespace {
AU.addRequired<AliasAnalysis>();
AU.addPreserved<ScalarEvolution>();
AU.addPreserved<DominanceFrontier>();
AU.addPreservedID(LoopSimplifyID);
}
bool doFinalization() {

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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>();

View File

@ -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;

View File

@ -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
}

View File

@ -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
}