[Refactor] Cleanup runtime code generation

+ Use regexp in two test case.
  + Refactor the runtime condition build function

llvm-svn: 215466
This commit is contained in:
Johannes Doerfert 2014-08-12 18:35:54 +00:00
parent d57db6e877
commit 9744c4af16
8 changed files with 83 additions and 53 deletions

View File

@ -101,5 +101,14 @@ private:
// PollyIRBuilder;
typedef PollyBuilderInserter<true> IRInserter;
typedef llvm::IRBuilder<true, llvm::ConstantFolder, IRInserter> PollyIRBuilder;
/// @brief Return an IR builder pointed before the @p BB terminator.
static inline PollyIRBuilder createPollyIRBuilder(llvm::BasicBlock *BB,
LoopAnnotator &LA) {
PollyIRBuilder Builder(BB->getContext(), llvm::ConstantFolder(),
polly::IRInserter(LA));
Builder.SetInsertPoint(BB->getTerminator());
return Builder;
}
}
#endif

View File

@ -15,6 +15,7 @@
namespace llvm {
class Pass;
class Value;
class BasicBlock;
}
@ -22,16 +23,12 @@ namespace polly {
class Scop;
/// @brief Execute a Scop conditionally.
/// @brief Execute a Scop conditionally wrt @p RTC.
///
/// 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.
/// in the CFG. A branch statement decides which version is executed based on
/// the runtime value of @p RTC.
///
/// Before transformation:
///
@ -53,9 +50,12 @@ class 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);
/// @param S The Scop to execute conditionally.
/// @param P A reference to the pass calling this function.
/// @param RTC The runtime condition checked before executing the new SCoP.
///
/// @return The 'StartBlock' to which new code can be added.
llvm::BasicBlock *executeScopConditionally(Scop &S, llvm::Pass *P,
llvm::Value *RTC);
}
#endif

View File

@ -615,6 +615,9 @@ public:
inline const Region &getRegion() const { return R; }
inline Region &getRegion() { return R; }
/// @brief Return the entry block for the underlying region.
inline llvm::BasicBlock *getRegionEntry() { return R.getEntry(); }
/// @brief Get the maximum depth of the loop.
///
/// @return The maximum depth of the loop.

View File

@ -1056,7 +1056,8 @@ public:
simplifyRegion(&S, this);
BasicBlock *StartBlock = executeScopConditionally(S, this);
Value *RTC = ConstantInt::getTrue(S.getRegionEntry()->getContext());
BasicBlock *StartBlock = executeScopConditionally(S, this, RTC);
PollyIRBuilder Builder(StartBlock->begin());

View File

@ -568,41 +568,58 @@ public:
IslCodeGeneration() : ScopPass(ID) {}
/// @name The analysis passes we need to generate code.
///
///{
LoopInfo *LI;
IslAstInfo *AI;
DominatorTree *DT;
ScalarEvolution *SE;
///}
/// @brief The loop anotator to generate llvm.loop metadata.
LoopAnnotator Annotator;
/// @brief Build the delinearization runtime condition.
///
/// Build the condition that evaluates at run-time to true iff all
/// delinearization assumptions taken for the SCoP hold, and to zero
/// otherwise.
///
/// @return A value evaluating to true/false if delinarization is save/unsave.
Value *buildRTC(PollyIRBuilder &Builder, IslExprBuilder &ExprBuilder) {
Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
Value *RTC = ExprBuilder.create(AI->getRunCondition());
return Builder.CreateIsNotNull(RTC);
}
bool runOnScop(Scop &S) {
LoopInfo &LI = getAnalysis<LoopInfo>();
IslAstInfo &AstInfo = getAnalysis<IslAstInfo>();
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
LI = &getAnalysis<LoopInfo>();
AI = &getAnalysis<IslAstInfo>();
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
SE = &getAnalysis<ScalarEvolution>();
assert(!S.getRegion().isTopLevelRegion() &&
"Top level regions are not supported");
simplifyRegion(&S, this);
PollyIRBuilder Builder =
createPollyIRBuilder(S.getRegionEntry(), Annotator);
BasicBlock *StartBlock = executeScopConditionally(S, this);
isl_ast_node *Ast = AstInfo.getAst();
LoopAnnotator Annotator;
PollyIRBuilder Builder(StartBlock->getContext(), llvm::ConstantFolder(),
polly::IRInserter(Annotator));
Builder.SetInsertPoint(StartBlock->begin());
IslNodeBuilder NodeBuilder(Builder, Annotator, this, LI, SE, DT);
Builder.SetInsertPoint(StartBlock->getSinglePredecessor()->begin());
IslNodeBuilder NodeBuilder(Builder, Annotator, this, *LI, *SE, *DT);
NodeBuilder.addMemoryAccesses(S);
NodeBuilder.addParameters(S.getContext());
// Build condition that evaluates at run-time if all assumptions taken
// for the scop hold. If we detect some assumptions do not hold, the
// original code is executed.
Value *V = NodeBuilder.getExprBuilder().create(AstInfo.getRunCondition());
Value *Zero = ConstantInt::get(V->getType(), 0);
V = Builder.CreateICmp(CmpInst::ICMP_NE, Zero, V);
BasicBlock *PrevBB = StartBlock->getUniquePredecessor();
BranchInst *Branch = dyn_cast<BranchInst>(PrevBB->getTerminator());
Branch->setCondition(V);
simplifyRegion(&S, this);
Builder.SetInsertPoint(
S.getRegion().getEnteringBlock()->getFirstInsertionPt());
Value *RTC = buildRTC(Builder, NodeBuilder.getExprBuilder());
BasicBlock *StartBlock = executeScopConditionally(S, this, RTC);
Builder.SetInsertPoint(StartBlock->begin());
NodeBuilder.create(Ast);
NodeBuilder.create(AI->getAst());
DEBUG(StartBlock->getParent()->dump());
return true;
}

