diff options
author | Tobias Grosser <grosser@fim.uni-passau.de> | 2012-05-29 09:11:54 +0000 |
---|---|---|
committer | Tobias Grosser <grosser@fim.uni-passau.de> | 2012-05-29 09:11:54 +0000 |
commit | 3a275d20ddee5c29f0ee05c8f808d72bc3a001b2 (patch) | |
tree | 18be8c10b4da8aee747cd8cc61004e6a772fad6e | |
parent | 0a91f3220bc7c908c1d45c0e5eeba508c8b20b96 (diff) | |
download | bcm5719-llvm-3a275d20ddee5c29f0ee05c8f808d72bc3a001b2.tar.gz bcm5719-llvm-3a275d20ddee5c29f0ee05c8f808d72bc3a001b2.zip |
Move executeScopConditionally() into its own file
We will reuse this function for the isl code generator.
llvm-svn: 157605
-rw-r--r-- | polly/include/polly/CodeGen/Utils.h | 63 | ||||
-rwxr-xr-x | polly/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | polly/lib/CodeGen/CodeGeneration.cpp | 148 | ||||
-rw-r--r-- | polly/lib/CodeGen/Utils.cpp | 84 |
4 files changed, 159 insertions, 137 deletions
diff --git a/polly/include/polly/CodeGen/Utils.h b/polly/include/polly/CodeGen/Utils.h new file mode 100644 index 00000000000..fc97d680a4f --- /dev/null +++ b/polly/include/polly/CodeGen/Utils.h @@ -0,0 +1,63 @@ +//===- Utils.h - Utility functions for code generation ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions for the code generation. +//===----------------------------------------------------------------------===// + +#ifndef POLLY_CODEGEN_UTILS_H +#define POLLY_CODEGEN_UTILS_H + +namespace llvm { + class Pass; + class BasicBlock; +} + +namespace polly { + + class Scop; + +/// @brief Execute a Scop conditionally. +/// +/// In the CFG the optimized code of the Scop is generated next to the +/// original code. Both the new and the original version of the code remain +/// in the CFG. A branch statement decides which version is executed. +/// For now, we always execute the new version (the old one is dead code +/// eliminated by the cleanup passes). In the future we may decide to execute +/// the new version only if certain run time checks succeed. This will be +/// useful to support constructs for which we cannot prove all assumptions at +/// compile time. +/// +/// Before transformation: +/// +/// bb0 +/// | +/// orig_scop +/// | +/// bb1 +/// +/// After transformation: +/// bb0 +/// | +/// polly.splitBlock +/// / \. +/// | startBlock +/// | | +/// orig_scop new_scop +/// \ / +/// \ / +/// bb1 (joinBlock) +/// +/// @param S The Scop to execute conditionally. +/// @param PassInfo A reference to the pass calling this function. +/// @return BasicBlock The 'StartBlock' to which new code can be added. +llvm::BasicBlock *executeScopConditionally(Scop &S, llvm::Pass *PassInfo); + +} +#endif + diff --git a/polly/lib/CodeGen/CMakeLists.txt b/polly/lib/CodeGen/CMakeLists.txt index 5e7e2ad18ea..a7f0c86c930 100755 --- a/polly/lib/CodeGen/CMakeLists.txt +++ b/polly/lib/CodeGen/CMakeLists.txt @@ -14,4 +14,5 @@ add_polly_library(PollyCodeGen ${CLOOG_FILES} ${ISL_CODEGEN_FILES} LoopGenerators.cpp + Utils.cpp ) diff --git a/polly/lib/CodeGen/CodeGeneration.cpp b/polly/lib/CodeGen/CodeGeneration.cpp index 13aa4d76950..9cb708f09ca 100644 --- a/polly/lib/CodeGen/CodeGeneration.cpp +++ b/polly/lib/CodeGen/CodeGeneration.cpp @@ -31,6 +31,7 @@ #include "polly/CodeGen/CodeGeneration.h" #include "polly/CodeGen/BlockGenerators.h" #include "polly/CodeGen/LoopGenerators.h" +#include "polly/CodeGen/Utils.h" #include "polly/Support/GICHelper.h" #include "llvm/Module.h" @@ -752,163 +753,36 @@ ClastStmtCodeGen::ClastStmtCodeGen(Scop *scop, IRBuilder<> &B, Pass *P) : namespace { class CodeGeneration : public ScopPass { - Region *region; - Scop *S; - DominatorTree *DT; - RegionInfo *RI; - - std::vector<std::string> parallelLoops; + std::vector<std::string> ParallelLoops; public: static char ID; CodeGeneration() : ScopPass(ID) {} - // Split the entry edge of the region and generate a new basic block on this - // edge. This function also updates ScopInfo and RegionInfo. - // - // @param region The region where the entry edge will be splitted. - BasicBlock *splitEdgeAdvanced(Region *region) { - BasicBlock *newBlock; - BasicBlock *splitBlock; - - newBlock = SplitEdge(region->getEnteringBlock(), region->getEntry(), this); - - if (DT->dominates(region->getEntry(), newBlock)) { - BasicBlock *OldBlock = region->getEntry(); - std::string OldName = OldBlock->getName(); - - // Update ScopInfo. - for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) - if ((*SI)->getBasicBlock() == OldBlock) { - (*SI)->setBasicBlock(newBlock); - break; - } - - // Update RegionInfo. - splitBlock = OldBlock; - OldBlock->setName("polly.split"); - newBlock->setName(OldName); - region->replaceEntry(newBlock); - RI->setRegionFor(newBlock, region); - } else { - RI->setRegionFor(newBlock, region->getParent()); - splitBlock = newBlock; - } - return splitBlock; - } + bool runOnScop(Scop &S) { + ParallelLoops.clear(); - // Create a split block that branches either to the old code or to a new basic - // block where the new code can be inserted. - // - // @param Builder A builder that will be set to point to a basic block, where - // the new code can be generated. - // @return The split basic block. - BasicBlock *addSplitAndStartBlock(IRBuilder<> *Builder) { - BasicBlock *StartBlock, *SplitBlock; - - SplitBlock = splitEdgeAdvanced(region); - SplitBlock->setName("polly.split_new_and_old"); - Function *F = SplitBlock->getParent(); - StartBlock = BasicBlock::Create(F->getContext(), "polly.start", F); - SplitBlock->getTerminator()->eraseFromParent(); - Builder->SetInsertPoint(SplitBlock); - Builder->CreateCondBr(Builder->getTrue(), StartBlock, region->getEntry()); - DT->addNewBlock(StartBlock, SplitBlock); - Builder->SetInsertPoint(StartBlock); - return SplitBlock; - } - - // Merge the control flow of the newly generated code with the existing code. - // - // @param SplitBlock The basic block where the control flow was split between - // old and new version of the Scop. - // @param Builder An IRBuilder that points to the last instruction of the - // newly generated code. - void mergeControlFlow(BasicBlock *SplitBlock, IRBuilder<> *Builder) { - BasicBlock *MergeBlock; - Region *R = region; - - if (R->getExit()->getSinglePredecessor()) - // No splitEdge required. A block with a single predecessor cannot have - // PHI nodes that would complicate life. - MergeBlock = R->getExit(); - else { - MergeBlock = SplitEdge(R->getExitingBlock(), R->getExit(), this); - // SplitEdge will never split R->getExit(), as R->getExit() has more than - // one predecessor. Hence, mergeBlock is always a newly generated block. - R->replaceExit(MergeBlock); - } + assert(S.getRegion().isSimple() && "Only simple regions are supported"); - Builder->CreateBr(MergeBlock); - MergeBlock->setName("polly.merge_new_and_old"); + BasicBlock *StartBlock = executeScopConditionally(S, this); - if (DT->dominates(SplitBlock, MergeBlock)) - DT->changeImmediateDominator(MergeBlock, SplitBlock); - } + IRBuilder<> Builder(StartBlock->begin()); - bool runOnScop(Scop &scop) { - S = &scop; - region = &S->getRegion(); - DT = &getAnalysis<DominatorTree>(); - RI = &getAnalysis<RegionInfo>(); - - parallelLoops.clear(); - - assert(region->isSimple() && "Only simple regions are supported"); - - // In the CFG the optimized code of the SCoP is generated next to the - // original code. Both the new and the original version of the code remain - // in the CFG. A branch statement decides which version is executed. - // For now, we always execute the new version (the old one is dead code - // eliminated by the cleanup passes). In the future we may decide to execute - // the new version only if certain run time checks succeed. This will be - // useful to support constructs for which we cannot prove all assumptions at - // compile time. - // - // Before transformation: - // - // bb0 - // | - // orig_scop - // | - // bb1 - // - // After transformation: - // bb0 - // | - // polly.splitBlock - // / \. - // | startBlock - // | | - // orig_scop new_scop - // \ / - // \ / - // bb1 (joinBlock) - IRBuilder<> builder(region->getEntry()); - - // The builder will be set to startBlock. - BasicBlock *splitBlock = addSplitAndStartBlock(&builder); - BasicBlock *StartBlock = builder.GetInsertBlock(); - - mergeControlFlow(splitBlock, &builder); - builder.SetInsertPoint(StartBlock->begin()); - - ClastStmtCodeGen CodeGen(S, builder, this); + ClastStmtCodeGen CodeGen(&S, Builder, this); CloogInfo &C = getAnalysis<CloogInfo>(); CodeGen.codegen(C.getClast()); - parallelLoops.insert(parallelLoops.begin(), + ParallelLoops.insert(ParallelLoops.begin(), CodeGen.getParallelLoops().begin(), CodeGen.getParallelLoops().end()); - return true; } virtual void printScop(raw_ostream &OS) const { - for (std::vector<std::string>::const_iterator PI = parallelLoops.begin(), - PE = parallelLoops.end(); PI != PE; ++PI) + for (std::vector<std::string>::const_iterator PI = ParallelLoops.begin(), + PE = ParallelLoops.end(); PI != PE; ++PI) OS << "Parallel loop with iterator '" << *PI << "' generated\n"; } diff --git a/polly/lib/CodeGen/Utils.cpp b/polly/lib/CodeGen/Utils.cpp new file mode 100644 index 00000000000..2f7943456e4 --- /dev/null +++ b/polly/lib/CodeGen/Utils.cpp @@ -0,0 +1,84 @@ +//===--- Utils.cpp - Utility functions for the code generation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions for the code generation. +// +//===----------------------------------------------------------------------===// + +#include "polly/CodeGen/Utils.h" + +#include "polly/ScopInfo.h" + +#include "llvm/Support/Debug.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" + +using namespace llvm; + +BasicBlock *polly::executeScopConditionally(Scop &S, Pass *PassInfo) { + BasicBlock *StartBlock, *SplitBlock, *NewBlock; + Region &R = S.getRegion(); + IRBuilder<> Builder(R.getEntry()); + DominatorTree &DT = PassInfo->getAnalysis<DominatorTree>(); + RegionInfo &RI = PassInfo->getAnalysis<RegionInfo>(); + + // Split the entry edge of the region and generate a new basic block on this + // edge. This function also updates ScopInfo and RegionInfo. + NewBlock = SplitEdge(R.getEnteringBlock(), R.getEntry(), PassInfo); + if (DT.dominates(R.getEntry(), NewBlock)) { + BasicBlock *OldBlock = R.getEntry(); + std::string OldName = OldBlock->getName(); + + // Update ScopInfo. + for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) + if ((*SI)->getBasicBlock() == OldBlock) { + (*SI)->setBasicBlock(NewBlock); + break; + } + + // Update RegionInfo. + SplitBlock = OldBlock; + OldBlock->setName("polly.split"); + NewBlock->setName(OldName); + R.replaceEntry(NewBlock); + RI.setRegionFor(NewBlock, &R); + } else { + RI.setRegionFor(NewBlock, R.getParent()); + SplitBlock = NewBlock; + } + + SplitBlock->setName("polly.split_new_and_old"); + Function *F = SplitBlock->getParent(); + StartBlock = BasicBlock::Create(F->getContext(), "polly.start", F); + SplitBlock->getTerminator()->eraseFromParent(); + Builder.SetInsertPoint(SplitBlock); + Builder.CreateCondBr(Builder.getTrue(), StartBlock, R.getEntry()); + DT.addNewBlock(StartBlock, SplitBlock); + Builder.SetInsertPoint(StartBlock); + + BasicBlock *MergeBlock; + + if (R.getExit()->getSinglePredecessor()) + // No splitEdge required. A block with a single predecessor cannot have + // PHI nodes that would complicate life. + MergeBlock = R.getExit(); + else { + MergeBlock = SplitEdge(R.getExitingBlock(), R.getExit(), PassInfo); + // SplitEdge will never split R.getExit(), as R.getExit() has more than + // one predecessor. Hence, mergeBlock is always a newly generated block. + R.replaceExit(MergeBlock); + } + + Builder.CreateBr(MergeBlock); + MergeBlock->setName("polly.merge_new_and_old"); + + if (DT.dominates(SplitBlock, MergeBlock)) + DT.changeImmediateDominator(MergeBlock, SplitBlock); + return StartBlock; +} |