- Add 'LoopTarget' pointer field to CFGBlock. This records if the block is used
  as the 'loop back' path back to the head of a loop.
- For ForStmt, encode the loop back target as the increment code.

llvm-svn: 70274
This commit is contained in:
Ted Kremenek 2009-04-28 00:51:56 +00:00
parent 5d72d41189
commit 902393b4b7
2 changed files with 28 additions and 14 deletions

View File

@ -61,12 +61,17 @@ class CFGBlock {
/// Label - An (optional) label that prefixes the executable
/// statements in the block. When this variable is non-NULL, it is
/// either an instance of LabelStmt or SwitchCase.
Stmt* Label;
Stmt *Label;
/// Terminator - The terminator for a basic block that
/// indicates the type of control-flow that occurs between a block
/// and its successors.
Stmt* Terminator;
Stmt *Terminator;
/// LoopTarget - Some blocks are used to represent the "loop edge" to
/// the start of a loop from within the loop body. This Stmt* will be
/// refer to the loop statement for such blocks (and be null otherwise).
const Stmt *LoopTarget;
/// BlockID - A numerical ID assigned to a CFGBlock during construction
/// of the CFG.
@ -80,7 +85,7 @@ class CFGBlock {
public:
explicit CFGBlock(unsigned blockid) : Label(NULL), Terminator(NULL),
BlockID(blockid) {}
LoopTarget(NULL), BlockID(blockid) {}
~CFGBlock() {};
// Statement iterators
@ -149,6 +154,7 @@ public:
void appendStmt(Stmt* Statement) { Stmts.push_back(Statement); }
void setTerminator(Stmt* Statement) { Terminator = Statement; }
void setLabel(Stmt* Statement) { Label = Statement; }
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
Stmt* getTerminator() { return Terminator; }
const Stmt* getTerminator() const { return Terminator; }
@ -159,6 +165,8 @@ public:
return const_cast<CFGBlock*>(this)->getTerminatorCondition();
}
const Stmt *getLoopTarget() const { return LoopTarget; }
bool hasBinaryBranchTerminator() const;
Stmt* getLabel() { return Label; }

View File

@ -752,21 +752,27 @@ CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
// Generate increment code in its own basic block. This is the target
// of continue statements.
Succ = Visit(I);
// Finish up the increment block if it hasn't been already.
if (Block) {
assert (Block == Succ);
FinishBlock(Block);
Block = 0;
}
ContinueTargetBlock = Succ;
}
else {
// No increment code. Continues should go the the entry condition block.
ContinueTargetBlock = EntryConditionBlock;
// No increment code. Create a special, empty, block that is used as
// the target block for "looping back" to the start of the loop.
assert(Succ == EntryConditionBlock);
Succ = createBlock();
}
// Finish up the increment (or empty) block if it hasn't been already.
if (Block) {
assert(Block == Succ);
FinishBlock(Block);
Block = 0;
}
ContinueTargetBlock = Succ;
// The starting block for the loop increment is the block that should
// represent the 'loop target' for looping back to the start of the loop.
ContinueTargetBlock->setLoopTarget(F);
// All breaks should go to the code following the loop.
BreakTargetBlock = LoopSuccessor;