From 3a275d20ddee5c29f0ee05c8f808d72bc3a001b2 Mon Sep 17 00:00:00 2001 From: Tobias Grosser Date: Tue, 29 May 2012 09:11:54 +0000 Subject: [PATCH] Move executeScopConditionally() into its own file We will reuse this function for the isl code generator. llvm-svn: 157605 --- polly/include/polly/CodeGen/Utils.h | 63 ++++++++++++ polly/lib/CodeGen/CMakeLists.txt | 1 + polly/lib/CodeGen/CodeGeneration.cpp | 148 ++------------------------- polly/lib/CodeGen/Utils.cpp | 84 +++++++++++++++ 4 files changed, 159 insertions(+), 137 deletions(-) create mode 100644 polly/include/polly/CodeGen/Utils.h create mode 100644 polly/lib/CodeGen/Utils.cpp diff --git a/polly/include/polly/CodeGen/Utils.h b/polly/include/polly/CodeGen/Utils.h new file mode 100644 index 000000000000..fc97d680a4fb --- /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 5e7e2ad18eae..a7f0c86c9305 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 13aa4d76950f..9cb708f09ca3 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 parallelLoops; + std::vector 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); + bool runOnScop(Scop &S) { + ParallelLoops.clear(); - if (DT->dominates(region->getEntry(), newBlock)) { - BasicBlock *OldBlock = region->getEntry(); - std::string OldName = OldBlock->getName(); + assert(S.getRegion().isSimple() && "Only simple regions are supported"); - // Update ScopInfo. - for (Scop::iterator SI = S->begin(), SE = S->end(); SI != SE; ++SI) - if ((*SI)->getBasicBlock() == OldBlock) { - (*SI)->setBasicBlock(newBlock); - break; - } + BasicBlock *StartBlock = executeScopConditionally(S, this); - // 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; - } + IRBuilder<> Builder(StartBlock->begin()); - return splitBlock; - } - - // 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); - } - - Builder->CreateBr(MergeBlock); - MergeBlock->setName("polly.merge_new_and_old"); - - if (DT->dominates(SplitBlock, MergeBlock)) - DT->changeImmediateDominator(MergeBlock, SplitBlock); - } - - bool runOnScop(Scop &scop) { - S = &scop; - region = &S->getRegion(); - DT = &getAnalysis(); - RI = &getAnalysis(); - - 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(); 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::const_iterator PI = parallelLoops.begin(), - PE = parallelLoops.end(); PI != PE; ++PI) + for (std::vector::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 000000000000..2f7943456e46 --- /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(); + RegionInfo &RI = PassInfo->getAnalysis(); + + // 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; +}