llvm-project/polly/lib/RegionSimplify.cpp

220 lines
6.6 KiB
C++

//===- RegionSimplify.cpp -------------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file converts refined regions detected by the RegionInfo analysis
// into simple regions.
//
//===----------------------------------------------------------------------===//
#include "polly/LinkAllPasses.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/RegionPass.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#define DEBUG_TYPE "region-simplify"
#include "llvm/Support/Debug.h"
using namespace llvm;
STATISTIC(NumEntries, "The # of created entry edges");
STATISTIC(NumExits, "The # of created exit edges");
namespace {
class RegionSimplify: public RegionPass {
// Remember the modified region.
Region *r;
void createSingleEntryEdge(Region *R);
void createSingleExitEdge(Region *R);
public:
static char ID;
explicit RegionSimplify() : RegionPass(ID), r(0) {}
virtual void print(raw_ostream &O, const Module *M) const;
virtual bool runOnRegion(Region *R, RGPassManager &RGM);
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
};
}
static RegisterPass<RegionSimplify>
X("polly-region-simplify", "Transform refined regions into simple regions");
char RegionSimplify::ID = 0;
namespace polly {
Pass *createRegionSimplifyPass() {
return new RegionSimplify();
}
}
void RegionSimplify::print(raw_ostream &O, const Module *M) const {
if (r == 0) return;
BasicBlock *enteringBlock = r->getEnteringBlock();
BasicBlock *exitingBlock = r->getExitingBlock();
O << "Region: " << r->getNameStr() << " Edges:\t";
if (enteringBlock)
O << "Entering: [" << enteringBlock->getNameStr() << " -> "
<< r->getEntry()->getName() << "], ";
if (exitingBlock) {
O << "Exiting: [" << exitingBlock->getNameStr() << " -> ";
if (r->getExit())
O << r->getExit()->getName();
else
O << "<return>";
O << "]";
}
O << "\n";
}
void RegionSimplify::getAnalysisUsage(AnalysisUsage &AU) const {
// Function SplitBlockPredecessors currently updates/preserves AliasAnalysis,
/// DominatorTree, LoopInfo, and LCCSA but no other analyses.
//AU.addPreserved<AliasAnalysis>(); Break SCEV-AA
AU.addPreserved<DominatorTree> ();
AU.addPreserved<LoopInfo>();
AU.addPreservedID(LCSSAID);
AU.addPreserved<RegionInfo> ();
AU.addRequired<RegionInfo> ();
}
// createSingleEntryEdge - Split the entry basic block of the given
// region after the last PHINode to form a single entry edge.
void RegionSimplify::createSingleEntryEdge(Region *R) {
BasicBlock *oldEntry = R->getEntry();
SmallVector<BasicBlock*, 4> Preds;
for (pred_iterator PI = pred_begin(oldEntry), PE = pred_end(oldEntry);
PI != PE; ++PI)
if (!R->contains(*PI))
Preds.push_back(*PI);
assert(Preds.size() && "This region has already a single entry edge");
BasicBlock *newEntry = SplitBlockPredecessors(oldEntry,
Preds.data(), Preds.size(),
".single_entry", this);
RegionInfo *RI = &getAnalysis<RegionInfo> ();
// We do not update entry node for children of this region.
// This make it easier to extract children regions because they do not share
// the entry node with their parents.
// all parent regions whose entry is oldEntry are updated with newEntry
Region *r = R->getParent();
// Put the new entry to R's parent.
RI->setRegionFor(newEntry,r);
while (r->getEntry() == oldEntry && !r->isTopLevelRegion()) {
r->replaceEntry(newEntry);
r = r->getParent();
}
// We do not update exit node for children of this region for the same reason
// of not updating entry node.
// All other regions whose exit is oldEntry are updated with new exit node
r = RI->getTopLevelRegion();
std::vector<Region *> RQ;
RQ.push_back(r);
while (!RQ.empty()){
r = RQ.back();
RQ.pop_back();
for (Region::const_iterator RI = r->begin(), RE = r->end(); RI!=RE; ++RI)
RQ.push_back(*RI);
if (r->getExit() == oldEntry && !R->contains(r))
r->replaceExit(newEntry);
}
}
// createSingleExitEdge - Split the exit basic of the given region
// to form a single exit edge.
void RegionSimplify::createSingleExitEdge(Region *R) {
BasicBlock *oldExit = R->getExit();
SmallVector<BasicBlock*, 4> Preds;
for (pred_iterator PI = pred_begin(oldExit), PE = pred_end(oldExit);
PI != PE; ++PI)
if (R->contains(*PI))
Preds.push_back(*PI);
DEBUG(dbgs() << "Going to create single exit for:\n");
DEBUG(R->print(dbgs(), true, 0, Region::PrintRN));
BasicBlock *newExit = SplitBlockPredecessors(oldExit,
Preds.data(), Preds.size(),
".single_exit", this);
RegionInfo *RI = &getAnalysis<RegionInfo>();
// We do not need to update entry nodes because this split happens inside
// this region and it affects only this region and all of its children.
// The new split node belongs to this region
RI->setRegionFor(newExit,R);
DEBUG(dbgs() << "Adding new exiting block: " << newExit->getName() << '\n');
// all children of this region whose exit is oldExit is changed to newExit
std::vector<Region *> RQ;
for (Region::const_iterator RI = R->begin(), RE = R->end(); RI!=RE; ++RI)
RQ.push_back(*RI);
while (!RQ.empty()){
R = RQ.back();
RQ.pop_back();
if (R->getExit() != oldExit)
continue;
for (Region::const_iterator RI = R->begin(), RE = R->end(); RI!=RE; ++RI)
RQ.push_back(*RI);
R->replaceExit(newExit);
DEBUG(dbgs() << "Replacing exit for:\n");
DEBUG(R->print(dbgs(), true, 0, Region::PrintRN));
}
DEBUG(dbgs() << "After split exit:\n");
DEBUG(R->print(dbgs(), true, 0, Region::PrintRN));
}
bool RegionSimplify::runOnRegion(Region *R, RGPassManager &RGM) {
r = 0;
if (!R->isTopLevelRegion()) {
// split entry node if the region has multiple entry edges
if (!(R->getEnteringBlock())
&& (pred_begin(R->getEntry()) != pred_end(R->getEntry()))) {
createSingleEntryEdge(R);
r = R;
++NumEntries;
}
// split exit node if the region has multiple exit edges
if (!(R->getExitingBlock())) {
createSingleExitEdge(R);
r = R;
++NumExits;
}
}
return r != 0;
}