[Polly][PATCH 2/8] [Refactor] Cleanup runtime code generation

Johannes Doerfert doerfert at cs.uni-saarland.de
Sun Aug 10 00:50:23 PDT 2014


  + Use regexp in two test case.
  + Refactor the runtime condition build function
---
 include/polly/CodeGen/IRBuilder.h                  |  9 +++
 include/polly/CodeGen/Utils.h                      | 22 +++----
 include/polly/ScopInfo.h                           |  3 +
 lib/CodeGen/CodeGeneration.cpp                     |  3 +-
 lib/CodeGen/IslCodeGeneration.cpp                  | 67 ++++++++++++++--------
 lib/CodeGen/Utils.cpp                              | 14 ++---
 ...tidim_2d_parametric_array_static_loop_bounds.ll |  9 ++-
 .../run-time-condition-with-scev-parameters.ll     |  9 +--
 8 files changed, 83 insertions(+), 53 deletions(-)

diff --git a/include/polly/CodeGen/IRBuilder.h b/include/polly/CodeGen/IRBuilder.h
index a2b7e31..2a21368 100644
--- a/include/polly/CodeGen/IRBuilder.h
+++ b/include/polly/CodeGen/IRBuilder.h
@@ -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
diff --git a/include/polly/CodeGen/Utils.h b/include/polly/CodeGen/Utils.h
index 341ba05..0752aa3 100644
--- a/include/polly/CodeGen/Utils.h
+++ b/include/polly/CodeGen/Utils.h
@@ -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
diff --git a/include/polly/ScopInfo.h b/include/polly/ScopInfo.h
index bf8ecef..7c7afb6 100644
--- a/include/polly/ScopInfo.h
+++ b/include/polly/ScopInfo.h
@@ -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.
diff --git a/lib/CodeGen/CodeGeneration.cpp b/lib/CodeGen/CodeGeneration.cpp
index 29f36c3..4a1f2ea 100644
--- a/lib/CodeGen/CodeGeneration.cpp
+++ b/lib/CodeGen/CodeGeneration.cpp
@@ -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());
 
diff --git a/lib/CodeGen/IslCodeGeneration.cpp b/lib/CodeGen/IslCodeGeneration.cpp
index 71ca008..9cf8bf8 100644
--- a/lib/CodeGen/IslCodeGeneration.cpp
+++ b/lib/CodeGen/IslCodeGeneration.cpp
@@ -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;
   }
 
diff --git a/lib/CodeGen/Utils.cpp b/lib/CodeGen/Utils.cpp
index 36722d3..eea99f9 100644
--- a/lib/CodeGen/Utils.cpp
+++ b/lib/CodeGen/Utils.cpp
@@ -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);
diff --git a/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll b/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
index 3bc8051..9d7e406 100644
--- a/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
+++ b/test/Isl/CodeGen/multidim_2d_parametric_array_static_loop_bounds.ll
@@ -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:
diff --git a/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll b/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
index 017f047..18e8e27 100644
--- a/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
+++ b/test/Isl/CodeGen/run-time-condition-with-scev-parameters.ll
@@ -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"
-- 
2.0.4




More information about the llvm-commits mailing list