private void findNonCanonicalRegions(RPST rpst, Region region) { Set<Region> childrenBefore = new HashSet<>(rpst.getChildren(region)); if (rpst.getChildCount(region) > 1) { boolean found = true; while (found) { found = false; // children ordered by dominance List<Region> children = new ArrayList<>(rpst.getChildren(region)); Collections.sort( children, new Comparator<Region>() { @Override public int compare(Region region1, Region region2) { return getDomInfo().dominates(region1.getEntry(), region2.getEntry()) ? 1 : -1; } }); for (Region child1 : children) { for (Region child2 : children) { if (!child1.equals(child2)) { if (isNonCanonicalRegion(rpst, child1, child2)) { Region newRegion = new RegionImpl(child1.getEntry(), child2.getExit(), ParentType.UNDEFINED); LOGGER.debug("New non canonical region {}", newRegion); rpst.addRegion(newRegion, region); rpst.setNewParent(child1, newRegion); rpst.setNewParent(child2, newRegion); found = true; break; } } } if (found) { break; } } } } for (Region child : childrenBefore) { findNonCanonicalRegions(rpst, child); } }
/** Test if two canonical regions could be merge in one non canonical region. */ private boolean isNonCanonicalRegion(RPST rpst, Region region1, Region region2) { if (!region1.getExit().equals(region2.getEntry())) { return false; } if (rpst.getChildCount(region2) == 0) { return false; } // basic blocks of merged region Set<BasicBlock> basicBlocks = new HashSet<>(); basicBlocks.addAll(rpst.getBasicBlocks(region1)); basicBlocks.addAll(rpst.getBasicBlocks(region2)); basicBlocks.add(region2.getExit()); if (!basicBlocks.containsAll(cfg.getSuccessorsOf(region1.getExit()))) { return false; } if (!basicBlocks.containsAll(cfg.getPredecessorsOf(region1.getExit()))) { return false; } return true; }