[polly] r303624 - [Polly][NewPM] Port CodeGen to the new PM

Philip Pfaffe via llvm-commits llvm-commits at lists.llvm.org
Tue May 23 03:18:13 PDT 2017


Author: pfaffe
Date: Tue May 23 05:18:12 2017
New Revision: 303624

URL: http://llvm.org/viewvc/llvm-project?rev=303624&view=rev
Log:
[Polly][NewPM] Port CodeGen to the new PM

Summary: To move CG to the new PM I outlined the various helper that were previously members of the CG class into free static functions. The CG class itself I moved into a header, which is required because we need to include it in `RegisterPasses` eventually.

Reviewers: grosser, Meinersbur

Reviewed By: grosser

Subscribers: pollydev, llvm-commits, sanjoy

Tags: #polly

Differential Revision: https://reviews.llvm.org/D33423

Modified:
    polly/trunk/include/polly/CodeGen/CodeGeneration.h
    polly/trunk/lib/CodeGen/CodeGeneration.cpp

Modified: polly/trunk/include/polly/CodeGen/CodeGeneration.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/CodeGen/CodeGeneration.h?rev=303624&r1=303623&r2=303624&view=diff
==============================================================================
--- polly/trunk/include/polly/CodeGen/CodeGeneration.h (original)
+++ polly/trunk/include/polly/CodeGen/CodeGeneration.h Tue May 23 05:18:12 2017
@@ -13,6 +13,7 @@
 #define POLLY_CODEGENERATION_H
 
 #include "polly/Config/config.h"
+#include "polly/ScopPass.h"
 #include "isl/map.h"
 #include "isl/set.h"
 
@@ -23,6 +24,11 @@ enum VectorizerChoice {
   VECTORIZER_POLLY,
 };
 extern VectorizerChoice PollyVectorizerChoice;
+
+struct CodeGenerationPass : public PassInfoMixin<CodeGenerationPass> {
+  PreservedAnalyses run(Scop &S, ScopAnalysisManager &SAM,
+                        ScopStandardAnalysisResults &AR, SPMUpdater &U);
+};
 } // namespace polly
 
 #endif // POLLY_CODEGENERATION_H

Modified: polly/trunk/lib/CodeGen/CodeGeneration.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGen/CodeGeneration.cpp?rev=303624&r1=303623&r2=303624&view=diff
==============================================================================
--- polly/trunk/lib/CodeGen/CodeGeneration.cpp (original)
+++ polly/trunk/lib/CodeGen/CodeGeneration.cpp Tue May 23 05:18:12 2017
@@ -19,6 +19,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "polly/CodeGen/CodeGeneration.h"
 #include "polly/CodeGen/IslAst.h"
 #include "polly/CodeGen/IslNodeBuilder.h"
 #include "polly/CodeGen/PerfMonitor.h"
@@ -31,8 +32,10 @@
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/BasicAliasAnalysis.h"
 #include "llvm/Analysis/GlobalsModRef.h"
+#include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/Debug.h"
 
