summaryrefslogtreecommitdiffstats
path: root/polly/lib/RegionSimplify.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/RegionSimplify.cpp')
-rw-r--r--polly/lib/RegionSimplify.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/polly/lib/RegionSimplify.cpp b/polly/lib/RegionSimplify.cpp
new file mode 100644
index 00000000000..5e6e9c7f3e8
--- /dev/null
+++ b/polly/lib/RegionSimplify.cpp
@@ -0,0 +1,219 @@
+//===- 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;
+}
OpenPOWER on IntegriCloud