View File

@ -20,18 +20,18 @@
using namespace llvm;
BasicBlock *polly::executeScopConditionally(Scop &S, Pass *PassInfo) {
BasicBlock *polly::executeScopConditionally(Scop &S, Pass *P, Value *RTC) {
BasicBlock *StartBlock, *SplitBlock, *NewBlock;
Region &R = S.getRegion();
PollyIRBuilder Builder(R.getEntry());
DominatorTree &DT =
PassInfo->getAnalysis<DominatorTreeWrapperPass>().getDomTree();
RegionInfo &RI = PassInfo->getAnalysis<RegionInfoPass>().getRegionInfo();
LoopInfo &LI = PassInfo->getAnalysis<LoopInfo>();
P->getAnalysis<DominatorTreeWrapperPass>().getDomTree();
RegionInfo &RI = P->getAnalysis<RegionInfoPass>().getRegionInfo();
LoopInfo &LI = P->getAnalysis<LoopInfo>();
// 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);
NewBlock = SplitEdge(R.getEnteringBlock(), R.getEntry(), P);
if (DT.dominates(R.getEntry(), NewBlock)) {
BasicBlock *OldBlock = R.getEntry();
std::string OldName = OldBlock->getName();
@ -59,7 +59,7 @@ BasicBlock *polly::executeScopConditionally(Scop &S, Pass *PassInfo) {
StartBlock = BasicBlock::Create(F->getContext(), "polly.start", F);
SplitBlock->getTerminator()->eraseFromParent();
Builder.SetInsertPoint(SplitBlock);
Builder.CreateCondBr(Builder.getTrue(), StartBlock, R.getEntry());
Builder.CreateCondBr(RTC, StartBlock, R.getEntry());
if (Loop *L = LI.getLoopFor(SplitBlock))
L->addBasicBlockToLoop(StartBlock, LI.getBase());
DT.addNewBlock(StartBlock, SplitBlock);
@ -72,7 +72,7 @@ BasicBlock *polly::executeScopConditionally(Scop &S, Pass *PassInfo) {
// PHI nodes that would complicate life.
MergeBlock = R.getExit();
else {
MergeBlock = SplitEdge(R.getExitingBlock(), R.getExit(), PassInfo);
MergeBlock = SplitEdge(R.getExitingBlock(), R.getExit(), P);
// SplitEdge will never split R.getExit(), as R.getExit() has more than
// one predecessor. Hence, mergeBlock is always a newly generated block.
R.replaceExitRecursive(MergeBlock);

View File

@ -10,11 +10,10 @@ target triple = "x86_64-unknown-linux-gnu"
; A[i][j] = 1.0;
; }
; CHECK: polly.split_new_and_old:
; CHECK: %0 = icmp sge i64 %m, 150
; CHECK: %1 = select i1 %0, i64 1, i64 0
; CHECK: %2 = icmp ne i64 0, %1
; CHECK: br i1 %2, label %polly.start, label %for.i
; CHECK: %[[T0:[._a-zA-Z0-9]]] = icmp sge i64 %m, 150
; CHECK: %[[T1:[._a-zA-Z0-9]]] = select i1 %[[T0]], i64 1, i64 0
; CHECK: %[[T2:[._a-zA-Z0-9]]] = icmp ne i64 %[[T1]], 0
; CHECK: br i1 %[[T2]], label %polly.start, label %for.i
define void @foo(i64 %n, i64 %m, double* %A) {
entry:

View File

@ -1,10 +1,11 @@
; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize < %s | FileCheck %s
; RUN: opt %loadPolly -polly-codegen-isl -S -polly-delinearize -polly-codegen-scev < %s | FileCheck %s
; CHECK: %1 = zext i32 %n to i64
; CHECK: %2 = icmp sge i64 %1, 1
; CHECK: %3 = select i1 %2, i64 1, i64 0
; CHECK: %4 = icmp ne i64 0, %3
; CHECK: zext i32 %n to i64
; CHECK: %[[T0:[._a-zA-Z0-9]]] = zext i32 %n to i64
; CHECK: %[[T1:[._a-zA-Z0-9]]] = icmp sge i64 %[[T0]], 1
; CHECK: %[[T2:[._a-zA-Z0-9]]] = select i1 %[[T1]], i64 1, i64 0
; CHECK: %[[T3:[._a-zA-Z0-9]]] = icmp ne i64 %[[T2]], 0
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"