@@ -52,6 +55,198 @@ static cl::opt<bool>
                    cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
 
 namespace {
+
+static void verifyGeneratedFunction(Scop &S, Function &F, IslAstInfo &AI) {
+  if (!Verify || !verifyFunction(F, &errs()))
+    return;
+
+  DEBUG({
+    errs() << "== ISL Codegen created an invalid function ==\n\n== The "
+              "SCoP ==\n";
+    S.print(errs());
+    errs() << "\n== The isl AST ==\n";
+    AI.print(errs());
+    errs() << "\n== The invalid function ==\n";
+    F.print(errs());
+  });
+
+  llvm_unreachable("Polly generated function could not be verified. Add "
+                   "-polly-codegen-verify=false to disable this assertion.");
+}
+
+// CodeGeneration adds a lot of BBs without updating the RegionInfo
+// We make all created BBs belong to the scop's parent region without any
+// nested structure to keep the RegionInfo verifier happy.
+static void fixRegionInfo(Function &F, Region &ParentRegion, RegionInfo &RI) {
+  for (BasicBlock &BB : F) {
+    if (RI.getRegionFor(&BB))
+      continue;
+
+    RI.setRegionFor(&BB, &ParentRegion);
+  }
+}
+
+/// Mark a basic block unreachable.
+///
+/// Marks the basic block @p Block unreachable by equipping it with an
+/// UnreachableInst.
+static void markBlockUnreachable(BasicBlock &Block, PollyIRBuilder &Builder) {
+  auto *OrigTerminator = Block.getTerminator();
+  Builder.SetInsertPoint(OrigTerminator);
+  Builder.CreateUnreachable();
+  OrigTerminator->eraseFromParent();
+}
+
+/// Remove all lifetime markers (llvm.lifetime.start, llvm.lifetime.end) from
+/// @R.
+///
+/// CodeGeneration does not copy lifetime markers into the optimized SCoP,
+/// which would leave the them only in the original path. This can transform
+/// code such as
+///
+///     llvm.lifetime.start(%p)
+///     llvm.lifetime.end(%p)
+///
+/// into
+///
+///     if (RTC) {
+///       // generated code
+///     } else {
+///       // original code
+///       llvm.lifetime.start(%p)
+///     }
+///     llvm.lifetime.end(%p)
+///
+/// The current StackColoring algorithm cannot handle if some, but not all,
+/// paths from the end marker to the entry block cross the start marker. Same
+/// for start markers that do not always cross the end markers. We avoid any
+/// issues by removing all lifetime markers, even from the original code.
+///
+/// A better solution could be to hoist all llvm.lifetime.start to the split
+/// node and all llvm.lifetime.end to the merge node, which should be
+/// conservatively correct.
+static void removeLifetimeMarkers(Region *R) {
+  for (auto *BB : R->blocks()) {
+    auto InstIt = BB->begin();
+    auto InstEnd = BB->end();
+
+    while (InstIt != InstEnd) {
+      auto NextIt = InstIt;
+      ++NextIt;
+
+      if (auto *IT = dyn_cast<IntrinsicInst>(&*InstIt)) {
+        switch (IT->getIntrinsicID()) {
+        case llvm::Intrinsic::lifetime_start:
+        case llvm::Intrinsic::lifetime_end:
+          BB->getInstList().erase(InstIt);
+          break;
+        default:
+          break;
+        }
+      }
+
+      InstIt = NextIt;
+    }
+  }
+}
+
+static bool CodeGen(Scop &S, IslAstInfo &AI, LoopInfo &LI, DominatorTree &DT,
+                    ScalarEvolution &SE, RegionInfo &RI) {
+  // Check if we created an isl_ast root node, otherwise exit.
+  isl_ast_node *AstRoot = AI.getAst();
+  if (!AstRoot)
+    return false;
+
+  auto &DL = S.getFunction().getParent()->getDataLayout();
+  Region *R = &S.getRegion();
+  assert(!R->isTopLevelRegion() && "Top level regions are not supported");
+
+  ScopAnnotator Annotator;
+  Annotator.buildAliasScopes(S);
+
+  simplifyRegion(R, &DT, &LI, &RI);
+  assert(R->isSimple());
+  BasicBlock *EnteringBB = S.getEnteringBlock();
+  assert(EnteringBB);
+  PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator);
+
+  // Only build the run-time condition and parameters _after_ having
+  // introduced the conditional branch. This is important as the conditional
+  // branch will guard the original scop from new induction variables that
+  // the SCEVExpander may introduce while code generating the parameters and
+  // which may introduce scalar dependences that prevent us from correctly
+  // code generating this scop.
+  BasicBlock *StartBlock =
+      executeScopConditionally(S, Builder.getTrue(), DT, RI, LI);
+  removeLifetimeMarkers(R);
+  auto *SplitBlock = StartBlock->getSinglePredecessor();
+
+  IslNodeBuilder NodeBuilder(Builder, Annotator, DL, LI, SE, DT, S, StartBlock);
+
+  if (PerfMonitoring) {
+    PerfMonitor P(EnteringBB->getParent()->getParent());
+    P.initialize();
+    P.insertRegionStart(SplitBlock->getTerminator());
+
+    BasicBlock *MergeBlock = SplitBlock->getTerminator()
+                                 ->getSuccessor(0)
+                                 ->getUniqueSuccessor()
+                                 ->getUniqueSuccessor();
+    P.insertRegionEnd(MergeBlock->getTerminator());
+  }
+
+  // First generate code for the hoisted invariant loads and transitively the
+  // parameters they reference. Afterwards, for the remaining parameters that
+  // might reference the hoisted loads. Finally, build the runtime check
+  // that might reference both hoisted loads as well as parameters.
+  // If the hoisting fails we have to bail and execute the original code.
+  Builder.SetInsertPoint(SplitBlock->getTerminator());
+  if (!NodeBuilder.preloadInvariantLoads()) {
+
+    // Patch the introduced branch condition to ensure that we always execute
+    // the original SCoP.
+    auto *FalseI1 = Builder.getFalse();
+    auto *SplitBBTerm = Builder.GetInsertBlock()->getTerminator();
+    SplitBBTerm->setOperand(0, FalseI1);
+
+    // Since the other branch is hence ignored we mark it as unreachable and
+    // adjust the dominator tree accordingly.
+    auto *ExitingBlock = StartBlock->getUniqueSuccessor();
+    assert(ExitingBlock);
+    auto *MergeBlock = ExitingBlock->getUniqueSuccessor();
+    assert(MergeBlock);
+    markBlockUnreachable(*StartBlock, Builder);
+    markBlockUnreachable(*ExitingBlock, Builder);
+    auto *ExitingBB = S.getExitingBlock();
+    assert(ExitingBB);
+    DT.changeImmediateDominator(MergeBlock, ExitingBB);
+    DT.eraseNode(ExitingBlock);
+
+    isl_ast_node_free(AstRoot);
+  } else {
+    NodeBuilder.allocateNewArrays();
+    NodeBuilder.addParameters(S.getContext());
+    Value *RTC = NodeBuilder.createRTC(AI.getRunCondition());
+
+    Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC);
+    Builder.SetInsertPoint(&StartBlock->front());
+
+    NodeBuilder.create(AstRoot);
+    NodeBuilder.finalize();
+    fixRegionInfo(*EnteringBB->getParent(), *R->getParent(), RI);
+  }
+
+  Function *F = EnteringBB->getParent();
+  verifyGeneratedFunction(S, *F, AI);
+  for (auto *SubF : NodeBuilder.getParallelSubfunctions())
+    verifyGeneratedFunction(S, *SubF, AI);
+
+  // Mark the function such that we run additional cleanup passes on this
+  // function (e.g. mem2reg to rediscover phi nodes).
+  F->addFnAttr("polly-optimized");
+  return true;
+}
+
 class CodeGeneration : public ScopPass {
 public:
   static char ID;
@@ -71,203 +266,15 @@ public:
   RegionInfo *RI;
   ///}
 
-  void verifyGeneratedFunction(Scop &S, Function &F) {
-    if (!Verify || !verifyFunction(F, &errs()))
-      return;
-
-    DEBUG({
-      errs() << "== ISL Codegen created an invalid function ==\n\n== The "
-                "SCoP ==\n";
-      S.print(errs());
-      errs() << "\n== The isl AST ==\n";
-      AI->print(errs());
-      errs() << "\n== The invalid function ==\n";
-      F.print(errs());
-    });
-
-    llvm_unreachable("Polly generated function could not be verified. Add "
-                     "-polly-codegen-verify=false to disable this assertion.");
-  }
-
-  // CodeGeneration adds a lot of BBs without updating the RegionInfo
-  // We make all created BBs belong to the scop's parent region without any
-  // nested structure to keep the RegionInfo verifier happy.
-  void fixRegionInfo(Function *F, Region *ParentRegion) {
-    for (BasicBlock &BB : *F) {
-      if (RI->getRegionFor(&BB))
-        continue;
-
-      RI->setRegionFor(&BB, ParentRegion);
-    }
-  }
-
-  /// Mark a basic block unreachable.
-  ///
-  /// Marks the basic block @p Block unreachable by equipping it with an
-  /// UnreachableInst.
-  void markBlockUnreachable(BasicBlock &Block, PollyIRBuilder &Builder) {
-    auto *OrigTerminator = Block.getTerminator();
-    Builder.SetInsertPoint(OrigTerminator);
-    Builder.CreateUnreachable();
-    OrigTerminator->eraseFromParent();
-  }
-
-  /// Remove all lifetime markers (llvm.lifetime.start, llvm.lifetime.end) from
-  /// @R.
-  ///
-  /// CodeGeneration does not copy lifetime markers into the optimized SCoP,
-  /// which would leave the them only in the original path. This can transform
-  /// code such as
-  ///
-  ///     llvm.lifetime.start(%p)
-  ///     llvm.lifetime.end(%p)
-  ///
-  /// into
-  ///
-  ///     if (RTC) {
-  ///       // generated code
-  ///     } else {
-  ///       // original code
-  ///       llvm.lifetime.start(%p)
-  ///     }
-  ///     llvm.lifetime.end(%p)
-  ///
-  /// The current StackColoring algorithm cannot handle if some, but not all,
-  /// paths from the end marker to the entry block cross the start marker. Same
-  /// for start markers that do not always cross the end markers. We avoid any
-  /// issues by removing all lifetime markers, even from the original code.
-  ///
-  /// A better solution could be to hoist all llvm.lifetime.start to the split
-  /// node and all llvm.lifetime.end to the merge node, which should be
-  /// conservatively correct.
-  void removeLifetimeMarkers(Region *R) {
-    for (auto *BB : R->blocks()) {
-      auto InstIt = BB->begin();
-      auto InstEnd = BB->end();
-
-      while (InstIt != InstEnd) {
-        auto NextIt = InstIt;
-        ++NextIt;
-
-        if (auto *IT = dyn_cast<IntrinsicInst>(&*InstIt)) {
-          switch (IT->getIntrinsicID()) {
-          case llvm::Intrinsic::lifetime_start:
-          case llvm::Intrinsic::lifetime_end:
-            BB->getInstList().erase(InstIt);
-            break;
-          default:
-            break;
-          }
-        }
-
-        InstIt = NextIt;
-      }
-    }
-  }
-
   /// Generate LLVM-IR for the SCoP @p S.
   bool runOnScop(Scop &S) override {
     AI = &getAnalysis<IslAstInfoWrapperPass>().getAI();
-
-    // Check if we created an isl_ast root node, otherwise exit.
-    isl_ast_node *AstRoot = AI->getAst();
-    if (!AstRoot)
-      return false;
-
     LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
     DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
     SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
     DL = &S.getFunction().getParent()->getDataLayout();
     RI = &getAnalysis<RegionInfoPass>().getRegionInfo();
-    Region *R = &S.getRegion();
-    assert(!R->isTopLevelRegion() && "Top level regions are not supported");
-
-    ScopAnnotator Annotator;
-    Annotator.buildAliasScopes(S);
-
-    simplifyRegion(R, DT, LI, RI);
-    assert(R->isSimple());
-    BasicBlock *EnteringBB = S.getEnteringBlock();
-    assert(EnteringBB);
-    PollyIRBuilder Builder = createPollyIRBuilder(EnteringBB, Annotator);
-
-    // Only build the run-time condition and parameters _after_ having
-    // introduced the conditional branch. This is important as the conditional
-    // branch will guard the original scop from new induction variables that
-    // the SCEVExpander may introduce while code generating the parameters and
-    // which may introduce scalar dependences that prevent us from correctly
-    // code generating this scop.
-    BasicBlock *StartBlock =
-        executeScopConditionally(S, Builder.getTrue(), *DT, *RI, *LI);
-    removeLifetimeMarkers(R);
-    auto *SplitBlock = StartBlock->getSinglePredecessor();
-
-    IslNodeBuilder NodeBuilder(Builder, Annotator, *DL, *LI, *SE, *DT, S,
-                               StartBlock);
-
-    if (PerfMonitoring) {
-      PerfMonitor P(EnteringBB->getParent()->getParent());
-      P.initialize();
-      P.insertRegionStart(SplitBlock->getTerminator());
-
-      BasicBlock *MergeBlock = SplitBlock->getTerminator()
-                                   ->getSuccessor(0)
-                                   ->getUniqueSuccessor()
-                                   ->getUniqueSuccessor();
-      P.insertRegionEnd(MergeBlock->getTerminator());
-    }
-
-    // First generate code for the hoisted invariant loads and transitively the
-    // parameters they reference. Afterwards, for the remaining parameters that
-    // might reference the hoisted loads. Finally, build the runtime check
-    // that might reference both hoisted loads as well as parameters.
-    // If the hoisting fails we have to bail and execute the original code.
-    Builder.SetInsertPoint(SplitBlock->getTerminator());
-    if (!NodeBuilder.preloadInvariantLoads()) {
-
-      // Patch the introduced branch condition to ensure that we always execute
-      // the original SCoP.
-      auto *FalseI1 = Builder.getFalse();
-      auto *SplitBBTerm = Builder.GetInsertBlock()->getTerminator();
-      SplitBBTerm->setOperand(0, FalseI1);
-
-      // Since the other branch is hence ignored we mark it as unreachable and
-      // adjust the dominator tree accordingly.
-      auto *ExitingBlock = StartBlock->getUniqueSuccessor();
-      assert(ExitingBlock);
-      auto *MergeBlock = ExitingBlock->getUniqueSuccessor();
-      assert(MergeBlock);
-      markBlockUnreachable(*StartBlock, Builder);
-      markBlockUnreachable(*ExitingBlock, Builder);
-      auto *ExitingBB = S.getExitingBlock();
-      assert(ExitingBB);
-      DT->changeImmediateDominator(MergeBlock, ExitingBB);
-      DT->eraseNode(ExitingBlock);
-
-      isl_ast_node_free(AstRoot);
-    } else {
-      NodeBuilder.allocateNewArrays();
-      NodeBuilder.addParameters(S.getContext());
-      Value *RTC = NodeBuilder.createRTC(AI->getRunCondition());
-
-      Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC);
-      Builder.SetInsertPoint(&StartBlock->front());
-
-      NodeBuilder.create(AstRoot);
-      NodeBuilder.finalize();
-      fixRegionInfo(EnteringBB->getParent(), R->getParent());
-    }
-
-    Function *F = EnteringBB->getParent();
-    verifyGeneratedFunction(S, *F);
-    for (auto *SubF : NodeBuilder.getParallelSubfunctions())
-      verifyGeneratedFunction(S, *SubF);
-
-    // Mark the function such that we run additional cleanup passes on this
-    // function (e.g. mem2reg to rediscover phi nodes).
-    F->addFnAttr("polly-optimized");
-
-    return true;
+    return CodeGen(S, *AI, *LI, *DT, *SE, *RI);
   }
 
   /// Register all analyses and transformation required.
@@ -300,6 +307,16 @@ public:
 };
 } // namespace
 
+PreservedAnalyses
+polly::CodeGenerationPass::run(Scop &S, ScopAnalysisManager &SAM,
+                               ScopStandardAnalysisResults &AR, SPMUpdater &U) {
+  auto &AI = SAM.getResult<IslAstAnalysis>(S, AR);
+  if (CodeGen(S, AI, AR.LI, AR.DT, AR.SE, AR.RI))
+    return PreservedAnalyses::none();
+
+  return PreservedAnalyses::all();
+}
+
 char CodeGeneration::ID = 1;
 
 Pass *polly::createCodeGenerationPass() { return new CodeGeneration(); }




More information about the llvm-commits mailing list