use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class CFGTranslationPhaseThree method process.
/**
* Perform phase three on the control flow graph {@code cfg}.
*
* @param cfg the control flow graph. Ownership is transfered to this method and the caller is not
* allowed to read or modify {@code cfg} after the call to {@code process} any more.
* @return the resulting control flow graph
*/
// TODO: successors
@SuppressWarnings("nullness")
public static ControlFlowGraph process(ControlFlowGraph cfg) {
Set<Block> worklist = cfg.getAllBlocks();
Set<Block> dontVisit = new HashSet<>();
// fix predecessor lists by removing any unreachable predecessors
for (Block c : worklist) {
BlockImpl cur = (BlockImpl) c;
for (Block pred : new HashSet<>(cur.getPredecessors())) {
if (!worklist.contains(pred)) {
cur.removePredecessor((BlockImpl) pred);
}
}
}
// remove empty blocks
for (Block cur : worklist) {
if (dontVisit.contains(cur)) {
continue;
}
if (cur.getType() == BlockType.REGULAR_BLOCK) {
RegularBlockImpl b = (RegularBlockImpl) cur;
if (b.isEmpty()) {
Set<RegularBlockImpl> emptyBlocks = new HashSet<>();
Set<PredecessorHolder> predecessors = new LinkedHashSet<>();
BlockImpl succ = computeNeighborhoodOfEmptyBlock(b, emptyBlocks, predecessors);
for (RegularBlockImpl e : emptyBlocks) {
succ.removePredecessor(e);
dontVisit.add(e);
}
for (PredecessorHolder p : predecessors) {
BlockImpl block = p.getBlock();
dontVisit.add(block);
succ.removePredecessor(block);
p.setSuccessor(succ);
}
}
}
}
// remove useless conditional blocks
/* Issue 3267 revealed that this is a dangerous optimization:
it merges a block that evaluates one condition onto an unrelated following block,
which can also be a condition. The then/else stores from the first block are still
set, leading to incorrect results for the then/else stores in the following block.
The correct result would be to merge the then/else stores from the previous block.
However, as this is late in the CFG construction, I didn't see how to add e.g. a
dummy variable declaration node in a dummy regular block, which would cause a merge.
So for now, let's not perform this optimization.
It would be interesting to know how large the impact of this optimization is.
worklist = cfg.getAllBlocks();
for (Block c : worklist) {
BlockImpl cur = (BlockImpl) c;
if (cur.getType() == BlockType.CONDITIONAL_BLOCK) {
ConditionalBlockImpl cb = (ConditionalBlockImpl) cur;
assert cb.getPredecessors().size() == 1;
if (cb.getThenSuccessor() == cb.getElseSuccessor()) {
BlockImpl pred = cb.getPredecessors().iterator().next();
PredecessorHolder predecessorHolder = getPredecessorHolder(pred, cb);
BlockImpl succ = (BlockImpl) cb.getThenSuccessor();
succ.removePredecessor(cb);
predecessorHolder.setSuccessor(succ);
}
}
}
*/
// merge consecutive basic blocks if possible
worklist = cfg.getAllBlocks();
for (Block cur : worklist) {
if (cur.getType() == BlockType.REGULAR_BLOCK) {
RegularBlockImpl b = (RegularBlockImpl) cur;
Block succ = b.getRegularSuccessor();
if (succ.getType() == BlockType.REGULAR_BLOCK) {
RegularBlockImpl rs = (RegularBlockImpl) succ;
if (rs.getPredecessors().size() == 1) {
b.setSuccessor(rs.getRegularSuccessor());
b.addNodes(rs.getNodes());
rs.getRegularSuccessor().removePredecessor(rs);
}
}
}
}
return cfg;
}
use of org.checkerframework.dataflow.cfg.block.Block in project checker-framework by typetools.
the class ControlFlowGraph method getDepthFirstOrderedBlocks.
/**
* Returns all basic blocks in this control flow graph, in reversed depth-first postorder. Blocks
* may appear more than once in the sequence.
*
* @return the list of all basic block in this control flow graph in reversed depth-first
* postorder sequence
*/
public List<Block> getDepthFirstOrderedBlocks() {
List<Block> dfsOrderResult = new ArrayList<>();
Set<Block> visited = new HashSet<>();
// worklist can contain values that are not yet in visited.
Deque<Block> worklist = new ArrayDeque<>();
worklist.add(entryBlock);
while (!worklist.isEmpty()) {
Block cur = worklist.getLast();
if (visited.contains(cur)) {
dfsOrderResult.add(cur);
worklist.removeLast();
} else {
visited.add(cur);
for (Block b : cur.getSuccessors()) {
if (!visited.contains(b)) {
worklist.add(b);
}
}
}
}
Collections.reverse(dfsOrderResult);
return dfsOrderResult;
}
Aggregations